Skip to content

WW-5841 fix(boot): restrict session tracking to cookies and set SameSite=Lax - #2117

Open
g0w6y wants to merge 2 commits into
apache:mainfrom
g0w6y:WW-5841-boot-session-tracking
Open

g0w6y wants to merge 2 commits into
apache:mainfrom
g0w6y:WW-5841-boot-session-tracking

Conversation

@g0w6y

@g0w6y g0w6y commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

Fixes WW-5841

Without a web.xml, the embedded Tomcat context StrutsBootServer starts defaulted to the servlet-spec COOKIE+URL session tracking modes, so a session id supplied only via ;jsessionid= in the URL (no cookie at all) was accepted and kept alive with no fresh Set-Cookie. Live-reproduced before this fix: a session established by cookie was resumed by replaying the id via the URL parameter with no Cookie header sent at all.

Restricts session tracking to COOKIE only, and the session cookie now carries SameSite=Lax. Boot is part of 7.5.0, unreleased, so this lands before anyone is exposed to it.

Verified: StrutsBootTomcatTest gains testSessionCookieHasSameSiteLax and a URL-supplied-session-id test, with a cookie-based-session control. Full boot: 52/0 failures.

…SameSite=Lax

Without a web.xml, the embedded Tomcat context defaulted to COOKIE+URL
session tracking, so a session id supplied only via ";jsessionid=" in the
URL was honoured with no fresh Set-Cookie -- a session-fixation vector.
Live-reproduced before this fix: a session established by cookie was resumed
by replaying the id via the URL parameter with no Cookie header sent at all.

Restricts session tracking to COOKIE only, and the session cookie now
carries SameSite=Lax (previously unset). Secure is deliberately not forced:
Boot opens a plain HTTP listener by default, and an operator terminating TLS
in front of it sets Secure themselves, as with any other servlet container.

Boot is part of 7.5.0 (unreleased, no production deployments yet), so this
lands before anyone is exposed to it.

Tests: StrutsBootTomcatTest gains testSessionCookieHasSameSiteLax and a
URL-supplied-session-id-is-not-honoured test, with a cookie-based-session-
still-works control. Full boot suite: 52/0 failures.

@lukaszlenart lukaszlenart left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, the change is the right one and I verified it locally: both new tests fail against main's StrutsBootServer (the URL-supplied id resumed the session, counter went to 2; no SameSite) and the whole StrutsBootTomcatTest is 16/16 green on this branch. One more effect worth stating in the ticket: on main, the first response of a Boot app already rewrites the id into every link rendered by <s:url> / <s:a> (URL=/sessionProbe.action;jsessionid=…), because Tomcat's encodeURL appends it whenever the session did not arrive by cookie and URL tracking is effective. With this branch those links are clean. That is the more visible symptom and the reason cookie-only is the right default, independent of how the id gets replayed.

Changes requested:

  1. THREAT_MODEL.md §5 lists the Boot container defaults the framework owns ("A deviation from these defaults is a Struts finding"). Please add two bullets there: session tracking is cookie-only, and the session cookie carries SameSite=Lax. Without them the new defaults are not part of the contract.
  2. The Secure paragraph in the Javadoc is not true for Boot — see the inline comment. Please drop the sentence; a struts.boot.* setting for the cookie attributes can be a separate ticket.
  3. Comments: keep them functional and short — what the code does, not the scenario it prevents. Inline comments mark the spots. Same for the test Javadoc and the // GREEN: marker.
  4. Naming: the two defaults are one decision; give them one method (inline).
  5. Commit headline: please use the repo form, e.g. WW-5841 fix(boot): restrict session tracking to cookies and set SameSite=Lax.

The branch is 4 commits behind main; none touch boot/, so no rebase is needed for this review.

Comment on lines +81 to +85
// Without a web.xml, a bare embedded context defaults to the servlet-spec
// tracking modes (COOKIE + URL): a session id supplied as ";jsessionid="
// in the URL is accepted and kept alive with no Set-Cookie, which is a
// session-fixation vector (the id can be planted via a link/Referer
// before the victim authenticates). Restrict to COOKIE only.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please reduce this to one line that says what the code does, e.g. // Tomcat defaults to COOKIE+URL when no web.xml sets <tracking-mode>; keep cookies only. The surrounding declarations carry one-line comments or none, and the scenario narration belongs in the ticket, not in the file.

