Back to skill

Security audit

12306购票搜索服务

Security checks for vulnerabilities and agentic risk

Overview

This train-ticket search skill should be reviewed before use because it stores an API key in a local plaintext .env file and contains stale Gaokao/school-search references that do not match its stated purpose.

Install only if you are comfortable giving this skill a Xiaobenyang API key and having it stored in a local .env file in plaintext. Review or fix the stale Gaokao/school-search references, use a dedicated secret store or tightly permissioned config file, and pin dependencies before relying on it.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/config.py:47
Finding

API Key Persisted in a Plaintext File Without Enforced Access Controls

Content
View full analysis

Vulnerability Details

File Location: scripts/config.py, lines 47-62
Vulnerability Type: Plaintext credential storage and unsafe configuration-file handling
Risk Level: Medium

python
try:
    env_path = Path(".env")
    lines = []
    if env_path.exists():
        lines = env_path.read_text(encoding="utf-8").splitlines()
    found = False
    new_lines = []
    for line in lines:
        if line.startswith("XBY_APIKEY="):
            new_lines.append(f"XBY_APIKEY={api_key}")
            found = True
        else:
            new_lines.append(line)
    if not found:
        new_lines.append(f"XBY_APIKEY={api_key}")
    env_path.write_text("\n".join(new_lines) + "\n", encoding="utf-8")
    os.environ["XBY_APIKEY"] = api_key
    return True

Technical Analysis

The supplied API key is persisted directly in a plaintext .env file. The implementation does not create the file with restrictive permissions, verify the permissions of an existing file, or correct overly permissive permissions after writing.

The file path is relative to the process working directory rather than anchored to a controlled, Skill-specific configuration directory. Consequently, the secret may be written into an unexpected project or shared directory. The implementation also does not reject symbolic links or use an atomic, securely created temporary file, so a locally prepared .env path could redirect the write to another file that the running process is permitted to modify.

The API key is additionally placed into the process environment. Although this is often required for configuration, it expands the set of process-level mechanisms through which the credential may become visible.

Attack Path

  1. The user supplies an API key as required by the Skill workflow.
  2. set_api_key() invokes the affected persistence function.
  3. The function writes the key as XBY_APIKEY=<secret> into ./.env. ...[truncated 1077 chars]
Remediation
View remediation

Remediation Suggestions

  • Prefer an operating-system credential manager, deployment secret manager, or environment-only configuration instead of plaintext persistence.
  • If file persistence is unavoidable, use a dedicated absolute configuration path owned by the current user rather than the process working directory.
  • Create new credential files with mode 0600 and verify or correct the permissions of existing files before reading or writing them.
  • Reject symbolic links and verify that the resolved destination remains inside the expected configuration directory.
  • Write updates atomically through a securely created temporary file in the same directory, apply restrictive permissions, and then replace the destination.
  • Add .env to .gitignore and other packaging or backup exclusion rules.
  • Avoid placing the key in the process environment unless required by the execution model.
  • Rotate any API key that may already have been stored in a shared, world-readable, or committed .env file.

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding

Unbounded Dependency Versions Permit Unaudited Future Releases

Content
View full analysis

Vulnerability Details

File Location: requirements.txt, lines 1-4
Vulnerability Type: Unlocked third-party dependency supply chain
Risk Level: Low

text
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1

Technical Analysis

Every dependency specifies only a minimum version. These constraints allow package installers to select arbitrary future releases that were not present during this audit. No lock file, upper bounds, or package hashes are provided.

This does not establish that any currently listed package is malicious. However, it makes installations non-reproducible and allows later compromised, incompatible, or unexpectedly changed releases to enter the execution environment without a corresponding source-code review. Python dependencies can execute code during installation and are imported with the privileges of the process running the Skill.

Attack Path

  1. An operator installs the project dependencies from requirements.txt.
  2. The package index resolves a newer release permitted by a >= constraint.
  3. The resolved release differs from the versions originally reviewed and tested.
  4. If that future release or its dependency chain is compromised, malicious code can execute during installation or when the Skill imports the package.
  5. The code runs with the permissions of the installing or executing user.

Impact Assessment

The potential impact depends on the privileges of the installation and runtime account. A compromised dependency could read files and environment variables accessible to that account, including the configured API key; make network requests; modify user-writable files; or alter application behavior.

The current repository does not demonstrate an actively compromised dependency. The confirmed weakness is the absence of reproducible, reviewed dependency resolution, so exploitation requires a malicious or compromised ...[truncated 50 chars]

