Skip to content

session persistence: always set cookie Path to / - #9950

Merged
zhaohuabing merged 4 commits into
envoyproxy:mainfrom
zhaohuabing:session-cookie-path-root
Sep 8, 2026
Merged

zhaohuabing merged 4 commits into
envoyproxy:mainfrom
zhaohuabing:session-cookie-path-root

Conversation

@zhaohuabing

@zhaohuabing zhaohuabing commented Sep 4, 2026 •

Copy link
Copy Markdown
Member

The session persistence cookie was scoped to the matched HTTPRoute path, so it was never sent back when the client-visible path differs from the path Envoy matches, e.g. when an edge proxy rewrites / to /foo/bar before the request reaches the gateway.

The GEP-1619 spec was changed in kubernetes-sigs/gateway-api#5046: the cookie Path now defaults to / instead of being derived from the route match, and a new cookieConfig.path field lets users override it. This PR follows the new default. The explicit path field is not in Gateway API 1.6.2 yet, so wiring the override is left for the 1.7 bump.

This is a breaking change: the cookie is now sent to every route on the same host, so HTTPRoute rules on the same host that enable cookie-based session persistence must use distinct sessionName values. Rules sharing a sessionName used to get separate cookies because their paths differed; they now overwrite each other's cookie. The release note and the session persistence task doc call this out.

Related to #8580

@zhaohuabing
zhaohuabing requested a review from a team as a code owner September 4, 2026 09:35
@netlify

netlify Bot commented Sep 4, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for cerulean-figolla-1f9435 ready!

Name Link
🔨 Latest commit e5cf08e
🔍 Latest deploy log https://app.netlify.com/projects/cerulean-figolla-1f9435/deploys/6a9fa35427c49a000858a9c4
😎 Deploy Preview https://deploy-preview-9950--cerulean-figolla-1f9435.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@codecov

codecov Bot commented Sep 4, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 81.31%. Comparing base (8cff2db) to head (e5cf08e).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #9950      +/-   ##
==========================================
- Coverage   81.33%   81.31%   -0.02%     
==========================================
  Files         264      264              
  Lines       40977    40963      -14     
==========================================
- Hits        33327    33309      -18     
- Misses       7649     7653       +4     
  Partials        1        1              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@zhaohuabing
zhaohuabing force-pushed the session-cookie-path-root branch from 7254f18 to c0b65f4 Compare September 4, 2026 10:05
@zhaohuabing

Copy link
Copy Markdown
Member Author

/retest

arkodg
arkodg previously approved these changes Sep 7, 2026
Comment thread release-notes/current/breaking_changes/8580-session-persistence-cookie-path.md Outdated
zirain
zirain previously approved these changes Sep 8, 2026
@zhaohuabing
zhaohuabing dismissed stale reviews from zirain and arkodg via 96f030d September 8, 2026 05:55
zhaohuabing and others added 4 commits September 7, 2026 22:55
The session persistence cookie was scoped to the matched HTTPRoute path,
so it was never sent back when the client-visible path differs from the
path Envoy matches, e.g. when an edge proxy rewrites / to /foo/bar before
the request reaches the gateway. GEP-1619 now defaults the cookie Path to
/ instead of deriving it from the route match, so follow that guidance.

Fixes envoyproxy#8580

Signed-off-by: Huabing (Robin) Zhao <zhaohuabing@gmail.com>
Signed-off-by: Huabing (Robin) Zhao <huabing@tetrate.io>
Signed-off-by: Huabing (Robin) Zhao <zhaohuabing@gmail.com>
Signed-off-by: Huabing (Robin) Zhao <huabing@tetrate.io>
… unset

Signed-off-by: Huabing (Robin) Zhao <zhaohuabing@gmail.com>
Signed-off-by: Huabing (Robin) Zhao <huabing@tetrate.io>
Signed-off-by: Huabing (Robin) Zhao <huabing@tetrate.io>
@zhaohuabing
zhaohuabing force-pushed the session-cookie-path-root branch from 96f030d to e5cf08e Compare September 8, 2026 05:55
@zhaohuabing
zhaohuabing merged commit 27cbfab into envoyproxy:main Sep 8, 2026
76 of 78 checks passed
@zhaohuabing
zhaohuabing deleted the session-cookie-path-root branch September 8, 2026 09:54
gianniskt pushed a commit to gianniskt/envoy-gateway that referenced this pull request Sep 8, 2026
* session persistence: always set cookie Path to /

