T09 · Insecure Skill Coding Practices
- Location
scripts/ai_hive_mcp.py:15- Finding
Authentication Credentials Can Be Sent to a User-Controlled MCP Endpoint
- Content
View full analysis
Vulnerability Details
File Location:
scripts/ai_hive_mcp.py, lines 15-72
Vulnerability Type: Unvalidated credential destination
Risk Level: Highpython 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"} 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_idTechnical Analysis
The remote MCP destination is read from the
AI_HIVE_MCP_URLenvironment variable without validating its scheme, hostname, port, or path. Thepost()function then unconditionally attaches either the bearer access token or the AI-HIVE API key ...[truncated 2437 chars]- Remediation
View remediation
Remediation Suggestions
-
Pin the authenticated endpoint. Remove the environment override unless it is operationally necessary:
python MCP_URL = "https://ai-hive.iclip.cn/api/mcp" -
If overrides are required, enforce an explicit allowlist. Parse the URL and require HTTPS, the expected hostname, the expected port, and an approved path before constructing authentication headers:
python from urllib.parse import urlparse ALLOWED_HOSTS = {"ai-hive.iclip.cn"} def validate_mcp_url(url: str) -> str: parsed = urlparse(url) if ( parsed.scheme != "https" or parsed.hostname not in ALLOWED_HOSTS or parsed.port not in (None, 443) or parsed.path != "/api/mcp" or parsed.username is not None or parsed.password is not None ): raise SystemExit("Refusing to send credentials to an unapproved MCP endpoint.") return url -
Bind credentials to the validated origin. Do not call
auth_headers()until the destination has passed validation. Never attach credentials to diagnostic or third-party endpoints. -
Prevent cross-origin credential forwarding. Disable automatic redirects for authenticated requests or validate every redirect target and strip authentication headers whenever the origin changes.
-
Separate development configuration from production authentication. If custom test servers are needed, require a dedicated opt-in flag and separate test credentials that cannot access production resources.
-
Minimize credential scope and lifetime. Prefer narrowly scoped, revocable, short-lived OAuth tokens where supported. Ensure API keys can be promptly revoked and rotated.
-
Add security tests. Verify that HTTP URLs, deceptive subdomains, embedded credentials, unexpected ports, altered paths, and cross-origin redirects are rejected before any secret is transmi ...[truncated 5 chars]
-
