This is an automated email from the ASF dual-hosted git repository.

lukaszlenart pushed a commit to branch fix/WW-5501-exclude-s7
in repository https://gitbox.apache.org/repos/asf/struts.git

commit 3d3b0761727d22ba9eef27a660703aa2ba1eeff6
Author: Lukasz Lenart <lukaszlen...@apache.org>
AuthorDate: Fri Jan 10 07:45:57 2025 +0100

    WW-5501 Only exclude malicious file names
---
 .../multipart/AbstractMultiPartRequest.java        | 26 ++++++++++++++--------
 .../multipart/JakartaMultiPartRequest.java         |  6 ++---
 .../multipart/JakartaStreamMultiPartRequest.java   |  4 ++--
 .../ActionFileUploadInterceptorTest.java           |  2 --
 4 files changed, 22 insertions(+), 16 deletions(-)

diff --git 
a/core/src/main/java/org/apache/struts2/dispatcher/multipart/AbstractMultiPartRequest.java
 
b/core/src/main/java/org/apache/struts2/dispatcher/multipart/AbstractMultiPartRequest.java
index aeace3120..b6b7f2682 100644
--- 
a/core/src/main/java/org/apache/struts2/dispatcher/multipart/AbstractMultiPartRequest.java
+++ 
b/core/src/main/java/org/apache/struts2/dispatcher/multipart/AbstractMultiPartRequest.java
@@ -19,6 +19,8 @@
 package org.apache.struts2.dispatcher.multipart;
 
 import org.apache.struts2.inject.Inject;
+import org.apache.struts2.security.DefaultExcludedPatternsChecker;
+import org.apache.struts2.security.ExcludedPatternsChecker;
 import jakarta.servlet.http.HttpServletRequest;
 import org.apache.commons.fileupload2.core.FileUploadByteCountLimitException;
 import org.apache.commons.fileupload2.core.FileUploadContentTypeException;
@@ -31,7 +33,6 @@ import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.apache.struts2.StrutsConstants;
 import org.apache.struts2.dispatcher.LocalizedMessage;
-import org.apache.struts2.security.NotExcludedAcceptedPatternsChecker;
 
 import java.io.IOException;
 import java.nio.charset.Charset;
