Back to skill

Security audit

12306购票搜索服务

Security checks for vulnerabilities and agentic risk

Overview

This train-ticket skill appears purpose-aligned overall, but it stores API keys in a plaintext local .env file and contains documentation inconsistencies that users should review before installing.

Install only if you are comfortable with the skill making external API calls and storing XBY_APIKEY in a local plaintext .env file. Prefer a disposable or low-privilege API key, avoid committing the .env file, and review the documentation mismatch before relying on it for automated actions.

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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (13)

Lp3

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding
The skill documentation instructs the agent to access environment configuration, persist an API key via local file/config writes, and call external network APIs, yet no permissions are declared. This creates a trust and governance gap: a host may expose capabilities the user did not explicitly approve, and the skill can solicit and store sensitive credentials without a clear permission model.

Intent-Code Divergence

Medium
Confidence
83% confidence
Finding
The documentation contains conflicting tool-call examples and project references to gaokao/school-search behavior inside a train-ticket skill. Such inconsistencies can cause the agent to invoke the wrong tools, mishandle parameters, or route user data to unintended functions or backends, which is a security-relevant integrity issue in an agent skill.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The function silently writes the provided API key into a local .env file and also mirrors it into process environment state without any user-visible disclosure or consent flow. Persisting credentials in plaintext can expose them through accidental commits, backups, shared workspaces, or local file disclosure.

Credential Access

High
Category
Privilege Escalation
Content
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")
Confidence
79% confidence
Finding
The code manually opens and parses .env specifically to extract XBY_APIKEY, bypassing the normal typed settings flow and broadening secret-handling logic in custom code. Custom secret parsing increases the chance of insecure storage assumptions, accidental leakage, or inconsistent behavior across environments.

Credential Access

High
Category
Privilege Escalation
Content
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")
            for line in content.splitlines():
Confidence
79% confidence
Finding
This line participates in manual reading of the .env file to access an API key in plaintext. While local secret loading is sometimes necessary, this custom credential access pattern increases exposure surface and is especially concerning given the project/skill identity mismatch in the file.

Credential Access

High
Category
Privilege Escalation
Content
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()
Confidence
90% confidence
Finding
This helper is explicitly designed to save an API key into a plaintext .env file. Persisting credentials in an unencrypted local file creates a realistic disclosure risk through source control mistakes, logs, backups, multi-user systems, or compromised local environments.

Credential Access

High
Category
Privilege Escalation
Content
def set_api_key(api_key: str) -> bool:
    """设置API key并持久化到.env"""
    if not api_key or not api_key.strip():
        return False
    api_key = api_key.strip()
Confidence
87% confidence
Finding
The API encourages setting and persisting the key as normal application behavior, making plaintext secret storage part of the skill's supported workflow. In the context of a ticket-search skill, this is more dangerous because credential persistence is ancillary to the stated user function and may not be expected by users.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1
Confidence
93% confidence
Finding
The dependency is specified with a lower bound only, which allows future installs to resolve to different versions over time. This weakens reproducibility and can unexpectedly introduce breaking changes or newly introduced vulnerable releases into the skill's runtime.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1
Confidence
93% confidence
Finding
Using an unpinned version range for pydantic means deployments may install different versions depending on resolution time and environment. That increases supply-chain and stability risk because security posture and behavior can change without code changes.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1
Confidence
92% confidence
Finding
An unpinned pydantic-settings dependency permits non-deterministic installs and increases exposure to accidental introduction of insecure or incompatible releases. While not an immediate exploit by itself, it is a real supply-chain hardening gap.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1
Confidence
92% confidence
Finding
python-dotenv is also specified with only a minimum version, so environments may resolve to varying releases with different behavior or vulnerabilities. This creates avoidable supply-chain uncertainty, especially for a server-side MCP skill that may be deployed repeatedly across environments.

Known Vulnerable Dependency: requests==2.31.0 — 5 advisory(ies): 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); CVE-2026-25645 (Requests has Insecure Temp File Reuse in its extract_zipped_paths() utility func) +2 more

Medium
Category
Supply Chain
Confidence
97% confidence
Finding
The finding indicates requests 2.31.0 has published advisories, including credential leakage via malicious URLs and request verification issues in some session flows. In an MCP-based ticket search service that likely makes outbound HTTP requests, a vulnerable HTTP client can materially increase risk if attacker-controlled URLs, redirects, or session behavior are involved.

Known Vulnerable Dependency: python-dotenv==1.0.1 — 1 advisory(ies): CVE-2026-28684 (python-dotenv: Symlink following in set_key allows arbitrary file overwrite via )

Low
Category
Supply Chain
Confidence
81% confidence
Finding
python-dotenv 1.0.1 is reported as affected by a symlink-following arbitrary file overwrite issue in set_key. This is only likely to be exploitable if the skill invokes dotenv file modification features on attacker-influenced paths, but it remains a genuine vulnerable dependency and should be treated as a real security weakness.

Static analysis

No suspicious patterns detected.