The session persistence cookie was scoped to the matched HTTPRoute path,
so it was never sent back when the client-visible path differs from the
path Envoy matches, e.g. when an edge proxy rewrites / to /foo/bar before
the request reaches the gateway. GEP-1619 now defaults the cookie Path to
/ instead of deriving it from the route match, so follow that guidance.

Fixes envoyproxy#8580

Signed-off-by: Huabing (Robin) Zhao <zhaohuabing@gmail.com>
Signed-off-by: Huabing (Robin) Zhao <huabing@tetrate.io>

* release note: breaking change, warn about shared sessionName

Signed-off-by: Huabing (Robin) Zhao <zhaohuabing@gmail.com>
Signed-off-by: Huabing (Robin) Zhao <huabing@tetrate.io>

* docs: note that EG generates a unique cookie name when sessionName is unset

Signed-off-by: Huabing (Robin) Zhao <zhaohuabing@gmail.com>
Signed-off-by: Huabing (Robin) Zhao <huabing@tetrate.io>

* summarize release note

Signed-off-by: Huabing (Robin) Zhao <huabing@tetrate.io>

---------

Signed-off-by: Huabing (Robin) Zhao <zhaohuabing@gmail.com>
Signed-off-by: Huabing (Robin) Zhao <huabing@tetrate.io>
Signed-off-by: gianniskt <gianniskt@gmail.com>
gianniskt pushed a commit to gianniskt/envoy-gateway that referenced this pull request Sep 8, 2026
* session persistence: always set cookie Path to /

The session persistence cookie was scoped to the matched HTTPRoute path,
so it was never sent back when the client-visible path differs from the
path Envoy matches, e.g. when an edge proxy rewrites / to /foo/bar before
the request reaches the gateway. GEP-1619 now defaults the cookie Path to
/ instead of deriving it from the route match, so follow that guidance.

Fixes envoyproxy#8580

Signed-off-by: Huabing (Robin) Zhao <zhaohuabing@gmail.com>
Signed-off-by: Huabing (Robin) Zhao <huabing@tetrate.io>

* release note: breaking change, warn about shared sessionName

Signed-off-by: Huabing (Robin) Zhao <zhaohuabing@gmail.com>
Signed-off-by: Huabing (Robin) Zhao <huabing@tetrate.io>

* docs: note that EG generates a unique cookie name when sessionName is unset

Signed-off-by: Huabing (Robin) Zhao <zhaohuabing@gmail.com>
Signed-off-by: Huabing (Robin) Zhao <huabing@tetrate.io>

* summarize release note

Signed-off-by: Huabing (Robin) Zhao <huabing@tetrate.io>

---------

