T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/help_read.py:48
- Finding
- Arbitrary URL Fetch Enables Server-Side Request Forgery## Vulnerability Details **File Location**: `scripts/help_read.py:48-63` **Vulnerability Type**: Arbitrary outbound request / SSRF **Risk Level**: High ### Vulnerable Code ```python url = args.url host = _url_host(url) # Ensure .md suffix if not url.endswith(".md"): # Only the two Help Center hosts serve raw Markdown at '<url>.md' if host in _DOC_HOSTS: url = url.rstrip("/") + ".md" site = (getattr(args, "site", None) or "").strip().lower() if site in SITES and host and host != SITES[site]["result_host"]: print(f"WARN[site-cross]: --site {site} points at {SITES[site]['result_host']} but the given URL is " f"on '{host}'; the URL is read as-is and no cross-site rewriting is performed", file=sys.stderr) text = fetch(url, max_bytes=DOC_MAX_BYTES) ``` The request is ultimately executed by the shared transport layer: ```python req = urllib.request.Request(url, headers={"User-Agent": UA}) opener = urllib.request.urlopen if allow_redirects else _NO_REDIRECT_OPENER.open try: with opener(req, timeout=effective_timeout(timeout or TIMEOUT)) as resp: data = resp.read() ``` ### Technical Analysis The `read` command accepts a user-controlled URL and derives its host with `_url_host()`. However, membership in `_DOC_HOSTS` is used only to determine whether the `.md` suffix should be appended. An unapproved host is never rejected. A site mismatch also produces only a warning and explicitly continues to read the URL as supplied. Consequently, arbitrary URL schemes and destinations accepted by `urllib.request` can reach the network transport. Redirects are enabled by default in `fetch()`. Therefore, even if direct input were later restricted to an approved Alibaba Cloud host, a redirect could still send the request to an unapproved destination unless every redirect target is validated. This behavior contradicts the module statement that only Help Center hosts are accepted and exceeds the minimum network access r ...[truncated 1478 chars]
- Remediation
- ## Remediation Suggestions 1. Enforce an exact destination allowlist before every request: - Require the `https` scheme. - Permit only `help.aliyun.com` and `www.alibabacloud.com`. - Reject missing hosts, user-information components, nonstandard schemes, and unexpected ports. 2. Do not merely warn on a host mismatch. Return an input error before making a request. 3. Disable automatic redirects for document reads. If redirects are required, process them manually and validate every destination against the same scheme, host, and port policy. 4. Resolve the destination and reject loopback, private, link-local, multicast, reserved, and unspecified IP addresses. Repeat validation after each redirect and account for multiple DNS answers. 5. Consider constraining paths to the documented Help Center layouts rather than allowing every path on an approved domain. 6. Add regression tests covering: - Direct requests to localhost and private IP addresses. - Link-local metadata addresses. - Unsupported schemes such as `file:`. - Approved hosts redirecting to unapproved hosts. - Hostname parsing edge cases, embedded credentials, and unexpected ports. - Valid China and international Help Center document URLs. A suitable validation flow is: ```python parsed = urllib.parse.urlsplit(url) if parsed.scheme != "https": raise _UsageError("Only HTTPS Help Center URLs are supported.") if parsed.hostname not in _DOC_HOSTS: raise _UsageError("Only official Alibaba Cloud Help Center hosts are supported.") if parsed.username or parsed.password or parsed.port not in (None, 443): raise _UsageError("URL credentials and nonstandard ports are not supported.") text = fetch(url, max_bytes=DOC_MAX_BYTES, allow_redirects=False) ``` If legitimate canonical redirects must be supported, follow them through a bounded loop and apply the full validation policy to each `Location` value before issuing the next request.
