T09 · Insecure Skill Coding Practices
- Location
scripts/utils.py:37- Finding
API Credential Stored in Plaintext Without Restrictive File Permissions
- Content
View full analysis
Vulnerability Details
File Location:
scripts/utils.py:37-47
Related Location:scripts/narration_generator.py:69-77
Vulnerability Type: Plaintext credential storage with insufficient file-permission enforcement
Risk Level: MediumThe application includes the user-supplied API key in the configuration object and persists that entire object to
config/user_config.json.python def save_user_config(config): """ Save user configuration. Args: config: Configuration dictionary """ config_path = get_config_path() with open(config_path, "w", encoding="utf-8") as f: json.dump(config, f, ensure_ascii=False, indent=2)The configuration object passed to this function contains the API key:
python config["api"] = { "base_url": base_url, "api_key": api_key, "model_narration": model_narration, "model_style": model_style, "timeout": timeout } save_user_config(config)Technical Analysis
Python's standard
open()call does not impose owner-only permissions on the resulting file. A newly created file inherits permissions determined by the process umask, while an existing file retains its previous permissions. The implementation neither creates the credential file with mode0600nor verifies and corrects existing permissions.The API key is therefore stored as recoverable plaintext in the project directory. On a shared system, permissive umask, broadly readable workspace, backup, source archive, or accidentally published repository, another party may obtain the credential.
Attack Path
- A user starts the application and enters a valid API key.
get_api_config()places the key inconfig["api"]["api_key"].save_user_config()serializes the complete configuration toconfig/user_config.json.- The operating system creates or updates the file without application-enforced owner- ...[truncated 664 chars]
- Remediation
View remediation
Remediation Suggestions
- Prefer an operating-system credential manager or an environment variable over project-local plaintext storage.
- If file persistence is necessary, create the file atomically with owner-only mode
0600. - Check and correct the permissions of existing configuration files before writing or reading credentials.
- Store non-secret settings separately from the API key.
- Add
config/user_config.jsonto version-control and packaging exclusion rules while retaining only a secret-free example file. - Warn users not to place the project directory in shared or synchronized storage.
- Provide documented credential revocation and rotation procedures.
- Avoid logging or displaying the API key in errors or diagnostic output.
