T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/ai_hive_mcp.py:19
- Finding
- Environment-overridable MCP endpoint can disclose AI-HIVE credentials## Vulnerability Details **File Location**: `scripts/ai_hive_mcp.py`, lines 19 and 47–74 **Vulnerability Type**: Arbitrary authenticated network destination **Risk Level**: High ### Vulnerable Code ```python MCP_URL = os.environ.get("AI_HIVE_MCP_URL", "https://ai-hive.iclip.cn/api/mcp") ``` ```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 read from the `AI_HIVE_MCP_URL` environment variable without validating its scheme, hostname, port, or path. The `post()` function then unconditionally adds either the `AI_HIVE_ACCESS_TOKEN` bearer token or the `AI_HIVE_API_KEY` header to requests sent to that destination. Consequently, an untrusted process launcher, shell configuration, CI environment, wrapper script, or other actor capable of influencing the process environment can redirect authenticated requests away from the documented AI-HIV ...[truncated 2282 chars]
- Remediation
- ## Remediation Suggestions 1. **Remove the endpoint override if it is not required.** Use a fixed authenticated endpoint: ```python MCP_URL = "https://ai-hive.iclip.cn/api/mcp" ``` 2. **If configurability is operationally necessary, strictly validate the destination before attaching credentials.** Require: - Scheme: `https` - Hostname: exactly `ai-hive.iclip.cn` - Default HTTPS port only - Expected path: `/api/mcp` - No embedded username or password - No URL fragments or unexpected query parameters 3. **Never send AI-HIVE credentials to custom endpoints.** Custom destinations should require a separate, explicit credential variable and a prominent confirmation. AI-HIVE credentials must remain bound to the canonical AI-HIVE origin. 4. **Prevent credential forwarding across redirects.** Disable automatic redirects for authenticated requests or validate every redirect target and strip authorization headers whenever the origin changes. 5. **Fail closed before constructing the authenticated request.** Validate and normalize the URL first, then call `auth_headers()` only after confirming that the destination is trusted. 6. **Prefer scoped, revocable credentials.** Use OAuth tokens restricted to the minimum required scope, short lifetimes, and server-side spending limits. Avoid long-lived API keys where possible. 7. **Document incident response.** If an override or redirect is suspected, immediately revoke the exposed key or token, inspect service usage and billing, and issue a new credential. A hardened validation pattern could begin with: ```python from urllib.parse import urlsplit EXPECTED_SCHEME = "https" EXPECTED_HOST = "ai-hive.iclip.cn" EXPECTED_PATH = "/api/mcp" def validate_mcp_url(raw_url: str) -> str: parsed = urlsplit(raw_url) if ( parsed.scheme != EXPECTED_SCHEME or parsed.hostname != EXPECTED_HOST or parsed.port not in (None, 443) or parsed.path != EXPECTED_PATH or parsed.use ...[truncated 228 chars]
