Back to skill

Security audit

快递追踪助手

Security checks for vulnerabilities and agentic risk

Overview

This China courier tracking skill does what it says, but users should understand that it sends tracking numbers to Kuaidi100 and stores a local tracking list in plaintext.

Install only if you are comfortable with courier tracking numbers being queried through Kuaidi100 and saved locally in a plaintext JSON file. Avoid using it for sensitive deliveries in shared-user environments, and be careful with clear/delete commands because the local list can be erased without a confirmation step.

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/express_tracker.py:27
Finding

Shipment Tracking Data Stored Without Explicit Access Controls

Content
View full analysis

Vulnerability Details

File Location: scripts/express_tracker.py, lines 27–36 and 167–175
Vulnerability Type: Plaintext storage of privacy-sensitive data without restrictive file permissions
Risk Level: Medium

Vulnerable Code

python
def load():
    os.makedirs(DATA_DIR, exist_ok=True)
    if os.path.exists(DATA_FILE):
        return json.load(open(DATA_FILE))
    return {"tracking": []}


def save(d):
    with open(DATA_FILE, "w") as f:
        json.dump(d, f, ensure_ascii=False, indent=2)

The following code persists tracking numbers, shipment status details, and event timestamps through the vulnerable save() function:

python
existing = [i for i in data["tracking"] if i["number"] == num]
if existing:
    existing[0].update({"carrier": carrier, "last_status": last_s, "last_time": last_t})
    save(data)
    return f"♻️ 更新 {num}({carrier})\n📍 {last_s}"
data["tracking"].append({"number": num, "carrier": carrier, "last_status": last_s, "last_time": last_t})
save(data)

Technical Analysis

The skill stores courier tracking numbers, carrier identifiers, latest shipment status descriptions, and event timestamps in a plaintext JSON file under the user's home directory. These values are privacy-sensitive because a valid tracking number can reveal shipment activity and may sometimes be used to query additional delivery information.

The directory is created without an explicit restrictive mode, and the file is opened without explicitly enforcing owner-only permissions. Consequently, the effective permissions depend on the process umask, inherited directory permissions, and any permissions retained by an existing file. In an environment with a permissive umask or shared access to the relevant directory, other local users or processes may be able to read the data.

The implementation also writes directly to the destination file rather than creating a protected temporary file ...[truncated 1795 chars]

Remediation
View remediation

Remediation Suggestions

  1. Create the storage directory with owner-only permissions and correct the permissions if it already exists:

    python
    os.makedirs(DATA_DIR, mode=0o700, exist_ok=True)
    os.chmod(DATA_DIR, 0o700)
    
  2. Create files with mode 0600 rather than relying on the process umask. Use os.open() with restrictive flags and permissions where appropriate:

    python
    fd = os.open(
        DATA_FILE,
        os.O_WRONLY | os.O_CREAT | os.O_TRUNC,
        0o600,
    )
    with os.fdopen(fd, "w", encoding="utf-8") as f:
        json.dump(d, f, ensure_ascii=False, indent=2)
    os.chmod(DATA_FILE, 0o600)
    
  3. Prefer an atomic save procedure: create a temporary file inside the protected data directory with mode 0600, flush and synchronize it, and then replace the destination with os.replace().

  4. Where supported, reject symbolic links using platform-appropriate protections such as O_NOFOLLOW, and verify that the destination and its parent directory are owned by the expected user.

  5. Minimize retained data. Store only fields necessary for the tracking-list feature, provide a clear deletion mechanism, and document the storage location and retention behavior.

  6. Handle file operations and malformed JSON safely so that permission corrections, interrupted writes, or corrupted state do not crash the skill or cause insecure recovery behavior.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (8)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared purpose suggests a simple tracking lookup, but the implementation also maintains a persistent local tracking database and supports list/add/update/delete/clear operations. This mismatch is dangerous because users may disclose shipment numbers assuming one-time lookups, while the skill actually retains and manages potentially sensitive logistics history on disk.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill advertises network access to query courier status and local JSON persistence, but the manifest does not declare any tool scope or permissions. That creates an authorization/transparency gap: users and platforms cannot easily tell that the skill can write local files and make outbound requests, which weakens review and consent controls.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The natural-language content of the skill, including its description and usage instructions, is entirely in Chinese. This can amount to a language policy violation because the skill implicitly forces a specific language without user opt-in or an explicit statement that it is intended only for Chinese-speaking users or a China-specific workflow.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The code stores tracking data in ~/.qclaw/skills/cn-express-tracker/data/express.json even though the description suggests a simple lookup assistant. Silent local persistence of shipment identifiers creates a privacy issue because tracking numbers can reveal purchasing habits, addresses, or sensitive deliveries.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

Tracking numbers are sent to kuaidi100, a third-party service, without any user-facing disclosure or consent flow. Package IDs are sensitive metadata, and exfiltrating them to an external service may violate user expectations, privacy policies, or enterprise data-handling rules.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill’s stated purpose is simple tracking lookup, but the handler also supports persistent add/delete/clear list management. This expands behavior beyond user expectations and can cause unintended retention or deletion of package-tracking data, especially in agent contexts where users may assume a transient query-only operation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The clear-all operation erases all stored tracking entries immediately when the input contains words like 清除 or 清空. In conversational or agent-driven environments, this can lead to accidental data loss from ambiguous input or unintended tool invocation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The top-level natural-language description is entirely Chinese and labels the skill as a CN express tracker, which signals a fixed language/locale experience. The file does not indicate that users can choose another language or that the locale restriction is explicitly documented as a justified region-specific constraint.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.