diff --git a/core/src/main/java/org/apache/struts2/interceptor/csp/CspSettings.java b/core/src/main/java/org/apache/struts2/interceptor/csp/CspSettings.java
index 7e8de5c706..585c650960 100644
--- a/core/src/main/java/org/apache/struts2/interceptor/csp/CspSettings.java
+++ b/core/src/main/java/org/apache/struts2/interceptor/csp/CspSettings.java
@@ -35,6 +35,7 @@ public interface CspSettings {
String CSP_REPORT_HEADER = "Content-Security-Policy-Report-Only";
String OBJECT_SRC = "object-src";
String SCRIPT_SRC = "script-src";
+ String STYLE_SRC = "style-src";
String BASE_URI = "base-uri";
String REPORT_URI = "report-uri";
String REPORT_TO = "report-to";
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 0343006f21..00945850cd 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
@@ -110,6 +110,10 @@ protected String createPolicyFormat(String nonceValue) {
.append(format(" 'nonce-%s' ", nonceValue))
.append(format("'%s' ", STRICT_DYNAMIC))
.append(format("%s %s; ", HTTP, HTTPS))
+ .append(STYLE_SRC)
+ .append(format(" 'nonce-%s' ", nonceValue))
+ .append(format("'%s' ", STRICT_DYNAMIC))
+ .append(format("%s %s; ", HTTP, HTTPS))
.append(BASE_URI)
.append(format(" '%s'; ", NONE));
diff --git a/core/src/main/java/org/apache/struts2/result/ServletRedirectResult.java b/core/src/main/java/org/apache/struts2/result/ServletRedirectResult.java
index 7bc8ab616d..9a0dcd52da 100644
--- a/core/src/main/java/org/apache/struts2/result/ServletRedirectResult.java
+++ b/core/src/main/java/org/apache/struts2/result/ServletRedirectResult.java
@@ -33,6 +33,8 @@
import org.apache.struts2.dispatcher.mapper.ActionMapping;
import org.apache.struts2.url.QueryStringBuilder;
+import org.apache.commons.text.StringEscapeUtils;
+
import java.io.IOException;
import java.io.Serial;
import java.net.MalformedURLException;
@@ -248,7 +250,7 @@ protected void sendRedirect(HttpServletResponse response, String finalLocation)
response.setStatus(statusCode);
response.setHeader("Location", finalLocation);
try {
- response.getWriter().write(finalLocation);
+ response.getWriter().write(StringEscapeUtils.escapeHtml4(finalLocation));
} finally {
response.getWriter().close();
}
diff --git a/core/src/main/resources/template/html5/radiomap.ftl b/core/src/main/resources/template/html5/radiomap.ftl
index 5826fe47ff..105e7e86dd 100644
--- a/core/src/main/resources/template/html5/radiomap.ftl
+++ b/core/src/main/resources/template/html5/radiomap.ftl
@@ -64,7 +64,7 @@ file for it's localized value. This is then used as a label -->
#if>
<#if attributes.name?has_content>
- name="${attributes.name?no_esc}"<#rt/>
+ name="${attributes.name?replace('"', '"')?no_esc}"<#rt/>
#if>
id="${attributes.id}${itemKeyStr?replace(".", "_")}"<#rt/>
<#if tag.contains(attributes.nameValue!'', itemKey)>
diff --git a/core/src/main/resources/template/simple/radiomap.ftl b/core/src/main/resources/template/simple/radiomap.ftl
index 524bc7f7f7..0fed41e019 100644
--- a/core/src/main/resources/template/simple/radiomap.ftl
+++ b/core/src/main/resources/template/simple/radiomap.ftl
@@ -63,7 +63,7 @@
#if>
<#if attributes.name?has_content>
- name="${attributes.name?no_esc}"<#rt/>
+ name="${attributes.name?replace('"', '"')?no_esc}"<#rt/>
#if>
id="${attributes.id}${itemKeyStr?replace(".", "_")}"<#rt/>
<#if tag.contains(attributes.nameValue!'', itemKey)>
diff --git a/core/src/test/java/org/apache/struts2/interceptor/CspInterceptorTest.java b/core/src/test/java/org/apache/struts2/interceptor/CspInterceptorTest.java
index 3a9f83348d..794aadf27f 100644
--- a/core/src/test/java/org/apache/struts2/interceptor/CspInterceptorTest.java
+++ b/core/src/test/java/org/apache/struts2/interceptor/CspInterceptorTest.java
@@ -240,23 +240,26 @@ public void checkHeader(String reportUri, boolean enforcingMode) {
public void checkHeader(String reportUri, String reportTo, boolean enforcingMode) {
String expectedCspHeader;
if (Strings.isEmpty(reportUri)) {
- expectedCspHeader = String.format("%s '%s'; %s 'nonce-%s' '%s' %s %s; %s '%s'; ",
+ expectedCspHeader = String.format("%s '%s'; %s 'nonce-%s' '%s' %s %s; %s 'nonce-%s' '%s' %s %s; %s '%s'; ",
CspSettings.OBJECT_SRC, CspSettings.NONE,
CspSettings.SCRIPT_SRC, session.getAttribute("nonce"), CspSettings.STRICT_DYNAMIC, CspSettings.HTTP, CspSettings.HTTPS,
+ CspSettings.STYLE_SRC, session.getAttribute("nonce"), CspSettings.STRICT_DYNAMIC, CspSettings.HTTP, CspSettings.HTTPS,
CspSettings.BASE_URI, CspSettings.NONE
);
} else {
if (Strings.isEmpty(reportTo)) {
- expectedCspHeader = String.format("%s '%s'; %s 'nonce-%s' '%s' %s %s; %s '%s'; %s %s; ",
+ expectedCspHeader = String.format("%s '%s'; %s 'nonce-%s' '%s' %s %s; %s 'nonce-%s' '%s' %s %s; %s '%s'; %s %s; ",
CspSettings.OBJECT_SRC, CspSettings.NONE,
CspSettings.SCRIPT_SRC, session.getAttribute("nonce"), CspSettings.STRICT_DYNAMIC, CspSettings.HTTP, CspSettings.HTTPS,
+ CspSettings.STYLE_SRC, session.getAttribute("nonce"), CspSettings.STRICT_DYNAMIC, CspSettings.HTTP, CspSettings.HTTPS,
CspSettings.BASE_URI, CspSettings.NONE,
CspSettings.REPORT_URI, reportUri
);
} else {
- expectedCspHeader = String.format("%s '%s'; %s 'nonce-%s' '%s' %s %s; %s '%s'; %s %s; %s %s; ",
+ expectedCspHeader = String.format("%s '%s'; %s 'nonce-%s' '%s' %s %s; %s 'nonce-%s' '%s' %s %s; %s '%s'; %s %s; %s %s; ",
CspSettings.OBJECT_SRC, CspSettings.NONE,
CspSettings.SCRIPT_SRC, session.getAttribute("nonce"), CspSettings.STRICT_DYNAMIC, CspSettings.HTTP, CspSettings.HTTPS,
+ CspSettings.STYLE_SRC, session.getAttribute("nonce"), CspSettings.STRICT_DYNAMIC, CspSettings.HTTP, CspSettings.HTTPS,
CspSettings.BASE_URI, CspSettings.NONE,
CspSettings.REPORT_URI, reportUri,
CspSettings.REPORT_TO, reportTo