[ 
https://issues.apache.org/jira/browse/WW-5833?focusedWorklogId=1051647&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-1051647
 ]

ASF GitHub Bot logged work on WW-5833:
--------------------------------------

                Author: ASF GitHub Bot
            Created on: 31/Oct/26 17:04
            Start Date: 31/Oct/26 17:04
    Worklog Time Spent: 10m 
      Work Description: g0w6y opened a new pull request, #2091:
URL: https://github.com/apache/struts/pull/2091

   Fixes [WW-5833](https://issues.apache.org/jira/browse/WW-5833)
   
   `@StrutsParameter` documents that "the depth dictates the number of periods 
or brackets that can appear in the parameter name", and 
`StrutsParameterAuthorizer` counts every `.`, `[` and `(` in the full name. The 
REST plugin's `AuthorizingValueDeserializer.prefixForNested` appended a single 
`[0]` for a container property, whatever the nesting. For `List<List<Bean>>`, 
`Map<String, List<Bean>>` and `Bean[][]` the members of the bean were therefore 
authorized as `items[0].secret` (depth 2) where the form path authorizes 
`items[0][0].secret` (depth 3). With `@StrutsParameter(depth = 2)` on `items`, 
`StrutsParameterAuthorizer` rejects `items[0][0].secret` (depth 3), while the 
same member in a JSON body `{"items":[[{"secret":"S"}]]}` was bound.
   
   `prefixForNested` now adds one `[0]` per container level of the property 
type. The two-phase copy in `ContentTypeInterceptor` (handlers that are not 
authorization-aware) copied a container nested in a container unfiltered; it 
now recurses into it with `path[0]`. A container of scalars nested in a 
container (`List<List<String>>`) is now copied in the two-phase path instead of 
being shared with the source object. Single-level containers, scalars and beans 
are unchanged.
   
   How verified: 5 new tests fail without the production change and pass with 
it (reverted with `git stash` on `plugins/rest/src/main`): 3 in 
`ParameterAuthorizingModuleTest` (`List<List<Address>>`, `Map<String, 
List<Address>>`, `Address[][]`) and 2 in 
`ContentTypeInterceptorIntegrationTest` (Jackson path, with the real 
`StrutsParameterAuthorizer` asserting that the form path rejects the same name; 
and the two-phase copy). Whole rest module: 242 run, 0 failures. Core 
`ParameterAuthorizerTest`, `ParameterAuthorizationContextTest`, 
`ParametersInterceptorTest` and the other parameter-authorizer tests: 104 run, 
0 failures.
   
   Also checked against a running Struts Boot app with the REST plugin and an 
action with `List<List<Bean>> items` annotated `@StrutsParameter(depth = 2)`: 
`POST /orders` with `{"items":[[{"name":"n","secret":"S"}]]}` ran `create()` 
with `name=n secret=S` on `main`; with this change the nested members are not 
bound, and with the annotation at `depth = 3` the same body binds `name=n 
secret=S`.
   
   Not changed: core, the authorizer's counting, single-level containers, 
Juneau, `requireAnnotations=false`.
   
   Compatibility: this tightens authorization. A REST-only application with a 
nested-container property (`List<List<Bean>>`, `Map<String, List<Bean>>`, 
`Bean[][]`) annotated at the old, one-level-shorter depth N will, after the 
upgrade, have the members of those nested beans dropped from request bodies 
until the depth is raised to N + 1 (the container itself and its beans are 
still created). Each rejection is logged at WARN. The authorizer already 
requires N + 1 for a form parameter of that name. Suggested release note: "REST 
plugin: @StrutsParameter depth is now counted per nested container level for 
REST bodies, as for request parameters; actions with List<List<Bean>>, 
Map<String, List<Bean>> or Bean[][] properties may need a depth one higher."
   




Issue Time Tracking
-------------------

            Worklog Id:     (was: 1051647)
    Remaining Estimate: 0h
            Time Spent: 10m

>  REST plugin authorizes nested container members one @StrutsParameter depth 
> level short of ParametersInterceptor
> ----------------------------------------------------------------------------------------------------------------
>
>                 Key: WW-5833
>                 URL: https://issues.apache.org/jira/browse/WW-5833
>             Project: Struts 2
>          Issue Type: Bug
>          Components: Plugin - REST
>    Affects Versions: 7.3.0, 7.4.0
>            Reporter: Gouri Sankar A
>            Priority: Minor
>          Time Spent: 10m
>  Remaining Estimate: 0h
>
> StrutsParameter documents that the depth is the number of periods or brackets 
> in the parameter name, and StrutsParameterAuthorizer counts every '.', '[' 
> and '(' in the full name. In the REST plugin, 
> AuthorizingValueDeserializer.prefixForNested appends "[0]" once for a 
> Collection, Map or array property, however deeply containers are nested. For 
> List<List<Bean>>, Map<String, List<Bean>> and Bean[][] the members of the 
> bean are authorized as items[0].secret (depth 2), where the form path 
> authorizes items[0][0].secret (depth 3). The two-phase copy in 
> ContentTypeInterceptor (used for content type handlers that are not 
> authorization-aware) copies a container nested in a container unfiltered.
> Reproduction (main): an action with a List<List<Bean>> items property 
> annotated @StrutsParameter(depth = 2) on getter and setter. 
> StrutsParameterAuthorizer.isAuthorized("items[0][0].secret") is false (depth 
> 3 > 2), but the JSON body \{"items":[[{"name":"n","secret":"S"}]]} through 
> the Jackson handler binds secret = "S". Same for Map<String, List<Bean>> and 
> Bean[][]. Reproduced on a running Struts Boot app with the REST plugin: POST 
> /orders with that body ran the action with name = n and secret = S; with the 
> fix the nested members are not bound, and with the annotation raised to depth 
> = 3 the same body binds them.
> Scope and impact: only the members of beans held in a container that is 
> itself nested in a container, and only where the developer's depth equals the 
> shorter count. Scalars, beans and single-level containers are not affected. 
> The members are of beans the developer already exposed. Affected versions: 
> AuthorizingValueDeserializer.prefixForNested appends a single "[0]" in the 
> 7.3.0 and 7.4.0 tags (source inspection); that class does not exist in the 
> 7.2.x tags, which I did not examine. The behaviour itself was only reproduced 
> on main.
> Fix: prefixForNested adds one "[0]" per container level of the property type; 
> the two-phase copy recurses into nested containers with path[0] (so a nested 
> container of scalars is now copied rather than shared with the source 
> object). Five new tests fail without the change and pass with it; the whole 
> rest module passes.
> Compatibility: the fix tightens authorization. A REST-only application with 
> such a property annotated at the old shorter depth will, after the upgrade, 
> have the members of those nested beans dropped from request bodies (WARN 
> logged) until the depth is raised by one; the authorizer already requires the 
> higher depth for a form parameter of that name. A release note is suggested.



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to