T09 · Insecure Skill Coding Practices
- Location
blog-big-kimi-kit.py:109- Finding
Unrestricted Base URL Enables Server-Side Request Forgery
- Content
View full analysis
Vulnerability Details
File Location:
blog-big-kimi-kit.py, lines 109-128 and 167-190
Vulnerability Type: Unrestricted outbound request destination
Risk Level: MediumVulnerable Code
python def _get_base_url(): """获取 API base URL——4 级优先级(与凭据读取一致)。""" creds = _load_credentials() base_url = creds.get('base_url', '').rstrip('/') if not base_url: print("未检测到 %s_BASE_URL 环境变量,也未在 .project-info/ 找到配置。" % _CRED_PREFIX) print("请输入目标系统 API 地址(如 http://host:port):") base_url = input("> ").strip().rstrip('/') if not base_url: print("错误:API 地址不能为空", file=sys.stderr) sys.exit(3) if not (base_url.startswith("http://") or base_url.startswith("https://")): print("错误:地址必须以 http:// 或 https:// 开头", file=sys.stderr) sys.exit(3) print("提示:可通过 export %s_BASE_URL=\"%s\" 永久设置,避免每次输入。" % (_CRED_PREFIX, base_url)) return base_urlpython base_url = _get_base_url() creds = _load_credentials() auth_result = _build_auth(creds) url = f"{base_url}{path}" try: if method == 'GET': resp = requests.get(url, params=params, timeout=30, **auth_kwargs) elif method == 'POST': resp = requests.post(url, json=payload, files=files, timeout=30, **auth_kwargs) elif method == 'PUT': resp = requests.put(url, json=payload, files=files, timeout=30, **auth_kwargs) elif method == 'PATCH': resp = requests.patch(url, json=payload, timeout=30, **auth_kwargs) elif method == 'DELETE': resp = requests.delete(url, params=params, timeout=30, **auth_kwargs)Technical Analysis
The API destination can be obtained from project configuration, an environment variable, or interactive input. The only validation applied to an interactively supplied value is that it starts with
http://orhttps://. Values loaded from configuration or the environment do not receive even that validation.The implementation does ...[truncated 2101 chars]
- Remediation
View remediation
Remediation Suggestions
- Require an explicit allowlist of approved API hostnames and ports.
- Parse the destination with
urllib.parse.urlsplitrather than checking string prefixes. - Resolve the hostname before connecting and reject loopback, private, link-local, multicast, unspecified, and reserved addresses using Python's
ipaddressmodule. - Explicitly block cloud metadata destinations, including IPv4 and IPv6 equivalents.
- Disable redirects with
allow_redirects=False, or validate every redirect destination using the same checks. - Revalidate the connected address to mitigate DNS rebinding and time-of-check/time-of-use discrepancies.
- Require HTTPS except for explicitly approved local development environments.
- Reject URLs containing user information, fragments, unexpected paths, or unsupported ports.
- Separate configuration of the trusted service from task-controlled input so untrusted content cannot silently change the destination.
