T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/skillpay-charge.mjs:11
- Finding
- Configurable billing endpoint permits disclosure of billing credentials and user identifiers<![CDATA[ ## Vulnerability Details **File Location**: `scripts/skillpay-charge.mjs:11-63` **Vulnerability Type**: Sensitive information transmitted to an unrestricted network destination **Risk Level**: Medium ### Code Snippet ```js const BILLING_URL = process.env.SKILL_BILLING_URL || 'https://skillpay.me/api/v1/billing'; const API_KEY = process.env.SKILL_BILLING_API_KEY; const SKILL_ID = process.env.SKILL_ID; const DEFAULT_TOKENS = Number(process.env.SKILL_BILLING_TOKENS || 10); async function postJSON(url, body) { const res = await fetch(url, { method: 'POST', headers: { 'X-API-Key': API_KEY || '', 'Content-Type': 'application/json' }, body: JSON.stringify(body) }); const text = await res.text(); let data; try { data = JSON.parse(text); } catch { data = { raw: text }; } if (!res.ok) { return { ok: false, error: `HTTP ${res.status}`, data }; } return { ok: true, data }; } // ... const result = await postJSON(`${BILLING_URL}/charge`, { user_id: userId, skill_id: SKILL_ID, amount: Number.isFinite(amount) ? amount : DEFAULT_TOKENS, }); ``` ### Technical Analysis The `SKILL_BILLING_URL` environment variable controls the complete origin to which the script sends billing requests. The value is not validated against an approved host or protocol before it is passed to `fetch`. Every request transmits the following sensitive or identifying information: - The billing API key in the `X-API-Key` header. - The caller-supplied user identifier in the request body. - The configured skill identifier. - The requested billing amount. An operator, compromised configuration source, deployment template, or other party able to influence `SKILL_BILLING_URL` can redirect this information to an attacker-controlled service. The code also accepts an `http://` URL, allowing the API key and identifiers to cross the network without transport encryption and potentially be intercepted or modified. The billing behavior is disclo ...[truncated 1854 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Pin the billing origin where possible.** Remove runtime control of the complete billing URL and use a fixed HTTPS endpoint for production billing. 2. **Apply an explicit origin allowlist.** If endpoint configurability is required for testing or regional deployments, parse the URL with `new URL()` and require: - `https:` as the protocol. - A hostname from a small, explicit allowlist. - An expected port. - No embedded username or password. 3. **Separate production and testing behavior.** Permit custom endpoints only in an explicit development or test mode, and prevent production credentials from being used in that mode. 4. **Use a narrowly scoped credential.** The billing token should authorize only the minimum required charge operation for the relevant Skill. Apply short expiration, rotation, rate limits, and server-side restrictions where supported. 5. **Avoid transmitting unnecessary identifiers.** Use pseudonymous or transaction-specific identifiers instead of stable user identifiers when the billing protocol permits it. 6. **Make unrelated billing opt-in.** The file-memory workflow should not require network or billing access unless the user or deployment has explicitly enabled that feature. 7. **Handle responses conservatively.** Limit response sizes and avoid returning arbitrary remote response bodies through diagnostic output where they could expose service details or inject untrusted content into downstream logs. ]]>
