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

lukaszlenart pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/struts-site.git


The following commit(s) were added to refs/heads/main by this push:
     new 08e3ed4e3 docs: scope the @StrutsParameter "never set" claim to named 
properties (#328)
08e3ed4e3 is described below

commit 08e3ed4e3de735c77840d0e2d197ae7a6a2351c5
Author: Lukasz Lenart <[email protected]>
AuthorDate: Fri Sep 11 06:00:11 2026 +0200

    docs: scope the @StrutsParameter "never set" claim to named properties 
(#328)
    
    The annotation page told readers that JSON and REST deserialization means
    unauthorized fields are never set on the target object. That is true of the
    properties the deserializer binds by name, but a Jackson any-setter is a
    separate sink that the REST plugin's authorization wrapper never wraps, so
    unknown keys routed to it are bound with no @StrutsParameter check at all --
    in the same request in which an ordinary unannotated setter on the same 
class
    is correctly rejected.
    
    Qualify the bullet and document the gap in its own section, alongside the
    existing creator-bound-properties note that covers the same class of 
problem.
    The JSON plugin is unaffected: it does not use Jackson, so its own page's
    identical wording stays accurate and is left alone.
    
    
    Claude-Session: https://claude.ai/code/session_012HF8BGrYmCVnqUdQJJ1XPM
    
    Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
---
 .../core-developers/struts-parameter-annotation.md | 26 +++++++++++++++++++++-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/source/core-developers/struts-parameter-annotation.md 
b/source/core-developers/struts-parameter-annotation.md
index 916607c7b..c9a1642c2 100644
--- a/source/core-developers/struts-parameter-annotation.md
+++ b/source/core-developers/struts-parameter-annotation.md
@@ -27,7 +27,10 @@ channel that can populate an action from request data:
   action chaining (opt-in via `struts.chaining.requireAnnotations`).
 - [Cookie Interceptor](cookie-interceptor.html) — cookie values.
 - [JSON](../../plugins/json) and [REST](../../plugins/rest) plugins — 
per-property
-  authorization performed during deserialization, so unauthorized fields are 
never set.
+  authorization performed during deserialization, so an unauthorized property 
is not set on
+  the target object. This covers the properties the deserializer binds **by 
name**; in the
+  REST plugin a Jackson any-setter is a separate sink that is not covered — see
+  [Jackson any-setters](#jackson-any-setters) below.
 
 ### Creator-bound properties
 
@@ -48,6 +51,27 @@ the same way as any nested object: `@StrutsParameter(depth = 
...)` on the getter
 model. Otherwise those values silently stop arriving.
 {:.alert .alert-warning}
 
+### Jackson any-setters
+
+A class that declares a Jackson any-setter — `@JsonAnySetter` on a method, on 
a field, or on a
+`@JsonCreator` parameter — tells Jackson to route **every otherwise-unknown 
key** in the request body
+to that member. The REST plugin's authorization wrapper covers the properties 
Jackson binds by name;
+an any-setter is a separate sink and is not wrapped. Keys arriving through it 
are therefore set
+without an `@StrutsParameter` check, even with 
`struts.parameters.requireAnnotations` enabled, and
+even in the same request in which an ordinary unannotated setter on the same 
class is correctly
+rejected.
+
+Two limits are worth knowing. An any-setter beneath an **unauthorized parent** 
is still unreachable:
+the parent is rejected first and its whole subtree is skipped. And 
`@JsonUnwrapped` is a named
+property, so it is unaffected by this.
+
+Declaring an any-setter on a class bound from a REST request body is the 
application accepting
+arbitrary names and values off the wire — the same decision as binding a 
`Map`, and it deserves the
+same scrutiny. Where that is not what you want, do not declare one on a 
request-bound class, or
+narrow what the method accepts before storing it. Tracked as
+[WW-5712](https://issues.apache.org/jira/browse/WW-5712).
+{:.alert .alert-warning}
+
 ## ModelDriven actions
 
 When an action implements `ModelDriven` and the [Model Driven

Reply via email to