T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/switch-model-with-fallback.js:229
- Finding
- Provider API Credential Sent to an Unvalidated Configurable Endpoint## Vulnerability Details **File Location**: `scripts/switch-model-with-fallback.js:229-240` **Additional Locations**: `openclaw-model-connectivity-test.md:50-56`, `openclaw-model-connectivity-test.md:181-187` **Vulnerability Type**: Credential disclosure through an unvalidated network destination **Risk Level**: High ### Vulnerable Code ```js const response = await fetch(`${providerConfig.baseUrl}/chat/completions`, { method: "POST", headers: { Authorization: `Bearer ${providerConfig.apiKey}`, "Content-Type": "application/json", }, body: JSON.stringify({ model, messages: [{ role: "user", content: "reply with OK" }], max_tokens: 8, }), signal: controller.signal, }); ``` The mandatory connectivity runbook documents the same behavior: ```js fetch(`${p.baseUrl}/chat/completions`,{ method:"POST", headers:{Authorization:`Bearer ${p.apiKey}`,"Content-Type":"application/json"}, body:JSON.stringify({ model, messages:[{role:"user",content:"reply with OK"}], max_tokens:8 }) }) ``` ### Technical Analysis The fallback script loads `baseUrl` and `apiKey` from the local OpenClaw configuration and sends the reusable API credential as an HTTP Bearer token to the configured endpoint. The code checks only that these values exist. It does not enforce HTTPS, verify the endpoint hostname against an approved provider list, restrict ports, reject local or private-network destinations, or establish an explicit trust decision for custom gateways. An authenticated provider probe is relevant to the Skill's model-connectivity functionality. However, forwarding a reusable credential to any configurable URL is broader than the minimum privilege necessary. Destination validation is required because configuration is data, not a sufficient security boundary. If the configuration is maliciously or accidentally changed, the probe becomes a credential-disclosure mechani ...[truncated 1982 chars]
- Remediation
- ## Remediation Suggestions 1. Parse the configured destination with the standard `URL` class and reject malformed URLs. 2. Require `https:` for all remote provider endpoints. Permit plaintext HTTP only through an explicit, separately named development override that displays a prominent warning. 3. Maintain an explicit allowlist of approved provider hostnames and ports. If custom gateways are supported, require an affirmative option such as `--allow-custom-endpoint` rather than trusting configuration implicitly. 4. Resolve the hostname and reject loopback, link-local, private, multicast, and other special-purpose addresses unless local gateways are an explicitly supported and confirmed use case. 5. Disable automatic redirects for authenticated probes with `redirect: "error"`, or independently validate every redirect destination before forwarding credentials. 6. Reject URLs containing embedded usernames or passwords and normalize the URL before validation to prevent parser-confusion and hostname-bypass techniques. 7. Use a narrowly scoped, probe-only credential where the provider supports one. Avoid exposing a broadly privileged production key to routine heartbeat checks. 8. Separate endpoint configuration from credential storage where possible, and apply restrictive filesystem permissions to the credential source. 9. Update `openclaw-model-connectivity-test.md` to use the same hardened validation helper rather than duplicating an unrestricted authenticated `fetch`. 10. Log only the validated origin and model identifier. Never print the API key, Authorization header, or full configuration object. 11. Add tests covering HTTP rejection, unapproved hosts, private IP addresses, embedded credentials, unusual ports, redirects, and approved custom-gateway behavior.
