Documentation
¶
Overview ¶
Package gitcorsproxy is a small, sovereign reverse proxy that lets a browser reach git smart-HTTP remotes that do not send CORS headers.
A browser-hosted git client (for example the go-tex playground's wasm git-worker, github.com/go-tex/go-tex.github.io playground/internal/browsergit) speaks the git smart-HTTP protocol over the Fetch API. GitHub and most ghcr-style hosts answer that protocol correctly but send no Access-Control-Allow-Origin, so the browser blocks the response. This proxy sits in front: the browser talks to it same-origin-friendly (with an explicit allowed-origin list), and the proxy streams the git bytes to and from the real upstream, adding the CORS headers the browser needs.
Route ¶
The proxy accepts exactly the git smart-HTTP endpoint shape, with the upstream host carried as the first path segment:
GET /<host>/<owner>/<repo>.git/info/refs?service=git-upload-pack GET /<host>/<owner>/<repo>.git/info/refs?service=git-receive-pack POST /<host>/<owner>/<repo>.git/git-upload-pack POST /<host>/<owner>/<repo>.git/git-receive-pack
and forwards them to https://<host>/<owner>/<repo>.git/… . The <owner>/<repo> portion may contain nested groups (Forgejo/GitLab subgroups). Any path that does not match this shape is rejected 400.
Security posture ¶
- CORS is scoped to a CONFIGURED explicit origin list. It is never "*", because the client's Authorization header (a PAT) is forwarded upstream; a wildcard origin with credential-bearing requests would let any web page drive the user's token.
- An upstream-host ALLOWLIST is the primary SSRF control: only the exact hosts an operator lists (github.com, the sovereign Forgejo host, …) are reachable. Everything else is 403.
- As defence in depth the target host is resolved and every IP is checked against a private/loopback/link-local/cloud-metadata denylist (ported from the loom server's checkRemoteIP), so an allowlisted host that resolves into an internal range is still refused.
- The Authorization header is forwarded upstream but NEVER logged. Nothing in this package writes a token, a header dump, or a request body to the logger.
The proxy stores nothing: it is a pure auth-passthrough. The browser holds the user's PAT and sends it on each request; the proxy relays it and forgets it.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Config ¶
type Config struct {
// AllowedOrigins is the explicit list of browser origins permitted to read
// proxied responses, e.g. []string{"https://go-tex.github.io"}. It must be
// non-empty and must not contain "*" — see the package doc for why a
// wildcard is refused when Authorization is forwarded.
AllowedOrigins []string
// UpstreamHosts is the allowlist of upstream hosts the proxy will reach,
// matched case-insensitively against the first path segment exactly as it
// appears in the URL (including any :port), e.g.
// []string{"github.com", "sources.example.net"}. It must be non-empty.
UpstreamHosts []string
// UpstreamScheme is the scheme used to reach the upstream. It defaults to
// "https" and should stay that way in production; tests set "http" to reach
// a local httptest server.
UpstreamScheme string
// Logger receives request/decision logs. Defaults to slog.Default(). The
// proxy never logs the Authorization header, any token, or a request body.
Logger *slog.Logger
// Transport performs the upstream round-trip. Defaults to an SSRF-agnostic
// http.Transport with compression passthrough (DisableCompression) so git
// bytes are relayed verbatim. Primarily an injection seam for tests; the
// SSRF decision itself lives in the ServeHTTP pre-flight, not here.
Transport http.RoundTripper
// LookupIP resolves a host to its IPs for the SSRF pre-flight. Defaults to
// net.LookupIP. Injectable for tests.
LookupIP func(host string) ([]net.IP, error)
}
Config configures a Proxy. AllowedOrigins and UpstreamHosts are required; the rest have production-safe defaults.
type Proxy ¶
type Proxy struct {
// contains filtered or unexported fields
}
Proxy is an http.Handler implementing the CORS git smart-HTTP proxy. It is safe for concurrent use.
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
gitcorsproxy
command
Command gitcorsproxy runs the sovereign CORS git smart-HTTP proxy.
|
Command gitcorsproxy runs the sovereign CORS git smart-HTTP proxy. |
