T09 · Insecure Skill Coding Practices
- Location
scripts/monitor.py:48- Finding
Unrestricted URL Fetching Enables SSRF and Local File Access
- Content
View full analysis
Vulnerability Details
File Location:
scripts/monitor.py, lines 48-61
Vulnerability Type: Server-Side Request Forgery (SSRF) and unrestricted URI scheme access
Risk Level: HighVulnerable Code
python def fetch_content(url: str, selector: str = None, headers: dict = None) -> str: req_headers = { "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) web-monitor/2.0" } if headers: req_headers.update(headers) req = Request(url, headers=req_headers) try: with urlopen(req, timeout=30) as resp: raw = resp.read().decode("utf-8", errors="replace") except HTTPError as e: raise RuntimeError(f"HTTP {e.code}: {e.reason}")Technical Analysis
The URL accepted by the
addcommand is passed directly tourllib.request.Requestandurlopenwithout validating its scheme, hostname, resolved IP address, port, or redirect destinations.The implementation does not:
- Restrict URLs to the
httpandhttpsschemes. - Reject loopback, private, link-local, reserved, multicast, or unspecified IP addresses.
- Prevent access to supported local-resource schemes such as
file://. - Validate DNS resolution results.
- Revalidate destinations reached through HTTP redirects.
- Restrict access to cloud instance metadata services.
- Impose a maximum response size before reading the response into memory.
Although outbound network access is necessary for the declared website-monitoring functionality, unrestricted access to local resources and private networks exceeds the minimum privileges needed to monitor public web pages.
There is no evidence that the code deliberately transmits credentials, environment variables, snapshots, or local files to a hardcoded third party. The principal risk is that attacker-controlled URLs can cause the process to retrieve sensitive resources, after which their contents may be stored ...[truncated 1782 chars]
- Restrict URLs to the
- Remediation
View remediation
Remediation Suggestions
-
Restrict URI schemes
- Parse URLs with
urllib.parse.urlsplit. - Permit only explicit
httpandhttpsschemes. - Reject URLs containing unsupported schemes, missing hostnames, or embedded credentials.
- Parse URLs with
-
Validate resolved destinations
- Resolve the hostname before making a request.
- Use Python's
ipaddressmodule to reject every resolved loopback, private, link-local, multicast, reserved, or unspecified address. - Explicitly block cloud metadata destinations such as
169.254.169.254. - Apply validation to both IPv4 and IPv6 addresses.
-
Secure redirect handling
- Disable automatic redirects or implement a custom redirect handler.
- Parse, resolve, and validate every redirect destination before following it.
- Set a small maximum redirect count.
-
Reduce DNS rebinding exposure
- Ensure that the address validated is the address used for the connection.
- Where feasible, use an outbound proxy or network policy that blocks private and link-local destinations.
-
Limit resource consumption
- Inspect
Content-Lengthwhen available. - Read responses incrementally and stop after a configured maximum number of bytes.
- Apply limits to snapshot and diff retention.
- Inspect
-
Apply deployment-level controls
- Run the Skill under a dedicated, low-privilege account.
- Deny unnecessary filesystem access.
- Restrict outbound traffic to approved public destinations where the environment permits it.
- Consider an explicit hostname allowlist when monitoring targets can be supplied by untrusted parties.
-
Add security tests
- Verify rejection of
file://URLs. - Verify rejection of loopback, RFC1918, link-local, metadata, IPv6-local, and alternate numeric IP representations.
- Verify that redirects and DNS changes cannot bypass destination validation.
- Verify rejection of
-
