T09 · Insecure Skill Coding Practices
- Location
scripts/monitor.py:50- Finding
Unrestricted URL Fetching Enables SSRF and Local Resource Access
- Content
View full analysis
str: """Fetch URL content, optionally extracting a CSS selector.""" req_headers = { "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) web-monitor/1.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") ``` The unrestricted function is reached using user-controlled or persistently stored URLs: ```python content = fetch_content(args.url, args.selector) ``` ```python new_content = fetch_content(url, watch.get("selector")) ``` ### Technical Analysis The URL supplied to the `add` command is passed directly to `urllib.request.urlopen()` without validating its scheme, hostname, resolved IP address, port, or redirect destination. The documented functionality only requires fetching public HTTP or HTTPS web pages. However, the implementation may also accept other handlers supported by `urllib`, including `file:` URLs. HTTP requests can target loopback, link-local, private-network, and cloud metadata addresses. Automatic redirects can also move a request from a public URL to a restricted internal destination. This creates an SSRF primitive and potential local-file read primitive. The fetched response is normalized and stored under the configured snapshot directory, after which the `snapshot` and `diff` commands can expose it through command output. ### Attack Path 1. An attacker persuades a user or Agent to add a crafted monitoring target, such as a loopback/private-service URL, cloud metadata endpoint, or `file:` URI. 2. The `add` command passes that v ...[truncated 1215 chars]- Remediation
View remediation
