Apache Struts2 Core Cross-Origin Protection Exemption Miskeyed to a Deployment-Wide Path
Full Disclosuremailing list archivesFrom: Daniel Owens via Fulldisclosure <fulld 2026-11-2 06:10:50 Author: seclists.org(查看原文) 阅读量:6 收藏

fulldisclosure logo

Full Disclosure mailing list archives


From: Daniel Owens via Fulldisclosure <fulldisclosure () seclists org>
Date: Thu, 29 Oct 2026 13:34:55 +0000

Description
Apache Struts2 Core version 7.4.0 and below's `FetchMetadataInterceptor`, `CoepInterceptor`, and `CoopInterceptor` each 
compare their `exemptedPaths` configuration -- a per-interceptor-reference, administrator-supplied set of paths 
intended to exempt specific actions from the corresponding cross-origin protection -- against 
`HttpServletRequest.getContextPath()`.  `getContextPath()` is fixed for the entire deployed web application and is 
identical on every request regardless of which action or servlet path is being invoked, so it cannot distinguish one 
action from another.

Impact
An administrator who configures `exemptedPaths` expecting it to exempt a specific action or endpoint, instead is 
configuring a value that can never match the real, single, deployment-wide context path returned on genuine traffic, so 
the per-action exemption never takes effect and the intended protection remains enforced everywhere, including on the 
endpoint the administrator believed was exempted.  More importantly, if an administrator's configured exemption string 
happens to coincide with the application's actual context path -- such as if an administrator assumes that the 
parameter takes a path-like value and supplies the deployment's own root or an equally-named segment -- 
`exemptedPaths.contains(contextPath)` evaluates to `true` on every single request to the application and Fetch Metadata 
request filtering, the Cross-Origin Embedder Policy (COEP) header, and the Cross-Origin Opener Policy (COOP) header are 
all silently disabled for the entire deployment (well beyond the endpoint that the administrator intended to exempt), 
disabling the protections that such code is intended to provide across the entire application.

Examples
Sample Code
All three interceptors, each in `struts2-core`, apply the identical pattern -- a per-action `exemptedPaths` set 
compared against the deployment-wide `getContextPath()` rather than against anything that actually varies per action.

```java
    private final Set<String> exemptedPaths = new HashSet<>();
    private final ResourceIsolationPolicy resourceIsolationPolicy = new StrutsResourceIsolationPolicy();

    @Inject(required = false)
    public void setExemptedPaths(String paths) {
        this.exemptedPaths.addAll(TextParseUtil.commaDelimitedStringToSet(paths));
    }

    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        ActionContext context = invocation.getInvocationContext();
        HttpServletRequest request = context.getServletRequest();

        addVaryHeaders(invocation);

        String contextPath = request.getContextPath();
        // Apply exemptions: paths/endpoints meant to be served cross-origin
        if (exemptedPaths.contains(contextPath)) {
            return invocation.invoke();
        }
```
Code snippet from `struts2-core`'s core/src/main/java/org/apache/struts2/interceptor/FetchMetadataInterceptor.java, 
lines 55-73

```java
    @Override
    public void beforeResult(ActionInvocation invocation, String resultCode) {
        HttpServletRequest req = invocation.getInvocationContext().getServletRequest();
        final String path = req.getContextPath();

        if (exemptedPaths.contains(path)) {
```
Snippet from `struts2-core`'s core/src/main/java/org/apache/struts2/interceptor/CoepInterceptor.java, lines 59-63

```java
    @Override
    public void beforeResult(ActionInvocation invocation, String resultCode) {
        HttpServletRequest request = invocation.getInvocationContext().getServletRequest();
        String path = request.getContextPath();

        if (isExempted(path)) {
```
Code from `struts2-core`'s core/src/main/java/org/apache/struts2/interceptor/CoopInterceptor.java, lines 61-65
_______________________________________________
Sent through the Full Disclosure mailing list
https://nmap.org/mailman/listinfo/fulldisclosure
Web Archives & RSS: https://seclists.org/fulldisclosure/


Current thread:

  • Apache Struts2 Core Cross-Origin Protection Exemption Miskeyed to a Deployment-Wide Path Daniel Owens via Fulldisclosure (Nov 01)

文章来源: https://seclists.org/fulldisclosure/2026/Nov/3
如有侵权请联系:admin#unsafe.sh