[
https://issues.apache.org/jira/browse/WW-5627?focusedWorklogId=1019503&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-1019503
]
ASF GitHub Bot logged work on WW-5627:
--------------------------------------
Author: ASF GitHub Bot
Created on: 09/May/26 17:23
Start Date: 09/May/26 17:23
Worklog Time Spent: 10m
Work Description: lukaszlenart opened a new pull request, #1681:
URL: https://github.com/apache/struts/pull/1681
## Summary
Fixes [WW-5627](https://issues.apache.org/jira/browse/WW-5627) —
`CookieInterceptor.populateCookieValueIntoStack` calls `stack.setValue`
directly (`CookieInterceptor.java:339,348` pre-fix), bypassing
`StrutsParameterAuthorizer` so cookies write to action setters that are not
annotated with `@StrutsParameter` even when
`struts.parameters.requireAnnotations=true`.
This PR retrofits the `@StrutsParameter` enforcement onto the cookie input
channel:
- New `ParameterAllowlister` interface (extension point) + default
`OgnlParameterAllowlister` impl extracted from
`ParametersInterceptor.performOgnlAllowlisting`. Mirrors the
`ParameterAuthorizer` pair from WW-5626. Apps can swap implementations via
`<constant name="struts.parameterAllowlister" value="..."/>`.
- `ParametersInterceptor` delegates to the new component (pure refactor, all
35 existing tests pass unchanged).
- `CookieInterceptor` adds a new `protected void
populateCookieValueIntoStack(name, value, map, stack, action)` extension hook.
The default impl runs `parameterAuthorizer.isAuthorized` →
`parameterAllowlister.allowlistAuthorizedPath` → existing 4-arg form. The 4-arg
form is `@Deprecated(since="7.2.0")` with body unchanged, so existing subclass
overrides automatically inherit the gate.
- DI registration in `struts-beans.xml`, `StrutsBeanSelectionProvider`, and
`DefaultConfiguration.bootstrapFactories()`.
**Default-config invariant:** when
`struts.parameters.requireAnnotations=false` (the 7.x default),
`ParameterAuthorizer.isAuthorized` short-circuits to `true`, so existing apps
see no behavior change. Only opt-in apps see cookies gated.
## Behavior matrix
| Config | Cookie name | Setter `@StrutsParameter`? | Outcome |
|---|---|---|---|
| `requireAnnotations=false` (default) | any | any | Injected (unchanged) |
| `requireAnnotations=true` | `flatName` | yes | Injected |
| `requireAnnotations=true` | `flatName` | no | Skipped, debug log |
| `requireAnnotations=true` | `user.role` | yes (depth ≥1) | Injected;
`ThreadAllowlist` primed |
| `requireAnnotations=true` | `user.role` | no / depth too low | Skipped,
debug log |
| `requireAnnotations=true`, transition | `flatName` | no | Injected
(depth-0 exemption) |
| `requireAnnotations=true`, ModelDriven model | any | n/a | Injected
against model |
## Migration notes (for the Confluence wiki)
> **Behavior change for `struts.parameters.requireAnnotations=true`
adopters:** `CookieInterceptor` now enforces `@StrutsParameter` annotations on
action setters when `struts.parameters.requireAnnotations=true`. Apps using
`<param name="cookiesName">*</param>` together with annotation enforcement must
annotate any setter intended to receive cookie values, or that cookie will be
silently skipped (debug-logged). No change for the default config.
## Stacking
Stacked on top of `WW-5626-approach-c` (where `ParameterAuthorizer` and
`StrutsParameterAuthorizer` were introduced). When WW-5626 merges to `main`,
this PR's base will be retargeted automatically.
## Test plan
- [x] `mvn test -DskipAssembly -pl core` — 2952/2952 green.
- [x] `mvn test -DskipAssembly -pl plugins/json` — 125/125 green (transitive
contract sanity).
- [x] New: `OgnlParameterAllowlisterTest` (6 unit tests).
- [x] New: `CookieInterceptorAnnotationTest` (8 tests covering the full
behavior matrix above, including subclass-override-of-deprecated-hook gets the
gate, ModelDriven exemption, transition mode).
- [x] Existing `CookieInterceptorTest` (9 tests) updated to wire
pass-through lambdas via a `disableAuthorizationGate(...)` helper since those
tests construct `CookieInterceptor` via `new` rather than the container.
- [x] Existing `ParametersInterceptorTest`,
`ActionMappingParametersInterceptorTest`, `StaticParametersInterceptorTest`,
`StrutsParameterAnnotationTest` all green after the refactor.
## Out of scope (separate Jira candidates)
- `ScopeInterceptor` (`ScopeInterceptor.java:306,328`) has the same
`stack.setValue` pattern from session/application scope — likely warrants its
own ticket.
- `ParametersInterceptor.hasValidAnnotated*` helpers (lines 432–548) appear
to be dead post-WW-5626 (only `StrutsParameterAuthorizer`'s versions are
reached at runtime). Cleanup is a separate audit.
- `ParameterNameAware` consultation in `CookieInterceptor` — not currently
consulted; adding it would be a larger behavior change.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Issue Time Tracking
-------------------
Worklog Id: (was: 1019503)
Remaining Estimate: 0h
Time Spent: 10m
> CookieInterceptor bypasses @StrutsParameter authorization
> ---------------------------------------------------------
>
> Key: WW-5627
> URL: https://issues.apache.org/jira/browse/WW-5627
> Project: Struts 2
> Issue Type: Improvement
> Components: Core Interceptors
> Reporter: Lukasz Lenart
> Assignee: Lukasz Lenart
> Priority: Major
> Fix For: 7.2.0
>
> Time Spent: 10m
> Remaining Estimate: 0h
>
> h2. Problem
>
> {{CookieInterceptor.populateCookieValueIntoStack}} calls
> {{stack.setValue(cookieName, cookieValue)}} directly
> ({{CookieInterceptor.java}} lines 339 and 348), which:
> - bypasses {{StrutsParameterAuthorizer}} / {{@StrutsParameter}} enforcement,
> - never primes {{ThreadAllowlist}}.
>
> Cookie injection therefore does not participate in the
> parameter-authorization machinery that {{ParametersInterceptor}}, the JSON
> plugin, and (post-[WW-5626|https://issues.apache.org/jira/browse/WW-5626])
> the REST plugin all share.
>
> h2. Impact
> When {{cookiesName=*}} is configured, every public setter on the action — and
> (subject to allowlist) any setter reachable through getter chains from the
> value-stack root — is writeable from cookie input without any
> {{@StrutsParameter}} opt-in. The OGNL allowlist (default {{enable=true}}
> since 7.0) blocks the nested-bean route via {{SecurityMemberAccess}}, but it
> does not require setters to be annotated with {{@StrutsParameter}}, so
> action-level setters remain reachable.
> h2. Proposed fix
>
> Replace {{stack.setValue}} in {{populateCookieValueIntoStack}} with
> {{stack.setParameter}} (or invoke {{StrutsParameterAuthorizer}} directly) so
> cookie injection participates in {{@StrutsParameter}} enforcement and
> {{ThreadAllowlist}} priming, aligning {{CookieInterceptor}} with
> {{ParametersInterceptor}}, the JSON plugin, and the REST plugin.
> h2. Dependencies
>
> Builds on [WW-5626|https://issues.apache.org/jira/browse/WW-5626] — reuses
> {{ParameterAuthorizationContext}} and {{ParameterAuthorizer.resolveTarget}}.
>
> h2. Backward compatibility
>
> Behavior change: apps relying on cookies populating un-annotated setters will
> stop working under strict authorization. Affected users must either add
> {{@StrutsParameter}} to the relevant setters or drop {{cookiesName=*}}.
> Migration-guide entry required.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)