T09 · Insecure Skill Coding Practices
- Location
scripts/token_pool.py:72- Finding
Provider Tokens Persisted in Plaintext Without Restrictive File Permissions
- Content
View full analysis
None: if not token: return self._reset_if_new_day(provider) provider_state = self._state.setdefault(provider, {}) exhausted = provider_state.setdefault("exhausted", {}) exhausted[token] = True self._save_state() ``` ```python def _save_state(self) -> None: self.state_file.parent.mkdir(parents=True, exist_ok=True) self.state_file.write_text( json.dumps(self._state, indent=2, ensure_ascii=True), encoding="utf-8", ) ``` ### Technical Analysis When a token encounters a quota error, the complete bearer token is inserted as a JSON object key and persisted to `token_status.json`. The implementation does not store a hash, fingerprint, or opaque token identifier. The state directory and file are created using the process's default permission behavior. No explicit owner-only mode such as `0700` for the directory or `0600` for the file is enforced. The resulting exposure depends on the process umask and surrounding filesystem permissions. The plaintext storage design is also documented in `references/token-rotation-policy.md`, whose example schema contains a complete token as a key. A token being quota-exhausted does not mean it is revoked; it may become usable again after a quota reset or retain access to other provider functionality. ### Attack Path 1. A user configures valid provider bearer tokens and invokes image generation. 2. A provider returns a response classified as a quota failure. 3. `mark_exhausted()` stores the complete token in the persistent state dictionary. 4. `_save_state()` writes the token to the configured state file in plaintext. 5. Another local user, compromised process, backup agent, or file ...[truncated 656 chars]- Remediation
View remediation
