T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/fnclub_signer.js:86
- Finding
- Authentication cookies and OAuth access tokens are stored in plaintext without enforced restrictive permissions<![CDATA[ ## Vulnerability Details **File Locations**: - `scripts/fnclub_signer.js:86-87` - `scripts/fnclub_signer.js:148-149` **Vulnerability Type**: Plaintext storage of reusable authentication credentials **Risk Level**: Medium ### Vulnerable Code Forum authentication cookies are serialized directly to a plaintext file: ```js const cookieList = cookies.map(c => ({ name: c.key, value: c.value, domain: c.domain, path: c.path })); fs.writeFileSync(this.config.cookieFile, JSON.stringify(cookieList, null, 2)); ``` The Baidu OAuth access token is also serialized directly to a plaintext file: ```js const { access_token, expires_in = 2592000 } = response.data; fs.writeFileSync(this.config.tokenCacheFile, JSON.stringify({ access_token, expires_time: Date.now() + (expires_in - 86400) * 1000 })); ``` ### Technical Analysis The application persists reusable forum session cookies and a Baidu OAuth access token using `fs.writeFileSync` without specifying a restrictive file mode. The effective permissions therefore depend on the process umask and the permissions of the selected data directory. By default, these files are stored under the script directory. However, the `FNCLUB_DATA_DIR` environment variable can redirect them to another directory. If that directory is shared, incorrectly permissioned, backed up insecurely, or accessible to another local account or process, the cached credentials may be disclosed. The stored forum cookies can represent an authenticated session and may allow account access without knowledge of the forum password. The Baidu access token can authorize OCR API requests until it expires or is revoked. ### Attack Path 1. The Skill runs and successfully authenticates to the forum or obtains a Baidu OAuth token. 2. It writes the credentials to `cookies.json` or `token_cache.json`. 3. The files receive permissions derived from the runtime umask rather than an explicitly enforced owner-only mode. 4. A local attacker, co-tenant process, or ser ...[truncated 1209 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Create the credential-cache directory with owner-only permissions: ```js fs.mkdirSync(dataDir, { recursive: true, mode: 0o700 }); ``` 2. Write each sensitive cache file with mode `0600`: ```js fs.writeFileSync( this.config.cookieFile, JSON.stringify(cookieList, null, 2), { encoding: 'utf8', mode: 0o600 } ); ``` ```js fs.writeFileSync( this.config.tokenCacheFile, JSON.stringify({ access_token, expires_time: Date.now() + (expires_in - 86400) * 1000 }), { encoding: 'utf8', mode: 0o600 } ); ``` 3. Explicitly correct permissions on existing files because the `mode` option does not necessarily tighten permissions when an existing file is overwritten: ```js fs.chmodSync(this.config.cookieFile, 0o600); fs.chmodSync(this.config.tokenCacheFile, 0o600); ``` 4. Validate `FNCLUB_DATA_DIR` before use. Reject shared or unexpectedly permissioned directories and avoid placing credential caches in temporary, network-mounted, or web-accessible locations. 5. Use atomic writes through a securely created temporary file in the same protected directory, followed by a rename. Ensure the temporary file is also created with mode `0600`. 6. Where available, store credentials in an operating-system credential vault or dedicated secret store rather than plaintext JSON. 7. Document that `cookies.json`, `token_cache.json`, and the optional `config.json` are sensitive. Exclude them from source control, logs, shared backups, and artifact bundles. 8. Provide a cleanup procedure that deletes cached files and instructs users to invalidate the forum session and revoke the Baidu token after suspected exposure. ]]>
