T09 · Insecure Skill Coding Practices
- Location
scripts/request_client.py:24- Finding
Unvalidated API Base URL Can Expose the Bearer Credential over Insecure Transport
- Content
View full analysis
Vulnerability Details
File Location:
scripts/request_client.py:24-54
Vulnerability Type: Unvalidated request destination and plaintext credential exposure
Risk Level: HighVulnerable Code
python if not base_url: raise ValueError("base_url 不能为空") if not api_key: raise ValueError("api_key 不能为空") self.base_url = base_url self.api_key = api_key self.timeout = timeout self.session = requests.Session() self.session.headers.update({ "Authorization": f"Bearer {self.api_key}", }) def _build_url(self, path: str) -> str: base_url = self.base_url.rstrip("/") path = path.lstrip("/") return f"{base_url}/{path}" def _request( self, method: str, path: str, *, params: Optional[dict[str, Any]] = None, data: Optional[dict[str, Any]] = None, json: Optional[dict[str, Any] | list[Any]] = None, **kwargs: Any, ) -> dict[str, Any] | list[Any] | None: url = self._build_url(path) response = self.session.request( method, url, params=params, data=data, json=json, timeout=self.timeout, **kwargs, )Technical Analysis
The client checks only whether
base_urlis nonempty. It does not parse or validate the URL, require HTTPS, restrict the destination hostname, or reject loopback, link-local, private-network, and otherwise unintended destinations.The API key is installed as a session-wide
Authorizationheader. Consequently, every request generated by this client sends the privileged bearer credential to the configured destination. IfRR_CLAW_BASE_URLis accidentally or maliciously configured with an attacker-controlledhttp://endpoint, the credential is sent to that endpoint without transport encryption. Plain HTTP also permits interception or modification by an on-path attacker.Because the destination is unrestricted, the client can additionally be directed toward unintended internal HTTP services. The confirmed security ...[truncated 1918 chars]
- Remediation
View remediation
Remediation Suggestions
- Parse
base_urlwithurllib.parse.urlparseand reject malformed values. - Require the
httpsscheme in production; do not permit plaintext HTTP for credential-bearing requests. - Reject embedded usernames or passwords, fragments, missing hostnames, and ambiguous URL forms.
- Maintain an administrator-approved hostname allowlist where deployment architecture permits it.
- Resolve and reject loopback, link-local, multicast, and private-network addresses unless a documented private deployment explicitly requires them.
- Disable automatic redirects for authenticated requests, or validate every redirect target before forwarding the
Authorizationheader. - Bind credentials to an expected origin and avoid using a session-wide authorization header when requests could reach any other origin.
- Use least-privileged, revocable API keys and rotate a key immediately if it may have been transmitted over HTTP or to an untrusted endpoint.
- Add automated tests covering HTTP URLs, attacker-controlled hosts, malformed URLs, internal addresses, and cross-origin redirects.
A hardened validation pattern should resemble:
python from urllib.parse import urlparse parsed = urlparse(base_url) if parsed.scheme != "https": raise ValueError("base_url must use HTTPS") if not parsed.hostname: raise ValueError("base_url must contain a valid hostname") if parsed.username or parsed.password or parsed.fragment: raise ValueError("base_url contains prohibited URL components") if parsed.hostname not in APPROVED_API_HOSTS: raise ValueError("base_url host is not approved")Redirect handling should then be disabled with
allow_redirects=False, or implemented with explicit destination validation before credentials are resent.- Parse
