lukaszlenart opened a new pull request, #1946:
URL: https://github.com/apache/struts/pull/1946

   Fixes [WW-5747](https://issues.apache.org/jira/browse/WW-5747)
   
   ## Problem
   
   `RedactionAwareDeserializer` drops a bean whose construction fails after a 
`@StrutsParameter` redaction by catching the `JsonMappingException` and 
returning `null`. It returned without moving the parser, so whatever tokens of 
the dropped object were still unread went to the *enclosing* bean: a 
creator-bound bean failing on its last creator parameter with fields after it, 
or a bean whose bean-typed `@JsonIdentityInfo` id failed to construct and could 
not be bound, left its remaining fields to the parent — a same-named parent 
property took the child's value, the parent's own later properties were lost, 
and an unknown field failed the parent inside a scope already marked redacted, 
dropping the root.
   
   ## Change
   
   - On entry the wrapper records the context of the object or array it is 
entered on. Before returning `null` it skips to that value's end token, 
consuming nested structures whole. The end is recognised by **context 
identity** — the first end token whose context no longer descends from the 
recorded one — which every parser keeps, including the token buffers Jackson 
replays `@JsonUnwrapped` and any-setter values from (those report no nesting 
depth at all; a depth comparison drained them). A parser left without a current 
token, as Jackson does before splicing a late type id, is advanced first. A 
scalar entry needs nothing.
   - A polymorphic value Jackson reads from a **spliced** parser (type id not 
the first key, or `visible = true`) straddles the splice and cannot be 
followed: it is the value entered mid-object on a buffer context while the 
parser is a `JsonParserSequence`, and its drop is not attempted. The exception 
propagates with the enclosing scope marked, so the nearest enclosing bean that 
can leave its parser in order drops itself; through the handlers' 
`readerForUpdating` root the read fails. Either replaces a silent 
desynchronisation. A bean nested inside such a value lies wholly on one side 
and is dropped normally. The refusal logs a WARN naming the type, so the 
resulting Jackson error can be tied to authorization.
   
   ## Review trail
   
   Three code-review and two security-review passes, each finding a deeper 
parser shape: depth → identity (token buffers), cleared current token after 
Jackson's splice, refusal too broad (nested beans inside a spliced value), 
refusal too narrow (a splice whose base parser is itself a buffer), parent 
scope not marked on refusal. All are regression tests now. Security: nothing 
newly introduced; every direction is "consume more or fail", never "leave 
unread for the parent".
   
   ## Tests
   
   `ParameterAuthorizingModuleTest`, nine new cases: null-id drop with trailing 
fields; creator failure with a nested object and trailing fields; late-type-id 
drop fails the read through `readerForUpdating`; a bean nested in a 
late-type-id value still drops in place; a refused drop marks the parent so it 
drops itself; a late-type-id value nested in another's buffer escalates rather 
than leaking; parent swallowing a refused subtype drop after 
`clearCurrentToken()`; drop inside an `@JsonUnwrapped` replay stops at the 
record's end.
   
   `mvn test -DskipAssembly -pl plugins/rest`: 210 tests, 0 failures.
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to