T09 · Insecure Skill Coding Practices
Warning
- Location
- index.js:1
- Finding
- API Credential Disclosure Through an Unrestricted Configurable Endpoint## Vulnerability Details **File Location**: `index.js`, lines 1–10 **Vulnerability Type**: Unrestricted transmission of an API credential to an environment-controlled destination **Risk Level**: Medium **Vulnerable Code**: ```js const BASE_URL = process.env.POKERPAL_API_URL; const API_KEY = process.env.POKERPAL_BOT_API_KEY; async function apiCall(path) { const res = await fetch(`${BASE_URL}${path}`, { headers: { "X-Bot-API-Key": API_KEY, "Content-Type": "application/json", }, }); ``` ### Technical Analysis Every exported tool ultimately calls `apiCall()`, which attaches the `POKERPAL_BOT_API_KEY` credential to a request whose base URL is taken directly from `POKERPAL_API_URL`. The implementation does not parse or validate that URL, require HTTPS, or restrict its hostname and port to an approved PokerPal service. Sending a credential to the legitimate PokerPal API is necessary for the Skill's documented read-only functionality. However, permitting the credential to be sent to any environment-configured origin exceeds the minimum safe network privilege. If deployment configuration is mistaken or modified by an attacker, the key can be transmitted to an attacker-controlled server. An `http://` URL could also expose the key to network interception. ### Attack Path 1. An attacker or compromised deployment process changes `POKERPAL_API_URL` to an attacker-controlled URL or an insecure HTTP endpoint. 2. A user invokes any exported tool, such as `list_groups` or `get_player_buyins`. 3. The tool calls `apiCall()` with its API path. 4. `fetch()` sends the `X-Bot-API-Key` header to the configured endpoint without validating its scheme or origin. 5. The attacker captures the API key and attempts to reuse it against the legitimate PokerPal API. ### Impact Assessment Successful exploitation discloses the bot API credential. The attacker's resulting privileges are limited by the server-side p ...[truncated 492 chars]
- Remediation
- ## Remediation Suggestions 1. Parse `POKERPAL_API_URL` with `new URL()` before making any request. 2. Require the `https:` protocol and reject plaintext HTTP. 3. Enforce an explicit allowlist of approved PokerPal hostnames and, where appropriate, approved ports. 4. Reject URLs containing embedded usernames or passwords. 5. Prefer a fixed trusted production API origin if runtime destination configurability is not required. 6. Validate the destination before constructing request options or attaching the API-key header, and fail closed on any validation error. 7. Apply least privilege to the API key on the server side, limiting it to the documented read-only endpoints. 8. Rotate the credential if it may previously have been used with an untrusted or plaintext endpoint. 9. Avoid logging request headers or environment values containing the key. Example hardening approach: ```js const configuredUrl = new URL(process.env.POKERPAL_API_URL); const allowedHosts = new Set(["api.pokerpal.example"]); if ( configuredUrl.protocol !== "https:" || !allowedHosts.has(configuredUrl.hostname) || configuredUrl.username || configuredUrl.password ) { throw new Error("Invalid PokerPal API endpoint"); } const BASE_URL = configuredUrl.origin; ```
