T09 · Insecure Skill Coding Practices
- Location
scripts/sec_edgar.py:79- Finding
Unrestricted Filing URL Fetch Exposes the SEC Identity Header and Enables SSRF
- Content
View full analysis
str: """Fetch raw text/HTML content from a URL.""" req = urllib.request.Request(url, headers={ "User-Agent": ua, "Accept": "text/html, application/xhtml+xml, text/plain, */*", }) try: with urllib.request.urlopen(req, timeout=60) as resp: return resp.read().decode("utf-8", errors="replace") except urllib.error.HTTPError as e: body = e.read().decode("utf-8", errors="replace")[:500] raise RuntimeError(f"EDGAR fetch error ({e.code}): {body}") from e ``` ```python def cmd_read_filing(url: str, section: str, max_chars: int, ua: str) -> dict: """Download a filing and return its text content.""" raw = _get_raw(url, ua) ``` ```python ap.add_argument("--url", default="", help="Direct filing document URL (for read-filing)") ``` ```python ua = args.user_agent or os.environ.get("SEC_EDGAR_USER_AGENT", DEFAULT_UA) ``` ### Technical Analysis The `read-filing` command accepts a caller-controlled URL and passes it directly to `urllib.request.urlopen`. The implementation does not validate the URL scheme, hostname, port, resolved IP address, path, or redirect destinations. Although sending an identifying User-Agent to SEC EDGAR is required and appropriate for requests to SEC services, `_get_raw` sends the same value to every supplied destination. The project documentation encourages users to configure this value with their real name and email address. Consequently, a request to an attacker-controlled host can disclose that identity. The unrestricted request also permits access to HTTP or HTTPS services reachable from the execution environment, ...[truncated 1936 chars]- Remediation
View remediation
