T09 · Insecure Skill Coding Practices
- Location
scripts/soul_extract.py:358- Finding
Sensitive Personal Data Is Persisted Without Enforcing the Configured Confirmation Gate
- Content
View full analysis
Vulnerability Details
File Location:
scripts/soul_extract.py:198-199, 358-429
Vulnerability Type: Missing authorization and consent enforcement for sensitive-data persistence
Risk Level: MediumVulnerable Code
The default configuration declares that health, financial, and intimate-relationship information requires confirmation:
python "sensitive_topics_filter": True, "require_confirmation_for": ["health", "finance", "intimate_relationships"],However, the persistence method loads the configuration but only enforces extraction-dimension switches. It does not inspect either sensitive-data setting before writing extracted information:
python def save_extraction(self, extraction: dict): changes = [] config = self.load_config() dims = config.get("extract_dimensions", {}) thr = self._dedup_threshold() # 1. Identity if dims.get("identity", True) and extraction.get("basic_info"): current = load_json(self.paths["basic_info"], DEFAULT_BASIC_INFO.copy()) updated = self._merge_identity(current, extraction["basic_info"], thr) if updated: save_json(self.paths["basic_info"], current) changes.append(f"identity: updated {', '.join(updated)}") # 2. Personality if dims.get("personality", True) and extraction.get("personality"): current = load_json(self.paths["personality"], DEFAULT_PERSONALITY.copy()) updated = self._merge_personality(current, extraction["personality"], thr) if updated: save_json(self.paths["personality"], current) changes.append(f"personality: updated {', '.join(updated)}") # 3. Language if dims.get("language_style", True) and extraction.get("language"): current = load_json(self.paths["language"], DEFAULT_LANGUAGE.copy()) updated = self._merge_language(current, extraction["language"], thr) if update ...[truncated 4409 chars]- Remediation
View remediation
Remediation Suggestions
- Enforce sensitive-topic policy inside
SoulArchive.save_extraction()so every caller is subject to the same authorization check. - Classify candidate records before any write operation and map them to the configured topic names in
require_confirmation_for. - Require an explicit, verifiable confirmation value for each sensitive extraction batch, rather than relying on natural-language instructions or an agent assertion.
- Reject or quarantine sensitive records when confirmation is missing. Return structured information describing which records require approval.
- Ensure
sensitive_topics_filter: falseand modifications torequire_confirmation_forhave clearly defined semantics and are changed only through an explicit user action. - Record consent metadata with approved entries, including the approved categories and confirmation time, without storing unnecessary conversation content.
- Add tests proving that health, finance, and intimate-relationship records cannot reach
save_json()orappend_jsonl()without confirmation, including through identity, topic, episodic, and emotional fields. - Consider restrictive filesystem permissions and optional encryption for the resulting archive because the affected records are intentionally stored as plaintext.
- Enforce sensitive-topic policy inside
