T09 · Insecure Skill Coding Practices
Error
- Location
- index.js:320
- Finding
- API Key Exposed Through Recharge URL and Chat Output<![CDATA[ ## Vulnerability Details **File Location**: `index.js:320-330` and `index.js:448-458` **Vulnerability Type**: Credential exposure through URL query parameters and rendered chat content **Risk Level**: High ### Vulnerable Code ```js const response = await fetchImpl(`${hostedApiBaseUrl}/v1/public/commerce-settings`); const body = response.ok ? await response.json() : {}; const settings = body.commerce_settings ?? {}; return { mode: "recharge_instructions", apiKey: resolved.apiKey, apiKeyHint: maskApiKey(resolved.apiKey), price: settings.betaPriceDisplay ?? "当前免费", paymentMethod: settings.paymentMethodLabel ?? "无需付款", buyPageUrl: `${hostedApiBaseUrl}/recharge?api_key=${encodeURIComponent(resolved.apiKey)}` }; ``` ```js export function formatRechargeMarkdown(recharge) { const buyPageUrl = recharge.buyPageUrl ?? recharge.rechargeUrl ?? "https://claw-temp.nydhfc.cn/recharge"; return [ "OpenClaw 温度层当前已改为免费 Beta,通常不需要充值。", "", `价格:${recharge.price ?? "当前免费"}`, `付款方式:${recharge.paymentMethod ?? "无需付款"}`, `API Key:${recharge.apiKey ?? recharge.apiKeyHint ?? "请让 OpenClaw 读取本地保存的 ocl_ key"}`, "", `查看免费说明:${buyPageUrl}` ].join("\n"); } ``` The behavior is explicitly validated by `tests/index.test.js:91-98`, which requires both the full API key and the URL containing it to appear in generated Markdown. ### Technical Analysis The API key is a bearer credential used to authorize reaction API requests. The implementation places that credential in a URL query parameter and also returns the unmasked credential in Markdown intended for display in a conversation. Credentials in query strings can be recorded by browser history, HTTP access logs, reverse proxies, monitoring systems, analytics services, screenshots, copied chat messages, and potentially referrer headers. Rendering the raw key in chat also unnecessarily expands its exposure to conversation storage, chat bridge operators, users with transcript access, and ...[truncated 1261 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove `apiKey` from the object returned by `getRechargeInstructions()`. 2. Never include reusable credentials in query parameters or rendered Markdown. 3. Display only a masked identifier such as `apiKeyHint`. 4. If account navigation is required, submit an authenticated POST request to create a short-lived, single-use session. 5. Return an opaque session URL that expires quickly and cannot be converted back into the API key. 6. Ensure server and proxy logs redact authorization headers, tokens, and session identifiers. 7. Replace the tests that require full-key disclosure with assertions that the raw key never appears in Markdown or URLs. 8. Rotate previously exposed keys where feasible. ]]>
