You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by lu...@apache.org on 2026/07/08 19:49:25 UTC
(struts) 08/08: WW-4858 test(json): cover nested and list-element paths; clarify filter comments
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 c4335c68d2cf5c05282200c47ed744df83ea3609
Author: Lukasz Lenart <lu...@apache.org>
AuthorDate: Wed Jul 8 20:58:25 2026 +0200
WW-4858 test(json): cover nested and list-element paths; clarify filter comments
Co-Authored-By: Claude Opus 4.8 <no...@anthropic.com>
---
.../org/apache/struts2/json/JSONInterceptor.java | 3 +-
.../apache/struts2/json/JSONInterceptorTest.java | 39 ++++++++++++++++++++++
2 files changed, 41 insertions(+), 1 deletion(-)
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 0d584d830..b1c172388 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
@@ -144,7 +144,7 @@ public class JSONInterceptor extends AbstractInterceptor {
if (rootObject == null) // model overrides action
rootObject = invocation.getStack().peek();
- // enforce @StrutsParameter authorization on JSON body keys
+ // enforce name/value acceptability (patterns, length, *Aware) and @StrutsParameter authorization on JSON body keys
filterUnacceptableKeys(json, rootObject, invocation.getAction());
// populate fields
@@ -263,6 +263,7 @@ public class JSONInterceptor extends AbstractInterceptor {
filterUnacceptableKeysRecursive((Map) item, elementPrefix, target, action);
} else if (item instanceof java.util.List) {
filterUnacceptableList((java.util.List) item, elementPrefix, target, action);
+ // Scalar list elements are value-checked only; their parent key already passed name/authorization checks.
} else if (!isAcceptableValue(elementPrefix, item, action)) {
it.remove();
}
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 89ec91dfb..e1aed361b 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,45 @@ public class JSONInterceptorTest extends StrutsTestCase {
assertNull(action.getBar());
}
+ public void testExcludedNamePatternRejectsNestedKey() throws Exception {
+ this.request.setContent("{\"bean\": {\"stringField\": \"keep\", \"intField\": 42}}".getBytes());
+ this.request.addHeader("Content-Type", "application/json");
+
+ JSONInterceptor interceptor = createInterceptor();
+ org.apache.struts2.security.DefaultExcludedPatternsChecker excluded =
+ new org.apache.struts2.security.DefaultExcludedPatternsChecker();
+ excluded.setExcludedPatterns("bean\\.intField");
+ interceptor.setExcludedPatterns(excluded);
+ TestAction action = new TestAction();
+
+ this.invocation.setAction(action);
+ this.invocation.getStack().push(action);
+
+ interceptor.intercept(this.invocation);
+
+ assertNotNull(action.getBean());
+ assertEquals("keep", action.getBean().getStringField());
+ assertEquals(0, action.getBean().getIntField());
+ }
+
+ public void testExcludedValuePatternRejectsListElement() throws Exception {
+ this.request.setContent("{\"list\": [\"good\", \"badvalue\"]}".getBytes());
+ this.request.addHeader("Content-Type", "application/json");
+
+ JSONInterceptor interceptor = createInterceptor();
+ interceptor.setExcludedValuePatterns("badvalue");
+ TestAction action = new TestAction();
+
+ this.invocation.setAction(action);
+ this.invocation.getStack().push(action);
+
+ interceptor.intercept(this.invocation);
+
+ assertNotNull(action.getList());
+ assertEquals(1, action.getList().size());
+ assertEquals("good", action.getList().get(0));
+ }
+
public void testParamNameMaxLengthRejectsLongKey() throws Exception {
this.request.setContent("{\"foo\":\"a\"}".getBytes());
this.request.addHeader("Content-Type", "application/json");