T09 · Insecure Skill Coding Practices
- Location
scripts/track17.py:1237- Finding
Webhook Signature Validation Fails Open
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This package-tracking skill mostly matches its stated purpose, but its optional webhook path can accept and store untrusted data too broadly and its daily report deletes delivered-package records.
Use this skill only if you are comfortable sending tracking numbers, carrier data, optional parameters, language, token-authenticated requests, and possibly label-derived tags to 17TRACK. Prefer manual polling over webhooks. Do not expose the webhook server beyond localhost until signature rejection and request-size limits are fixed. Avoid sensitive labels, and be aware that running the daily report removes delivered packages from the local database.
scripts/track17.py:1237Webhook Signature Validation Fails Open
scripts/track17.py:1388Unbounded Webhook Requests Can Exhaust Memory and Disk
scripts/track17.py:743Local Package Labels Are Unnecessarily Transmitted to 17TRACK
The skill description advertises API polling and webhook ingestion but does not clearly disclose that tracking numbers, shipment metadata, and related updates are sent to an external third-party service. Because shipment data can reveal sensitive personal or business logistics information, the missing privacy warning reduces informed consent and can lead to inappropriate exposure of user data.
The trigger examples are broad enough to match generic phrases like 'where is my package?' or 'any updates on my orders?', which can cause the skill to activate in contexts the user did not clearly intend. In a package-tracking skill that can query external services and manipulate stored tracking data, over-broad routing increases the chance of unintended data disclosure or unintended actions.
Automatic removal of delivered packages is an autonomous action that changes local state without an explicit per-item user decision. In the context of shipment records, this can destroy useful history and create operational or evidentiary issues if a delivery is disputed or if cleanup logic behaves incorrectly.
- **Add packages** — "track RR123456789CN, it's my new headphones"
- **Check status** — "where is my package?" / "any updates on my orders?"
- **Sync updates** — polls 17TRACK API for latest tracking events
- **Auto-cleanup** — delivered packages are automatically removed by daily reports
- **Webhook support** — optional real-time push updates from 17TRACK
## Features
The README states that delivered packages are automatically removed by daily reports, but it does not clearly warn users that package history may be deleted without explicit review or consent. This creates a data-retention and integrity risk because users may lose records they expected to preserve for disputes, audits, or reimbursement purposes.
The skill declares broad operational capabilities in practice (environment access, filesystem reads/writes, network access, and shell execution) but does not explicitly constrain them with a tool scope. That increases the blast radius if the skill is invoked unexpectedly or modified later, because the agent may grant more authority than is necessary for parcel tracking tasks.
The invocation guidance includes very broad trigger phrases such as 'track this', 'where is my order', and 'any updates on my package', which can match common conversational requests without sufficient user intent verification. In a skill with network, shell, and local database capabilities, over-broad activation can cause unnecessary external API calls, local state changes, or processing of sensitive shipment data when the user did not clearly intend to use this specific integration.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
print("❌ TRACK17_TOKEN not set")
return False
result = subprocess.run(
[sys.executable, str(TRACK17_SCRIPT), "sync"],
capture_output=True,
text=True,
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def remove_package(pkg_id):
"""Remove a package via track17.py."""
result = subprocess.run(
[sys.executable, str(TRACK17_SCRIPT), "remove", str(pkg_id)],
capture_output=True,
text=True,
The script automatically removes delivered packages during report generation, creating an unexpected destructive side effect for what appears to be a read/report operation. In this skill context, package tracking data may be operationally important, so silent deletion can cause loss of audit/history, user confusion, and missed follow-up actions if delivery records are needed later.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
import urllib.request
from typing import Any, Dict, Iterable, List, Optional, Sequence, Tuple
API_BASE = "https://api.17track.net/track/v2.2"
CARRIERS_URL = "https://res.17track.net/asset/carrier/info/apicarrier.all.json"
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
import urllib.request
from typing import Any, Dict, Iterable, List, Optional, Sequence, Tuple
API_BASE = "https://api.17track.net/track/v2.2"
CARRIERS_URL = "https://res.17track.net/asset/carrier/info/apicarrier.all.json"
This code writes raw webhook bodies and request headers to files in the local inbox directory, which can include tracking data and metadata from external requests. Although the module docstring mentions webhook ingestion and storage directories, there is no nearby user-facing warning, confirmation, or explicit disclosure when enabling the webhook server that incoming request contents and headers will be persisted to disk.
The docstring frames the script as producing stdout-only reporting with no effects beyond contacting 17TRACK, but main() performs auto-cleanup by calling track17.py remove for delivered packages. That behavior changes local tracking state, so the documentation understates the script's side effects.
The status formatter hardcodes Italian-language labels such as In Transito, Consegnato, and Non Trovato regardless of user preference. This imposes a specific language/locale in natural-language output without offering choice or documenting a justified locale restriction.
The natural-language documentation states the default translation language is "en", and the code uses English as the fallback language in multiple places. This imposes a specific locale by default rather than prompting for or offering a language choice at runtime.