fix: detect TLS per-request in CSRF middleware to fix login
All checks were successful
check / check (push) Successful in 2m0s
All checks were successful
check / check (push) Successful in 2m0s
The CSRF middleware previously tied its PlaintextHTTPRequest wrapping and cookie Secure flag to the IsDev() environment check. This meant production mode always assumed HTTPS, which broke login in two common deployment scenarios: 1. Production behind a TLS-terminating reverse proxy: gorilla/csrf assumed HTTPS but r.TLS was nil, causing Origin/Referer scheme mismatches and 'referer not supplied' errors. 2. Production over direct HTTP (testing/development with prod config): the Secure cookie flag prevented the browser from sending the CSRF cookie back on POST, causing 'CSRF token invalid' errors. The fix detects the actual transport protocol per-request using r.TLS (direct TLS) and the X-Forwarded-Proto header (reverse proxy). Two gorilla/csrf instances are maintained — one with Secure cookies for TLS and one without for plaintext — since the csrf.Secure option is set at creation time. Both instances share the same signing key, so cookies are interchangeable between them. Behavior after fix: - Direct TLS: Secure cookies, strict Origin/Referer checks - Behind TLS proxy (X-Forwarded-Proto: https): same as direct TLS - Plaintext HTTP: non-Secure cookies, relaxed Origin/Referer checks (csrf.PlaintextHTTPRequest), token validation still enforced Closes #53
This commit is contained in:
19
README.md
19
README.md
@@ -62,6 +62,21 @@ or `prod` (default: `dev`). The setting controls several behaviors:
|
||||
| CORS | Allows any origin (`*`) | Disabled (no-op) |
|
||||
| Session cookie Secure | `false` (works over plain HTTP) | `true` (requires HTTPS) |
|
||||
|
||||
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).
|
||||
|
||||
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
|
||||
TTY detection, and security headers are always applied.
|
||||
@@ -841,7 +856,9 @@ Additionally, form endpoints (`/pages`, `/sources`, `/source/*`) apply a
|
||||
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)
|
||||
`/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
|
||||
- **SSRF prevention** for HTTP delivery targets: private/reserved IP
|
||||
ranges (RFC 1918, loopback, link-local, cloud metadata) are blocked
|
||||
both at target creation time (URL validation) and at delivery time
|
||||
|
||||
Reference in New Issue
Block a user