Back to skill

Security audit

国内油价实时查询 - 即刻数据

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to query fuel prices as advertised, but it has an undisclosed setting that can redirect API-key-bearing requests to another server.

Install only if you trust the publisher and your runtime environment. Keep the Jike AppKey low-privilege, do not set JIKE_API_BASE_URL unless intentionally testing, and prefer a version that fixes the API host to https://api.jikeapi.cn or validates any override against an HTTPS allowlist.

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/petrol_query.py:21
Finding

Undocumented API Base URL Override Allows AppKey Disclosure

Content
View full analysis

Vulnerability Details

File Location: scripts/petrol_query.py, lines 21 and 143–147
Vulnerability Type: Credential disclosure through an unvalidated destination URL
Risk Level: Medium

Vulnerable Code

python
API_BASE_URL = os.environ.get("JIKE_API_BASE_URL", "https://api.jikeapi.cn").rstrip("/")
python
params = {"appkey": appkey}
if province:
    params["province"] = province
url = f"{API_BASE_URL}{API_PATH}?{urllib.parse.urlencode(params)}"
try:
    with urllib.request.urlopen(url, timeout=15) as response:
        return json.loads(response.read().decode("utf-8"))

Technical Analysis

The script accepts an undocumented JIKE_API_BASE_URL environment variable and uses its value as the destination for API requests without validating its scheme or hostname. The AppKey is then inserted into the query string and transmitted to that destination.

Although the documented service endpoint is https://api.jikeapi.cn, an execution environment can replace it with an arbitrary URL, including an attacker-controlled HTTP or HTTPS server. Consequently, a secret obtained independently from --key, JIKE_PETROL_QUERY_KEY, JIKE_APPKEY, or scripts/.env can be sent outside the intended trust boundary.

Placing the credential in the query string further increases exposure because URLs may be retained in web-server access logs, reverse-proxy logs, monitoring systems, and diagnostic records.

Attack Path

  1. An attacker controls or influences the environment used to launch the skill, while the legitimate AppKey remains available through another configured credential source.
  2. The attacker sets JIKE_API_BASE_URL to an attacker-controlled endpoint, such as https://attacker.example.
  3. A user or agent executes the documented petrol query command.
  4. load_appkey obtains the legitimate AppKey from the command line, environment, or local .env file.
  5. request_api constructs a ...[truncated 870 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove the JIKE_API_BASE_URL override in production and use a fixed trusted endpoint:

    python
    API_BASE_URL = "https://api.jikeapi.cn"
    
  2. If endpoint customization is required for testing, expose it only through an explicit development mode and validate the parsed URL:

    • Require the https scheme.
    • Require the hostname to match an allowlist.
    • Reject embedded credentials, unexpected ports, fragments, and non-HTTPS destinations.
    • Resolve and validate the final destination after redirects, or disable cross-origin redirects.
  3. Prefer transmitting the AppKey in an authorization header rather than the query string if the API supports it:

    python
    request = urllib.request.Request(url)
    request.add_header("Authorization", f"Bearer {appkey}")
    
  4. Avoid logging complete request URLs or headers containing credentials.

  5. Rotate any AppKey that may have been used while an untrusted JIKE_API_BASE_URL value was present.

  6. Add tests confirming that HTTP endpoints, unknown hostnames, malformed URLs, and cross-origin redirects are rejected before any credential is transmitted.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (6)

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

Critical
Category
Data Flow
Confidence
94% confidence
Finding

The request URL is built from API_BASE_URL, which is sourced from the JIKE_API_BASE_URL environment variable, and then used directly in urllib.request.urlopen. If an attacker can influence the runtime environment, they can redirect requests to an arbitrary host and receive the AppKey in the query string, causing credential exfiltration and unexpected outbound network access.

Content

Scanner excerpt · scripts/petrol_query.py (reported line 153)May include surrounding context.

python
params["province"] = province
    url = f"{API_BASE_URL}{API_PATH}?{urllib.parse.urlencode(params)}"
    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/petrol_query.py (reported line 50)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
94% confidence
Finding

The skill requires environment access for API keys and performs network requests, but it does not declare an explicit tool scope such as permissions or allowed-tools. This creates an unnecessary trust gap: a host agent may permit broader capabilities than intended, making it harder to enforce least privilege or review what the skill can access.

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 45)May include surrounding context.

md
"title": "国内油价实时查询 - 即刻数据",
  "description": "按省份查询 92号汽油、95号汽油、98号汽油和0号柴油价格,也支持不传省份返回全部地区油价。",
  "env": "JIKE_PETROL_QUERY_KEY",
  "api_url": "https://api.jikeapi.cn/v1/petrol/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": "按省份查询 92号汽油、95号汽油、98号汽油和0号柴油价格,也支持不传省份返回全部地区油价。",
  "env": "JIKE_PETROL_QUERY_KEY",
  "api_url": "https://api.jikeapi.cn/v1/petrol/query",
  "homepage": "https://www.jikeapi.cn/"
}

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The AppKey is included as a URL query parameter, which increases exposure because URLs may be logged by proxies, servers, client tooling, shell history, monitoring systems, or error traces. Even though HTTPS protects the transport, placing credentials in the URL broadens the number of places where the secret can be unintentionally retained.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.