Back to skill

Security audit

车牌号码归属地 - 即刻数据

Security checks for vulnerabilities and agentic risk

Overview

This skill does the advertised vehicle-plate lookup, but it has an under-disclosed endpoint override that could send the API key and queried plate to an unexpected server.

Review before installing. Use it only with a dedicated Jike API key, avoid passing the key on the command line, and ensure JIKE_API_BASE_URL is unset or restricted to the official Jike API host.

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/vehicle_plate_query.py:24
Finding

Unrestricted API Endpoint Override Can Expose AppKey and Vehicle Plate Data

Content
View full analysis

Vulnerability Details

File Location: scripts/vehicle_plate_query.py, lines 24 and 100–114
Vulnerability Type: Unvalidated API destination and sensitive credentials in URL query parameters
Risk Level: Medium

Vulnerable Code

python
API_BASE_URL = os.environ.get("JIKE_API_BASE_URL", "https://api.jikeapi.cn").rstrip("/")
API_PATH = "/v1/vehicle/plate/query"
APPKEY_ENV_NAMES = ("JIKE_VEHICLE_PLATE_QUERY_KEY", "JIKE_APPKEY")
python
def request_api(plate_number: str, appkey: str) -> dict[str, Any]:
    """
    功能说明:
    1. 调用即刻数据车牌号码归属地接口。
    2. 使用 `plate_number` 和 `appkey` 查询参数。
    3. 返回接口 JSON;网络异常时返回统一错误结构。

    @param plate_number 车牌号码或车牌前缀
    @param appkey 即刻数据 AppKey
    @return dict 接口返回或错误结构
    """
    url = f"{API_BASE_URL}{API_PATH}?{urllib.parse.urlencode({'plate_number': plate_number, 'appkey': appkey})}"
    try:
        with urllib.request.urlopen(url, timeout=15) as response:
            return json.loads(response.read().decode("utf-8"))

Technical Analysis

The API base URL is obtained from the undeclared JIKE_API_BASE_URL environment variable without validating its scheme or hostname. Although the default value points to the documented official HTTPS service, an inherited or attacker-controlled process environment can redirect requests to an arbitrary HTTP or HTTPS server.

The request includes both the AppKey and queried vehicle plate number in the URL query string. Consequently, redirection to an attacker-controlled endpoint directly discloses both values. Even when the official endpoint is used, query-string credentials can be retained in web server, reverse-proxy, monitoring, or diagnostic logs.

This is not evidence of intentional exfiltration: the default destination is consistent with SKILL.md and _meta.json. The issue is an insecure configuration and credential-transmission pattern that becomes exploitable when an attacker can influence the execution environment.

Attack Path

  1. An attac ...[truncated 1712 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove the runtime endpoint override in production and use the fixed official endpoint:

    python
    API_BASE_URL = "https://api.jikeapi.cn"
    
  2. If endpoint configurability is required for testing, parse and strictly validate it:

    • Require the https scheme.
    • Allow only an explicit hostname allowlist, such as api.jikeapi.cn.
    • Reject embedded credentials, fragments, unexpected ports, and malformed hosts.
    • Keep test endpoint configuration unavailable in production builds.
  3. Prefer transmitting the AppKey in an authorization header rather than the URL if supported by the API:

    python
    request = urllib.request.Request(url_without_appkey)
    request.add_header("Authorization", f"Bearer {appkey}")
    
  4. If the provider mandates query-string authentication, ensure URLs are never printed or included in exceptions and configure proxies, servers, and monitoring systems to redact the appkey parameter.

  5. Deprecate the --key option because command-line arguments may be visible in shell history and process listings. Prefer a protected environment variable or secret manager.

  6. Restrict access to scripts/.env, exclude it from source control and packaged artifacts, and document secure file permissions.

  7. Add tests confirming that plaintext HTTP URLs, unapproved hosts, and redirect attempts to unapproved destinations are rejected. Consider disabling automatic cross-origin redirects or validating the final redirect destination before transmitting credentials.

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
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (7)

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

Critical
Category
Data Flow
Confidence
94% confidence
Finding

The request URL is built from an environment-controlled base URL and includes the AppKey as a query parameter, then sent via urlopen without validating the destination host. If JIKE_API_BASE_URL is overridden, the script can exfiltrate the AppKey and user-supplied plate number to an attacker-controlled server, turning a simple lookup tool into an SSRF/credential-leak path. In this skill context, the script is expected to contact a fixed vendor API, so allowing the endpoint to be redirected makes the issue more dangerous rather than less.

Content

Scanner excerpt · scripts/vehicle_plate_query.py (reported line 113)May include surrounding context.

python
"""
    url = f"{API_BASE_URL}{API_PATH}?{urllib.parse.urlencode({'plate_number': plate_number, 'appkey': appkey})}"
    try:
        with urllib.request.urlopen(url, timeout=15) as response:
            return json.loads(response.read().decode("utf-8"))
    except urllib.error.HTTPError as exc:
        return {"code": exc.code, "message": f"接口请求失败: HTTP {exc.code}", "data": ""}

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

python
if env_value:
            return env_value

    env_file = Path(__file__).parent / ".env"
    if not env_file.exists():
        return ""

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill declares executable behavior that uses environment variables, reads local files, and performs network access, but it does not declare an explicit tool scope such as permissions or allowed-tools. This weakens isolation and reviewability because an agent/runtime may grant broader capabilities than users expect, increasing the chance of unintended secret exposure or unauthorized external requests.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

md
"title": "车牌号码归属地 - 即刻数据",
  "description": "输入车牌号码或至少前两位车牌前缀,查询车牌前缀、省份简称、省份和城市。",
  "env": "JIKE_VEHICLE_PLATE_QUERY_KEY",
  "api_url": "https://api.jikeapi.cn/v1/vehicle/plate/query",
  "homepage": "https://www.jikeapi.cn/"
}

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · _meta.json (reported line 8)May include surrounding context.

json
"title": "车牌号码归属地 - 即刻数据",
  "description": "输入车牌号码或至少前两位车牌前缀,查询车牌前缀、省份简称、省份和城市。",
  "env": "JIKE_VEHICLE_PLATE_QUERY_KEY",
  "api_url": "https://api.jikeapi.cn/v1/vehicle/plate/query",
  "homepage": "https://www.jikeapi.cn/"
}

Vague Triggers

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

This manifest description says the skill works when the user provides a plate number or 'at least the first two prefix characters,' but it does not define any explicit trigger phrases, activation boundaries, or exclusions. In a manifest file, this kind of broad natural-language invocation description can cause ambiguous matching for short alphanumeric inputs that may appear in unrelated contexts.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

This code sends the queried plate number and credential to a remote API via URL parameters. Although the module docstring states that it calls the external interface, there is no runtime disclosure, prompt, or explicit user-facing warning immediately before transmitting potentially sensitive user input and credentials.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.