T09 · Insecure Skill Coding Practices
Note
- Location
- scripts/backlink-audit.mjs:147
- Finding
- Legacy Plaintext Credential Is Read Unnecessarily## Vulnerability Details **File Location**: `scripts/backlink-audit.mjs:147-150` **Vulnerability Type**: Unnecessary access to plaintext credential material **Risk Level**: Low ### Vulnerable Code ```js /** Does a legacy plaintext credentials file exist? Used ONLY to explain, never to authenticate. */ function legacyFileExists() { try { return Boolean(JSON.parse(fs.readFileSync(CRED_FILE, "utf8"))?.api_key); } catch { return false; } } ``` The fixed credential path is declared earlier in the same file: ```js const CRED_FILE = path.join(os.homedir(), ".config", "backlinks-sh", "credentials.json"); ``` ### Technical Analysis The function is intended only to determine whether a legacy credential file exists so that the program can display migration guidance. However, it calls `fs.readFileSync`, parses the complete JSON document, and accesses its `api_key` property. This causes a legacy plaintext API key to enter the Node.js process memory even though neither the key's value nor the file's contents are required for the warning. It violates the principle of least privilege and conflicts with the documentation's claim that the legacy credential is never read. The key is not subsequently used for authentication, logged, or transmitted by this code. Exploitation therefore requires an additional local capability, such as process instrumentation, runtime inspection, a compromised Node environment, or injected code capable of observing process memory. This limits the issue to low severity. The related guidance in `references/sources.md:15` also incorrectly describes the legacy credential file as a supported mode-0600 fallback. That contradicts the implementation, tests, and primary documentation, potentially encouraging users to retain plaintext credentials. ### Attack Path 1. A credential remains at `~/.config/backlinks-sh/credentials.json` from an earlier version. 2. No `BACKLINKS_SH_API_KEY` environment variable or usable keychain entry is available. 3. ...[truncated 961 chars]
- Remediation
- ## Remediation Suggestions 1. Replace content inspection with a presence-only check: ```js function legacyFileExists() { return fs.existsSync(CRED_FILE); } ``` 2. If file-type validation is desired, use `fs.lstatSync` without reading the file and reject or warn about symbolic links and non-regular files. 3. Update `references/sources.md:15` to state that: - The legacy plaintext file is unsupported. - Its contents are never used for authentication. - `--logout` can remove it. - Credentials must be supplied through `BACKLINKS_SH_API_KEY` or the OS keychain. 4. Extend the credential regression tests to verify that legacy detection checks only path metadata and never invokes a content-reading operation. 5. Preserve the existing protections that prevent the legacy key from being logged, authenticated with, or transmitted.
