[
https://issues.apache.org/jira/browse/WW-5669?focusedWorklogId=1041178&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-1041178
]
ASF GitHub Bot logged work on WW-5669:
--------------------------------------
Author: ASF GitHub Bot
Created on: 13/Sep/26 08:14
Start Date: 13/Sep/26 08:14
Worklog Time Spent: 10m
Work Description: lukaszlenart opened a new pull request, #1927:
URL: https://github.com/apache/struts/pull/1927
Fixes [WW-5669](https://issues.apache.org/jira/browse/WW-5669)
## What was wrong
`StrutsConstants.STRUTS_CSP_NONCE_SOURCE` is `struts.csp.nonce.source`, but
`default.properties` shipped the setting as `struts.csp.nonceSource`. Nothing
ever read the camel-case name, so a deployment that copied it into its own
configuration got session-scoped nonces regardless of the value.
One correction to the ticket: the setting *was* configurable all along under
the constant's name — `<constant name="struts.csp.nonce.source"
value="request"/>` reaches both `DefaultCspSettings` (setter injection via
`container.inject`) and `StrutsCspNonceReader` (constructor injection). The new
`testCanonicalKeyStoresNonceInRequest` passes on `main` unchanged; only
`testLegacyKeyStoresNonceInRequest` was red.
## Change
- `CspNonceSource.resolve(canonical, legacy)` is the single place the value
is decided: `struts.csp.nonce.source` wins, then the deprecated
`struts.csp.nonceSource` (one WARN per JVM pointing at the new name), otherwise
`SESSION`. Both consumers call it instead of each carrying its own `valueOf`.
- `StrutsCspNonceReader` gains a two-argument `@Inject` constructor with
per-parameter keys; the one-argument constructor stays and delegates.
- `DefaultCspSettings` keeps `setNonceSource` and adds a deprecated
`setLegacyNonceSource`; the value is resolved in `addCspHeaders` because setter
order is not guaranteed.
- `StrutsConstants.STRUTS_CSP_NONCE_SOURCE_LEGACY` added as
`@Deprecated(since = "7.4.0", forRemoval = true)`; `STRUTS_CSP_NONCE_SOURCE`
gets the Javadoc it was missing.
- `default.properties`: the dead line becomes a commented `#
struts.csp.nonce.source=session`. It has to be commented, not active — an
active canonical default would always win and the legacy name could never take
effect. Code default is already `SESSION` in both consumers, so nothing changes
for deployments that set neither.
## Behaviour change to call out
This is the path the ticket itself flags: a deployment carrying
`struts.csp.nonceSource=request` switches from session-scoped to request-scoped
CSP nonces on upgrade without touching its files. The WARN log and a Version
Notes / Migration Guide line are the mitigation; the docs PR (struts-site)
documents the setting for the first time and states the switch plainly.
## Tests
- `CspNonceSourceConfigTest` — container-level: canonical key, legacy key,
and the default each end with the nonce in the right place and read back by the
`CspNonceReader` bean; also asserts `default.properties` no longer binds the
legacy key.
- `CspNonceSourceTest` — precedence, blank handling, case-insensitivity,
unknown value rejected.
- `StrutsCspNonceReaderTest` — the previously untested reader paths (missing
session without creating one, missing request attribute).
`mvn test -DskipAssembly -pl core,plugins/javatemplates`: 3318 + 80 tests, 0
failures.
## Follow-ups (not in this PR)
- WW ticket at 8.0.0 to remove `STRUTS_CSP_NONCE_SOURCE_LEGACY`,
`setLegacyNonceSource` and the second constructor parameter.
- Backport to `support/struts-6-x-x` (bug exists since 6.8.0).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Issue Time Tracking
-------------------
Worklog Id: (was: 1041178)
Remaining Estimate: 0h
Time Spent: 10m
> CSP nonce source is not configurable: struts.csp.nonceSource never reaches
> the injection point
> ----------------------------------------------------------------------------------------------
>
> Key: WW-5669
> URL: https://issues.apache.org/jira/browse/WW-5669
> Project: Struts 2
> Issue Type: Bug
> Reporter: Lukasz Lenart
> Priority: Major
> Fix For: 7.4.0
>
> Time Spent: 10m
> Remaining Estimate: 0h
>
> h2. Problem
> The constant {{StrutsConstants.STRUTS_CSP_NONCE_SOURCE}} declares the key
> {{struts.csp.nonce.source}}, but {{default.properties}} defines the setting
> as {{struts.csp.nonceSource}}. The two names never meet, so the injection
> point is never satisfied and the setting has no effect.
> Because both injection points are declared {{required = false}}, nothing
> fails at startup. The nonce source silently falls back to {{SESSION}}
> regardless of what is configured.
> h2. Evidence
> A search of the whole repository for {{struts.csp.nonce}} returns exactly
> three hits:
> * {{core/src/main/resources/org/apache/struts2/default.properties}} —
> {{struts.csp.nonceSource=session}}
> * {{core/src/main/java/org/apache/struts2/StrutsConstants.java}} —
> {{STRUTS_CSP_NONCE_READER = "struts.csp.nonce.reader"}}
> * {{core/src/main/java/org/apache/struts2/StrutsConstants.java}} —
> {{STRUTS_CSP_NONCE_SOURCE = "struts.csp.nonce.source"}}
> Nothing defines a constant named {{struts.csp.nonce.source}}, and nothing
> reads {{struts.csp.nonceSource}}.
> The key is consumed in two places, both asking for the name that is never
> defined:
> * {{StrutsCspNonceReader}} — constructor annotated {{@Inject(value =
> StrutsConstants.STRUTS_CSP_NONCE_SOURCE, required = false)}}; a blank value
> takes the {{CspNonceSource.SESSION}} branch
> * {{DefaultCspSettings#setNonceSource}} — same annotation; the field is
> already initialised to {{CspNonceSource.SESSION}}
> By contrast {{STRUTS_CSP_NONCE_READER}} is wired correctly, at
> {{StrutsBeanSelectionProvider:466}}, and is not affected.
> h2. Effect
> Setting {{struts.csp.nonceSource=request}} does nothing. The nonce is always
> stored in and read from the session, so applications that deliberately chose
> the request-scoped nonce — typically stateless or clustered deployments —
> silently get session-scoped behaviour instead.
> This is a functional defect rather than a security one: the ignored
> configuration leaves the safer of the two modes in force.
> h2. Affected versions
> Both names were introduced together in commit {{1b43b53c6}} under WW-5504, so
> the setting has never worked. First released in 6.8.0; still present on
> {{main}} and on {{support/struts-6-x-x}}.
> h2. Suggested fix
> Make the two names agree, and add the test coverage whose absence let this
> through — there is currently no test referencing the nonce source at all.
> Which name should win is worth deciding deliberately:
> * Renaming the property to {{struts.csp.nonce.source}} matches the constant
> and the neighbouring {{struts.csp.nonce.reader}}, and cannot change behaviour
> for anyone. Users who already set the camelCase name keep getting {{SESSION}}
> until they rename it.
> * Renaming the constant to {{struts.csp.nonceSource}} avoids asking users to
> change anything, but it silently *activates* a setting that has always been
> inert. Any deployment currently carrying {{struts.csp.nonceSource=request}}
> would switch from session-scoped to request-scoped nonces on upgrade, without
> touching its configuration.
> The first option is the safer default. Supporting both names, with the
> camelCase form deprecated, would avoid the migration entirely if that is
> preferred.
> Documentation on struts.apache.org should be checked and corrected to
> whichever name is chosen.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)