Documentation
¶
Overview ¶
Package ssrfguard is an opt-in SSRF egress guard for flate's outbound source fetches. When flate renders UNTRUSTED input (e.g. konflate rendering a fork PR), a fork can place attacker-chosen URLs in the tree — kustomize remote resources/bases and GitRepository/OCIRepository/HelmRepository/Bucket spec.url — which flate would otherwise fetch server-side from inside the cluster, reaching cloud metadata (169.254.169.254), in-cluster services, and RFC1918/loopback hosts.
The guard installs a net.Dialer.Control hook on every fetch transport (via WrapTransport, wired into source.NewHTTPTransport, the helm getter, and the kustomize remote-fetch client). Control runs at dial time, AFTER DNS resolution, for every connection INCLUDING redirect targets, so one hook closes both DNS-rebinding and redirect SSRF without a CheckRedirect.
It is OFF by default and gated by a single process-global toggle (Restrict): flate normally renders TRUSTED repos that legitimately fetch from private/LAN hosts (self-hosted Gitea, in-cluster registries), so an always-on private block would break the common case. A consumer rendering untrusted input (konflate fork mode, or the `flate --restrict-egress` flag) turns it on. The toggle is process-global, not per-render, because go-git v5 installs its HTTPS transport on a process-global protocol map with no per-clone hook — so a per-render git egress policy is impossible, and a process-global toggle is the honest model. Set it once at process init; last writer wins.
Boundaries (deliberately NOT covered):
- A configured HTTP proxy is a trust boundary the operator owns: with Transport.Proxy set, the dial (and thus Control) sees the proxy IP, not the CONNECT target.
- SSH git (ssh://) dials via ssh.Dial, outside this HTTP transport; SSH to a metadata/RFC1918 endpoint is implausible and out of scope.
- This blocks reaching INTERNAL addresses; full egress-deny (incl. public hosts) is the consumer's NetworkPolicy job.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Blocked ¶
Blocked reports whether a resolved address must not be dialed. It is pure (no I/O) and is the unit-testable core of the guard. The standard SSRF set (loopback, RFC1918+ULA, link-local incl. 169.254.169.254, multicast, unspecified) plus the ranges and IPv6-embedded-IPv4 forms net/netip misses.
func Restrict ¶
func Restrict(on bool)
Restrict enables or disables the egress guard process-wide. The orchestrator sets it from Config.RestrictEgress; tests reset it. Safe for concurrent use, but it is a single process-level setting (last writer wins) — see the package doc on why per-render is not possible.
func WrapTransport ¶
WrapTransport installs the guard's Control hook on tr's dialer. It mirrors http.DefaultTransport's dialer settings (Timeout/KeepAlive) so that with the guard off the transport behaves identically to an unwrapped one. Idempotent and safe to call on every transport flate builds.
Types ¶
This section is empty.