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

lukaszlenart pushed a commit to branch WW-4858-json-parameter-filtering
in repository https://gitbox.apache.org/repos/asf/struts.git

commit 77c096080fbec94fefda31edc7d0d066cacef80d
Author: Lukasz Lenart <[email protected]>
AuthorDate: Wed Jul 8 20:35:57 2026 +0200

    WW-4858 feat(json): enforce param-name max length on JSON population
    
    Co-Authored-By: Claude Opus 4.8 <[email protected]>
---
 .../java/org/apache/struts2/json/JSONInterceptor.java    | 14 ++++++++++++++
 .../org/apache/struts2/json/JSONInterceptorTest.java     | 16 ++++++++++++++++
 2 files changed, 30 insertions(+)

diff --git 
a/plugins/json/src/main/java/org/apache/struts2/json/JSONInterceptor.java 
b/plugins/json/src/main/java/org/apache/struts2/json/JSONInterceptor.java
index a4d084e0a..c508fee86 100644
--- a/plugins/json/src/main/java/org/apache/struts2/json/JSONInterceptor.java
+++ b/plugins/json/src/main/java/org/apache/struts2/json/JSONInterceptor.java
@@ -83,6 +83,7 @@ public class JSONInterceptor extends AbstractInterceptor {
     private int maxLength = 2_097_152;  // 2MB
     private int maxStringLength = JSONReader.DEFAULT_MAX_STRING_LENGTH;
     private int maxKeyLength = JSONReader.DEFAULT_MAX_KEY_LENGTH;
+    private int paramNameMaxLength = 100;
 
     @SuppressWarnings("unchecked")
     public String intercept(ActionInvocation invocation) throws Exception {
@@ -258,6 +259,10 @@ public class JSONInterceptor extends AbstractInterceptor {
 
     @SuppressWarnings("rawtypes")
     private boolean isAcceptableKey(String fullPath, Object target, Object 
action) {
+        if (fullPath.length() > paramNameMaxLength) {
+            LOG.warn("JSON body parameter [{}] is too long, allowed length is 
[{}]; rejected", fullPath, paramNameMaxLength);
+            return false;
+        }
         if (excludedPatterns != null && 
excludedPatterns.isExcluded(fullPath).isExcluded()) {
             LOG.warn("JSON body parameter [{}] matches an excluded pattern; 
rejected", fullPath);
             return false;
@@ -674,6 +679,15 @@ public class JSONInterceptor extends AbstractInterceptor {
         this.acceptedPatterns = acceptedPatterns;
     }
 
+    /**
+     * If the dotted JSON key path exceeds the configured maximum length it 
will not be accepted.
+     *
+     * @param paramNameMaxLength maximum length of a JSON key path
+     */
+    public void setParamNameMaxLength(int paramNameMaxLength) {
+        this.paramNameMaxLength = paramNameMaxLength;
+    }
+
     @Inject(value = JSONConstants.JSON_MAX_ELEMENTS, required = false)
     public void setMaxElements(String maxElements) {
         this.maxElements = Integer.parseInt(maxElements);
diff --git 
a/plugins/json/src/test/java/org/apache/struts2/json/JSONInterceptorTest.java 
b/plugins/json/src/test/java/org/apache/struts2/json/JSONInterceptorTest.java
index 2986e557f..82a562f00 100644
--- 
a/plugins/json/src/test/java/org/apache/struts2/json/JSONInterceptorTest.java
+++ 
b/plugins/json/src/test/java/org/apache/struts2/json/JSONInterceptorTest.java
@@ -749,6 +749,22 @@ public class JSONInterceptorTest extends StrutsTestCase {
         assertNull(action.getBar());
     }
 
+    public void testParamNameMaxLengthRejectsLongKey() throws Exception {
+        this.request.setContent("{\"foo\":\"a\"}".getBytes());
+        this.request.addHeader("Content-Type", "application/json");
+
+        JSONInterceptor interceptor = createInterceptor();
+        interceptor.setParamNameMaxLength(2); // "foo" is length 3, over the 
limit
+        TestAction action = new TestAction();
+
+        this.invocation.setAction(action);
+        this.invocation.getStack().push(action);
+
+        interceptor.intercept(this.invocation);
+
+        assertNull(action.getFoo());
+    }
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();

Reply via email to