diff --git a/core/src/main/java/org/apache/struts2/interceptor/CoepInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/CoepInterceptor.java
index 935f568740..5f0d40ca4f 100644
--- a/core/src/main/java/org/apache/struts2/interceptor/CoepInterceptor.java
+++ b/core/src/main/java/org/apache/struts2/interceptor/CoepInterceptor.java
@@ -19,6 +19,7 @@
package org.apache.struts2.interceptor;
import org.apache.struts2.ActionInvocation;
+import org.apache.struts2.RequestUtils;
import org.apache.struts2.interceptor.AbstractInterceptor;
import org.apache.struts2.interceptor.PreResultListener;
import org.apache.struts2.util.TextParseUtil;
@@ -58,7 +59,7 @@ public String intercept(ActionInvocation invocation) throws Exception {
@Override
public void beforeResult(ActionInvocation invocation, String resultCode) {
HttpServletRequest req = invocation.getInvocationContext().getServletRequest();
- final String path = req.getContextPath();
+ final String path = RequestUtils.getUri(req);
if (exemptedPaths.contains(path)) {
// no need to add headers
diff --git a/core/src/main/java/org/apache/struts2/interceptor/CoopInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/CoopInterceptor.java
index 794064f0cc..6c39391461 100644
--- a/core/src/main/java/org/apache/struts2/interceptor/CoopInterceptor.java
+++ b/core/src/main/java/org/apache/struts2/interceptor/CoopInterceptor.java
@@ -19,6 +19,7 @@
package org.apache.struts2.interceptor;
import org.apache.struts2.ActionInvocation;
+import org.apache.struts2.RequestUtils;
import org.apache.struts2.interceptor.AbstractInterceptor;
import org.apache.struts2.interceptor.PreResultListener;
import org.apache.struts2.util.TextParseUtil;
@@ -60,7 +61,7 @@ public String intercept(ActionInvocation invocation) throws Exception {
@Override
public void beforeResult(ActionInvocation invocation, String resultCode) {
HttpServletRequest request = invocation.getInvocationContext().getServletRequest();
- String path = request.getContextPath();
+ String path = RequestUtils.getUri(request);
if (isExempted(path)) {
// no need to add headers
diff --git a/core/src/main/java/org/apache/struts2/interceptor/FetchMetadataInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/FetchMetadataInterceptor.java
index 570b1fa972..c1dc1405f5 100644
--- a/core/src/main/java/org/apache/struts2/interceptor/FetchMetadataInterceptor.java
+++ b/core/src/main/java/org/apache/struts2/interceptor/FetchMetadataInterceptor.java
@@ -20,6 +20,7 @@
import org.apache.struts2.ActionContext;
import org.apache.struts2.ActionInvocation;
+import org.apache.struts2.RequestUtils;
import org.apache.struts2.inject.Inject;
import org.apache.struts2.interceptor.AbstractInterceptor;
import org.apache.struts2.util.TextParseUtil;
@@ -67,9 +68,9 @@ public String intercept(ActionInvocation invocation) throws Exception {
addVaryHeaders(invocation);
- String contextPath = request.getContextPath();
+ String path = RequestUtils.getUri(request);
// Apply exemptions: paths/endpoints meant to be served cross-origin
- if (exemptedPaths.contains(contextPath)) {
+ if (exemptedPaths.contains(path)) {
return invocation.invoke();
}
@@ -78,7 +79,7 @@ public String intercept(ActionInvocation invocation) throws Exception {
return invocation.invoke();
}
- LOG.warn("Fetch metadata rejected cross-origin request to: {}", contextPath);
+ LOG.warn("Fetch metadata rejected cross-origin request to: {}", path);
return SC_FORBIDDEN;
}
diff --git a/core/src/test/java/org/apache/struts2/interceptor/CoepInterceptorTest.java b/core/src/test/java/org/apache/struts2/interceptor/CoepInterceptorTest.java
index 760740606e..35fb60274f 100644
--- a/core/src/test/java/org/apache/struts2/interceptor/CoepInterceptorTest.java
+++ b/core/src/test/java/org/apache/struts2/interceptor/CoepInterceptorTest.java
@@ -52,7 +52,19 @@ public void testEnforcingHeader() throws Exception {
}
public void testExemptedPath() throws Exception{
- request.setContextPath("/foo");
+ request.setServletPath("/foo");
+ interceptor.setEnforcingMode("true");
+
+ interceptor.intercept(mai);
+
+ String header = response.getHeader(COEP_ENFORCING_HEADER);
+ assertTrue("COEP applied to exempted path", Strings.isEmpty(header));
+ }
+
+ public void testExemptedPathInfo() throws Exception {
+ interceptor.setExemptedPaths("/rest/orders");
+ request.setServletPath("/rest");
+ request.setPathInfo("/orders");
interceptor.setEnforcingMode("true");
interceptor.intercept(mai);
@@ -61,6 +73,16 @@ public void testExemptedPath() throws Exception{
assertTrue("COEP applied to exempted path", Strings.isEmpty(header));
}
+ public void testHeaderSetWhenOnlyContextPathIsExempted() throws Exception {
+ request.setContextPath("/foo");
+ request.setServletPath("/index.action");
+ interceptor.setEnforcingMode("true");
+
+ interceptor.intercept(mai);
+
+ assertEquals("COEP header value is incorrect", HEADER_CONTENT, response.getHeader(COEP_ENFORCING_HEADER));
+ }
+
public void testReportingHeader() throws Exception {
interceptor.setEnforcingMode("false");
diff --git a/core/src/test/java/org/apache/struts2/interceptor/CoopInterceptorTest.java b/core/src/test/java/org/apache/struts2/interceptor/CoopInterceptorTest.java
index f6cd09341a..83096592b8 100644
--- a/core/src/test/java/org/apache/struts2/interceptor/CoopInterceptorTest.java
+++ b/core/src/test/java/org/apache/struts2/interceptor/CoopInterceptorTest.java
@@ -38,7 +38,7 @@ public class CoopInterceptorTest extends StrutsInternalTestCase {
String COOP_HEADER = "Cross-Origin-Opener-Policy";
public void testHeaderIsSetNonExemptedPath() throws Exception {
- request.setContextPath("/some");
+ request.setServletPath("/some.action");
interceptor.intercept(mai);
String header = response.getHeader(COOP_HEADER);
@@ -47,16 +47,34 @@ public void testHeaderIsSetNonExemptedPath() throws Exception {
}
public void testHeaderIsNotSetExemptedPath() throws Exception {
- request.setContextPath("/foo");
+ request.setServletPath("/foo");
+ interceptor.intercept(mai);
+
+ String header = response.getHeader(COOP_HEADER);
+ assertTrue("Coop header exists in exempted path", Strings.isEmpty(header));
+ }
+
+ public void testHeaderIsNotSetExemptedPathInfo() throws Exception {
+ interceptor.setExemptedPaths("/rest/orders");
+ request.setServletPath("/rest");
+ request.setPathInfo("/orders");
interceptor.intercept(mai);
String header = response.getHeader(COOP_HEADER);
assertTrue("Coop header exists in exempted path", Strings.isEmpty(header));
}
+ public void testHeaderIsSetWhenOnlyContextPathIsExempted() throws Exception {
+ request.setContextPath("/foo");
+ request.setServletPath("/index.action");
+ interceptor.intercept(mai);
+
+ assertEquals("Coop header is not same-origin", SAME_ORIGIN, response.getHeader(COOP_HEADER));
+ }
+
public void testChangeDefaultMode() throws Exception {
interceptor.setMode("unsafe-none");
- request.setContextPath("/some");
+ request.setServletPath("/some.action");
interceptor.intercept(mai);
String header = response.getHeader(COOP_HEADER);
@@ -65,7 +83,7 @@ public void testChangeDefaultMode() throws Exception {
}
public void testErrorNotRecognizedMode() {
- request.setContextPath("/some");
+ request.setServletPath("/some.action");
try{
interceptor.setMode("foobar");
diff --git a/core/src/test/java/org/apache/struts2/interceptor/FetchMetadataInterceptorTest.java b/core/src/test/java/org/apache/struts2/interceptor/FetchMetadataInterceptorTest.java
index 15bb244e05..65242f3b32 100644
--- a/core/src/test/java/org/apache/struts2/interceptor/FetchMetadataInterceptorTest.java
+++ b/core/src/test/java/org/apache/struts2/interceptor/FetchMetadataInterceptorTest.java
@@ -34,6 +34,7 @@
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
+import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.Collection;
@@ -151,21 +152,46 @@ public void testInvalidTopLevelNavigation() throws Exception {
public void testPathInExemptedPaths() throws Exception {
request.addHeader(SEC_FETCH_SITE_HEADER, "foo");
- request.setContextPath("/foo");
+ request.setServletPath("/foo");
assertNotEquals("Expected interceptor to accept this request", SC_FORBIDDEN, interceptor.intercept(mai));
}
public void testPathNotInExemptedPaths() throws Exception {
request.addHeader(SEC_FETCH_SITE_HEADER, "foo");
- request.setContextPath("/foobar");
+ request.setServletPath("/foobar");
+
+ assertEquals("Expected interceptor to NOT accept this request", SC_FORBIDDEN, interceptor.intercept(mai));
+ }
+
+ public void testPathInfoInExemptedPaths() throws Exception {
+ interceptor.setExemptedPaths("/rest/orders");
+ request.addHeader(SEC_FETCH_SITE_HEADER, SITE_CROSS_SITE);
+ request.setServletPath("/rest");
+ request.setPathInfo("/orders");
+
+ assertNotEquals("Expected interceptor to accept this request", SC_FORBIDDEN, interceptor.intercept(mai));
+ }
+
+ public void testContextPathInExemptedPathsDoesNotExempt() throws Exception {
+ request.addHeader(SEC_FETCH_SITE_HEADER, SITE_CROSS_SITE);
+ request.setContextPath("/foo");
+ request.setServletPath("/index.action");
assertEquals("Expected interceptor to NOT accept this request", SC_FORBIDDEN, interceptor.intercept(mai));
}
+ public void testIncludedPathInExemptedPaths() throws Exception {
+ request.addHeader(SEC_FETCH_SITE_HEADER, SITE_CROSS_SITE);
+ request.setServletPath("/outer.action");
+ request.setAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH, "/foo");
+
+ assertNotEquals("Expected interceptor to accept this request", SC_FORBIDDEN, interceptor.intercept(mai));
+ }
+
public void testVaryHeaderAcceptedReq() throws Exception {
request.addHeader(SEC_FETCH_SITE_HEADER, "foo");
- request.setContextPath("/foo");
+ request.setServletPath("/foo");
interceptor.intercept(mai);
@@ -223,11 +249,11 @@ public void testSetExemptedPathsInjectionIndirectly() throws Exception {
FetchMetadataInterceptor configuredFetchMetadataInterceptor = (FetchMetadataInterceptor) configuredFetchMetadataInterceptorMapping.getInterceptor();
request.removeHeader(SEC_FETCH_SITE_HEADER);
request.addHeader(SEC_FETCH_SITE_HEADER, "foo");
- request.setContextPath("/foo");
+ request.setServletPath("/foo");
assertEquals("Expected interceptor to NOT accept this request [/foo]", SC_FORBIDDEN, configuredFetchMetadataInterceptor.intercept(mai));
- request.setContextPath("/fetchMetadataExemptedGlobal");
+ request.setServletPath("/fetchMetadataExemptedGlobal.action");
assertNotEquals("Expected interceptor to accept this request [/fetchMetadataExemptedGlobal]", SC_FORBIDDEN, configuredFetchMetadataInterceptor.intercept(mai));
- request.setContextPath("/someOtherPath");
+ request.setServletPath("/someOtherPath.action");
assertNotEquals("Expected interceptor to accept this request [/someOtherPath]", SC_FORBIDDEN, configuredFetchMetadataInterceptor.intercept(mai));
// The test configuration in "struts-testing.xml" should also contain three actions configured differently for the "fetchMetadata" interceptor.
@@ -258,8 +284,8 @@ public void testSetExemptedPathsInjectionIndirectly() throws Exception {
configuredFetchMetadataInterceptor = (FetchMetadataInterceptor) configuredFetchMetadataInterceptorMapping.getInterceptor();
request.removeHeader(SEC_FETCH_SITE_HEADER);
request.addHeader(SEC_FETCH_SITE_HEADER, fetchMetadataExemptedActionConfig.getName());
- request.setContextPath("/" + fetchMetadataExemptedActionConfig.getName());
- assertNotEquals("Expected interceptor to accept this request [" + "/" + fetchMetadataExemptedActionConfig.getName() + "]", SC_FORBIDDEN, configuredFetchMetadataInterceptor.intercept(mai));
+ request.setServletPath("/" + fetchMetadataExemptedActionConfig.getName() + ".action");
+ assertNotEquals("Expected interceptor to accept this request [" + "/" + fetchMetadataExemptedActionConfig.getName() + ".action" + "]", SC_FORBIDDEN, configuredFetchMetadataInterceptor.intercept(mai));
// Test fetchMetadata interceptor for the "fetchMetadataNotExempted" action.
currentActionInterceptors = fetchMetadataNotExemptedActionConfig.getInterceptors();
@@ -278,8 +304,8 @@ public void testSetExemptedPathsInjectionIndirectly() throws Exception {
configuredFetchMetadataInterceptor = (FetchMetadataInterceptor) configuredFetchMetadataInterceptorMapping.getInterceptor();
request.removeHeader(SEC_FETCH_SITE_HEADER);
request.addHeader(SEC_FETCH_SITE_HEADER, fetchMetadataNotExemptedActionConfig.getName());
- request.setContextPath("/" + fetchMetadataNotExemptedActionConfig.getName());
- assertEquals("Expected interceptor to NOT accept this request [" + "/" + fetchMetadataNotExemptedActionConfig.getName() + "]", SC_FORBIDDEN, configuredFetchMetadataInterceptor.intercept(mai));
+ request.setServletPath("/" + fetchMetadataNotExemptedActionConfig.getName() + ".action");
+ assertEquals("Expected interceptor to NOT accept this request [" + "/" + fetchMetadataNotExemptedActionConfig.getName() + ".action" + "]", SC_FORBIDDEN, configuredFetchMetadataInterceptor.intercept(mai));
// Test fetchMetadata interceptor for the "fetchMetadataExemptedGlobal" action.
currentActionInterceptors = fetchMetadataExemptedGlobalActionConfig.getInterceptors();
@@ -298,8 +324,8 @@ public void testSetExemptedPathsInjectionIndirectly() throws Exception {
configuredFetchMetadataInterceptor = (FetchMetadataInterceptor) configuredFetchMetadataInterceptorMapping.getInterceptor();
request.removeHeader(SEC_FETCH_SITE_HEADER);
request.addHeader(SEC_FETCH_SITE_HEADER, fetchMetadataExemptedGlobalActionConfig.getName());
- request.setContextPath("/" + fetchMetadataExemptedGlobalActionConfig.getName());
- assertNotEquals("Expected interceptor to accept this request [" + "/" + fetchMetadataExemptedGlobalActionConfig.getName() + "]", SC_FORBIDDEN, configuredFetchMetadataInterceptor.intercept(mai));
+ request.setServletPath("/" + fetchMetadataExemptedGlobalActionConfig.getName() + ".action");
+ assertNotEquals("Expected interceptor to accept this request [" + "/" + fetchMetadataExemptedGlobalActionConfig.getName() + ".action" + "]", SC_FORBIDDEN, configuredFetchMetadataInterceptor.intercept(mai));
}
}
diff --git a/core/src/test/resources/struts-testing.xml b/core/src/test/resources/struts-testing.xml
index a43c3de7ef..e163532fb5 100644
--- a/core/src/test/resources/struts-testing.xml
+++ b/core/src/test/resources/struts-testing.xml
@@ -28,21 +28,21 @@
- /fetchMetadataExemptedGlobal,/someOtherPath
+ /fetchMetadataExemptedGlobal.action,/someOtherPath.action
- /fetchMetadataExempted
+ /fetchMetadataExempted.action
hello.jsp
- /nonMatchingActionPath
+ /nonMatchingActionPath.action
hello.jsp