T09 · Insecure Skill Coding Practices
Error
- Location
- distill.py:421
- Finding
- Unredacted credentials and personal data are persisted in plaintext<![CDATA[ ## Vulnerability Details **File Location**: `distill.py:421-447`, `distill.py:483-503`; confirmed sensitive records in `data/experiences/2e40b3400fb0.json:37-46,211` and personal data in `data/experiences/d17102135085.json:88-89` **Vulnerability Type**: Plaintext sensitive-data storage and secret exposure **Risk Level**: High ### Vulnerable Code ```python def extract_facts(sections: list[dict]) -> list[dict]: """Extract specific, concrete facts.""" facts = [] seen = set() for section in sections: body = section["body"] header = section["header"] for line in body.splitlines(): line = line.strip() if len(line) < 15 or len(line) > 400: continue if any(re.search(p, line) for p in FACT_PATTERNS): key = line[:50] if key in seen: continue seen.add(key) # Strip markdown formatting clean = re.sub(r"\*{1,2}(.+?)\*{1,2}", r"\1", line) clean = re.sub(r"`(.+?)`", r"\1", clean) facts.append({ "fact": clean[:400], "domain": detect_domain(line + " " + header), "tags": extract_tags(line) }) return facts[:20] ``` The extracted values are subsequently written without redaction: ```python experience = { "id": exp_id, "source": relative, "source_date": source_date, "distilled_at": datetime.now().isoformat(), "hash": h, **extracted } EXP_DIR.mkdir(parents=True, exist_ok=True) exp_path = EXP_DIR / f"{exp_id}.json" exp_path.write_text(json.dumps(experience, indent=2)) ``` The package contains records matching live credential formats, including an API key identifier, an API secret, a service key, credential file paths, and an email address. The credential values are intentionally not reproduced in this report. ### Technical Analysis The `FACT_ ...[truncated 1939 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Immediately revoke and rotate every credential contained in bundled experience files and repository history. 2. Remove all credentials and unnecessary personal information from distributed JSON, SQLite files, commits, release archives, and backups. 3. Replace secret-oriented fact extraction with an allowlist of safe fact types. 4. Add redaction before persistence for: - API keys and bearer tokens - High-entropy secret strings - Private keys and seed phrases - Passwords and authentication cookies - Email addresses and other personal identifiers - Credential and configuration file contents 5. Store only indirect references, such as “credential available through the configured secret manager.” 6. Run the same redaction pipeline before indexing, printing, saving briefings, and making any external API call. 7. Apply restrictive permissions such as owner-only access to generated data files. 8. Consider encrypting sensitive local state with a key held outside the project directory. 9. Add automated secret scanning to tests and release packaging. 10. Fail closed when a record resembles a secret, requiring explicit user approval before retention. ]]>
