ayuhito/safehttp

GitHub: ayuhito/safehttp

Stars: 1 | Forks: 0

# safehttp [![Go Reference](https://pkg.go.dev/badge/github.com/ayuhito/safehttp.svg)](https://pkg.go.dev/github.com/ayuhito/safehttp) `safehttp` is an SSRF-resistant wrapper around Go's `net/http` for outbound requests whose URL is provided by an untrusted source. Use it when your service fetches URLs from users, webhooks, OAuth metadata, imported documents, third-party API payloads, or any other source you do not fully control. It keeps those requests constrained to allowed public destinations and blocks loopback, RFC1918 networks, Kubernetes, cloud metadata, and other internal or special-use addresses. ## Defaults `NewClient()` starts with a public-HTTPS-only configuration. Requests must use HTTPS, target a public destination, and use port `443`. URL credentials, custom `Request.Host`, proxies, other schemes or ports, and internal or special-use IP ranges are blocked. Redirects are followed by default, but every redirect target is revalidated. ## Install go get github.com/ayuhito/safehttp ## Usage Create one client and reuse it. client, err := safehttp.NewClient( safehttp.ClientTimeout(5*time.Second), safehttp.MaxResponseBytes(10<<20), safehttp.NoRedirects(), ) if err != nil { return err } resp, err := client.Get(rawURL) if err != nil { return err } defer resp.Body.Close() If the set of valid destinations is known, add a host allowlist. client, err := safehttp.NewClient( safehttp.AllowHosts( "api.github.com", "uploads.github.com", "*.githubusercontent.com", ), safehttp.AllowMethods(http.MethodGet, http.MethodHead), safehttp.MaxRedirects(3), safehttp.ClientTimeout(5*time.Second), safehttp.MaxResponseBytes(8<<20), ) ## Existing Transports Use `NewTransport` to reuse an existing transport configuration. base := http.DefaultTransport.(*http.Transport).Clone() base.MaxIdleConnsPerHost = 32 rt, err := safehttp.NewTransport(base, safehttp.AllowHosts("api.github.com")) if err != nil { return err } client := &http.Client{Transport: rt} `safehttp` clones the transport before applying its settings, so the original transport is not modified. Use `safehttp.Dialer` for custom dialer settings. Transport settings that bypass safehttp's connection checks or disable TLS certificate verification are rejected. ## Guard-Only Checks `NewGuard` exposes validation without constructing an `http.Client`. guard, err := safehttp.NewGuard(safehttp.AllowHosts("api.github.com")) if err != nil { return err } if err := guard.CheckRequest(req); err != nil { return err } Use guard-only checks for preflight validation. They do not send the request; use `NewClient` or `NewTransport` for the outbound HTTP path. ## API Reference Constructors: func NewClient(opts ...Option) (*http.Client, error) func NewTransport(base *http.Transport, opts ...Option) (http.RoundTripper, error) func NewGuard(opts ...Option) (*Guard, error) Options: - destination policy: `AllowSchemes`, `AllowPorts`, `AllowHosts`, `AllowMethods` - redirects: `MaxRedirects`, `NoRedirects` - explicit opt-ins: `AllowCredentials`, `AllowCustomHostHeader` - address policy: `AllowPrefixes`, `DenyPrefixes`, `AllowCIDRs`, `DenyCIDRs` - transport/client limits: `Dialer`, `ClientTimeout`, `MaxResponseHeaderBytes`, `MaxResponseBytes` `AllowPrefixes` and `AllowCIDRs` opt in to additional address ranges, for example private infrastructure or local tests. `DenyPrefixes` and `DenyCIDRs` make the address policy stricter. Deny rules are evaluated before allow rules. ## Performance Create one client and reuse it. The added checks are negligible to performance and is safe to use concurrently. go test -run '^$' -bench Benchmark -benchmem ## Acknowledgements This library was inspired by and borrows from the following projects: - [`doyensec/safeurl`](https://github.com/doyensec/safeurl) - [`daenney/ssrf`](https://github.com/daenney/ssrf)
标签:EVTX分析