T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/analyze_patterns.py:232
- Finding
- Plaintext Persistent Caching of Sensitive Memory Content<![CDATA[ ## Vulnerability Details **File Location**: `scripts/analyze_patterns.py:69-71, 232`; `scripts/analyze_patterns.py:514-516`; `scripts/state.py:57-67` **Vulnerability Type**: Plaintext storage of memory-derived sensitive data **Risk Level**: Medium ### Vulnerable Code ```python def parse_memory_file(filepath: Path) -> list[dict]: """Parse a memory file into structured events (one per H2 section).""" text = filepath.read_text(encoding="utf-8", errors="replace") ``` ```python return { "section": header, "keywords": keywords, "actions": actions, "entities": extract_entities(full_text), "has_steps": detect_steps(body), "time_hint": extract_time_hint(header, body), "day_of_week": day_of_week, "is_formalized": detect_formalized(header, body), "raw_summary": body[:500].strip(), } ``` ```python events = parse_memory_file(filepath) add_events(state, date_str, events) new_event_count += len(events) ``` ```python def save_state(state: dict, path: Optional[str] = None) -> None: """Write state to disk atomically.""" p = Path(path) if path else DEFAULT_STATE_PATH p.parent.mkdir(parents=True, exist_ok=True) tmp = p.with_suffix(".tmp") with open(tmp, "w") as f: json.dump(state, f, indent=2, default=str) tmp.replace(p) ``` ### Technical Analysis The analyzer reads Agent memory files and stores up to 500 characters from each parsed section in the `raw_summary` field. These excerpts are added to the persistent `event_cache` and serialized into `state.json` as plaintext. Atomic replacement protects the state file from partial writes but does not protect confidentiality. The implementation has no secret redaction, encryption, data minimization, expiration policy, or explicit restrictive file permissions. The resulting file permissions depend on the process umask and execution environment. Because Agent memory may contain private conversations, project information, credentials, tokens, inte ...[truncated 1361 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Do not persist `raw_summary` by default. Cache only normalized keywords, hashes, counts, and other minimum features required for clustering. 2. If summaries are required, make retention explicitly opt-in and document exactly what is stored. 3. Apply secret and personal-data redaction before serialization, including patterns for API keys, access tokens, credentials, private keys, email addresses, and internal URLs. 4. Enforce a configurable retention period and purge events older than the required analysis window. 5. Create the state and temporary files with permissions limited to the owner, such as mode `0600`. 6. Verify the parent directory is not group-writable or world-readable. 7. Consider encrypting persisted memory-derived content using an operating-system credential store or a user-managed key. 8. Ensure reset and uninstall procedures securely remove all cached memory-derived data. ]]>
