T09 · Insecure Skill Coding Practices
Warning
- Location
- src/utils/request.js:105
- Finding
- API Token Exposed in URL Query Strings<![CDATA[ ## Vulnerability Details **File Location**: - `src/api/search.js:59-62, 104-113` - `src/api/comment.js:38-41, 67-72` - `src/api/post.js:23-26, 50-54` - `src/api/hot.js:18-22` - `src/utils/request.js:105-112, 128-136` **Vulnerability Type**: Sensitive credential exposure through URL query parameters **Risk Level**: Medium ### Vulnerable Code The API modules place the secret token into request parameter objects: ```js // src/api/search.js const params = { _: Date.now(), token: token, }; ``` ```js // src/api/search.js const params = { _: Date.now(), token: token, keyword: keyword, sort_type: sort, publish_time: time, filter_duration: duration, content_type: content, limit: limit, }; ``` ```js // src/api/comment.js const params = { _: Date.now(), token: token, }; ``` ```js // src/api/comment.js const params = { _: Date.now(), token: token, url: url, limit: limit, }; ``` ```js // src/api/post.js const params = { _: Date.now(), token: token, }; ``` ```js // src/api/post.js const params = { _: Date.now(), token: token, url: url, limit: limit, }; ``` ```js // src/api/hot.js const res = await getJson("/api/douyin/hot-search", { _: Date.now(), token: token, }); ``` The shared request implementation serializes all such parameters into the URL: ```js // src/utils/request.js 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), }, }; ``` ```js // src/utils/request.js const fullPath = `${path}?${querystring.stringify(params)}`; const options = { host: constants.BASE_URL, path: fullPath, method: "GET", headers: { "Accept-Encoding": "identity" }, }; ``` ### Technical Analysis `GUAIKEI_API_TOKEN` is an authentication credential, but th ...[truncated 2476 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Move authentication out of the URL.** Send the token through a standard authorization header: ```js const options = { host: constants.BASE_URL, path, method: "GET", headers: { Authorization: `Bearer ${token}`, "Accept-Encoding": "identity", }, }; ``` 2. **Remove `token` from every query parameter object** in: - `src/api/search.js` - `src/api/comment.js` - `src/api/post.js` - `src/api/hot.js` 3. **Separate authentication from ordinary parameters.** Change the shared request interface to accept the token independently: ```js async function getJson(path, params, token) { const fullPath = `${path}?${querystring.stringify(params)}`; return request({ host: constants.BASE_URL, path: fullPath, method: "GET", headers: { Authorization: `Bearer ${token}`, "Accept-Encoding": "identity", }, }); } ``` 4. **Apply server-side redaction.** Configure API gateways, reverse proxies, application logs, tracing platforms, and error-reporting systems to redact: - `Authorization` headers. - Legacy `token` query parameters. - Any request metadata that may already contain credentials. 5. **Rotate potentially exposed tokens.** Tokens previously used by affected versions may remain in retained URL logs and should be revoked and replaced. 6. **Reject query-string authentication after migration.** Once clients have moved to header-based authentication, the API should stop accepting tokens in URLs to prevent regression. 7. **Add automated tests** asserting that generated request paths never contain `token=`, credential values, or other authentication material. 8. **Update documentation** to explain that the token is transmitted to the third-party API for authentication and is protected using an authorization header rather than a URL parameter. ]]>
