Compare commits
1 Commits
7923146db9
...
b1c66b8227
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b1c66b8227 |
68
README.md
68
README.md
@@ -76,35 +76,25 @@ automatically via `godotenv/autoload`).
|
||||
The environment is selected by setting `WEBHOOKER_ENVIRONMENT` to `dev`
|
||||
or `prod` (default: `dev`). The setting controls several behaviors:
|
||||
|
||||
| Behavior | `dev` | `prod` |
|
||||
| -------- | ----------------------- | ---------------- |
|
||||
| CORS | Allows any origin (`*`) | Disabled (no-op) |
|
||||
| Behavior | `dev` | `prod` |
|
||||
| --------------------- | -------------------------------- | ------------------------------- |
|
||||
| CORS | Allows any origin (`*`) | Disabled (no-op) |
|
||||
| Session cookie Secure | `false` (works over plain HTTP) | `true` (requires HTTPS) |
|
||||
|
||||
The environment setting does **not** control cookie security. Both the
|
||||
session cookie and the CSRF cookie get their `Secure` flag, and the
|
||||
CSRF middleware its Origin/Referer validation mode, from the transport
|
||||
of each individual request, decided by one predicate —
|
||||
`internal/reqtls.IsTLS`. It reports TLS for a direct TLS connection
|
||||
(`r.TLS`) or for a TLS-terminating reverse proxy that reports one in
|
||||
`X-Forwarded-Proto`:
|
||||
The CSRF cookie's `Secure` flag and Origin/Referer validation mode are
|
||||
determined per-request based on the actual transport protocol, not the
|
||||
environment setting. The middleware checks `r.TLS` (direct TLS) and the
|
||||
`X-Forwarded-Proto` header (TLS-terminating reverse proxy) to decide:
|
||||
|
||||
- **Direct TLS or `X-Forwarded-Proto: https`**: Secure cookies, strict
|
||||
Origin/Referer validation.
|
||||
- **Plaintext HTTP**: Non-Secure cookies, relaxed Origin/Referer
|
||||
checks (token validation still enforced).
|
||||
|
||||
The `X-Forwarded-Proto` value is matched case-insensitively on its
|
||||
first comma-separated element, trimmed, so `HTTPS` and the appended
|
||||
chains a proxy behind another proxy emits (`https, http`) are all read
|
||||
as TLS.
|
||||
|
||||
This means both cookie security and CSRF protection work correctly in
|
||||
all deployment scenarios: behind a TLS-terminating reverse proxy, with
|
||||
direct TLS, or over plain HTTP during development — a plain-HTTP local
|
||||
run gets non-`Secure` cookies and remains usable, and a proxied
|
||||
deployment gets `Secure` ones without the operator setting anything.
|
||||
When running behind a reverse proxy, ensure it sets the
|
||||
`X-Forwarded-Proto: https` header.
|
||||
This means CSRF protection works correctly in all deployment scenarios:
|
||||
behind a TLS-terminating reverse proxy, with direct TLS, or over plain
|
||||
HTTP during development. When running behind a reverse proxy, ensure it
|
||||
sets the `X-Forwarded-Proto: https` header.
|
||||
|
||||
All other differences (log format, security headers, etc.) are
|
||||
independent of the environment setting — log format is determined by
|
||||
@@ -1863,16 +1853,13 @@ the rest. Nothing dropped is needed for the likeliest use, debugging a
|
||||
CSRF rejection. Its three inputs are the TLS decision, `Origin` and
|
||||
`Referer`; the latter two are kept, and the first is the scheme of the
|
||||
retained URL, because the SDK derives that scheme from
|
||||
`r.TLS != nil || r.Header.Get("X-Forwarded-Proto") == "https"`. That
|
||||
predicate is the SDK's own and is stricter than `internal/reqtls.IsTLS`,
|
||||
which this service now uses everywhere it decides transport: the SDK
|
||||
reports `http` for the `HTTPS` and `https, http` spellings `reqtls`
|
||||
accepts. Only a reported scheme is affected, no decision is, so it is
|
||||
left to the SDK rather than reimplemented. That is what the rewrite
|
||||
above preserves it for, and it is why dropping `X-Forwarded-Proto`
|
||||
costs nothing. The dropped provider headers (`X-GitHub-Event`,
|
||||
`X-Gitlab-Event` and the like) are real signal but are recorded
|
||||
locally on the event, and
|
||||
`r.TLS != nil || r.Header.Get("X-Forwarded-Proto") == "https"` — byte
|
||||
for byte the predicate `internal/middleware/csrf.go` uses to choose
|
||||
between the `csrf.Secure(true)` and `csrf.Secure(false)` handlers.
|
||||
That is what the rewrite above preserves it for, and it is why
|
||||
dropping `X-Forwarded-Proto` costs nothing. The dropped provider
|
||||
headers (`X-GitHub-Event`, `X-Gitlab-Event` and the like) are real
|
||||
signal but are recorded locally on the event, and
|
||||
`Sentry-Trace`/`Baggage` are already reflected in the event's trace
|
||||
context.
|
||||
|
||||
@@ -2528,9 +2515,8 @@ check, see [The login endpoint](#the-login-endpoint).
|
||||
|
||||
- **Web UI:** Cookie-based sessions using gorilla/sessions with
|
||||
encrypted cookies. Sessions are configured with HttpOnly, SameSite
|
||||
Lax, and Secure whenever the request is on TLS — the flag follows the
|
||||
request's transport, not the environment. Absolute session lifetime
|
||||
is 7 days, with a sliding idle timeout on top of it (see
|
||||
Lax, and Secure (in production). Absolute session lifetime is 7 days,
|
||||
with a sliding idle timeout on top of it (see
|
||||
[Sessions](#sessions)).
|
||||
- **API (planned):** API key authentication via `Authorization: Bearer`
|
||||
header. API keys are stored per-user with usage tracking
|
||||
@@ -2543,10 +2529,7 @@ check, see [The login endpoint](#the-login-endpoint).
|
||||
### Security
|
||||
|
||||
- Passwords hashed with Argon2id (64 MB memory cost)
|
||||
- Session cookies are HttpOnly, SameSite Lax, and Secure on any request
|
||||
that arrived over TLS (directly or through a reverse proxy reporting
|
||||
it), decided per-request by `internal/reqtls.IsTLS` rather than by the
|
||||
configured environment
|
||||
- Session cookies are HttpOnly, SameSite Lax, Secure (prod only)
|
||||
- Session regeneration on login to prevent session fixation attacks
|
||||
- Session key is a 32-byte value auto-generated on first startup and
|
||||
stored in the database
|
||||
@@ -2559,10 +2542,9 @@ check, see [The login endpoint](#the-login-endpoint).
|
||||
on all state-changing forms (cookie-based double-submit tokens with
|
||||
HMAC authentication). Applied to `/pages`, `/sources`, `/source`, and
|
||||
`/user` routes. Excluded from `/webhook` (inbound webhook POSTs) and
|
||||
`/api` (stateless API). The middleware detects TLS per-request through
|
||||
`internal/reqtls.IsTLS` — the same predicate the session cookie uses —
|
||||
to set appropriate cookie security flags and Origin/Referer validation
|
||||
mode
|
||||
`/api` (stateless API). The middleware auto-detects TLS status
|
||||
per-request (via `r.TLS` and `X-Forwarded-Proto`) to set appropriate
|
||||
cookie security flags and Origin/Referer validation mode
|
||||
- **Optional inbound signature verification** per entrypoint (GitHub
|
||||
`X-Hub-Signature-256`, GitLab `X-Gitlab-Token`). Off by default and
|
||||
off after an upgrade, so behaviour is unchanged until an operator
|
||||
|
||||
Reference in New Issue
Block a user