Back to skill

Security audit

12306火车票查询与预订

Security checks for vulnerabilities and agentic risk

Overview

This skill does what it claims: it sends travel, station, route, and hotel queries to external transport/travel services and returns results, with no evidence of persistence, local data harvesting, or destructive behavior.

Install only if you are comfortable with your train routes, station addresses, dates, and hotel preferences being sent to external China travel/mapping services through the publisher's proxy endpoints. Operators should understand that PROXY_TOKEN, if set, is transmitted to those proxy endpoints as an authentication header.

Vulnerability Patterns
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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
Findings (12)

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

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/train_ticket.py (reported line 45)May include surrounding context.

python
req = urllib.request.Request(url, data=data, headers=headers, method="POST")
    try:
        t = timeout or 30
        with urllib.request.urlopen(req, timeout=t) as resp:
            return json.loads(resp.read().decode("utf-8"))
    except Exception as e:
        return {"error": str(e)}

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

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/train_ticket.py (reported line 58)May include surrounding context.

python
method="POST",
    )
    try:
        with urllib.request.urlopen(req, timeout=15) as r:
            data = json.loads(r.read().decode("utf-8"))
            if isinstance(data, dict) and data.get("code") == 0 and "data" in data:
                return data["data"]

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

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/train_ticket.py (reported line 83)May include surrounding context.

python
url = "https://kyfw.12306.cn/otn/resources/js/framework/station_name.js"
    try:
        req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"})
        with urllib.request.urlopen(req, timeout=10) as r:
            text = r.read().decode("utf-8")
        m = re.search(r"'(.+)'", text)
        if not m:

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

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/train_ticket.py (reported line 129)May include surrounding context.

python
url = "https://kyfw.12306.cn/otn/resources/js/framework/station_name.js"
    try:
        req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"})
        with urllib.request.urlopen(req, timeout=10) as r:
            text = r.read().decode("utf-8")
        m = re.search(r"'(.+)'", text)
        if not m:

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
84% confidence
Finding

The skill exposes multiple network-backed capabilities via declared tools and explicitly describes data flow to 12306 and travel platforms, but it does not define any explicit tool scope such as permissions or allowed-tools. Without restrictive scoping, an agent runtime may grant broader-than-necessary access or make it harder to enforce least privilege and review what external connectivity the skill actually needs.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

All user-facing docstrings and returned messages are written in Chinese, and date parsing only recognizes Chinese terms such as "今天/明天/后天" plus Chinese-formatted dates. Under SQP-3, forcing a specific language or locale without opt-in can violate language/locale policy unless the constraint is explicitly justified or the user is given a choice.

Content

No source excerpt is available for this finding.

Unbounded Resource Access

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill allows unbounded resource consumption (API calls, storage, compute). Without rate limits or quotas, a compromised or misbehaving agent can cause denial-of-service or cost overruns.

Content

Scanner excerpt · scripts/train_ticket.py (reported line 36)May include surrounding context.

python
# ============ 代理调用 ============
def _call_tuniu(rtype, params, timeout=None):
    """调用途牛SCF代理"""
    url = TUNIU_PROXY
    headers = {"Content-Type": "application/json", "X-Proxy-Token": PROXY_TOKEN}

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

User-provided travel search data such as origin, destination, date, and preferences is sent to an external proxy service without any visible consent, disclosure, or privacy notice in this file. In this skill context, that data can reveal travel plans and behavior patterns, so undisclosed third-party transmission is materially sensitive.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The transport tool sends origin addresses and station destinations to an external mapping proxy, but there is no visible disclosure in the code that precise location data leaves the local skill. Because addresses and station destinations can reveal highly sensitive movement and whereabouts information, the lack of transparency increases privacy risk.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The hotel recommendation tool claims to provide lodging recommendations, but it actually calls the same 'tuniu_train_search' request type used for train searches. That mismatch can cause users to send free-form lodging preferences to an unexpected backend path, creating data handling ambiguity and increasing the risk of privacy violations or incorrect downstream processing.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The lodging tool transmits free-form hotel preference queries to an external proxy without visible disclosure. Free-form text can contain sensitive details such as budget, companions, neighborhoods, schedule, or special needs, making undisclosed transfer to a third party a real privacy concern.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The code reads a proxy token from the environment, which is a form of sensitive credential access. While the token is not exposed, SQP-2 asks for disclosure around sensitive environment-variable or credential access when no prompt, comment, or broader warning is present; this file only defines the variable without explaining the sensitivity or operational implications to users/operators.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.