Lukasz Lenart created WW-5669:
---------------------------------
Summary: 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
Fix For: 7.4.0
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)