Skip to content

fix(api): harden /api/swarm SSRF guard for caller-supplied baseUrl#26

Closed
AliaksandrNazaruk wants to merge 1 commit into
profullstack:mainfrom
AliaksandrNazaruk:fix/swarm-ssrf-guard
Closed

fix(api): harden /api/swarm SSRF guard for caller-supplied baseUrl#26
AliaksandrNazaruk wants to merge 1 commit into
profullstack:mainfrom
AliaksandrNazaruk:fix/swarm-ssrf-guard

Conversation

@AliaksandrNazaruk

Copy link
Copy Markdown
Contributor

Problem

/api/swarm accepts a caller-supplied baseUrl; buildModel only rejected /localhost|127.0.0.1/, missing IPv6 loopback, 0.0.0.0, the rest of 127.0.0.0/8, cloud metadata 169.254.169.254, RFC1918 and CGNAT. A signed-in caller could therefore reach internal/metadata endpoints (SSRF) — see #25.

Fix

  • New ssrf-guard.ts isBlockedHost() — loopback / unspecified / link-local / ULA / private / CGNAT for IPv4 and IPv6 (incl. IPv4-mapped), plus localhost/.local/.internal.
  • Applied in buildModel to the parsed hostname and to the DNS-resolved addresses (defense-in-depth vs. a public name resolving to a private IP). Public provider hosts (api.openai.com, …) are unaffected.

Tests

ssrf-guard.test.ts; logic verified standalone (24 blocked / 12 allowed).

Fixes #25.

buildModel() only rejected a baseUrl matching /localhost|127.0.0.1/, so a
signed-in caller could point baseUrl at other internal targets — IPv6 loopback
[::1], 0.0.0.0, the rest of 127.0.0.0/8, cloud metadata 169.254.169.254,
RFC1918 ranges, and CGNAT 100.64.0.0/10 — and make the server issue requests
there (SSRF).

Add ssrf-guard.ts (isBlockedHost) covering loopback/unspecified/link-local/
ULA/private/CGNAT for both IPv4 and IPv6 (incl. IPv4-mapped) plus localhost/
.local/.internal, and apply it in buildModel to the parsed hostname AND to the
DNS-resolved addresses (defense against a public name resolving to a private
IP). Public provider hosts (api.openai.com, etc.) are unaffected. Adds
ssrf-guard.test.ts; logic verified standalone (24 blocked / 12 allowed).
@ralyodio ralyodio closed this Jul 2, 2026
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: /api/swarm baseUrl guard only blocks localhost/127.0.0.1

2 participants