T09 · Insecure Skill Coding Practices
- Location
app/core/security.py:35- Finding
Unrestricted SSRF Through Arbitrary URL Forwarding
- Content
View full analysis
bool: """ 验证 URL 格式 - 必须以 http:// 或 https:// 开头 """ if not url: return False return url.startswith(("http://", "https://")) ``` ```python async def fetch_url( self, url: str, method: str = "GET", headers: Optional[Dict[str, str]] = None, body: Optional[str] = None, region: str = "us" ) -> dict: proxy_url = f"http://localhost:{self.upstream_mixed_port}" transport = httpx.AsyncHTTPTransport(proxy=proxy_url) async with httpx.AsyncClient( timeout=30.0, follow_redirects=True, transport=transport ) as client: request_headers = headers or {} request_headers.setdefault("User-Agent", "ProxyGateway/0.3.0") response = await client.request( method=method.upper(), url=url, headers=request_headers, content=body ) return { 'success': True, 'status_code': response.status_code, 'headers': dict(response.headers), 'content': response.text, 'content_type': response.headers.get('content-type') } ``` ### Technical Analysis URL validation verifies only that the input begins with `http://` or `https://`. It does not parse the destination or reject: - Loopback addresses such as `127.0.0.1` and `::1` - RFC 1918 private networks - Link-local and cloud metadata addresses - Localhost or internal DNS names - Alternative or encoded IP representations - Hostnames that resolve to private addresses - DNS rebinding - Redirects from public hosts to restricted destinations The forwarding implementation also enables `follow_redirects=T ...[truncated 1478 chars]- Remediation
View remediation