Signed-off-by: Huabing (Robin) Zhao <zhaohuabing@gmail.com>
Signed-off-by: Huabing (Robin) Zhao <huabing@tetrate.io>
Signed-off-by: gianniskt <gianniskt@gmail.com>
zhaohuabing added a commit that referenced this pull request Sep 22, 2026
* api: add HTTP/3 advertised port to ClientTrafficPolicy (#9855)

* api: add HTTP/3 advertised port to ClientTrafficPolicy

Signed-off-by: Haseeb Nazir <36381672+iamhaseebn@users.noreply.github.com>

* docs: use PR number for release note

Signed-off-by: Haseeb Nazir <36381672+iamhaseebn@users.noreply.github.com>

* fix: preserve listener-specific HTTP/3 advertised ports

Signed-off-by: Haseeb Nazir <36381672+iamhaseebn@users.noreply.github.com>

* test: cover HTTP/3 advertised port in e2e

Signed-off-by: Haseeb Nazir <36381672+iamhaseebn@users.noreply.github.com>

---------

Signed-off-by: Haseeb Nazir <36381672+iamhaseebn@users.noreply.github.com>
Signed-off-by: gianniskt <gianniskt@gmail.com>

* api: add claimPath to SecurityPolicy JWT ClaimToHeader

Envoy's jwt_authn filter supports claim_path for extracting claims via
explicit path segments, including top-level claims whose names contain
dots (e.g. URI-namespaced OIDC claims such as
https://example.com/claims/tenant_name). SecurityPolicy currently only
exposes claim-to-header extraction via the dot-split claim field, so
such claims can never be addressed.

Add an optional claimPath []string field to ClaimToHeader, mutually
exclusive with claim, that maps 1:1 to Envoy's claim_path path
segments. Existing claim-based configs are unaffected.

Refs #9964

Signed-off-by: gianniskt <gianniskt@gmail.com>

* generated necessary manifest with make

Signed-off-by: gianniskt <gianniskt@gmail.com>

* feat: add codeVerifierTTL to the OIDC SecurityPolicy (#9645)

csrfTokenTTL already bounds the lifetime of the nonce cookie Envoy sets when
it starts an authorization flow, but there was no equivalent for the PKCE code
verifier cookie, which stayed pinned at the oauth2 filter's 600s default.

Both cookies are only consumed on the callback endpoint, so a flow that is
started but never completed leaves them in the browser until they expire.
Exposing code_verifier_token_expires_in lets an operator bound that window for
the code verifier the same way csrfTokenTTL already does for the nonce.

Signed-off-by: Huabing (Robin) Zhao <zhaohuabing@gmail.com>
Signed-off-by: gianniskt <gianniskt@gmail.com>

* [tools] make e2e-mac and conformance-mac (#9859)

Signed-off-by: Arko Dasgupta <arkodg@gmail.com>
Signed-off-by: gianniskt <gianniskt@gmail.com>

* session persistence: always set cookie Path to / (#9950)

* session persistence: always set cookie Path to /

The session persistence cookie was scoped to the matched HTTPRoute path,
so it was never sent back when the client-visible path differs from the
path Envoy matches, e.g. when an edge proxy rewrites / to /foo/bar before
the request reaches the gateway. GEP-1619 now defaults the cookie Path to
/ instead of deriving it from the route match, so follow that guidance.

Fixes #8580

Signed-off-by: Huabing (Robin) Zhao <zhaohuabing@gmail.com>
Signed-off-by: Huabing (Robin) Zhao <huabing@tetrate.io>

* release note: breaking change, warn about shared sessionName

Signed-off-by: Huabing (Robin) Zhao <zhaohuabing@gmail.com>
Signed-off-by: Huabing (Robin) Zhao <huabing@tetrate.io>

* docs: note that EG generates a unique cookie name when sessionName is unset

Signed-off-by: Huabing (Robin) Zhao <zhaohuabing@gmail.com>
Signed-off-by: Huabing (Robin) Zhao <huabing@tetrate.io>

* summarize release note

Signed-off-by: Huabing (Robin) Zhao <huabing@tetrate.io>

---------

Signed-off-by: Huabing (Robin) Zhao <zhaohuabing@gmail.com>
Signed-off-by: Huabing (Robin) Zhao <huabing@tetrate.io>
Signed-off-by: gianniskt <gianniskt@gmail.com>

* generated envoy-gateway-crds.out.yaml

Signed-off-by: gianniskt <gianniskt@gmail.com>

* docs: add release-note fragment for JWT claimPath

Signed-off-by: gianniskt <gianniskt@gmail.com>

* test: add CEL admission and e2e coverage for JWT claimPath

Adds CEL-validation admission tests exercising the generated CRD schema
and CEL rule for claimPath (claim-only, claimPath-only, both set, neither
set, and empty path segments), and an e2e conformance test that signs a
real JWT containing a dotted, URI-namespaced claim and verifies Envoy
extracts it via claim_path into the configured request header, using
route-based header matching (as the existing JWT e2e tests do).

Signed-off-by: gianniskt <gianniskt@gmail.com>

* test(e2e): sign claimPath JWT with a locally-embedded key

The previous token was signed with examples/kubernetes/jwt/key.json, but
the currently-published envoyproxy/gateway-static-file-server image only
serves the key backing v1Token/v2Token (whose private key isn't checked
into the repo), so the new token failed verification against the served
JWKS in e2e.

Switch jwt-claim-path.yaml to a dedicated localJWKS (inline), following
the existing jwt-local-jwks-inline.yaml pattern, using a fresh keypair
generated solely for this test (private key discarded, only the public
JWK is committed). Re-signed dottedClaimToken with that key and verified
the signature independently with openssl. This removes the dependency on
the shared static-file-server image entirely.

Signed-off-by: gianniskt <gianniskt@gmail.com>

---------

Signed-off-by: Haseeb Nazir <36381672+iamhaseebn@users.noreply.github.com>
Signed-off-by: gianniskt <gianniskt@gmail.com>
Signed-off-by: Huabing (Robin) Zhao <zhaohuabing@gmail.com>
Signed-off-by: Arko Dasgupta <arkodg@gmail.com>
Signed-off-by: Huabing (Robin) Zhao <huabing@tetrate.io>
Co-authored-by: Haseeb Nazir <36381672+iamhaseebn@users.noreply.github.com>
Co-authored-by: Huabing (Robin) Zhao <zhaohuabing@gmail.com>
Co-authored-by: Arko Dasgupta <arkodg@users.noreply.github.com>
Co-authored-by: zirain <zirain2009@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants