T09 · Insecure Skill Coding Practices
- Location
scripts.py:28- Finding
Unrestricted API Base URL Can Exfiltrate Credentials and Enable SSRF
- Content
View full analysis
Vulnerability Details
File Location:
scripts.py:28-38andscripts.py:69-73
Vulnerability Type: Unvalidated credential-bearing network destination
Risk Level: MediumVulnerable Code
python def baidu_search(api_key: str, client: str, environment: str, api_base: str, request_body: dict) -> dict: url = f"{api_base}/api/v1/proxy/baidu/search" headers = { "Authorization": f"Bearer {api_key}", "client": client, "environment": environment, "Content-Type": "application/json", "User-Agent": "openclaw-baidu-web-search", } response = requests.post(url, json=request_body, headers=headers, timeout=30)The destination is obtained from configuration without validation:
python _cfg = _load_env_from_config() api_key = _getcfg("TURING_API_KEY", _cfg) client = _getcfg("TURING_CLIENT", _cfg) environment = _getcfg("TURING_ENVIRONMENT", _cfg) api_base = (_getcfg("TURING_API_BASE", _cfg) or "https://live-turing.cn.llm.tcljd.com").rstrip("/")Technical Analysis
The script supports a configurable
TURING_API_BASE, then unconditionally sends the bearer API key, client identifier, environment identifier, and user-supplied search query to that destination. It does not verify the URL scheme, hostname, port, or resolved network address.Sending these values to the documented Turing proxy is necessary for the Skill's declared web-search functionality. Allowing the same credentials to be forwarded to an arbitrary destination exceeds the minimum network privilege required for that functionality.
A malicious or incorrectly modified configuration can set
TURING_API_BASEto an attacker-controlled server. Plain HTTP is also accepted, which can expose credentials and query contents to network observers. Setting the value to a loopback, private, link-local, or other internal address creates an SSRF primitive from the en ...[truncated 1869 chars]- Remediation
View remediation
Remediation Suggestions
- Remove
TURING_API_BASEconfigurability if custom proxy deployments are not an explicit functional requirement. - Otherwise, parse the URL with
urllib.parse.urlparseand require:- The
httpsscheme. - A nonempty hostname.
- No embedded username or password.
- An expected port, normally 443.
- A hostname from an explicit allowlist of trusted Turing endpoints.
- The
- Resolve the hostname and reject loopback, private, link-local, multicast, reserved, and unspecified IP addresses. Revalidate connections against DNS rebinding where custom hosts must be supported.
- Disable automatic redirects for this credential-bearing request with
allow_redirects=False, or independently validate every redirect destination before forwarding sensitive headers. - Do not send production credentials to custom endpoints by default. If custom deployments are required, use separately scoped credentials and require an explicit trust decision.
- Validate configuration at startup and fail closed with a clear error before constructing or sending the request.
- Apply least privilege to the API token, including restricted operations, environments, quotas, and expiration or rotation policies.
- Add automated tests confirming rejection of HTTP URLs, unexpected hosts and ports, embedded credentials, loopback addresses, private network addresses, and unsafe redirect targets.
- Remove