@@ -53,6 +54,8 @@ public abstract class AbstractMultiPartRequest implements 
MultiPartRequest {
 
     private static final Logger LOG = 
LogManager.getLogger(AbstractMultiPartRequest.class);
 
+    private static final String EXCLUDED_FILE_PATTERN = 
".*[<>&\"'|;\\\\/?*:]+.*|.*\\.\\..*";
+
     /**
      * Defines the internal buffer size used during streaming operations.
      */
@@ -108,7 +111,13 @@ public abstract class AbstractMultiPartRequest implements 
MultiPartRequest {
      */
     protected Map<String, List<String>> parameters = new HashMap<>();
 
-    protected NotExcludedAcceptedPatternsChecker patternsChecker;
+
+    private final ExcludedPatternsChecker patternsChecker;
+
+    public AbstractMultiPartRequest() {
+        patternsChecker = new DefaultExcludedPatternsChecker();
+        ((DefaultExcludedPatternsChecker) 
patternsChecker).setAdditionalExcludePatterns(EXCLUDED_FILE_PATTERN);
+    }
 
     /**
      * @param bufferSize Sets the buffer size to be used.
@@ -183,11 +192,6 @@ public abstract class AbstractMultiPartRequest implements 
MultiPartRequest {
         return Charset.forName(charsetStr);
     }
 
-    @Inject
-    public void 
setNotExcludedAllowedPatternsChecker(NotExcludedAcceptedPatternsChecker 
patternsChecker) {
-        this.patternsChecker = patternsChecker;
-    }
-
     /**
      * Creates an instance of {@link JakartaServletDiskFileUpload} used by the 
parser to extract uploaded files
      *
@@ -425,8 +429,12 @@ public abstract class AbstractMultiPartRequest implements 
MultiPartRequest {
         }
     }
 
-    protected boolean isAccepted(String fileName) {
-        return patternsChecker.isAllowed(fileName).isAllowed();
+    /**
+     * @param fileName file name to check
+     * @return true if the file name is excluded
+     */
+    protected boolean isExcluded(String fileName) {
+        return patternsChecker.isExcluded(fileName).isExcluded();
     }
 
 }
diff --git 
a/core/src/main/java/org/apache/struts2/dispatcher/multipart/JakartaMultiPartRequest.java
 
b/core/src/main/java/org/apache/struts2/dispatcher/multipart/JakartaMultiPartRequest.java
index b36e6e2f8..737ba23f8 100644
--- 
a/core/src/main/java/org/apache/struts2/dispatcher/multipart/JakartaMultiPartRequest.java
+++ 
b/core/src/main/java/org/apache/struts2/dispatcher/multipart/JakartaMultiPartRequest.java
@@ -79,7 +79,7 @@ public class JakartaMultiPartRequest extends 
AbstractMultiPartRequest {
     protected void processNormalFormField(DiskFileItem item, Charset charset) 
throws IOException {
         LOG.debug("Item: {} is a normal form field", item.getName());
 
-        if (!isAccepted(item.getFieldName())) {
+        if (isExcluded(item.getFieldName())) {
             LOG.warn(() -> "Form field [%s] is 
rejected!".formatted(normalizeSpace(item.getFieldName())));
             return;
         }
@@ -105,12 +105,12 @@ public class JakartaMultiPartRequest extends 
AbstractMultiPartRequest {
     }
 
     protected void processFileField(DiskFileItem item) {
-        if (!isAccepted(item.getName())) {
+        if (isExcluded(item.getName())) {
             LOG.warn(() -> "File name [%s] is not 
accepted".formatted(normalizeSpace(item.getName())));
             return;
         }
 
-        if (!isAccepted(item.getFieldName())) {
+        if (isExcluded(item.getFieldName())) {
             LOG.warn(() -> "Field name [%s] is not 
accepted".formatted(normalizeSpace(item.getFieldName())));
             return;
         }
diff --git 
a/core/src/main/java/org/apache/struts2/dispatcher/multipart/JakartaStreamMultiPartRequest.java
 
b/core/src/main/java/org/apache/struts2/dispatcher/multipart/JakartaStreamMultiPartRequest.java
index 7fb44f21f..2d2b67c68 100644
--- 
a/core/src/main/java/org/apache/struts2/dispatcher/multipart/JakartaStreamMultiPartRequest.java
+++ 
b/core/src/main/java/org/apache/struts2/dispatcher/multipart/JakartaStreamMultiPartRequest.java
@@ -116,7 +116,7 @@ public class JakartaStreamMultiPartRequest extends 
AbstractMultiPartRequest {
         String fieldName = fileItemInput.getFieldName();
         String fieldValue = readStream(fileItemInput.getInputStream());
 
-        if (!isAccepted(fieldName)) {
+        if (isExcluded(fieldName)) {
             LOG.warn(() -> "Form field [%s] is 
rejected!".formatted(normalizeSpace(fieldName)));
             return;
         }
@@ -198,7 +198,7 @@ public class JakartaStreamMultiPartRequest extends 
AbstractMultiPartRequest {
             return;
         }
 
-        if (!isAccepted(fileItemInput.getName())) {
+        if (isExcluded(fileItemInput.getName())) {
             LOG.warn(() -> "File field [%s] 
rejected".formatted(normalizeSpace(fileItemInput.getName())));
             return;
         }
diff --git 
a/core/src/test/java/org/apache/struts2/interceptor/ActionFileUploadInterceptorTest.java
 
b/core/src/test/java/org/apache/struts2/interceptor/ActionFileUploadInterceptorTest.java
index 9aca62717..84f6c12db 100644
--- 
a/core/src/test/java/org/apache/struts2/interceptor/ActionFileUploadInterceptorTest.java
+++ 
b/core/src/test/java/org/apache/struts2/interceptor/ActionFileUploadInterceptorTest.java
@@ -610,8 +610,6 @@ public class ActionFileUploadInterceptorTest extends 
StrutsInternalTestCase {
         jak.setMaxFiles(String.valueOf(maxfiles));
         jak.setMaxStringLength(String.valueOf(maxStringLength));
         jak.setDefaultEncoding(StandardCharsets.UTF_8.name());
-        DefaultNotExcludedAcceptedPatternsChecker patternsChecker = 
container.inject(DefaultNotExcludedAcceptedPatternsChecker.class);
-        jak.setNotExcludedAllowedPatternsChecker(patternsChecker);
 
         return new MultiPartRequestWrapper(jak, request, 
tempDir.getAbsolutePath(), new DefaultLocaleProvider());
     }

Reply via email to