T09 · Insecure Skill Coding Practices
- Location
trending.py:125- Finding
Unrestricted Webhook Destinations Allow Server-Side Request Forgery
- Content
View full analysis
Vulnerability Details
File Location:
trending.py, lines 125–136 and 146–157
Vulnerability Type: Server-Side Request Forgery through user-controlled webhook URLs
Risk Level: MediumVulnerable Code
python try: req = urllib.request.Request(webhook, data=json.dumps(data).encode('utf-8'), headers={ 'Content-Type': 'application/json' }) with urllib.request.urlopen(req, timeout=30) as response: result = json.loads(response.read().decode('utf-8')) return result.get('errcode', -1) == 0 except Exception as e: print(f"钉钉发送失败: {e}") return Falsepython try: req = urllib.request.Request(webhook, data=json.dumps(data).encode('utf-8'), headers={ 'Content-Type': 'application/json' }) with urllib.request.urlopen(req, timeout=30) as response: result = json.loads(response.read().decode('utf-8')) return result.get('errcode', -1) == 0 except Exception as e: print(f"企业微信发送失败: {e}") return FalseTechnical Analysis
The
--webhookargument is passed directly tourllib.request.Requestandurllib.request.urlopen. The implementation does not validate:- The URL scheme
- The destination hostname
- The resolved IP address
- Whether the destination is loopback, private, link-local, or reserved
- Redirect destinations
- Whether the URL belongs to an official DingTalk or WeCom webhook service
Consequently, a party able to control the program arguments can instruct the process to issue an HTTP POST request to an arbitrary URL reachable from the host. This creates a server-side request forgery primitive.
Exploitation is constrained because the request body is a fixed notification JSON structure and the response is only parsed for
errcode, rather than being displayed to the caller. Nevertheless, the request can reach internal HTTP services that are inaccessible to an external attacke ...[truncated 1425 chars]- Remediation
View remediation
Remediation Suggestions
- Use separate DingTalk and WeCom webhook parameters and allowlist only the official HTTPS webhook hostnames required by each provider.
- Reject all schemes except
https. - Resolve the hostname before connecting and reject loopback, private, link-local, multicast, unspecified, and reserved IPv4 and IPv6 addresses.
- Disable automatic redirects or validate the scheme, hostname, and resolved address of every redirect target.
- Reject URLs containing unexpected user information, ports, fragments, or malformed hostnames.
- Apply outbound firewall or proxy rules so the process can connect only to GitHub and approved notification API domains.
- Add tests covering localhost, private IPv4 ranges, IPv6 loopback, link-local destinations, DNS rebinding scenarios, and redirects to prohibited destinations.
