T09 · Insecure Skill Coding Practices
- Location
scripts/_auth.py:47- Finding
Credential File Permissions Are Applied Non-Atomically and Permission Failures Are Suppressed
- Content
View full analysis
Vulnerability Details
File Location:
scripts/_auth.py:47-59
Vulnerability Type: Insecure credential storage
Risk Level: Mediumpython def write_config(data): CONFIG_DIR.mkdir(parents=True, exist_ok=True) try: os.chmod(CONFIG_DIR, 0o700) except Exception: pass with open(CONFIG_FILE, "w", encoding="utf-8") as f: json.dump(data, f, indent=2, ensure_ascii=False) try: os.chmod(CONFIG_FILE, 0o600) except Exception: passTechnical Analysis
The configuration file contains
app_id,secret_key, and a cachedaccess_token. It is created using the process's default file-creation permissions and restricted to mode0600only after its contents have been written. This creates a non-atomic protection sequence in which the file's initial permissions depend on the active umask.The parent directory is similarly hardened after creation rather than created with a guaranteed restrictive mode. If the configured directory already exists, is shared, resides on a filesystem with unsuitable permission semantics, or a permission change fails, sensitive data may be exposed.
Both
chmodoperations suppress every exception, so execution continues even when credential protection cannot be established. The implementation also does not verify the file's resulting owner, type, or permissions.Attack Path
- A victim runs the Skill with a permissive umask or sets
CHANJING_CONFIG_DIRto an existing shared or insufficiently protected directory. write_config()opens and writescredentials.jsonusing process-default creation permissions.- The subsequent
chmod()fails, is ineffective on the selected filesystem, or cannot correct exposure that occurred during creation. - The exception is silently ignored, and the program continues as if credential storage were secure.
- Another local user or process with directory access reads
credentials.json. - The exposed
secret_keyor c ...[truncated 704 chars]
- A victim runs the Skill with a permissive umask or sets
- Remediation
View remediation
Remediation Suggestions
- Create the configuration directory with mode
0700from the outset and verify its ownership and final permissions. - Write credentials to a securely created temporary file using exclusive creation and mode
0600, then atomically replace the destination withos.replace(). - Flush and synchronize the temporary file before replacement where durability is required.
- Reject symlinks and non-regular destination files where platform APIs permit.
- Do not suppress permission errors. Fail closed with a clear error if secure storage cannot be established.
- Verify the final file owner and permissions after writing.
- Consider separating the long-lived secret key and cached access token from non-sensitive configuration and using an operating-system credential store where available.
A hardened implementation should ensure that sensitive content is never present in a file with process-default or unverified permissions, even temporarily.
- Create the configuration directory with mode
