T09 · Insecure Skill Coding Practices
- Location
scripts/generate_qwen.py:49- Finding
ModelScope API Key Stored with Potentially Unsafe POSIX Permissions in Qwen Generator
- Content
View full analysis
Vulnerability Details
File Location:
scripts/generate_qwen.py:49-63andscripts/generate_qwen.py:158
Vulnerability Type: Plaintext credential storage with insufficient permission enforcement
Risk Level: MediumVulnerable Code
python CONFIG_DIR = Path.home() / ".modelscope" CONFIG_FILE = CONFIG_DIR / "api_key"python def save_api_key(api_key: str): CONFIG_DIR.mkdir(parents=True, exist_ok=True) CONFIG_FILE.write_text(api_key) if sys.platform == "win32": import stat os.chmod(CONFIG_FILE, stat.S_IREAD | stat.S_IWRITE)The key can also be provided as a command-line argument:
python parser.add_argument("--api-key", help="API Key")Technical Analysis
The
--save-keyoperation writes the ModelScope API key to~/.modelscope/api_keyas plaintext. Explicit permission hardening is performed only whensys.platform == "win32". On POSIX systems, the resulting directory and file permissions depend on the process umask and any pre-existing directory or file permissions.Under a permissive umask or unsafe pre-existing permissions, other local accounts or processes may be able to read the credential. Supplying the key through
--api-keyalso places the secret in the process command line, where it may be exposed through shell history, process inspection, logging, or monitoring software.No evidence shows that the script intentionally sends the credential to an unrelated party. The bearer token is sent to the declared ModelScope HTTPS API, which is necessary for the advertised image-generation functionality. The weakness concerns local credential handling.
Attack Path
- A user invokes
generate_qwen.py --save-key SECRET, or supplies the token through--api-key SECRET. - The script writes the token to
~/.modelscope/api_keywithout enforcing restrictive POSIX permissions, or the command is retained in shell history and process metadata. - A local account or process with access to t ...[truncated 833 chars]
- A user invokes
- Remediation
View remediation
Remediation Suggestions
- On POSIX systems, create
~/.modelscopewith mode0700and the key file with mode0600. - Use atomic, exclusive file creation to prevent symlink and pre-existing-file permission issues.
- Verify the ownership and permissions of both the directory and key file before reading or writing credentials.
- Apply equivalent restrictive ACLs on Windows rather than relying only on generic read/write mode flags.
- Prefer an operating-system credential manager or keyring instead of a plaintext file.
- Avoid accepting secrets directly through command-line arguments. Support hidden interactive input, standard input, an OS keyring, or a protected environment variable instead.
- Update documentation to warn that prompts are transmitted to ModelScope and that command-line secrets may be recorded in shell history.
Example POSIX hardening:
python CONFIG_DIR.mkdir(parents=True, exist_ok=True, mode=0o700) os.chmod(CONFIG_DIR, 0o700) fd = os.open(CONFIG_FILE, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600) with os.fdopen(fd, "w", encoding="utf-8") as key_file: key_file.write(api_key) os.chmod(CONFIG_FILE, 0o600)- On POSIX systems, create
