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)

Reply via email to