T09 · Insecure Skill Coding Practices
Warning
- Location
- src/utils/request.js:94
- Finding
- API Token Transmitted in URL Query Strings<![CDATA[ ## Vulnerability Details **File Locations**: - `src/utils/request.js:94-121` - `src/utils/request.js:123-143` - `src/api/search.js:59-62` - `src/api/search.js:104-107` - `src/api/comment.js:38-41` - `src/api/comment.js:67-70` - `src/api/post.js:23-26` - `src/api/post.js:50-53` - `src/api/hot.js:19-21` **Vulnerability Type**: Credential exposure through URL query parameters **Risk Level**: Medium **Classification**: T09: Insecure Skill Coding Practices ### Vulnerable Code The API modules place the secret token in the request parameter object: ```js const params = { _: Date.now(), token: token, }; ``` For result polling, the token is included alongside the user-supplied query parameters: ```js const params = { _: Date.now(), token: token, keyword: keyword, sort_type: sort, publish_time: time, filter_duration: duration, content_type: content, limit: limit, }; ``` The shared request implementation serializes the complete parameter object into the URL: ```js async function postJson(path, params, data) { if (!path || typeof path !== "string") { throw new SkillError("PATH_INVALID", "path 必须是非空字符串"); } if (!params || typeof params !== "object") { throw new SkillError("PARAM_INVALID", "params 必须是对象"); } if (!data || typeof data !== "object") { throw new SkillError("DATA_INVALID", "data 必须是对象"); } params.skill_name = skillName(); const fullPath = `${path}?${querystring.stringify(params)}`; const jsonData = JSON.stringify(data); const options = { host: constants.BASE_URL, path: fullPath, method: "POST", headers: { "Content-Type": "application/json", "Accept-Encoding": "identity", "Content-Length": Buffer.byteLength(jsonData), }, }; return await request(options, jsonData); } ``` The GET implementation uses the same unsafe construction: ```js async function getJson(path, params) { if (!path || typeof path !== "string") { throw new SkillError("PATH_INVA ...[truncated 2690 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove `token` from every URL parameter object. 2. Pass the token through a dedicated authorization header, for example: ```js const options = { host: constants.BASE_URL, path: fullPath, method: "POST", headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json", "Accept-Encoding": "identity", "Content-Length": Buffer.byteLength(jsonData), }, }; ``` 3. Change `postJson`, `getJson`, and `requestApi` so authentication is handled separately from ordinary request parameters. 4. Ensure request, error, proxy, and application logs redact authorization headers and any legacy `token` query parameter. 5. Update the server API to reject credentials supplied through query strings after a controlled migration period. 6. Rotate tokens that have previously been sent by affected versions because they may already exist in retained infrastructure logs. 7. Add automated tests that assert generated request paths never contain `token`, `api_key`, or other credential fields. ]]>
