T09 · Insecure Skill Coding Practices
Warning
- Location
- SKILL.md:52
- Finding
- Reusable COROS Credential Exposed Through Weak Storage and Logging Guidance<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:19-23`, `SKILL.md:52-58`, `scripts/.env:1-3`, `scripts/util.js:8-10`, `scripts/coros.js:42-49` **Vulnerability Type**: Reusable credential exposure and insecure secret handling **Risk Level**: Medium ### Vulnerable Code `scripts/util.js:8-10`: ```js let genHashedPassword = (password) => { const hashedPassword = createHash("md5").update(password).digest("hex"); return hashedPassword; }; ``` `SKILL.md:52-58`: ```js import { genHashedPassword } from "./util.js"; const hashedPassword = genHashedPassword("your_plain_password"); console.log(hashedPassword); // Output the MD5-hashed password for COROS_PASSWORD ``` `scripts/.env:1-3`: ```env # COROS account configuration COROS_ACCOUNT=xxx COROS_PASSWORD=xxx ``` `scripts/coros.js:42-49`: ```js const response = await axios.post( COROS_URLS.LOGIN_URL, { account: this.account, accountType: 2, pwd: this.password, }, { headers: DEFAULT_HEADERS, timeout: 60000 }, ); ``` ### Technical Analysis The generated MD5 value is transmitted directly as the `pwd` login parameter. It therefore functions as a reusable password-equivalent credential rather than merely as a non-reversible password-verification record. MD5 is a fast, unsalted hash and is unsuitable for protecting passwords. More importantly, because the COROS endpoint accepts the hash itself for authentication, an attacker may not need to recover the original plaintext password: possession of the hash may be sufficient for replay. The documentation recommends storing this credential in a project-local `.env` file and demonstrates printing it to standard output. This can expose the credential through: - Accidental source-control commits. - Terminal scrollback and shell-session capture. - CI/CD logs. - Process output collected by monitoring systems. - Backups or copies of the project directory. - Excessively permissive local file permissions. The checked-in `.env` contains ...[truncated 1454 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove all examples that print the MD5 credential: ```js const hashedPassword = genHashedPassword(password); // Do not log hashedPassword. ``` 2. Treat the MD5 value as a full password-equivalent secret in all documentation and code. 3. Prefer an official OAuth, scoped API-token, or device-authorization mechanism if COROS provides one. 4. Store credentials in an operating-system keychain, encrypted secret manager, or CI/CD secret store rather than a project-local file. 5. If `.env` support must remain: - Add `.env` and `scripts/.env` to `.gitignore`. - Distribute only a placeholder `.env.example`. - Restrict permissions to the owning user, such as mode `0600`. - Add secret scanning to commits and CI pipelines. 6. Minimize token lifetime and clear in-memory credential references when they are no longer needed. 7. Never include credentials or access tokens in errors, telemetry, debug output, or request logs. 8. Document credential rotation procedures for users who may already have exposed the hash. ]]>