Remediation
View remediation

Remediation Suggestions

  • Pin each direct and transitive dependency to a reviewed version through a generated lock file.
  • Use cryptographic package hashes, such as pip's --require-hashes workflow, to ensure that installations retrieve approved artifacts.
  • Install only from trusted package indexes over authenticated TLS connections.
  • Review and test dependency updates before changing the lock file.
  • Run automated dependency vulnerability and provenance checks in continuous integration.
  • Perform installations and runtime execution under a least-privileged account.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (30)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The documented purpose is train-ticket search, but the behavior includes reading and persisting API keys and references to a mismatched gaokao/XBY project structure. This mismatch is dangerous because it can mislead reviewers and users about what code will do, conceal secret-handling behavior, and indicate the skill may be repurposed or incorrectly wired to another service.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The file claims to provide a 12306 ticket-search service, but the surrounding examples/project references indicate high-school exam or school-search functionality. Such identity inconsistency is a serious trust and supply-chain issue because it suggests copy-paste reuse, wrong backend invocation, or concealed behavior that may route user inputs and secrets to an unintended service.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The configuration module for a 12306 ticket-search skill contains unrelated XBY/Gaokao service identifiers and API-key persistence logic, indicating code reuse or hidden coupling to a different backend. In this skill context, unexplained external service configuration and credential handling materially increases the risk of unintended data flow, misrouting requests, or covert integration beyond the declared ticket-search purpose.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/config.py (reported line 13)May include surrounding context.

python
model_config = SettingsConfigDict(
        env_prefix="XBY_GAOKAO_",
        env_file=".env",
        env_file_encoding="utf-8",
        extra="ignore",
    )

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/config.py (reported line 32)May include surrounding context.

python
model_config = SettingsConfigDict(
        env_prefix="XBY_GAOKAO_",
        env_file=".env",
        env_file_encoding="utf-8",
        extra="ignore",
    )

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

This code manually opens and parses the .env file to extract XBY_APIKEY, bypassing the settings library’s normal controls and creating bespoke secret-handling logic. Custom credential parsing is risky because it is harder to audit, easier to misuse, and unnecessary for the stated read-only search function.

Content

Scanner excerpt · scripts/config.py (reported line 31)May include surrounding context.

python
default_year: int = 2025

    def model_post_init(self, __context):
        # 强制从 .env 文件读取 XBY_APIKEY
        env_path = Path(".env")
        if env_path.exists():
            content = env_path.read_text(encoding="utf-8")

Credential Access

High
Category
Privilege Escalation
Confidence
91% confidence
Finding

Reading XBY_APIKEY directly from the process environment into application state extends the flow of sensitive credentials through code that is unrelated to the skill’s declared purpose. In this context, undocumented secret consumption for an unrelated service increases the risk of credential misuse and hidden dependency on external infrastructure.

Content

Scanner excerpt · scripts/config.py (reported line 39)May include surrounding context.

python
if line.startswith("XBY_APIKEY="):
                    self.api_key = line.split("=", 1)[1].strip()
                    break
        # 如果环境变量有值,覆盖 .env 的值
        env_val = os.getenv("XBY_APIKEY", "")
        if env_val:
            self.api_key = env_val

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

This function persists API keys to a .env file, creating a durable secret artifact on disk that may be exposed through backups, logs, repository mistakes, or other local access. Because the skill is advertised as a ticket-search interface, this credential-storage capability is more dangerous than in a dedicated credential-management utility and appears unnecessary to core functionality.

Content

Scanner excerpt · scripts/config.py (reported line 48)May include surrounding context.

