T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/skill_router.py:51
- Finding
- API Key Disclosure Through Cross-Origin HTTP Redirects<![CDATA[ ## Vulnerability Details **File Location**: `scripts/skill_router.py`, lines 51–67 **Vulnerability Type**: Credential disclosure through unsafe redirect handling **Risk Level**: Medium ### Vulnerable Code ```python # Restrict outbound requests to the expected Media.io API host. parsed = urlparse(url) if parsed.scheme != 'https' or parsed.netloc.lower() != 'openapi.media.io': return {'error': f"Blocked endpoint host: {parsed.netloc}"} headers = { 'X-API-KEY': resolved_api_key, 'Content-Type': 'application/json' } # Replace path parameters in endpoint URLs. if '{' in url: for k, v in params.items(): url = url.replace(f'{{{k}}}', str(v)) # Keep non-path parameters in the JSON body. body = {k: v for k, v in params.items() if f'{{{k}}}' not in api['endpoint']} try: resp = requests.request(method, url, headers=headers, json={'data': body} if body else {}, timeout=30) ``` ### Technical Analysis The implementation verifies that the initial request URL uses HTTPS and has the exact hostname `openapi.media.io`. However, `requests.request()` follows HTTP redirects by default, while the code does not validate the destination of each redirect. The API credential is carried in the custom `X-API-KEY` header. Custom authentication headers are not guaranteed to be removed automatically when a redirect crosses origins. Therefore, if the validated Media.io endpoint returns a redirect to another hostname, the client may send the API key to that destination. The initial hostname check does not protect subsequent redirect hops. Exploitation requires the legitimate endpoint, or infrastructure controlling its response, to issue a cross-origin redirect. No evidence was found that ordinary request parameters currently let an untrusted caller directly select such a redirect destination, so the issue is conditional rather than an immediate arbitrary-host request vulnerability. ### Attack Path 1. A victim invokes one of the configured Media.io ...[truncated 1069 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions Disable automatic redirects for authenticated API requests: ```python resp = requests.request( method, url, headers=headers, json={'data': body} if body else {}, timeout=30, allow_redirects=False, ) ``` If redirects are required, handle them explicitly and apply all of the following controls: 1. Validate every redirect destination before sending another request. 2. Require the `https` scheme and the exact hostname `openapi.media.io`. 3. Reject user-information components, unexpected ports, and malformed hostnames. 4. Enforce a small redirect limit to prevent redirect loops. 5. Never forward `X-API-KEY` when the scheme, hostname, or effective port changes. 6. Prefer rejecting redirects entirely for fixed API endpoints because all configured destinations are already known. 7. Add automated tests covering same-origin redirects, cross-origin redirects, scheme downgrades, malformed destinations, and redirect loops. ]]>
