This is an automated email from the ASF dual-hosted git repository.
lukaszlenart pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/struts.git
The following commit(s) were added to refs/heads/main by this push:
new 4af86aea1 WW-5669 Honour struts.csp.nonceSource alongside
struts.csp.nonce.source (#1927)
4af86aea1 is described below
commit 4af86aea17d74326a77e88e7933d0251a2fab5f4
Author: Lukasz Lenart <[email protected]>
AuthorDate: Sun Sep 13 10:39:09 2026 +0200
WW-5669 Honour struts.csp.nonceSource alongside struts.csp.nonce.source
(#1927)
* WW-5669 fix(core): honour struts.csp.nonceSource alongside
struts.csp.nonce.source
default.properties shipped the CSP nonce-source setting as
struts.csp.nonceSource while both @Inject points asked for
StrutsConstants.STRUTS_CSP_NONCE_SOURCE (struts.csp.nonce.source), so the
camel-case name was never read. The dotted name did work when set in
struts.xml; only deployments that copied the default.properties name were
stuck on session-scoped nonces.
CspNonceSource.resolve(canonical, legacy) now decides the value in one
place: the dotted name wins, the camel-case name is honoured as a
deprecated fallback with a one-time WARN, otherwise SESSION. Both
consumers call it. The default.properties line becomes a commented
example under the dotted name so the legacy fallback is never satisfied
by the framework's own defaults.
A deployment carrying struts.csp.nonceSource=request switches to
request-scoped nonces on upgrade without a config change; this goes in
the Version Notes.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
* WW-5669 test(core): use assertNull for the no-session check
Sonar flags assertTrue(x == null) in favour of assertNull.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
---------
Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
---
.../java/org/apache/struts2/StrutsConstants.java | 12 +++
.../struts2/interceptor/csp/CspNonceSource.java | 33 +++++++-
.../interceptor/csp/DefaultCspSettings.java | 26 +++---
.../interceptor/csp/StrutsCspNonceReader.java | 16 ++--
.../org/apache/struts2/default.properties | 2 +-
.../interceptor/csp/CspNonceSourceConfigTest.java | 93 ++++++++++++++++++++++
.../interceptor/csp/CspNonceSourceTest.java | 54 +++++++++++++
.../interceptor/csp/StrutsCspNonceReaderTest.java | 90 +++++++++++++++++++++
.../resources/struts-csp-nonce-source-legacy.xml} | 20 +++--
.../resources/struts-csp-nonce-source.xml} | 20 +++--
10 files changed, 331 insertions(+), 35 deletions(-)
diff --git a/core/src/main/java/org/apache/struts2/StrutsConstants.java
b/core/src/main/java/org/apache/struts2/StrutsConstants.java
index ffc135f0b..3d3fef328 100644
--- a/core/src/main/java/org/apache/struts2/StrutsConstants.java
+++ b/core/src/main/java/org/apache/struts2/StrutsConstants.java
@@ -834,8 +834,20 @@ public final class StrutsConstants {
* @since 6.8.0
*/
public static final String STRUTS_CSP_NONCE_READER =
"struts.csp.nonce.reader";
+
+ /**
+ * See {@link org.apache.struts2.interceptor.csp.CspNonceSource}
+ *
+ * @since 6.8.0
+ */
public static final String STRUTS_CSP_NONCE_SOURCE =
"struts.csp.nonce.source";
+ /**
+ * @deprecated since 7.4.0, use {@link #STRUTS_CSP_NONCE_SOURCE} instead
+ */
+ @Deprecated(since = "7.4.0", forRemoval = true)
+ public static final String STRUTS_CSP_NONCE_SOURCE_LEGACY =
"struts.csp.nonceSource";
+
/**
* See {@link org.apache.struts2.action.CspReportAction}
*
diff --git
a/core/src/main/java/org/apache/struts2/interceptor/csp/CspNonceSource.java
b/core/src/main/java/org/apache/struts2/interceptor/csp/CspNonceSource.java
index cc34e3581..4af2a8582 100644
--- a/core/src/main/java/org/apache/struts2/interceptor/csp/CspNonceSource.java
+++ b/core/src/main/java/org/apache/struts2/interceptor/csp/CspNonceSource.java
@@ -18,10 +18,41 @@
*/
package org.apache.struts2.interceptor.csp;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.struts2.StrutsConstants;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
/**
* Source of the nonce value
*/
public enum CspNonceSource {
REQUEST,
- SESSION
+ SESSION;
+
+ private static final Logger LOG =
LogManager.getLogger(CspNonceSource.class);
+ private static final AtomicBoolean LEGACY_WARNED = new AtomicBoolean();
+
+ /**
+ * Resolves the configured source: {@link
StrutsConstants#STRUTS_CSP_NONCE_SOURCE} wins, then the deprecated
+ * {@link StrutsConstants#STRUTS_CSP_NONCE_SOURCE_LEGACY}, otherwise
{@link #SESSION}.
+ *
+ * @since 7.4.0
+ */
+ @SuppressWarnings("removal")
+ public static CspNonceSource resolve(String canonical, String legacy) {
+ if (StringUtils.isNotBlank(canonical)) {
+ return valueOf(canonical.trim().toUpperCase());
+ }
+ if (StringUtils.isNotBlank(legacy)) {
+ if (LEGACY_WARNED.compareAndSet(false, true)) {
+ LOG.warn("Constant '{}' is deprecated, use '{}' instead",
+ StrutsConstants.STRUTS_CSP_NONCE_SOURCE_LEGACY,
StrutsConstants.STRUTS_CSP_NONCE_SOURCE);
+ }
+ return valueOf(legacy.trim().toUpperCase());
+ }
+ return SESSION;
+ }
}
diff --git
a/core/src/main/java/org/apache/struts2/interceptor/csp/DefaultCspSettings.java
b/core/src/main/java/org/apache/struts2/interceptor/csp/DefaultCspSettings.java
index 0343006f2..973bbb1a4 100644
---
a/core/src/main/java/org/apache/struts2/interceptor/csp/DefaultCspSettings.java
+++
b/core/src/main/java/org/apache/struts2/interceptor/csp/DefaultCspSettings.java
@@ -21,7 +21,6 @@ package org.apache.struts2.interceptor.csp;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.struts2.inject.Inject;
-import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.StrutsConstants;
@@ -50,7 +49,8 @@ public class DefaultCspSettings implements CspSettings {
private final SecureRandom sRand = new SecureRandom();
- private CspNonceSource nonceSource = CspNonceSource.SESSION;
+ private String nonceSource;
+ private String legacyNonceSource;
protected String reportUri;
protected String reportTo;
@@ -59,21 +59,27 @@ public class DefaultCspSettings implements CspSettings {
@Inject(value = StrutsConstants.STRUTS_CSP_NONCE_SOURCE, required = false)
public void setNonceSource(String nonceSource) {
- if (StringUtils.isBlank(nonceSource)) {
- this.nonceSource = CspNonceSource.SESSION;
- } else {
- this.nonceSource =
CspNonceSource.valueOf(nonceSource.toUpperCase());
- }
+ this.nonceSource = nonceSource;
+ }
+
+ /**
+ * @deprecated since 7.4.0, use {@link #setNonceSource(String)} instead
+ */
+ @Deprecated(since = "7.4.0", forRemoval = true)
+ @Inject(value = StrutsConstants.STRUTS_CSP_NONCE_SOURCE_LEGACY, required =
false)
+ public void setLegacyNonceSource(String legacyNonceSource) {
+ this.legacyNonceSource = legacyNonceSource;
}
@Override
public void addCspHeaders(HttpServletRequest request, HttpServletResponse
response) {
- if (this.nonceSource == CspNonceSource.SESSION) {
+ CspNonceSource source = CspNonceSource.resolve(nonceSource,
legacyNonceSource);
+ if (source == CspNonceSource.SESSION) {
addCspHeadersWithSession(request, response);
- } else if (this.nonceSource == CspNonceSource.REQUEST) {
+ } else if (source == CspNonceSource.REQUEST) {
addCspHeadersWithRequest(request, response);
} else {
- LOG.warn("Unknown nonce source: {}, ignoring CSP settings",
nonceSource);
+ LOG.warn("Unknown nonce source: {}, ignoring CSP settings",
source);
}
}
diff --git
a/core/src/main/java/org/apache/struts2/interceptor/csp/StrutsCspNonceReader.java
b/core/src/main/java/org/apache/struts2/interceptor/csp/StrutsCspNonceReader.java
index d857b8df9..07b800adb 100644
---
a/core/src/main/java/org/apache/struts2/interceptor/csp/StrutsCspNonceReader.java
+++
b/core/src/main/java/org/apache/struts2/interceptor/csp/StrutsCspNonceReader.java
@@ -20,7 +20,6 @@ package org.apache.struts2.interceptor.csp;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
-import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.StrutsConstants;
@@ -37,13 +36,16 @@ public class StrutsCspNonceReader implements CspNonceReader
{
private final CspNonceSource nonceSource;
- @Inject(value = StrutsConstants.STRUTS_CSP_NONCE_SOURCE, required = false)
public StrutsCspNonceReader(String source) {
- if (StringUtils.isBlank(source)) {
- this.nonceSource = CspNonceSource.SESSION;
- } else {
- this.nonceSource = CspNonceSource.valueOf(source.toUpperCase());
- }
+ this(source, null);
+ }
+
+ @Inject
+ public StrutsCspNonceReader(
+ @Inject(value = StrutsConstants.STRUTS_CSP_NONCE_SOURCE, required
= false) String source,
+ @Inject(value = StrutsConstants.STRUTS_CSP_NONCE_SOURCE_LEGACY,
required = false) String legacySource
+ ) {
+ this.nonceSource = CspNonceSource.resolve(source, legacySource);
}
@Override
diff --git a/core/src/main/resources/org/apache/struts2/default.properties
b/core/src/main/resources/org/apache/struts2/default.properties
index a35001534..dfaf09a4e 100644
--- a/core/src/main/resources/org/apache/struts2/default.properties
+++ b/core/src/main/resources/org/apache/struts2/default.properties
@@ -368,7 +368,7 @@ struts.url.encoder=strutsUrlEncoder
struts.url.decoder=strutsUrlDecoder
### Defines source to read nonce value from, possible values are: request,
session
-struts.csp.nonceSource=session
+# struts.csp.nonce.source=session
### Maximum size, in characters, of a CSP violation report accepted by
CspReportAction
### Reports larger than this are discarded. Values outside 1..1048576 are
ignored.
diff --git
a/core/src/test/java/org/apache/struts2/interceptor/csp/CspNonceSourceConfigTest.java
b/core/src/test/java/org/apache/struts2/interceptor/csp/CspNonceSourceConfigTest.java
new file mode 100644
index 000000000..22eca826b
--- /dev/null
+++
b/core/src/test/java/org/apache/struts2/interceptor/csp/CspNonceSourceConfigTest.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.struts2.interceptor.csp;
+
+import org.apache.struts2.ActionContext;
+import org.apache.struts2.StrutsConstants;
+import org.apache.struts2.StrutsInternalTestCase;
+import org.apache.struts2.dispatcher.SessionMap;
+import org.apache.struts2.interceptor.csp.CspNonceReader.NonceValue;
+import org.apache.struts2.mock.MockActionInvocation;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+
+/**
+ * Proves the nonce source setting reaches both consumers through the
container,
+ * under the canonical key and under the legacy camel-case key.
+ */
+public class CspNonceSourceConfigTest extends StrutsInternalTestCase {
+
+ private final MockHttpServletRequest request = new
MockHttpServletRequest();
+ private final MockHttpServletResponse response = new
MockHttpServletResponse();
+
+ public void testCanonicalKeyStoresNonceInRequest() throws Exception {
+ initDispatcherWithConfigs("struts-default.xml,
struts-csp-nonce-source.xml");
+
+ assertNonceStoredInRequestAndReadBack();
+ }
+
+ public void testLegacyKeyStoresNonceInRequest() throws Exception {
+ initDispatcherWithConfigs("struts-default.xml,
struts-csp-nonce-source-legacy.xml");
+
+ assertNonceStoredInRequestAndReadBack();
+ }
+
+ @SuppressWarnings("removal")
+ public void testDefaultStoresNonceInSession() throws Exception {
+ initDispatcherWithConfigs("struts-default.xml");
+ assertNull("default.properties must not bind the deprecated key",
+ container.getInstance(String.class,
StrutsConstants.STRUTS_CSP_NONCE_SOURCE_LEGACY));
+
+ intercept();
+
+ assertNull("nonce must not be a request attribute by default",
request.getAttribute("nonce"));
+ assertNotNull("nonce must be in the session by default",
request.getSession().getAttribute("nonce"));
+ NonceValue read =
container.getInstance(CspNonceReader.class).readNonceValue(ActionContext.getContext().getValueStack());
+ assertEquals(CspNonceSource.SESSION, read.getSource());
+ assertEquals(request.getSession().getAttribute("nonce"),
read.getNonceValue());
+ }
+
+ private void assertNonceStoredInRequestAndReadBack() throws Exception {
+ intercept();
+
+ Object nonce = request.getAttribute("nonce");
+ assertNotNull("nonce must be a request attribute", nonce);
+ assertNull("nonce must not leak into the session",
request.getSession().getAttribute("nonce"));
+
+ NonceValue read =
container.getInstance(CspNonceReader.class).readNonceValue(ActionContext.getContext().getValueStack());
+ assertEquals(CspNonceSource.REQUEST, read.getSource());
+ assertEquals(nonce, read.getNonceValue());
+ }
+
+ private void intercept() throws Exception {
+ request.getSession(true);
+ ActionContext context = ActionContext.getContext()
+ .withContainer(container)
+ .withServletRequest(request)
+ .withServletResponse(response)
+ .withSession(new SessionMap(request))
+ .bind();
+ MockActionInvocation mai = new MockActionInvocation();
+ mai.setInvocationContext(context);
+
+ CspInterceptor interceptor = new CspInterceptor();
+ container.inject(interceptor);
+ interceptor.intercept(mai);
+ }
+}
diff --git
a/core/src/test/java/org/apache/struts2/interceptor/csp/CspNonceSourceTest.java
b/core/src/test/java/org/apache/struts2/interceptor/csp/CspNonceSourceTest.java
new file mode 100644
index 000000000..2a6e23974
--- /dev/null
+++
b/core/src/test/java/org/apache/struts2/interceptor/csp/CspNonceSourceTest.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.struts2.interceptor.csp;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class CspNonceSourceTest {
+
+ @Test
+ public void canonicalValueWins() {
+ assertEquals(CspNonceSource.REQUEST, CspNonceSource.resolve("request",
"session"));
+ }
+
+ @Test
+ public void legacyValueAppliesWhenCanonicalIsBlank() {
+ assertEquals(CspNonceSource.REQUEST, CspNonceSource.resolve(" ",
"request"));
+ assertEquals(CspNonceSource.REQUEST, CspNonceSource.resolve(null,
"request"));
+ }
+
+ @Test
+ public void defaultsToSessionWhenNothingIsSet() {
+ assertEquals(CspNonceSource.SESSION, CspNonceSource.resolve(null,
null));
+ assertEquals(CspNonceSource.SESSION, CspNonceSource.resolve("", " "));
+ }
+
+ @Test
+ public void valueIsCaseInsensitive() {
+ assertEquals(CspNonceSource.REQUEST, CspNonceSource.resolve("Request",
null));
+ assertEquals(CspNonceSource.SESSION, CspNonceSource.resolve(null,
"SESSION"));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void unknownValueIsRejected() {
+ CspNonceSource.resolve("cookie", null);
+ }
+}
diff --git
a/core/src/test/java/org/apache/struts2/interceptor/csp/StrutsCspNonceReaderTest.java
b/core/src/test/java/org/apache/struts2/interceptor/csp/StrutsCspNonceReaderTest.java
new file mode 100644
index 000000000..488bb62e3
--- /dev/null
+++
b/core/src/test/java/org/apache/struts2/interceptor/csp/StrutsCspNonceReaderTest.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.struts2.interceptor.csp;
+
+import org.apache.struts2.ActionContext;
+import org.apache.struts2.interceptor.csp.CspNonceReader.NonceValue;
+import org.apache.struts2.util.ValueStack;
+import org.junit.Test;
+import org.springframework.mock.web.MockHttpServletRequest;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class StrutsCspNonceReaderTest {
+
+ private final MockHttpServletRequest request = new
MockHttpServletRequest();
+
+ @Test
+ public void readsNonceFromSession() {
+ request.getSession(true).setAttribute("nonce", "abc");
+
+ NonceValue value = new
StrutsCspNonceReader("session").readNonceValue(stack());
+
+ assertEquals(CspNonceSource.SESSION, value.getSource());
+ assertEquals("abc", value.getNonceValue());
+ }
+
+ @Test
+ public void reportsMissingSessionWithoutCreatingOne() {
+ NonceValue value = new
StrutsCspNonceReader("session").readNonceValue(stack());
+
+ assertEquals(CspNonceSource.SESSION, value.getSource());
+ assertFalse(value.isNonceValueSet());
+ assertNull("reader must not start a session",
request.getSession(false));
+ }
+
+ @Test
+ public void readsNonceFromRequestAttribute() {
+ request.setAttribute("nonce", "xyz");
+
+ NonceValue value = new
StrutsCspNonceReader("request").readNonceValue(stack());
+
+ assertEquals(CspNonceSource.REQUEST, value.getSource());
+ assertEquals("xyz", value.getNonceValue());
+ }
+
+ @Test
+ public void reportsMissingRequestAttribute() {
+ NonceValue value = new
StrutsCspNonceReader("request").readNonceValue(stack());
+
+ assertEquals(CspNonceSource.REQUEST, value.getSource());
+ assertFalse(value.isNonceValueSet());
+ }
+
+ @Test
+ public void legacyKeyFallsBackWhenCanonicalIsUnset() {
+ request.setAttribute("nonce", "xyz");
+
+ NonceValue value = new StrutsCspNonceReader(null,
"request").readNonceValue(stack());
+
+ assertEquals(CspNonceSource.REQUEST, value.getSource());
+ assertEquals("xyz", value.getNonceValue());
+ }
+
+ private ValueStack stack() {
+ ActionContext context = ActionContext.of().withServletRequest(request);
+ ValueStack stack = mock(ValueStack.class);
+ when(stack.getActionContext()).thenReturn(context);
+ return stack;
+ }
+}
diff --git
a/core/src/main/java/org/apache/struts2/interceptor/csp/CspNonceSource.java
b/core/src/test/resources/struts-csp-nonce-source-legacy.xml
similarity index 69%
copy from
core/src/main/java/org/apache/struts2/interceptor/csp/CspNonceSource.java
copy to core/src/test/resources/struts-csp-nonce-source-legacy.xml
index cc34e3581..d194c1f3b 100644
--- a/core/src/main/java/org/apache/struts2/interceptor/csp/CspNonceSource.java
+++ b/core/src/test/resources/struts-csp-nonce-source-legacy.xml
@@ -1,3 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -16,12 +18,14 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.struts2.interceptor.csp;
+-->
+<!DOCTYPE struts PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 6.0//EN"
+ "https://struts.apache.org/dtds/struts-6.0.dtd">
+<struts>
+ <constant name="struts.csp.nonceSource" value="request"/>
-/**
- * Source of the nonce value
- */
-public enum CspNonceSource {
- REQUEST,
- SESSION
-}
+ <package name="default" extends="struts-default">
+ </package>
+
+</struts>
diff --git
a/core/src/main/java/org/apache/struts2/interceptor/csp/CspNonceSource.java
b/core/src/test/resources/struts-csp-nonce-source.xml
similarity index 69%
copy from
core/src/main/java/org/apache/struts2/interceptor/csp/CspNonceSource.java
copy to core/src/test/resources/struts-csp-nonce-source.xml
index cc34e3581..6c6b842c7 100644
--- a/core/src/main/java/org/apache/struts2/interceptor/csp/CspNonceSource.java
+++ b/core/src/test/resources/struts-csp-nonce-source.xml
@@ -1,3 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -16,12 +18,14 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.struts2.interceptor.csp;
+-->
+<!DOCTYPE struts PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 6.0//EN"
+ "https://struts.apache.org/dtds/struts-6.0.dtd">
+<struts>
+ <constant name="struts.csp.nonce.source" value="request"/>
-/**
- * Source of the nonce value
- */
-public enum CspNonceSource {
- REQUEST,
- SESSION
-}
+ <package name="default" extends="struts-default">
+ </package>
+
+</struts>