T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/gateway.py:33
- Finding
- API Credential Disclosure Through Cross-Origin HTTP Redirects<![CDATA[ ## Vulnerability Details **File Location**: `scripts/gateway.py`, lines 33-39 **Vulnerability Type**: Cross-origin credential forwarding through unrestricted redirects **Risk Level**: High ### Vulnerable Code ```python key=os.environ.get('OPENLX_WEIXIN_API_KEY') if not key: raise ValueError('OPENLX_ACCESS_CREDENTIAL_MISSING') headers={'Content-Type':'application/json','x-api-key':key} # Gateway does not guarantee idempotency-key deduplication. Never blind retry a write. req=urllib.request.Request('https://wx.openlx.cn/v2/proxy/'+endpoint,data=json.dumps(payload,ensure_ascii=False).encode(),headers=headers) try: with urllib.request.urlopen(req,timeout=180) as r: return json.load(r) ``` ### Technical Analysis The request places the sensitive `OPENLX_WEIXIN_API_KEY` value in the `x-api-key` header and passes the request to `urllib.request.urlopen`. Python's standard URL-opening behavior follows HTTP redirects by default. The implementation neither disables redirects nor verifies that the final response remains on the exact `https://wx.openlx.cn` origin. During redirect processing, custom request headers may be retained. Therefore, a redirect to a different HTTPS origin can result in the API-key header being forwarded to that origin. Using HTTPS only protects the connection to the selected destination. It does not prevent disclosure when the destination itself changes to an attacker-controlled HTTPS server. Exploitation requires the OpenLX gateway, its routing infrastructure, or an upstream response path to return a malicious or compromised redirect. ### Attack Path 1. A user configures a valid `OPENLX_WEIXIN_API_KEY` and invokes `scripts/gateway.py`. 2. The client sends an authenticated request to `https://wx.openlx.cn/v2/proxy/...`. 3. The gateway or compromised upstream infrastructure returns an HTTP redirect to an attacker-controlled HTTPS origin. 4. `urllib.request.urlopen` follows the redirect because redirects are enabled by default. 5. ...[truncated 983 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Disable automatic redirects for authenticated gateway requests. 2. If redirects are operationally required, implement a custom redirect handler that: - Accepts only the `https` scheme. - Accepts only the exact hostname `wx.openlx.cn`. - Accepts only the expected HTTPS port. - Rejects redirects involving user information, unexpected ports, or alternate subdomains. 3. Remove `x-api-key` before constructing any redirected request and restore it only after confirming that the destination has the same trusted origin. 4. Validate the final response URL before reading or trusting the response. 5. Prefer rejecting all cross-origin redirects rather than relying on header-removal behavior. 6. Add automated tests covering 301, 302, 303, 307, and 308 responses to same-origin and cross-origin destinations. 7. Rotate potentially exposed API keys if logs indicate that authenticated requests previously encountered unexpected redirects. ]]>
