T09 · Insecure Skill Coding Practices
- Location
scripts/pqebot-web.py:34- Finding
Unrestricted URL Fetch Enables Server-Side Request Forgery
- Content
View full analysis
Vulnerability Details
File Location:
scripts/pqebot-web.py, lines 34–50
Vulnerability Type: Server-Side Request Forgery (SSRF)
Risk Level: MediumVulnerable Code
python def fetch_weixin_article(self, url: str) -> Optional[Dict]: """获取微信公众号文章内容""" try: # 注意:微信公众号文章需要特殊处理,这里仅做示例 response = self.session.get(url, timeout=10) if response.status_code == 200: # 实际中需要解析微信公众号的特殊页面结构 return { "url": url, "title": self._extract_title(response.text), "content": self._extract_content(response.text), "publish_time": self._extract_publish_time(response.text), "success": True } except Exception as e: print(f"获取文章出错: {e}") return NoneTechnical Analysis
The public
fetch_weixin_articlemethod accepts an arbitrary URL and passes it directly torequests.Session.get()without validating its scheme, hostname, resolved IP address, port, or redirect destination.Although the method is described as a WeChat article fetcher, the implementation does not restrict requests to WeChat domains. The
requestslibrary also follows HTTP redirects by default. Consequently, a caller able to control theurlargument can make the application initiate requests to:- Loopback services such as
127.0.0.1 - Private network ranges
- Link-local addresses, including cloud metadata services
- Services exposed on otherwise inaccessible internal ports
- Public URLs that redirect to prohibited internal destinations
When a target returns HTTP status 200, up to 1,000 characters of extracted response content can be returned through the method. This creates a response-based SSRF primitive rather than only a blind SSRF condition.
The audited command-line entry point does not currently invoke this method, which reduces immediate exposure ...[truncated 1805 chars]
- Loopback services such as
- Remediation
View remediation
Remediation Suggestions
-
Apply a strict destination allowlist
- Permit only
https. - Restrict requests to explicitly approved WeChat hostnames.
- Compare normalized hostnames exactly or against carefully defined subdomain boundaries.
- Permit only
-
Validate resolved addresses
- Resolve the hostname before connecting.
- Reject loopback, private, link-local, multicast, unspecified, and reserved IPv4 and IPv6 ranges.
- Validate every resolved address to mitigate DNS rebinding and mixed public/private DNS responses.
-
Control redirects
- Prefer
allow_redirects=False. - If redirects are required, validate the scheme, hostname, port, and resolved addresses at every redirect hop.
- Set a low maximum redirect count.
- Prefer
-
Restrict URL syntax
- Reject embedded credentials, fragments, malformed hostnames, and unexpected ports.
- Normalize internationalized domain names before allowlist comparison.
- Do not accept non-HTTP schemes.
-
Limit response processing
- Stream responses and enforce a small maximum response size.
- Set separate connection and read timeouts.
- Restrict accepted content types to expected HTML content.
-
Reduce exposure
- Do not connect this method directly to untrusted Agent or web input.
- Keep network retrieval disabled unless explicitly required.
- Run the Skill with outbound network controls that deny private and metadata address ranges.
-
Add security tests
- Test rejection of loopback, RFC 1918, link-local, IPv6 local, decimal or encoded IP representations, DNS rebinding scenarios, and public-to-private redirects.
-
