Skip to content

feat: implement SSRF guard to block private/internal IP fetches and a…#51

Open
anushkrishnav wants to merge 1 commit into
openswarm-ai:mainfrom
anushkrishnav:main
Open

feat: implement SSRF guard to block private/internal IP fetches and a…#51
anushkrishnav wants to merge 1 commit into
openswarm-ai:mainfrom
anushkrishnav:main

Conversation

@anushkrishnav

Copy link
Copy Markdown

Closes #47

Fixes CWE-918 (Server-Side Request Forgery) in the WebFetch tool.

Problem

WebFetch performed zero host/IP validation before fetching URLs. Any
http:// URL — including http://169.254.169.254/ (cloud metadata) and
RFC-1918 LAN addresses — passed through. follow_redirects=True made
it worse: a public URL redirecting to an internal address bypassed any
hypothetical scheme-only check entirely.

Changes

  • tools/ssrf_guard.py (new): single source of truth for the
    blocked-network list (loopback, link-local/cloud-metadata, RFC-1918,
    CGN, IPv6 ULA). Exposes is_safe_url() and assert_safe_url() /
    SSRFBlockedError.
  • tools/web.py: replaced follow_redirects=True with a manual
    _safe_fetch() that calls assert_safe_url() on the initial URL
    and every Location header before following it.
  • apps/web/web.py: /api/web/fetch calls assert_safe_url()
    before any cascade — returns HTTP 422 if blocked.
  • web_mcp_server.py: imports is_safe_url from ssrf_guard
    (fail-closed fallback if package unavailable); checks URL after the
    scheme guard.

Tests

42 new tests in tests/test_ssrf_guard.py covering:

  • Every blocked range (loopback, 169.254.x, RFC-1918, CGN, IPv6)
  • DNS failure → blocked
  • Missing hostname → blocked
  • Public URLs still allowed
  • Redirect-pivot attack blocked (public → internal 301)
  • MCP shim guard
  • Zero regressions against existing suite

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SSRF: WebFetch tool fetches arbitrary internal/cloud URLs with no host validation

1 participant