T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/auth.mjs:91
- Finding
- Bearer API Key Stored Without Explicit Restrictive File Permissions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/auth.mjs`, lines 91-100 **Vulnerability Type**: Insecure credential storage **Risk Level**: Medium ### Vulnerable Code ```js const { access_token } = await tokenResp.json(); // Save to config if (!existsSync(CONFIG_DIR)) { mkdirSync(CONFIG_DIR, { recursive: true }); } writeFileSync( CONFIG_PATH, JSON.stringify({ api_key: access_token, created_at: new Date().toISOString() }, null, 2) ); ``` ### Technical Analysis The OAuth access token is a bearer credential that authorizes Playlistable MCP operations. The script saves it to `config/auth.json` without specifying a restrictive filesystem mode. The resulting permissions depend on the process umask and operating-system defaults. In a multi-user or otherwise insufficiently isolated environment, the file may be readable by local principals that do not require access to the Playlistable account. The credential is not transmitted to an unrelated host: its exchange through the fixed HTTPS endpoint `https://mcp.playlistable.io/oauth/token` is necessary for the documented OAuth workflow. The vulnerability concerns how the resulting credential is persisted locally. ### Attack Path 1. A victim runs `node scripts/auth.mjs` and completes OAuth authentication. 2. The returned bearer API key is written to `config/auth.json` using ambient filesystem permissions. 3. Another local user or compromised process with access to the project directory reads the file. 4. The attacker extracts the `api_key` value. 5. The attacker supplies the key as an `Authorization: Bearer` credential to `https://mcp.playlistable.io`. 6. The attacker invokes the MCP operations available to the victim's account. This path requires local filesystem access sufficient to read the file; remote exploitation is not established by the audited code alone. ### Impact Assessment A stolen bearer key can allow impersonation of the authenticated Playlistable user within the token's server ...[truncated 440 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Create the credential directory with owner-only permissions: ```js mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 }); ``` 2. Write the credential file with mode `0600`: ```js writeFileSync( CONFIG_PATH, JSON.stringify( { api_key: access_token, created_at: new Date().toISOString() }, null, 2 ), { mode: 0o600 } ); ``` 3. Explicitly enforce permissions on an existing directory and file, since creation modes do not correct pre-existing permissive paths. 4. Defend against symlink-based redirection by validating the destination and using safe, exclusive or atomic file-creation practices. 5. Prefer an operating-system credential store or secret manager where available. 6. Remove token-fragment logging so credential material is never unnecessarily exposed in terminal output. 7. Document credential revocation and rotation procedures for users who suspect local disclosure. ]]>
