T09 · Insecure Skill Coding Practices
- Location
src/request.js:17- Finding
API Key Disclosure Through Authenticated Requests to Arbitrary URLs
- Content
View full analysis
"); await performRequest(state, config, { method: state.method, path: requestPath, body: state.data, }); } export async function runCommand(state, config) { const [command] = state.commandArgs; if (!command) { return false; } if (command.startsWith("/") || /^https?:\/\//i.test(command)) { await handleGenericRequest(state, config, state.commandArgs); return true; } ``` ```js const target = normalizePath(request.path); const url = /^https?:\/\//i.test(target) ? target : `${appState.baseUrl}${target}`; const headers = { Accept: "application/json", ...state.headers, ...request.headers, }; if (appState.apiKey) { headers.Authorization = `Bearer ${appState.apiKey}`; } ``` ```js const response = await fetch(url, { method: request.method, headers, body, }); ``` ### Technical Analysis The generic request interface accepts an absolute HTTP or HTTPS URL. The HTTP layer then adds the configured Twexapi API key to the `Authorization` header without verifying that the destination belongs to Twexapi. Consequently, authentication credentials are sent to any destination supplied as the command argument. Plaintext HTTP URLs are also accepted, allowing the key to be exposed through network interception. This violates credential-origin binding: a credential issued for one service must not be forwarded to an unrelated origin. The same functionality also permits the CLI to make requests to loopback, private-network, or link-local destinations, although exploitation of that request capability depends on where and how the CLI is execut ...[truncated 1304 chars]- Remediation
View remediation
