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

robertlazarski pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/axis-axis2-java-core.git

commit 1b43f48c24d85a92e60936312d00a1753b9659bf
Author: Robert Lazarski <[email protected]>
AuthorDate: Sun Oct 11 06:14:00 2026 -1000

    Test that json field filter dot paths cannot reach excluded fields
    
    The nested walker selects fields separately from the top-level prune, so
    cover this$0 and @Json(ignore = true) fields reached through dot notation
    (items.this$0, this$0.dbPassword, creds.apiToken) as well.
    
    Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
 .../FieldFilteringMessageFormatterTest.java        | 36 ++++++++++++++++++++++
 .../MoshiStreamingMessageFormatterTest.java        | 30 ++++++++++++++++++
 2 files changed, 66 insertions(+)

diff --git 
a/modules/json/test/org/apache/axis2/json/streaming/FieldFilteringMessageFormatterTest.java
 
b/modules/json/test/org/apache/axis2/json/streaming/FieldFilteringMessageFormatterTest.java
index 7a215ce51e..bc104cab48 100644
--- 
a/modules/json/test/org/apache/axis2/json/streaming/FieldFilteringMessageFormatterTest.java
+++ 
b/modules/json/test/org/apache/axis2/json/streaming/FieldFilteringMessageFormatterTest.java
@@ -293,6 +293,35 @@ public class FieldFilteringMessageFormatterTest {
             raw.contains("db-password-123"));
     }
 
+    @Test
+    public void testSyntheticFieldsNotReachableThroughDotNotation() throws 
Exception {
+        // The nested walker enumerates fields separately from the top-level
+        // prune, so a dot path must not reach this$0 either -- directly on
+        // the return object or on elements of a nested collection.
+        EnclosingService svc = new EnclosingService("db-password-123");
+        List<EnclosingService.Result> items = new ArrayList<>();
+        items.add(svc.new Result("ok"));
+        setReturnObject(new ResultHolder("SUCCESS", items));
+        outMsgContext.setProperty(JsonConstant.FIELD_FILTER,
+            setOf("status", "items.status", "items.this$0"));
+
+        formatter.writeTo(outMsgContext, outputFormat, outputStream, false);
+        Assert.assertFalse("enclosing instance state must not leak via 
items.this$0",
+            outputStream.toString("UTF-8").contains("db-password-123"));
+        JsonElement item = parseResponse().getAsJsonObject()
+            .getAsJsonArray("items").get(0);
+        Assert.assertEquals("ok", 
item.getAsJsonObject().get("status").getAsString());
+        Assert.assertFalse(item.getAsJsonObject().has("this$0"));
+
+        outputStream.reset();
+        setReturnObject(svc.new Result("ok"));
+        outMsgContext.setProperty(JsonConstant.FIELD_FILTER,
+            setOf("status", "this$0.dbPassword"));
+        formatter.writeTo(outMsgContext, outputFormat, outputStream, false);
+        Assert.assertFalse("enclosing instance state must not leak via 
this$0.dbPassword",
+            outputStream.toString("UTF-8").contains("db-password-123"));
+    }
+
     // ── parseFieldsCsv / parseFieldsFromUrl tests ─────────────────────────
 
     @Test
@@ -470,6 +499,13 @@ public class FieldFilteringMessageFormatterTest {
         }
     }
 
+    /** Holds a collection of inner-class results for nested filtering tests. 
*/
+    public static class ResultHolder {
+        public String status;
+        public List<EnclosingService.Result> items;
+        public ResultHolder(String s, List<EnclosingService.Result> i) { 
status = s; items = i; }
+    }
+
     /** POJO with static and transient fields for modifier filtering test. */
     public static class StaticTransientData {
         public static final String CONSTANT = "should-never-serialize";
diff --git 
a/modules/json/test/org/apache/axis2/json/streaming/MoshiStreamingMessageFormatterTest.java
 
b/modules/json/test/org/apache/axis2/json/streaming/MoshiStreamingMessageFormatterTest.java
index e66f342104..8065c4ce6d 100644
--- 
a/modules/json/test/org/apache/axis2/json/streaming/MoshiStreamingMessageFormatterTest.java
+++ 
b/modules/json/test/org/apache/axis2/json/streaming/MoshiStreamingMessageFormatterTest.java
@@ -192,6 +192,29 @@ public class MoshiStreamingMessageFormatterTest {
             result.contains("secret-token-xyz"));
     }
 
+    /**
+     * Same as above for an ignored field on elements of a nested
+     * collection, which go through the nested walker rather than the
+     * top-level prune.
+     */
+    @Test
+    public void testDotNotationDoesNotExposeIgnoredField() throws Exception {
+        CredentialHolder holder = new CredentialHolder(java.util.List.of(
+            new CredentialData("public-label", "secret-token-xyz")));
+        outMsgContext.setProperty(JsonConstant.RETURN_OBJECT, holder);
+        outMsgContext.setProperty(JsonConstant.RETURN_TYPE, 
CredentialHolder.class);
+        outMsgContext.setProperty(JsonConstant.FIELD_FILTER,
+            new LinkedHashSet<>(Arrays.asList("creds.label", 
"creds.apiToken")));
+
+        new MoshiStreamingMessageFormatter().writeTo(
+            outMsgContext, outputFormat, outputStream, false);
+
+        String result = outputStream.toString("UTF-8");
+        Assert.assertTrue(result.contains("\"label\":\"public-label\""));
+        Assert.assertFalse("@Json(ignore = true) field must not be exposed via 
dot notation",
+            result.contains("secret-token-xyz"));
+    }
+
     /**
      * Test content type passthrough.
      */
@@ -219,6 +242,13 @@ public class MoshiStreamingMessageFormatterTest {
         return fault;
     }
 
+    /** Wraps CredentialData in a collection for the nested filtering test. */
+    public static class CredentialHolder {
+        public java.util.List<CredentialData> creds;
+        public CredentialHolder() {}
+        public CredentialHolder(java.util.List<CredentialData> c) { creds = c; 
}
+    }
+
     /** POJO with a field opted out of serialization via {@code @Json(ignore = 
true)}. */
     public static class CredentialData {
         public String label;

Reply via email to