python
def save_api_key_to_env(api_key: str) -> bool:
    """将API key保存到.env文件"""
    try:
        env_path = Path(".env")
        lines = []
        if env_path.exists():
            lines = env_path.read_text(encoding="utf-8").splitlines()

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill declares no explicit tool scope or permission boundaries despite requiring environment access, file read/write, and network use. In an agent setting, this over-broad and undocumented capability surface can let the model invoke sensitive operations beyond what users expect, especially when combined with instructions to persist secrets locally.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The workflow example invokes a school-search function that does not belong to the declared ticket-search toolset. Contradictory invocation guidance can cause the agent to call the wrong code path, mishandle user data, or interact with unintended services, which increases the chance of data leakage and unsafe execution.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill repeatedly requires queries to use Chinese city and station names, e.g. '通过中文城市名' and '通过具体的中文车站名', which imposes a language constraint in the instructions. The file does not offer an opt-in choice for other languages or explain that the skill is intentionally limited to Chinese-language use for a documented regional/compliance reason.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This code sends params to a remote endpoint and includes an API key in request headers, which can transmit user or system data off-box. There is logging for success/error, but no user-facing disclosure, confirmation prompt, or warning in this file that data will be sent to an external service.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The code declares one environment-variable namespace via env_prefix="XBY_GAOKAO_" but bypasses it to manually read XBY_APIKEY from .env and os.environ. This inconsistency can cause operators to misconfigure secrets, accidentally expose credentials in the wrong variable name, or believe protections and conventions are being followed when they are not.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill can write an API key to a local .env file and mutate the process environment, which exceeds the minimum capability needed for a read-only ticket search service. Persisting credentials locally expands the attack surface by leaving secrets on disk and enabling later unintended reuse by other components or sessions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

API keys are written to .env without any visible warning, confirmation, or indication that credentials will be stored on disk. In an agent skill ecosystem, silent credential persistence is dangerous because users may reasonably expect ephemeral use while the secret remains recoverable from the workspace or source tree.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The docstrings repeatedly require Chinese city or station names, such as '通过中文城市名查询' and examples limited to Chinese-language inputs. This imposes a language constraint in natural-language instructions without any opt-in, alternative locale handling, or explicit justification for why only Chinese is supported.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The instructions state that the interface is for users providing Chinese city names and examples only use Chinese inputs. Because this is a natural-language constraint affecting how users must interact with the skill, it represents a locale/language policy issue unless clearly justified or made optional.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This function description explicitly says it queries by concrete Chinese station names and provides only Chinese examples. That is a language-specific interaction rule presented as mandatory behavior, with no user choice or documented rationale in the file.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
98% confidence
Finding

The dependency specification uses a lower-bound range (requests>=2.31.0) rather than a pinned version, which makes builds non-reproducible and can result in different environments resolving to different releases. In a network-facing MCP service, this increases supply-chain risk and makes it impossible to determine from the manifest alone whether a vulnerable or incompatible version is installed.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The manifest includes requests without an exact version pin, while the package has multiple published advisories. Because this MCP service likely makes outbound HTTP requests to search ticket data, using an unpinned HTTP client prevents verification that deployed versions are free from known issues such as credential leakage or request-validation flaws.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
98% confidence
Finding

The manifest leaves pydantic unpinned with pydantic>=2.7.0, allowing dependency resolution to drift over time. This can introduce unexpected vulnerable releases or breaking behavior, especially important for an API/MCP service that relies on strict data validation semantics.

Content

Scanner excerpt · requirements.txt (reported line 2)May include surrounding context.

text
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1

Unverifiable Dependency: pydantic has 4 known advisory(ies) (CVE-2021-29510 (Use of "infinity" as an input to datetime and date fields causes infinite loop i); CVE-2024-3772 (Pydantic regular expression denial of service); CVE-2021-29510 (Pydantic is a data validation and settings management using Python type hinting.) +1 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
93% confidence
Finding

pydantic has known advisories, but the requirements file does not pin the installed version, so the security posture cannot be verified from source control. Since this service likely parses and validates model or API input, an affected version could enable denial of service or parser-related issues depending on how the library is used elsewhere in the project.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

pydantic-settings is specified as a minimum version only, so deployments may install different releases depending on when and where the environment is built. This weakens reproducibility and may expose the service to supply-chain or known-version issues that cannot be assessed from the file alone.

Content

Scanner excerpt · requirements.txt (reported line 3)May include surrounding context.

text
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1

Unverifiable Dependency: pydantic-settings has 1 known advisory(ies) (CVE-2026-58203 (pydantic-settings: NestedSecretsSettingsSource follows symlinks outside secrets_)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
91% confidence
Finding

pydantic-settings is associated with at least one advisory, and the lack of version pinning means the deployed build could resolve to a vulnerable release. For a service that probably uses environment- or file-based configuration, that uncertainty is security-relevant even if exploitability depends on code paths outside this file.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

python-dotenv is not pinned, so the environment may resolve to any later release satisfying the minimum version. For a service likely to load configuration from environment files, this creates avoidable uncertainty around security fixes, regressions, and exposure to future vulnerable releases.

Content

Scanner excerpt · requirements.txt (reported line 4)May include surrounding context.

text
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1