T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/set-token.js:44
- Finding
- Liepin Token Is Accepted Through Process Arguments and Stored in Plaintext## Vulnerability Details **File Location**: `scripts/set-token.js:44-58` **Vulnerability Type**: Plaintext credential exposure through command-line arguments and insecure file storage **Risk Level**: Medium ### Vulnerable Code ```javascript var args = process.argv.slice(2); if (args.length === 0 || args[0] === '--show') { showStatus(); } else if (args[0] === '--clear') { if (fs.existsSync(configPath)) { fs.unlinkSync(configPath); console.log('已清除 config.json'); } else console.log('没有 config.json 可清除'); } else { var dir = path.dirname(configPath); if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); fs.writeFileSync(configPath, JSON.stringify({ token: args[0] }, null, 2)); console.log('已保存到 config.json'); console.log('Tip: 也可以设置环境变量 LIEPIN_TOKEN 更安全'); } ``` The insecure invocation pattern is also explicitly documented at `SKILL.md:39-43`: ```bash node scripts/set-token.js <token> ``` ### Technical Analysis The credential is read directly from `process.argv`. Depending on the operating system and execution environment, command-line arguments can be exposed through process inspection utilities, monitoring systems, audit logs, terminal history, or wrapper scripts. The token is then serialized directly into `config.json` using `fs.writeFileSync` without an explicit restrictive file mode. Consequently, the file's permissions depend on the process umask and any permissions already associated with the file. The implementation does not verify that the resulting file is readable only by its owner. The credential reportedly remains valid for up to 90 days and authorizes authenticated Liepin operations, including access to résumé information and account-mutating actions. ### Attack Path 1. A user follows the documented command and passes the Liepin token as a command-line argument. 2. A local user, process monitor, shell-history collector, or logging integration records ...[truncated 948 chars]
- Remediation
- ## Remediation Suggestions 1. Do not accept credentials as positional command-line arguments. Read the token from a non-echoing interactive prompt, standard input, or an operating-system credential store. 2. Create `config.json` with an explicit owner-only mode such as `0600`: ```javascript fs.writeFileSync( configPath, JSON.stringify({ token: token }, null, 2), { mode: 0o600 } ); ``` 3. If the file already exists, verify and correct its permissions before writing. 4. Ensure the containing directory is not writable or readable by unintended users. 5. Prefer a platform secret store or a dedicated secrets manager rather than plaintext JSON. 6. Update `SKILL.md` and `references/api.md` so examples never place real credentials in command-line arguments. 7. Document token revocation and rotation procedures for suspected exposure. 8. Consider rejecting tokens with leading or trailing whitespace and avoid printing any token-derived substring unless operationally necessary.
