T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/run_x_search.mjs:63
- Finding
- Bearer Credential Disclosure Through an Unrestricted API Base Override<![CDATA[ ## Vulnerability Details **File Location**: `scripts/run_x_search.mjs:63-76` and `scripts/run_x_search.mjs:250-256` **Vulnerability Type**: Unrestricted credential-bearing endpoint override **Risk Level**: High ### Vulnerable Code ```javascript async function postApi(apiBase, apiKey, path, body, timeoutMs) { const res = await fetchWithRetry( `${apiBase}/v2${path}`, { method: 'POST', headers: { Accept: 'application/json', Authorization: `Bearer ${apiKey}`, 'Content-Type': 'application/json', }, body: JSON.stringify(body), }, timeoutMs, ); ``` ```javascript const apiKey = process.env.FELO_API_KEY?.trim(); if (!apiKey) { console.error('ERROR: FELO_API_KEY not set'); process.exit(1); } const apiBase = (process.env.FELO_API_BASE?.trim() || DEFAULT_API_BASE).replace(/\/$/, ''); ``` ### Technical Analysis The script obtains the destination URL from the `FELO_API_BASE` environment variable without validating its scheme, hostname, port, or trust relationship. It then sends the value of `FELO_API_KEY` to that destination in an `Authorization: Bearer` header. Although sending the key to the default `https://openapi.felo.ai` endpoint is necessary for the declared X search functionality, allowing an unrestricted environment-controlled destination exceeds the minimum privileges required. An attacker who can influence the inherited environment can set the base URL to an attacker-controlled server. The script also does not enforce HTTPS, so a plain HTTP URL can expose the credential and request data in transit. The request bodies can contain search terms, usernames, tweet identifiers, time filters, and pagination cursors. Consequently, exploitation can disclose both the API credential and potentially sensitive user search activity. ### Attack Path 1. The victim configures a valid `FELO_API_KEY`. 2. An attacker influences the execution environment, wrapper script, shell profile, CI conf ...[truncated 1271 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove `FELO_API_BASE` support if custom endpoints are not essential. 2. Otherwise, parse the configured value with `new URL()` and enforce: - The `https:` protocol. - An explicit allowlist of trusted Felo hostnames. - Expected ports only. - No embedded username or password. 3. Bind credential transmission to the trusted origin rather than attaching the bearer token to every configured destination. 4. Reject unexpected redirects and ensure authorization headers are never forwarded to another origin. 5. Prefer separate credentials for development or test endpoints rather than reusing production API keys. 6. Emit a clear error and terminate before sending a request when endpoint validation fails. 7. Document the security implications of endpoint overrides if the feature must remain. An example validation approach is: ```javascript function getTrustedApiBase() { const configured = process.env.FELO_API_BASE?.trim() || DEFAULT_API_BASE; const url = new URL(configured); if (url.protocol !== 'https:') { throw new Error('FELO_API_BASE must use HTTPS'); } const allowedHosts = new Set(['openapi.felo.ai']); if (!allowedHosts.has(url.hostname)) { throw new Error('FELO_API_BASE host is not trusted'); } if (url.username || url.password || (url.port && url.port !== '443')) { throw new Error('FELO_API_BASE contains unsupported URL components'); } return url.origin; } ``` ]]>
