T09 · Insecure Skill Coding Practices
Error
- Location
- poly-resolution-tracking/scripts/scrape_source.py:48
- Finding
- Unrestricted resolution-source fetching enables server-side request forgery<![CDATA[ ## Vulnerability Details **File Location**: `poly-resolution-tracking/scripts/scrape_source.py:48-54`; reachable through `poly-resolution-tracking/scripts/monitor.py:198-232` **Vulnerability Type**: Server-side request forgery through unvalidated URLs **Risk Level**: High ### Vulnerable Code ```python def fetch_html(url: str, max_retries: int = 3, backoff: float = 1.0) -> str: """Fetch URL content as string with retry.""" for attempt in range(max_retries): try: req = urllib.request.Request(url, headers=HEADERS) with urllib.request.urlopen(req, timeout=30) as resp: return resp.read().decode("utf-8", errors="replace") ``` The monitor automatically extracts URLs from market descriptions and passes them to the unrestricted fetch function: ```python # Generic URL extraction urls = re.findall(r'https?://[^\s<>"]+', description) if urls: return { "type": "generic_url", "url": urls[0], } ``` ```python url = source.get("url", "") if source_type == "arena_leaderboard": return scrape_source(url, "arena_leaderboard") elif source_type == "generic_url" and url: return scrape_source(url, "generic") ``` The same implementation pattern exists in the corresponding `poly-resolution-tracking-zh` scripts. ### Technical Analysis The fetch function passes an externally derived URL directly to `urllib.request.urlopen`. It does not: - Restrict requests to HTTPS. - Maintain an allowlist of approved resolution-source domains. - Resolve and reject loopback, private, link-local, multicast, reserved, or cloud-metadata addresses. - Revalidate the destination after redirects. - Limit the response body size. - Prevent DNS rebinding between validation and connection. The URL can be provided directly through `scrape_source.py --url`, and the monitoring workflow can also obtain it from an untrusted Polymarket market description. This creates a reachable SSRF primitive rather than merely an ...[truncated 1491 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Permit only `https` URLs and reject all other schemes. 2. Use an explicit allowlist of trusted resolution-source domains where feasible. 3. Before connecting, resolve every hostname and reject all loopback, private, link-local, multicast, unspecified, reserved, and metadata-address ranges for both IPv4 and IPv6. 4. Disable automatic redirects or validate the scheme, hostname, port, and resolved address at every redirect. 5. Protect against DNS rebinding by connecting to the validated address while preserving the intended TLS hostname. 6. Block nonstandard ports unless explicitly required. 7. Apply a strict maximum response size and content-type allowlist. 8. Require explicit user approval before fetching a source URL extracted from third-party market text. 9. Apply the same changes to the English and Chinese variants. ]]>
