T09 · Insecure Skill Coding Practices
- Location
scripts/weixin_fetch.py:39- Finding
Unrestricted URL Fetching Enables Server-Side Request Forgery
- Content
View full analysis
Vulnerability Details
File Location:
scripts/weixin_fetch.py, lines 39–49 and 136–142
Vulnerability Type: Server-Side Request Forgery (SSRF) caused by insufficient URL and redirect validation
Risk Level: HighVulnerable Code
python def validate_url(url: str) -> Tuple[bool, str]: """Validate URL: must be http(s) with valid domain.""" try: p = urlparse(url) if p.scheme not in ('http', 'https'): return False, f"Only http/https allowed, got '{p.scheme or 'none'}'" if not p.netloc: return False, "Missing domain" return True, "" except Exception as e: return False, str(e)python with httpx.Client( follow_redirects=True, max_redirects=MAX_REDIRECTS, timeout=30.0 ) as client: response = client.get(url, headers=headers) response.raise_for_status()Technical Analysis
Although the skill is documented as a specialized fetcher for
mp.weixin.qq.com,validate_url()only verifies that the URL uses HTTP or HTTPS and contains a network location. It does not enforce the documented WeChat hostname.Consequently, attacker-controlled URLs targeting loopback addresses, link-local addresses, private network ranges, or other services reachable from the host are accepted. Examples include local web services, private administrative interfaces, and cloud instance metadata endpoints.
The HTTP client is also configured with
follow_redirects=True. Even if validation of the initial hostname were added independently, a permitted public URL could redirect to an internal destination unless every redirect target is separately validated.The implementation additionally lacks protection against:
- IPv4 and IPv6 loopback addresses.
- Private, link-local, reserved, unspecified, and multicast addresses.
- DNS records resolving a public hostname to a prohibited address.
- DNS rebinding o ...[truncated 2262 chars]
- Remediation
View remediation
Remediation Suggestions
-
Enforce the intended hostname allowlist
- Normalize the hostname using IDNA rules.
- Require an exact match for
mp.weixin.qq.com, or use a narrowly defined list of approved WeChat hosts. - Do not use suffix checks that could accept domains such as
mp.weixin.qq.com.attacker.example. - Reject URLs containing embedded user-information.
-
Validate resolved addresses
- Resolve all destination hostnames before making a request.
- Reject IPv4 and IPv6 loopback, private, link-local, reserved, multicast, and unspecified addresses.
- Validate every resolved address rather than accepting a hostname when only one result appears safe.
- Where supported, verify the actual connected peer address to reduce DNS-rebinding and time-of-check/time-of-use risks.
-
Secure redirect processing
- Disable automatic redirects with
follow_redirects=False. - Process redirects manually.
- Normalize and validate every
Locationdestination using the same hostname and IP restrictions before following it. - Apply a strict redirect count limit.
- Disable automatic redirects with
-
Limit response resource consumption
- Stream response data instead of loading the entire response body through
response.text. - Enforce a maximum byte count while reading.
- Reject unexpectedly large
Content-Lengthvalues and stop streaming once the configured limit is reached. - Consider restricting accepted content types to expected HTML media types.
- Stream response data instead of loading the entire response body through
-
Apply network-level defense in depth
- Run the skill in a restricted environment with egress access limited to approved WeChat endpoints.
- Block access to loopback, private networks, and cloud metadata services at the firewall or sandbox layer.
- Avoid relying exclusively on application-level URL validation.
-
