Skip to content
ssrfguard

go · zero deps · dial-time

Stop SSRF at dial time.

A dependency-free Go library that validates outbound URLs and blocks internal addresses — enforced after DNS resolution, just before connect, so it holds up against the DNS-rebinding attacks that most up-front URL checks miss.

MIT licensed · no third-party dependencies · Go 1.26+

guard.go
client := ssrfguard.New().Client()
resp, err := client.Get(untrustedURL)
if errors.Is(err, ssrfguard.ErrBlockedAddress) {
    // refused to connect to an internal address
}

what you get

Defense that fires where it counts.

One small guard that inspects the real socket destination — closing the gap between URL validation and the actual connection.

Dial-time enforcement

Inspects the real IP the socket will reach — via net.Dialer.Control, which runs after DNS resolution and just before connect — closing the DNS-rebinding window.

Blocks the dangerous ranges

Loopback, RFC 1918 / RFC 4193 private, link-local — including the cloud metadata address 169.254.169.254 — and unspecified addresses.

Zero dependencies

Pure standard library. Nothing to audit beyond Go itself, and nothing to pull into your supply chain.

Composable

Use a guarded http.Client, wrap your own tuned http.Transport, or attach the control directly to a net.Dialer.

Validate now, fetch later

ValidateURL / ValidateURLContext give you an up-front check for URLs you store and dereference later.

Configurable

Scheme allowlist with WithSchemes, WithAllowPrivate, and a custom WithResolver. It correctly classifies IPv4-mapped IPv6 addresses.

usage

Guard the fetch, or check up front.

Use a guarded client when you fetch immediately; validate the URL first when you store it now and dereference it later.

// Guarded client — enforced at dial time
client := ssrfguard.New().Client()
resp, err := client.Get(untrustedURL)
if errors.Is(err, ssrfguard.ErrBlockedAddress) {
    // refused to dial an internal address
}
// Up-front check — store now, fetch later
if err := ssrfguard.ValidateURL(u); err != nil {
    // reject before you persist the URL
    return err
}
  • New / .Client
  • ValidateURL
  • ValidateURLContext
  • ErrBlockedAddress
  • WithSchemes
  • WithAllowPrivate
  • WithResolver

install

Add it to your module.

One import, no transitive dependencies. Requires Go 1.26+.

go get go get github.com/richardwooding/ssrfguard
import import "github.com/richardwooding/ssrfguard"

Requires Go 1.26+ with no third-party dependencies. Full API docs live on pkg.go.dev.