T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/ai_hive_mcp.py:19
- Finding
- Credential and MCP Payload Exfiltration Through an Unrestricted Endpoint Override<![CDATA[ ## Vulnerability Details **File Location**: `scripts/ai_hive_mcp.py:19, 47-50, 57-74` **Vulnerability Type**: Unrestricted network destination with automatic credential forwarding **Risk Level**: High ### Vulnerable Code ```python MCP_URL = os.environ.get("AI_HIVE_MCP_URL", "https://ai-hive.iclip.cn/api/mcp") ORIGIN = "https://ai-hive.iclip.cn" PROTECTED_RESOURCE = f"{ORIGIN}/.well-known/oauth-protected-resource/api/mcp" AUTHORIZATION_SERVER = f"{ORIGIN}/.well-known/oauth-authorization-server" READ_ONLY_TOOLS = {"ai_hive_list_models", "ai_hive_get_task"} ``` ```python def auth_headers() -> dict[str, str]: key = os.environ.get("AI_HIVE_API_KEY", "").strip() token = os.environ.get("AI_HIVE_ACCESS_TOKEN", "").strip() if token: return {"authorization": f"Bearer {token}"} if key: return {"x-ai-hive-api-key": key} raise SystemExit( "缺少凭据。OAuth 用户请在 MCP 客户端中完成登录;本脚本调用工具时需通过环境变量提供 " "AI_HIVE_API_KEY,或仅运行 doctor。" ) def post(payload: dict, session_id: str | None = None) -> tuple[dict, str | None]: headers = { "content-type": "application/json", "accept": "application/json, text/event-stream", **auth_headers(), } if session_id: headers["mcp-session-id"] = session_id request = urllib.request.Request( MCP_URL, data=json.dumps(payload, ensure_ascii=False).encode("utf-8"), headers=headers, method="POST", ) try: with urllib.request.urlopen(request, timeout=60) as response: result = parse_payload(response.read(), response.headers.get("content-type", "")) return result, response.headers.get("mcp-session-id") or session_id ``` ### Technical Analysis The MCP destination is taken directly from the `AI_HIVE_MCP_URL` environment variable without validating its scheme, hostname, port, path, or relationship to the documented AI-HIVE service. The `post()` function then automatically attaches eithe ...[truncated 2462 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Remove the endpoint override when it is not operationally required.** ```python MCP_URL = "https://ai-hive.iclip.cn/api/mcp" ``` 2. **If custom endpoints are necessary, require explicit opt-in and enforce an allowlist.** Validate the parsed URL before loading or attaching credentials: ```python from urllib.parse import urlparse ALLOWED_MCP_ENDPOINTS = { ("https", "ai-hive.iclip.cn", 443, "/api/mcp"), } def validate_mcp_url(raw_url: str) -> str: parsed = urlparse(raw_url) port = parsed.port or 443 candidate = (parsed.scheme, parsed.hostname, port, parsed.path) if parsed.username or parsed.password: raise SystemExit("MCP URLs must not contain user information.") if candidate not in ALLOWED_MCP_ENDPOINTS: raise SystemExit("Unapproved AI-HIVE MCP endpoint.") if parsed.query or parsed.fragment: raise SystemExit("MCP URLs must not contain a query or fragment.") return raw_url ``` 3. **Never attach credentials to untrusted origins.** Bind credentials to the expected HTTPS origin and fail closed if the destination differs. 4. **Control redirects explicitly.** Disable automatic redirects for authenticated requests or validate every redirect target before resending a request. Credentials and request bodies must never be forwarded across origins. 5. **Reject plaintext transport.** Require HTTPS and reject `http`, local-file, or other URL schemes. 6. **Separate development credentials from production credentials.** If testing against a custom MCP server is required, use a separate command-line mode that does not load `AI_HIVE_API_KEY` or `AI_HIVE_ACCESS_TOKEN` and requires dedicated, non-production credentials. 7. **Document the trust boundary.** State that authenticated requests are restricted to the official AI-HIVE origin and that endpoint customization must not be controlled through untruste ...[truncated 51 chars]
