lukaszlenart opened a new pull request, #1916: URL: https://github.com/apache/struts/pull/1916
Fixes [WW-5725](https://issues.apache.org/jira/browse/WW-5725) `AuthorizingSettableBeanProperty` authorized a property in `deserializeAndSet` / `deserializeSetAndReturn` and wrapped the value deserializer only for creator-bound properties. Jackson takes neither route for a non-creator property it buffers during property-based creation: a setter property that appears in the body before the last creator parameter is read through the `final` `SettableBeanProperty.deserialize()` with no authorization and no path push, and assigned after construction through `SettableBeanProperty.set()`, which the `Delegating` base forwarded unchecked. The same property after the last creator parameter, or on a setter-only type, was already rejected, so member order alone decided whether the check applied, and the members of a buffered bean-valued property were checked one level too shallow. Three gates now cover the paths between them: - `deserializeAndSet` / `deserializeSetAndReturn` keep authorizing the direct path and skipping the value on rejection, so the setter never fires, but no longer push the path themselves. - `AuthorizingValueDeserializer` wraps every property's value deserializer, not only creator properties, and owns the path push for nested members. It covers all three of Jackson's entry points — `deserialize(p, ctxt)`, the in-place `deserialize(p, ctxt, intoValue)` used for setterless collections, and `deserializeWithType` for polymorphic properties — and classifies the `[0]` element prefix on the property's declared type. On the direct path it re-checks a path `deserializeAndSet` already accepted; the authorizer is stateless, so the answer is the same. - `set` / `setAndReturn` authorize the already-materialized assignment, which also covers a buffered `null` (Jackson skips the value deserializer for a null token) and the other callers of `set()` in jackson-databind: `@JsonMerge`, `@JsonManagedReference`, inner-class valued properties, `EXTERNAL_PROPERTY` type ids and the `@JsonIdentityInfo` id property, none of which were authorized before. All gates go through `DynamicKeyAuthorizationContext`, so a dynamic-key scope authorizes by depth on every path. **Tests** (all in `ParameterAuthorizingModuleTest`): setter before and after the last creator parameter, a setter-only type with the same member order, a nested creator, a creator-plus-setter type inside a dynamic-key scope, a buffered bean-valued setter whose members must be authorized at their own depth, a setterless collection, and a polymorphic property. The last two are written in the direction that matters — a sibling grant on the enclosing bean must not authorize a collapsed nested path — and both failed against an intermediate version of this change that had moved the push but not yet covered the 3-arg and typed entry points. **Behaviour notes.** No configuration or API change. A request that previously had an unauthorized property assigned only because of its position in the body now has it dropped, consistent with every other position. Properties assigned through the other `set()` callers listed above are now subject to the same authorization as ordinary setters — most visibly, an `@JsonIdentityInfo` id property now needs `@StrutsParameter` like any other. A buffered rejection logs twice (once at the read, once at the assignment); the assignment-side warning is kept because it is the only one for the other `set()` callers. 🤖 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]
