T09 · Insecure Skill Coding Practices
- Location
scripts/main.py:180- Finding
Automatic Plaintext Retention and Disclosure of Rotated Secrets
- Content
View full analysis
Vulnerability Details
File Location:
scripts/main.py:180-191,scripts/main.py:257-304, andscripts/main.py:436
Vulnerability Type: Plaintext sensitive-data storage and disclosure
Risk Level: HighVulnerable 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 passpython 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
View remediation
Remediation Suggestions
- Disable rotation history by default and require an explicit option such as
--enable-historybefore retaining metadata. - Never store secret values in history. Retain only non-sensitive metadata such as timestamps, normalized file identifiers, rotated key names, and operation status.
- 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. - Remove
new_valuesfrom normal JSON output. Return key names and operation status instead. - 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.
- 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.
- Ensure the
historycommand cannot return legacy plaintext values. Provide a migration or cleanup procedure that securely removes existingnew_valuesfields from~/.env-rotation-history.json. - Add automated tests confirming that default rotations neither persist nor print generated secret values.
- Disable rotation history by default and require an explicit option such as
