Repository navigation
Conversation
Behind a TLS-terminating reverse proxy the session and OAuth cookies were marked Secure only when the proxy sent exactly "X-Forwarded-Proto: https". "Forwarded: proto=https" (RFC 7239), "X-Forwarded-Ssl: on", an upper-case value or a chained "https, http" all produced a cookie without Secure, and Google login then failed because browsers reject SameSite=None without Secure. isHTTPS now also accepts these forms, reading only the client-facing hop of a chained header. It can only turn Secure on, so no existing deployment changes behaviour. The reverse-proxy note in config.md says which header the proxy must send and that HSTS belongs at the proxy.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description of the Change
Problem
When a reverse proxy terminates TLS and forwards to PentAGI over plain HTTP (
SERVER_USE_SSL=false),isHTTPS()inbackend/pkg/server/services/cookies.gomarks the session and OAuth cookiesSecureonly if the request carries exactlyX-Forwarded-Proto: https. Other common forms produce a cookie withoutSecure:Forwarded: proto=https(RFC 7239)X-Forwarded-Ssl: onX-Forwarded-Proto: HTTPS(upper case)X-Forwarded-Proto: https, http(appended by chained proxies)In those setups the session cookie can be sent over plain HTTP. Google login also fails, because its state/nonce cookies are
SameSite=None(auth.go:371-376), and browsers reject aSameSite=Nonecookie that is notSecure.The stock
docker-compose.ymlis not affected, because there the server terminates TLS itself (SERVER_USE_SSL=trueplus the certificate generated byentrypoint.sh).Solution
isHTTPS()also acceptsX-Forwarded-Ssl: onandproto=httpsfromForwarded, compares case-insensitively, and reads only the client-facing (first) element of a chainedX-Forwarded-Proto/Forwarded.Secureon, so no existing deployment changes behaviour. The headers stay honoured regardless ofTRUSTED_PROXIES, asX-Forwarded-Protois today: a forged header can only mark the sender's own cookieSecure.backend/docs/config.md: a short note next toTRUSTED_PROXIESon which header the proxy must send (with the nginx line) and that HSTS belongs at the proxy.I deliberately did not derive
SecurefromPUBLIC_URLor force it on. That would break login for plain-HTTP deployments that kept the.env.exampledefaultPUBLIC_URL=https://localhost:8443. If you'd like an opt-inCOOKIE_SECUREswitch or HSTS emission, I'm happy to send that as a follow-up.Type of Change
Areas Affected
Testing and Verification
Test Configuration
Test Steps
go test -count=1 -run TestCookies_ -v ./pkg/server/services/cookies.gorestored in a throwaway copy of the tree.go vet ./pkg/server/services/,go test -count=1 -race ./pkg/server/...andgolangci-lint run ./pkg/server/services/Test Results
The new
TestCookies_SessionOptions_ReadsTheSchemeFromEveryCommonProxyHeaderdrives the realAuthLoginhandler viahttptest. It has 13 rows, 6 of them negative (http,http, https,X-Forwarded-Ssl: off,proto=httpsonly on an inner hop,Forwardedwithoutproto, no headers).TestCookies_*tests still pass.cookies.go, exactly the 5 newly recognised forms fail and the negatives pass:go vetis clean.go test -race ./pkg/server/...passes for all packages.golangci-lint run ./pkg/server/services/(v2.12.2 on Go 1.26.5, as pinned in CI) reports 0 issues.Security Considerations
This is hardening. The cookie
Secureflag is now set in more proxy configurations and never unset in any configuration. There are no new dependencies, permissions or config fields.Performance Impact
Negligible: a few string operations per cookie write.
Documentation Updates
Deployment Notes
None. Operators whose proxy sends none of these headers still need to add one; the new doc note says how.
Checklist
Code Quality
go fmtandgo vet(for Go code)Security
Compatibility
Documentation