lukaszlenart commented on PR #1889:
URL: https://github.com/apache/struts/pull/1889#issuecomment-5530239163

   Thanks for this, and apologies for the wait — the review is on us, not you.
   
   The shape is what we agreed: sink-level consent on the any-setter, default 
off
   (`struts.rest.anySetter.requireAnnotations=false`), wrapper not even 
installed unless an
   application opts in. I'm happy with that part and with the `REJECTED_VALUE` 
sentinel handling —
   I checked that it can't leak through `PropertyValue.AnyProperty.assign` or 
`AnyParameter.assign`,
   since both route through `SettableAnyProperty.set`, which you override.
   
   A couple of notes, none of them blocking.
   
   **Depth semantics — checked, and they're right**
   
   I went in suspecting the dynamic key might not consume its share of the 
depth budget, and that the
   method form and the `Map`-typed field form might disagree because 
`prefixForNested`
   (`AuthorizingSettableAnyProperty.java:259-265`) only appends `[0]` for the 
map-like case. I wrote a
   parity test for both forms and it came out clean — same grant, same body, 
same reach:
   
       METHOD depth=1 -> ACCEPTED home.city=Warsaw
       FIELD  depth=1 -> ACCEPTED home.city=Warsaw
   
   which is as it should be: an any-setter on the root object takes its keys as 
root-level properties,
   so `{"home":{"city":"Warsaw"}}` authorizes `home` and then `home.city` — one 
nesting character,
   `depth = 1`, exactly the rule `@StrutsParameter` uses everywhere else. The 
gate is `valueDepth`
   computed on the JSON, so it doesn't vary by declaration form. Mentioning it 
only so you know it was
   checked rather than assumed.
   
   The one gap it did show up: the suite pins the nested cases only for the 
method form
   (`testDynamicKeyDepthZero/One/TwoAnySetterBean`), while the field form is 
covered for scalars alone.
   Worth adding a nested field-form case so the equivalence is held by a test 
rather than by
   inspection — happy to hand you the one I wrote.
   
   I should also say plainly, since it's the thing most likely to be raised at 
you later: within a
   granted dynamic-key scope the annotation authorizer is deliberately not 
consulted for members
   beneath the key, and your tests assert exactly that (a deny-everything 
authorizer, nested member
   still set). That is correct and consistent with the rest of the framework —
   `StrutsParameterAuthorizer.isAuthorized` authorizes the root property plus a 
total depth budget, so
   `user.admin` needs an annotation on `user` and never on `User.admin`. No 
change wanted there.
   
   **Smaller items**
   
   - `AuthorizingSettableAnyProperty.java:155` — `parser.currentName()` is null 
when Jackson routes
     through `BeanDeserializer._deserializeUsingPropertyBasedWithUnwrapped`, 
which passes a value-only
     `TokenBuffer`. A bean combining `@JsonUnwrapped` with a `@JsonCreator` and 
an any-setter therefore
     drops every dynamic property, even when correctly annotated. Fail-closed, 
but silent — worth at
     least a distinguishable log, ideally handling.
   - `:209-211` — `allowedDepth()` short-circuits on `creatorParameter` before 
looking at `permission`,
     so a creator-parameter any-setter is rejected unconditionally with no 
opt-in. The annotation is
     discoverable there (`prop.getMember()` is the `AnnotatedParameter`); if 
the intent is that it's
     unsupported, the WARN should say so permanently rather than read like a 
missing annotation.
   - `:221` — one WARN per rejected key, and unlike bean properties the key 
space is attacker-
     controlled and unbounded. We've had a run of DoS-shaped reports lately, so 
please log once per
     body with a count instead.
   - `ParameterAuthorizingModule.java:94` — `setRequireAnySetterAnnotations` 
only takes effect at
     deserializer-build time and Jackson caches those per mapper, so a call 
after the mapper is in use
     is silently a no-op. Both handlers already have the `(boolean)` 
constructor; injecting the
     constant there removes the hazard rather than documenting it.
   - `TokenBuffer.asCopyOfValue(JsonParser)` (`:122,168,243`) is deprecated 
since Jackson 2.13 in
     favour of `DeserializationContext.bufferAsCopyOfValue(p)`, and `context` 
is in scope at both sites.
   
   The `@StrutsParameter` documentation correction is on me, not you — it's 
tracked on WW-5712 and I'll
   handle it alongside the ModelDriven wording.
   
   One process note: because this touches parameter authorization, I'll run our 
security review over
   the branch before merging. That's routine for this area and not a comment on 
the change.
   
   Credit for the report and the patch is yours in the release notes.
   


-- 
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