Documentation
¶
Overview ¶
Package httpsec provides SSRF-safe URL validation and HTTP client construction. Any code path that fetches a URL chosen at runtime by a tenant (webhook delivery, avatar import, OAuth callback, SCM discovery) MUST pipe the URL through ValidateURL before dialing, otherwise an attacker who controls that URL can point it at the cloud metadata service (169.254.169.254) or internal RFC1918 ranges and read back secrets via response echo.
The blocklist is deliberately conservative — prod deployments rarely need to POST to 10.x or 172.16.x from the API container, and when they do, the right fix is a per-tenant allowlist, not loosening this file.
This package is the canonical SSRF guard. internal/infra/fetchers/ has an older duplicate with identical ranges; follow-up work should consolidate that callsite onto this package.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AllowPrivate ¶
func AllowPrivate() bool
AllowPrivate reports whether the RFC1918 / ULA ranges are currently treated as reachable. Exposed for log-at-startup observability; do not consult this to decide individual calls — that branches inside IsIPBlocked.
func IsIPBlocked ¶
IsIPBlocked reports whether the given IP is not reachable under the current policy. Hard-blocked CIDRs always return true; the RFC1918 / ULA block is conditional on allowPrivate.
func SafeHTTPClient ¶
SafeHTTPClient returns an *http.Client whose dialer rejects any connection attempt to a blocked CIDR at the transport layer. This is the belt to ValidateURL's braces: even if a caller forgets to validate up front, the dial will fail closed. Use this as the default http.Client for tenant-facing outbound HTTP.
Callers should still ValidateURL themselves because the dialer-only check happens AFTER DNS resolution, so a request to a tenant-supplied URL will have burned a DNS lookup and possibly emitted it to a DNS server the attacker controls. ValidateURL rejects before the lookup leaves the host process.
Types ¶
type ValidationResult ¶
ValidationResult carries the parsed URL + the DNS-pinned IP set so callers that want to prevent DNS rebinding can dial one of the resolved IPs rather than re-resolve at dial time.
func ValidateURL ¶
func ValidateURL(rawURL string) (*ValidationResult, error)
ValidateURL parses rawURL, confirms scheme is http/https, blocks common dangerous hostnames, resolves DNS and rejects if any A/AAAA hits a blocked CIDR. Returns the parsed URL + pinned IPs. On any failure, returns an error — callers MUST NOT proceed to dial.
Fail-closed on DNS lookup failure: if we cannot resolve, we cannot verify the target is safe, so the request is rejected.