Documentation
¶
Overview ¶
Package fetch retrieves a remote image on behalf of a request, under the server-side request forgery guards docs/SECURITY.md Layer 4 promises.
style.logo may name a URL, and a service that dereferences a URL chosen by an untrusted caller is a request-forgery primitive: the caller picks the destination, and the server brings a routing table, a place inside the network perimeter, and often an identity the caller does not have. The guards are therefore deny-by-default and layered:
- https only, so no caller can reach file:, gopher:, or a plaintext port;
- an exact host allowlist, empty by default, so nothing is reachable at all until an operator names it;
- resolution and address vetting done here, in front of the dialler, and a dial to the vetted address rather than to the name, so DNS cannot change between the check and the connection;
- no redirects, because following one means re-running every check above on the new target and refusing is far easier to get right;
- caps on time and on bytes, the byte cap checked twice, because a host that answers slowly or endlessly is a denial-of-service amplifier.
Errors from this package never carry the underlying network error. A dial failure names the address it dialled, and that address is precisely what these guards exist to keep from the caller.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrDisabled means the options carry no time or byte budget, which is // what an unconfigured fetcher looks like. ErrDisabled = errors.New("remote fetching is not configured") // ErrNotAllowed means the host is not on the allowlist. An empty // allowlist puts every host in this state. ErrNotAllowed = errors.New("host is not on the fetch allowlist") // ErrPrivateAddress means the host resolved to an address that is not // publicly routable — loopback, RFC 1918, link-local, and the rest. ErrPrivateAddress = errors.New("host resolves to a non-public address") // ErrUnresolved means the host has no address at all. ErrUnresolved = errors.New("host could not be resolved") // ErrTooLarge means the response is bigger than MaxBytes. ErrTooLarge = errors.New("remote image exceeds the size cap") // ErrBadStatus means the host answered with a non-2xx status, refused a // redirect, or could not be reached at all. ErrBadStatus = errors.New("remote image could not be retrieved") // ErrBadScheme means the URL is not an https URL. ErrBadScheme = errors.New("url scheme is not https") // ErrTimeout means the fetch did not finish inside Timeout. ErrTimeout = errors.New("remote image fetch timed out") // ErrNotImage means the body is not an image, whatever the host claimed // in its Content-Type. ErrNotImage = errors.New("remote resource is not an image") )
Sentinel errors. The HTTP layer maps these onto stable error codes, so a reworded message can never change what a client sees.
Functions ¶
func Enabled ¶
Enabled reports whether o could fetch anything at all, so that a caller can tell "switched off" from "switched on and misconfigured" and say so.
Types ¶
type Options ¶
type Options struct {
// Allowlist is the set of hosts that may be fetched from. Matching is
// exact on the whole host, case-insensitive, and ignores the port.
Allowlist []string
// Timeout bounds the entire operation: resolution, connection, and body.
Timeout time.Duration
// MaxBytes caps the response body.
MaxBytes int64
// contains filtered or unexported fields
}
Options bounds a fetch.
The zero value fetches nothing, which is the intended default: an empty allowlist means no host is reachable, and a zero timeout or byte cap means the feature was never configured.