T09 · Insecure Skill Coding Practices
- Location
bangumi_tracker.py:215- Finding
OAuth Tokens Stored in Plaintext Without Enforced Access Permissions
- Content
View full analysis
Vulnerability Details
File Location:
bangumi_tracker.py, lines 215-230; related directory creation at lines 128-131
Vulnerability Type: Plaintext sensitive-data storage with insufficient permission enforcement
Risk Level: MediumVulnerable Code
python def ensure_config_dir(): """Ensure config directory exists""" CONFIG_DIR.mkdir(parents=True, exist_ok=True)python def save_token(token: Dict[str, Any]): """Save access token to Windows Credential Manager""" ensure_config_dir() if is_windows(): # Save sensitive data to Credential Manager if token.get("access_token"): save_credential(CRED_TARGET_ACCESS_TOKEN, "access_token", token["access_token"]) print(f"✅ Access token saved to Windows Credential Manager") if token.get("refresh_token"): save_credential(CRED_TARGET_REFRESH_TOKEN, "refresh_token", token["refresh_token"]) print(f"✅ Refresh token saved to Windows Credential Manager") # Save expires_at to file (non-sensitive) if "expires_at" in token: with open(TOKEN_FILE, 'w', encoding='utf-8') as f: json.dump({"expires_at": token["expires_at"]}, f, indent=2) else: # Fallback to file for non-Windows with open(TOKEN_FILE, 'w', encoding='utf-8') as f: json.dump(token, f, indent=2) print(f"✅ Token saved to {TOKEN_FILE}")Technical Analysis
On non-Windows platforms, the complete OAuth token object—including the access token and refresh token—is serialized as plaintext JSON in
~/.bangumi/token.json.The code creates
~/.bangumiand the token file without explicitly enforcing owner-only permissions. Their effective permissions therefore depend on the process umask and any pre-existing directory or file permissions. Under a permissive umask, or when the paths already have unsafe permiss ...[truncated 1809 chars]- Remediation
View remediation
Remediation Suggestions
- Use a supported operating-system credential store on every platform, such as macOS Keychain, Secret Service on Linux, or an established cross-platform keyring library.
- If a file fallback is unavoidable:
- Create
~/.bangumiwith mode0700. - Create a new token file with mode
0600using exclusive, low-level file creation. - Correct unsafe permissions on existing paths before use.
- Verify that the directory and file are owned by the current user.
- Reject symbolic links and non-regular files.
- Write to a protected temporary file, flush it, and atomically replace the destination.
- Create
- Minimize persisted token fields and never print tokens in logs or error messages.
- Document the storage risk and provide a command that revokes or removes all locally stored credentials.
- Consider encrypting file-based tokens with a key held by an operating-system credential store, rather than storing the encryption key beside the ciphertext.
