T09 · Insecure Skill Coding Practices
- Location
package.json:47- Finding
Plaintext API Credentials Created Without Restrictive File Permissions
- Content
View full analysis
~/.config/porkbun/config.json << EOF", " {", " \"apiKey\": \"your-pk1-key\",", " \"secretApiKey\": \"your-sk1-key\"", " }", " EOF" ``` The skill documentation similarly instructs users to store both credentials in plaintext without requiring permission hardening: ```markdown ### Set up API credentials 1. Generate API keys: https://porkbun.com/account/api 2. Save credentials to config file: `~/.config/porkbun/config.json` ```json { "apiKey": "your-api-key", "secretApiKey": "your-secret-api-key" } ``` ``` The CLI then reads and uses this file without checking whether it is accessible by other local users: ```javascript const configPath = path.join(process.env.HOME, '.config', 'porkbun', 'config.json'); if (fs.existsSync(configPath)) { try { const config = JSON.parse(fs.readFileSync(configPath, 'utf8')); ``` ### Technical Analysis Shell redirection creates files according to the process umask. Under a common umask such as `022`, the configuration file can be created with mode `0644`, while `mkdir -p` can create the containing directories with mode `0755`. This may allow other local accounts to traverse the directory and read the plaintext Porkbun secret API key. The application does not validate file ownership or permission bits before accepting credentials from the configuration file. Consequently, it provides no warning or refusal when the secret is stored in a group-readable or world-readable file. The API credentials are security-sensitive because the t ...[truncated 1930 chars]- Remediation
View remediation
"$HOME/.config/porkbun/config.json" <<'EOF' { "apiKey": "your-pk1-key", "secretApiKey": "your-sk1-key" } EOF chmod 600 "$HOME/.config/porkbun/config.json" ``` 3. Update both `package.json` and `SKILL.md` so every file-based setup example explicitly enforces mode `0600` for the file and mode `0700` for its directory. 4. Before reading the file, use `fs.lstatSync()` or `fs.statSync()` to verify that: - The path is a regular file rather than a symbolic link. - The file is owned by the current effective user. - Group and other permission bits are not set. - The containing directory is not writable by untrusted users. 5. Reject insecure files with a clear message rather than silently loading them. For example, reject the configuration when `(stat.mode & 0o077) !== 0`. 6. Prefer environment injection from a trusted secret manager or operating-system credential store when available. Avoid placing credentials in command-line arguments because command lines may be visible to other processes. 7. Recommend scoped API credentials and enable Porkbun API access only for domains that require automation. Rotate credentials immediately if an existing configuration file may have been readable by other users. ]]>
