T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/main.py:180
- Finding
- Automatic Plaintext Retention and Disclosure of Rotated Secrets## Vulnerability Details **File Location**: `scripts/main.py:180-191`, `scripts/main.py:257-304`, and `scripts/main.py:436` **Vulnerability Type**: Plaintext sensitive-data storage and disclosure **Risk Level**: High ### Vulnerable Code ```python # Record history if not dry_run: self._record_history(filepath, keys_to_rotate, new_values) result = { "status": "success", "file": filepath, "rotated_keys": keys_to_rotate, "new_values": new_values, "backup": backup_path, "vault_commands": vault_commands, "dry_run": dry_run, "target_file": target_file if output_file else filepath } ``` ```python def _record_history(self, filepath: str, keys: List[str], new_values: Dict[str, str]): """Record rotation history (optional).""" try: history = [] if self.history_file.exists(): with open(self.history_file) as f: history = json.load(f) entry = { "timestamp": datetime.now(timezone.utc).isoformat(), "file": filepath, "keys": keys, "new_values": new_values } history.append(entry) # Keep only last 100 entries if len(history) > 100: history = history[-100:] with open(self.history_file, 'w') as f: json.dump(history, f, indent=2) except Exception: # History recording is optional, don't fail on error pass ``` ```python def get_history(self, filepath: Optional[str] = None, key: Optional[str] = None) -> Dict[str, Any]: """Get rotation history.""" try: if not self.history_file.exists(): return {"status": "success", "history": [], "count": 0} with open(self.history_file) as f: history = json.load(f) # Filter by file and/or key filtered = [] for entry in history: i ...[truncated 3494 chars]
- Remediation
- ## Remediation Suggestions 1. Disable rotation history by default and require an explicit option such as `--enable-history` before retaining metadata. 2. Never store secret values in history. Retain only non-sensitive metadata such as timestamps, normalized file identifiers, rotated key names, and operation status. 3. If a metadata file is required, create it atomically with owner-only permissions (`0600`) and verify existing file ownership and permissions before reading or writing it. 4. Remove `new_values` from normal JSON output. Return key names and operation status instead. 5. Do not include secret-bearing Vault commands in default output. Provide templates, accept secrets through protected standard input, or require a dedicated explicit reveal option. 6. If plaintext display remains available, present a clear warning and require affirmative user action. Document that the output must not be used in logged CI or Agent environments. 7. Ensure the `history` command cannot return legacy plaintext values. Provide a migration or cleanup procedure that securely removes existing `new_values` fields from `~/.env-rotation-history.json`. 8. Add automated tests confirming that default rotations neither persist nor print generated secret values.
