T09 · Insecure Skill Coding Practices
- 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: MediumVulnerable 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
-
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) -
Create files with mode
0600rather than relying on the process umask. Useos.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) -
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 withos.replace(). -
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. -
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.
-
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.
-
