T09 · Insecure Skill Coding Practices
Warning
- Location
- src/config.js:8
- Finding
- API Key Can Be Transmitted to an Arbitrary Plaintext Endpoint<![CDATA[ ## Vulnerability Details **File Location**: `src/config.js:8-23`, `src/api-client.js:14-19`, `README.md:30-31` **Vulnerability Type**: Unrestricted destination and insecure transport for API credentials **Risk Level**: Medium ### Vulnerable Code `src/config.js:8-23`: ```js export const API_BASE_URL = (process.env.STOCK_API_BASE_URL || "").replace(/\/+$/, ""); export const API_KEY = process.env.STOCK_API_KEY || ""; export const API_TIMEOUT = Number(process.env.STOCK_API_TIMEOUT || "30") * 1000; export const API_PREFIX = "/api/v1"; export function getApiUrl(path) { if (!API_BASE_URL) { throw new Error("未设置 STOCK_API_BASE_URL 环境变量"); } return `${API_BASE_URL}${API_PREFIX}${path}`; } export function getAuthHeaders() { const headers = { "Content-Type": "application/json", Accept: "application/json" }; if (API_KEY) headers["X-API-Key"] = API_KEY; return headers; } ``` `src/api-client.js:14-19`: ```js const res = await fetch(url, { method, headers: getAuthHeaders(), body: body ? JSON.stringify(body) : undefined, signal: controller.signal, }); ``` `README.md:30-31`: ```bash export STOCK_API_BASE_URL="http://localhost:8000" export STOCK_API_KEY="your-api-key-here" ``` ### Technical Analysis The application accepts `STOCK_API_BASE_URL` as an unrestricted string and directly uses it to construct every API URL. It does not parse the value as a URL, enforce HTTPS, verify the destination hostname, reject embedded credentials, or apply an endpoint allowlist. At the same time, `getAuthHeaders()` attaches `STOCK_API_KEY` to every request through the `X-API-Key` header. Consequently, whoever controls or influences `STOCK_API_BASE_URL` controls the destination to which the credential is sent. If a non-loopback endpoint uses plaintext HTTP, an on-path attacker can observe or modify the request and recover the API key. If configuration is changed to an attacker-controlled endpoint, invoking any registered tool sends the key directly t ...[truncated 1541 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Parse the configured endpoint with `new URL()` and reject malformed URLs before any request is made. 2. Require the `https:` protocol for all non-loopback destinations. 3. If local development requires HTTP, permit it only for explicitly recognized loopback hosts such as `localhost`, `127.0.0.1`, and `[::1]`. 4. Reject URL schemes other than `https:` and the narrowly scoped loopback `http:` exception. 5. Reject URLs containing embedded usernames or passwords. 6. Where deployment topology is known, enforce an administrator-controlled hostname or origin allowlist. 7. Bind credential transmission to the validated origin so redirects or future request changes cannot forward `X-API-Key` to another host. 8. Consider disabling automatic cross-origin redirects or stripping authentication headers whenever the redirect origin changes. 9. Document that remote API endpoints must use valid TLS certificates and that endpoint configuration must be treated as security-sensitive. 10. Rotate the API key if it may previously have been sent to an untrusted or plaintext remote endpoint. 11. Apply least-privilege server-side authorization so read-only consumers cannot perform factor creation, modification, sorting, or deletion. ]]>
