Back to skill

Security audit

航班查询 - 聚合数据

Security checks for vulnerabilities and agentic risk

Overview

This skill coherently performs Juhe flight searches and has no hidden or destructive behavior, but users should handle the API key carefully.

Install only if you are comfortable sending flight search details to Juhe. Prefer setting JUHE_FLIGHT_KEY through your environment or a managed secret store, avoid passing the key with --key, do not commit scripts/.env, and rotate the key if it has been exposed in shell history or logs.

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/flight_query.py:119
Finding

API Credential Exposure Through Command-Line Arguments, Plaintext Files, and URL Query Parameters

Content
View full analysis

Vulnerability Details

File Location: scripts/flight_query.py:90-105, 119-126, 245-247, 329-337; SKILL.md:29-40
Vulnerability Type: Insecure handling and transmission of sensitive API credentials
Risk Level: Medium

Vulnerable Code

The script loads the API key from an unprotected plaintext .env file:

python
def load_api_key(cli_key: str = None) -> str:
    """按优先级加载 API Key"""
    if cli_key:
        return cli_key

    env_key = os.environ.get("JUHE_FLIGHT_KEY", "").strip()
    if env_key:
        return env_key

    env_file = Path(__file__).parent / ".env"
    if env_file.exists():
        for line in env_file.read_text(encoding="utf-8").splitlines():
            line = line.strip()
            if line.startswith("JUHE_FLIGHT_KEY="):
                val = line.split("=", 1)[1].strip().strip('"').strip("'")
                if val:
                    return val

    return ""

It then places the credential directly in the request URL:

python
params = {
    "key": api_key,
    "departure": departure,
    "arrival": arrival,
    "departureDate": departure_date,
}
url = f"{API_URL}?{urllib.parse.urlencode(params)}"

try:
    with urllib.request.urlopen(url, timeout=15) as resp:
        result = json.loads(resp.read().decode("utf-8"))

The command-line parser supports passing the credential as a process argument:

python
if args[i] == "--key" and i + 1 < len(args):
    cli_key = args[i + 1]
    i += 2

The missing-key error also recommends both plaintext-file and command-line storage:

python
if not api_key:
    print("❌ 未找到 API Key,请通过以下方式之一配置:")
    print("   1. 环境变量:export JUHE_FLIGHT_KEY=your_api_key")
    print("   2. .env 文件:在脚本目录创建 .env,写入 JUHE_FLIGHT_KEY=your_api_key")
    print("   3. 命令行参数:python flight_query.py --key your_api_key --departure BJS --arrival SHA --date 2025-06-18")
    print(f"\n免费申请 Key:
...[truncated 3864 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove or deprecate the --key command-line option. Prefer JUHE_FLIGHT_KEY supplied through the environment or a platform-managed secret facility.
  2. If interactive entry is needed, use getpass.getpass() so the key is neither echoed nor included in process arguments.
  3. If .env support remains necessary:
    • Require the file to be owned by the current user.
    • Reject or warn about permissions broader than 0600.
    • Add scripts/.env and equivalent secret files to .gitignore.
    • Update the documentation to create it securely, such as with umask 077.
    • Clearly warn users never to commit, archive, or share the file.
  4. If the Juhe API supports header-based authentication, send the key in an authorization header instead of the query string.
  5. If the upstream API requires the key in the query string, document that unavoidable risk and ensure application, proxy, telemetry, and exception logs redact the key parameter.
  6. Avoid printing or propagating complete request URLs in future diagnostics. Introduce a URL-redaction helper before logging network errors.
  7. Rotate any API key that may previously have been passed through command-line arguments, stored with permissive file permissions, committed to source control, or captured in logs.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (9)

Credential Access

High
Category
Privilege Escalation
Confidence
88% confidence
Finding

The documentation instructs users to place an API key into a local .env file under the scripts directory, which increases the chance of accidental exposure through source control, backups, or local file disclosure. While storing secrets in environment variables is common, recommending plaintext secret files without accompanying safeguards is a credential-handling weakness.

Content

Scanner excerpt · SKILL.md (reported line 27)May include surrounding context.

md
# 方式一:环境变量(推荐,一次配置永久生效)
export JUHE_FLIGHT_KEY=你的 AppKey

# 方式二:.env 文件(在脚本目录创建)
echo "JUHE_FLIGHT_KEY=你的 AppKey" > scripts/.env

# 方式三:每次命令行传入

Credential Access

High
Category
Privilege Escalation
Confidence
96% confidence
Finding

The example shows passing the AppKey directly on the command line with --key, which can expose the credential via shell history, process listings, logs, and telemetry. In this skill context, the key is the only authentication factor for the third-party API, so disclosure could enable unauthorized API use, quota exhaustion, and billing or service abuse.

Content

Scanner excerpt · SKILL.md (reported line 28)May include surrounding context.

md
export JUHE_FLIGHT_KEY=你的 AppKey

# 方式二:.env 文件(在脚本目录创建)
echo "JUHE_FLIGHT_KEY=你的 AppKey" > scripts/.env

# 方式三:每次命令行传入
python scripts/flight_query.py --key 你的 AppKey --departure BJS --arrival SHA --date 2025-06-18

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/flight_query.py (reported line 12)May include surrounding context.

python
API Key 配置(任选其一,优先级从高到低):
    1. 命令行参数:python flight_query.py --key your_api_key ...
    2. 环境变量:export JUHE_FLIGHT_KEY=your_api_key
    3. 脚本同目录的 .env 文件:JUHE_FLIGHT_KEY=your_api_key

免费申请 API Key: https://www.juhe.cn/docs/api/id/818
"""

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/flight_query.py (reported line 331)May include surrounding context.

python
API Key 配置(任选其一,优先级从高到低):
    1. 命令行参数:python flight_query.py --key your_api_key ...
    2. 环境变量:export JUHE_FLIGHT_KEY=your_api_key
    3. 脚本同目录的 .env 文件:JUHE_FLIGHT_KEY=your_api_key

免费申请 API Key: https://www.juhe.cn/docs/api/id/818
"""

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/flight_query.py (reported line 85)May include surrounding context.

python
if env_key:
        return env_key

    env_file = Path(__file__).parent / ".env"
    if env_file.exists():
        for line in env_file.read_text(encoding="utf-8").splitlines():
            line = line.strip()

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill declares capabilities that imply environment-variable access, file reads, and outbound network use, but it does not explicitly declare a tool scope such as permissions or allowed-tools. This weakens sandboxing and reviewability because the runtime may grant broader access than users or platform operators expect, especially since the skill also instructs use of local files and secrets.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The description lists examples such as "查询某日航班" and "机票价格查询" without defining invocation boundaries or exclusions. These phrases are broad enough that ordinary user discussion about flights or prices could unintentionally match the skill, and the file does not provide negative examples or scope constraints to narrow activation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill sends user-provided travel details to a third-party API, but it does not prominently disclose that origin, destination, and travel date will be transmitted off-platform to Juhe. This creates a privacy and consent risk because users may reasonably assume their travel queries stay within the assistant unless told otherwise.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

This code file contains natural-language documentation entirely in Chinese and later emits help/error/output text only in Chinese, which imposes a specific language on users without offering a language or locale choice. The policy explicitly calls for flagging skills that force a specific language without user opt-in.

Content

No source excerpt is available for this finding.