T09 · Insecure Skill Coding Practices
- Location
scripts/desensitize.py:160- Finding
Privacy share packages retain credential directories and copy binary files without sanitization
- Content
View full analysis
Vulnerability Details
File Location:
scripts/desensitize.py, lines 160–180
Vulnerability Type: Sensitive data exposure in privacy share-package generation
Risk Level: HighTechnical Analysis
The
make_share_packagefunction recursively processes the entire source migration package. Its directory filter excludes only entries listed inSKIP_DIRS, which does not include the documentedcredentials/directory.Text files receive limited regex-based masking, while every other file type is copied byte-for-byte into the share package:
python def make_share_package(src_dir, out_dir, manifest, mf): """整目录 → 分享包:_share/ 脱敏副本 + _credentials_needed.md。""" share_dir = os.path.join(out_dir, "_share") os.makedirs(share_dir, exist_ok=True) hits, copied, binaries, masked_files = {}, 0, [], 0 for root, dirs, files in os.walk(src_dir): dirs[:] = [d for d in dirs if d not in SKIP_DIRS] for fn in sorted(files): if fn in SKIP_FILES or fn.endswith((".pyc", ".pyo")) or fn.startswith("_desensitize_map"): continue sp = os.path.join(root, fn) dp = os.path.join(share_dir, os.path.relpath(sp, src_dir)) if fn.endswith(TEXT_EXT): desensitize_text_file(sp, dp, manifest, hits) masked_files += 1 else: # 非文本(图片/二进制)原样复制;截图可能含敏感信息,登记待人工确认 os.makedirs(os.path.dirname(dp) or ".", exist_ok=True) shutil.copy2(sp, dp) binaries.append(os.path.relpath(sp, src_dir)) copied += 1This conflicts with the documented privacy boundary in
SKILL.md, which states that a share package excludescredentials/. Merely printing a warning about binary files does not enforce that boundary or prevent the resulting package from being distributed.The text sanitizer is also not a safe fallback for credential files: it recognizes only selected extensions and credentia ...[truncated 1614 chars]
- Remediation
View remediation
Remediation Suggestions
- Exclude
credentials/unconditionally while constructing_share/, regardless of filename or extension. - Use an explicit allowlist of safe shareable paths and formats instead of recursively copying the private package by default.
- Fail closed for images, archives, databases, key stores, and unknown file formats. Require explicit per-file approval before including them.
- Treat common secret-bearing formats such as
.pem,.key,.p12,.pfx,.kdbx, SQLite databases, browser exports, and archives as forbidden. - Perform a final structural validation that rejects any share artifact containing
credentials/, mapping files, private-key material, or other prohibited paths. - Write output to a fresh directory and fail if
_share/already exists, preventing stale sensitive files from surviving a later sanitized run. - Add regression tests demonstrating that:
credentials/never appears in share output;- non-text files are rejected unless explicitly approved;
- unsupported credential formats cause generation to fail;
- the completed share tree passes a post-generation secret and forbidden-path check.
- Exclude