Comment on lines +195 to +198
* default (treated as Lax). Secure is deliberately not forced here: Boot opens a plain
* HTTP listener by default (§5/§5a transport is the operator's), and a Secure cookie would
* simply be refused by the browser on that default deployment -- an operator who terminates
* TLS in front of Boot sets this themselves, as with any other servlet container.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This paragraph does not hold for Boot. There is no web.xml, StrutsBootApplication only exposes actions(ActionRegistry), and BootSettings carries only port, address and contextPath — an operator has no way to set Secure (or change SameSite) at all. Please drop the sentence. Making the cookie attributes configurable (struts.boot.session.cookie.secure / .sameSite) is a sensible follow-up, but a separate ticket; none of the parked Boot tickets (WW-5793…WW-5808) covers it. The remaining Javadoc can be one line: Session cookie defaults for the embedded context: SameSite=Lax; Secure is left to the operator's TLS setup.

* simply be refused by the browser on that default deployment -- an operator who terminates
* TLS in front of Boot sets this themselves, as with any other servlet container.
*/
private static void hardenSessionTracking(Context context) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hardenSessionTracking only configures the cookie processor, while the tracking-mode call sits inside the registry-attribute initializer at line 86. The two are one decision; please move the setSessionTrackingModes initializer in here (as its own addServletContainerInitializer call) and name the method for what it does, e.g. configureSessionCookies(Context) or restrictSessionTracking(Context).

Comment on lines +140 to +146
/**
* Without a web.xml, a bare embedded {@code Context}
* defaults to the servlet-spec tracking modes (COOKIE + URL), so a session id supplied
* only via {@code ;jsessionid=} in the URL (no cookie at all) is honoured and kept alive
* with no fresh {@code Set-Cookie} -- the session-fixation vector. Control: the normal
* cookie-based flow must still carry a session across requests.
*/

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test Javadoc: one functional line is enough — A session id supplied only in the URL is not resumed; the cookie-based flow still is. The default-modes explanation is now in the production comment, and the rest is narration.

Comment on lines +153 to +156
// Attacker-style request: the session id travels only in the URL, never as a cookie.
HttpResponse<String> viaUrl = get(server.baseUrl() + "/sessionProbe.action;jsessionid=" + sessionId);
// GREEN: a brand-new session is created (counter resets to 1, a fresh id is issued) --
// the URL-supplied id from the first request was not resumed.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please drop these three comment lines (the // GREEN: marker is a TDD artefact). The assertions already say it: a new session with a different id.

…nts, threat model bullets

- fold the tracking-mode initializer and the SameSite cookie processor into
  one method, restrictSessionTracking(Context)
- drop the Secure claim from the Javadoc and reduce the comments to what the
  code does
- reduce the test Javadoc and drop the narrating comment lines
- THREAT_MODEL.md section 5: add the cookie-only tracking and SameSite=Lax
  defaults to the Boot container defaults list
@g0w6y g0w6y changed the title WW-5841 Restrict Struts Boot to cookie-only session tracking and add SameSite=Lax WW-5841 fix(boot): restrict session tracking to cookies and set SameSite=Lax Nov 8, 2026
@g0w6y

g0w6y commented Nov 8, 2026

Copy link
Copy Markdown
Contributor Author

Addressed in bfc956e:

  • THREAT_MODEL.md §5: added "session tracking is cookie-only" and "the session cookie carries SameSite=Lax" to the Boot container defaults list
  • dropped the Secure claim from the Javadoc; the remaining Javadoc is two lines
  • setSessionTrackingModes now lives in the same method as the cookie processor, renamed restrictSessionTracking(Context); the registry initializer is back to its original one-liner
  • comments reduced to what the code does; test Javadocs are one line each and the // GREEN: lines are gone
  • PR title changed to the repo form

I'll update the ticket text to drop the Secure sentence and add the <s:url>/<s:a> link effect. Full boot suite: 52/0 failures; both new tests fail against main's StrutsBootServer.

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.

2 participants