This is an automated email from the ASF dual-hosted git repository.

lukaszlenart pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/struts-site.git


The following commit(s) were added to refs/heads/main by this push:
     new 29a1090fd docs: document Struts 7.2.0 changes (@StrutsParameter 
authorization, JSON limits) (#303)
29a1090fd is described below

commit 29a1090fdee3c8b3fb448ca6f2627fe7f6755e50
Author: Lukasz Lenart <[email protected]>
AuthorDate: Sun Jun 14 19:56:41 2026 +0200

    docs: document Struts 7.2.0 changes (@StrutsParameter authorization, JSON 
limits) (#303)
    
    * docs: add 7.2.0 content audit design spec
    
    Captures the documentation gap analysis for the Struts 7.2.0 release notes:
    the @StrutsParameter authorization expansion (ChainingInterceptor,
    CookieInterceptor, JSON/REST) and the new JSON deserialization limits.
    Announcement mechanics are out of scope.
    
    Co-Authored-By: Claude Opus 4.8 <[email protected]>
    
    * docs: add 7.2.0 content audit implementation plan
    
    Co-Authored-By: Claude Opus 4.8 <[email protected]>
    
    * docs: document chaining interceptor @StrutsParameter enforcement (WW-5631)
    
    Co-Authored-By: Claude Opus 4.8 <[email protected]>
    
    * docs: document cookie interceptor @StrutsParameter authorization (WW-5627)
    
    Co-Authored-By: Claude Opus 4.8 <[email protected]>
    
    * docs: make @StrutsParameter page the authorization hub (WW-5626/5631/5627)
    
    Co-Authored-By: Claude Opus 4.8 <[email protected]>
    
    * docs: document JSON deserialization limits and per-property authorization 
(WW-5618/5626)
    
    Co-Authored-By: Claude Opus 4.8 <[email protected]>
    
    * docs: note AuthorizationAwareContentTypeHandler in REST plugin (WW-5626)
    
    Co-Authored-By: Claude Opus 4.8 <[email protected]>
    
    ---------
    
    Co-authored-by: Claude Opus 4.8 <[email protected]>
---
 .../plans/2026-06-14-struts-720-content-audit.md   | 350 +++++++++++++++++++++
 .../2026-06-14-struts-720-content-audit-design.md  | 112 +++++++
 source/core-developers/chaining-interceptor.md     |  21 ++
 source/core-developers/cookie-interceptor.md       |  13 +
 .../core-developers/struts-parameter-annotation.md |  13 +
 source/plugins/json/index.md                       |  28 ++
 source/plugins/rest/index.md                       |   7 +
 7 files changed, 544 insertions(+)

diff --git a/docs/superpowers/plans/2026-06-14-struts-720-content-audit.md 
b/docs/superpowers/plans/2026-06-14-struts-720-content-audit.md
new file mode 100644
index 000000000..bc42ccdf5
--- /dev/null
+++ b/docs/superpowers/plans/2026-06-14-struts-720-content-audit.md
@@ -0,0 +1,350 @@
+# Struts 7.2.0 Content Audit Implementation Plan
+
+> **For agentic workers:** REQUIRED SUB-SKILL: Use 
superpowers:subagent-driven-development (recommended) or 
superpowers:executing-plans to implement this plan task-by-task. Steps use 
checkbox (`- [ ]`) syntax for tracking.
+
+**Goal:** Document the 7.2.0 `@StrutsParameter` authorization expansion 
(chaining, cookies, JSON/REST) and the new JSON deserialization limits on the 
Struts website.
+
+**Architecture:** Pure content edits to five existing Markdown pages under 
`source/`. `struts-parameter-annotation.md` becomes the hub for the 
authorization story; the interceptor/plugin pages each gain a focused section 
and cross-link back to it. No `_config.yml`, `announce-*`, or `releases.md` 
changes (announcement is out of scope).
+
+**Tech Stack:** Jekyll 4.2, Kramdown Markdown. Verification by `grep` plus a 
final `jekyll build`.
+
+**Source of truth (verified against the `STRUTS_7_2_0` tag):**
+- `struts.chaining.requireAnnotations=false` (`core/.../default.properties`)
+- `struts.json.maxElements=10000`, `maxDepth=64`, `maxLength=2097152`, 
`maxStringLength=262144`, `maxKeyLength=512`, `writer=struts`, `reader=struts` 
(`plugins/json/.../struts-plugin.xml`)
+
+**Conventions:** All commands run from repo root 
`/Users/lukaszlenart/Projects/Apache/struts-site`. Commit messages use the 
`docs:` type and end with the `Co-Authored-By` trailer per repo convention.
+
+---
+
+### Task 1: Chaining Interceptor — opt-in `@StrutsParameter` enforcement 
(WW-5631)
+
+**Files:**
+- Modify: `source/core-developers/chaining-interceptor.md` (insert between the 
copy-constants `### Example` block and `## Parameters`)
+
+- [ ] **Step 1: Add the Parameter Authorization section**
+
+Use Edit. `old_string`:
+
+```
+<constant name="struts.xwork.chaining.copyErrors" value="true"/>
+```
+
+(the existing one-line code block, then the `## Parameters` heading follows). 
Insert a new section immediately before `## Parameters`. Replace this anchor:
+
+```
+```
+
+## Parameters
+```
+
+with:
+
+````
+```
+
+## Parameter Authorization
+
+By default the Chaining Interceptor copies **all** properties of the objects on
+the value stack into the target action, regardless of any `@StrutsParameter`
+annotation. To restrict copying to annotated properties only, set the global
+constant:
+
+```xml
+<constant name="struts.chaining.requireAnnotations" value="true"/>
+```
+
+When enabled (default is `false`):
+
+- Only properties whose target setters carry 
[`@StrutsParameter`](struts-parameter-annotation.html)
+  are copied; rejected properties are skipped and logged at `WARN`.
+- Authorization uses the same `ParameterAuthorizer` service as the
+  [Parameters Interceptor](parameters-interceptor.html), keeping semantics 
consistent.
+- The behaviour is **fail-closed**: if the target action cannot be 
introspected,
+  no properties are copied.
+- This is a **global** constant only — there is no per-interceptor override.
+
+## Parameters
+````
+
+- [ ] **Step 2: Verify the content is present**
+
+Run: `grep -n "struts.chaining.requireAnnotations" 
source/core-developers/chaining-interceptor.md`
+Expected: one match inside the new `## Parameter Authorization` section.
+
+- [ ] **Step 3: Commit**
+
+```bash
+git add source/core-developers/chaining-interceptor.md
+git commit -m "docs: document chaining interceptor @StrutsParameter 
enforcement (WW-5631)
+
+Co-Authored-By: Claude Opus 4.8 <[email protected]>"
+```
+
+---
+
+### Task 2: Cookie Interceptor — `@StrutsParameter` authorization (WW-5627)
+
+**Files:**
+- Modify: `source/core-developers/cookie-interceptor.md` (insert a new section 
after the `CookiesAware` paragraph at line 24, before `## Parameters`)
+
+- [ ] **Step 1: Add the Parameter Authorization section**
+
+Use Edit. `old_string`:
+
+```
+The action could implement `CookiesAware` in order to have a `Map` of filtered 
cookies set into it.
+
+## Parameters
+```
+
+`new_string`:
+
+```
+The action could implement `CookiesAware` in order to have a `Map` of filtered 
cookies set into it.
+
+## Parameter Authorization
+
+Cookie values are injected through the same `@StrutsParameter` authorization 
path
+as the [Parameters Interceptor](parameters-interceptor.html) (previously the
+interceptor wrote directly to the value stack and bypassed authorization).
+
+> **Behaviour change in 7.2.0:** when annotation enforcement is active (the
+> default `struts.parameters.requireAnnotations=true`), cookies will only 
populate
+> setters marked with [`@StrutsParameter`](struts-parameter-annotation.html).
+> Applications that relied on cookies populating un-annotated setters must 
either
+> add the annotation to those setters or stop using `cookiesName=*`.
+{:.alert .alert-warning}
+
+## Parameters
+```
+
+- [ ] **Step 2: Verify the content is present**
+
+Run: `grep -n "Behaviour change in 7.2.0" 
source/core-developers/cookie-interceptor.md`
+Expected: one match inside the new `## Parameter Authorization` section.
+
+- [ ] **Step 3: Commit**
+
+```bash
+git add source/core-developers/cookie-interceptor.md
+git commit -m "docs: document cookie interceptor @StrutsParameter 
authorization (WW-5627)
+
+Co-Authored-By: Claude Opus 4.8 <[email protected]>"
+```
+
+---
+
+### Task 3: StrutsParameter annotation — authorization hub (WW-5626/5631/5627)
+
+**Files:**
+- Modify: `source/core-developers/struts-parameter-annotation.md` (insert a 
new section after the intro at line 13, before `## Usage`)
+
+- [ ] **Step 1: Add the "Where authorization applies" section**
+
+Use Edit. `old_string`:
+
+```
+Why it matters: by default (when annotations are required), Struts will only 
inject request parameters into fields or setter methods that have this 
annotation. This prevents attackers from setting values on fields you didn't 
intend to expose.
+
+## Usage
+```
+
+`new_string`:
+
+```
+Why it matters: by default (when annotations are required), Struts will only 
inject request parameters into fields or setter methods that have this 
annotation. This prevents attackers from setting values on fields you didn't 
intend to expose.
+
+## Where authorization applies
+
+As of Struts 7.2.0 the `@StrutsParameter` authorization is enforced across 
every
+channel that can populate an action from request data:
+
+- [Parameters Interceptor](parameters-interceptor.html) — request parameters
+  (default, governed by `struts.parameters.requireAnnotations`).
+- [Chaining Interceptor](chaining-interceptor.html) — value-stack copying 
during
+  action chaining (opt-in via `struts.chaining.requireAnnotations`).
+- [Cookie Interceptor](cookie-interceptor.html) — cookie values.
+- [JSON](../../plugins/json) and [REST](../../plugins/rest) plugins — 
per-property
+  authorization performed during deserialization, so unauthorized fields are 
never set.
+
+## Usage
+```
+
+- [ ] **Step 2: Verify the content is present**
+
+Run: `grep -n "Where authorization applies" 
source/core-developers/struts-parameter-annotation.md`
+Expected: one match for the new section heading.
+
+- [ ] **Step 3: Commit**
+
+```bash
+git add source/core-developers/struts-parameter-annotation.md
+git commit -m "docs: make @StrutsParameter page the authorization hub 
(WW-5626/5631/5627)
+
+Co-Authored-By: Claude Opus 4.8 <[email protected]>"
+```
+
+---
+
+### Task 4: JSON plugin — deserialization limits and per-property 
authorization (WW-5618/5626)
+
+**Files:**
+- Modify: `source/plugins/json/index.md` (insert after the `### Accepting 
JSON` block, before `## JSON RPC` at line 565)
+
+- [ ] **Step 1: Add the Deserialization limits + authorization section**
+
+Use Edit. `old_string`:
+
+```
+Please be aware that those are scoped params per stack, which means, once set 
it will be used by actions in scope of this stack.
+
+## JSON RPC
+```
+
+`new_string`:
+
+````
+Please be aware that those are scoped params per stack, which means, once set 
it will be used by actions in scope of this stack.
+
+### Deserialization limits
+
+To guard against malicious or oversized payloads, JSON deserialization enforces
+the following limits. Each can be set globally as a constant or 
per-interceptor as
+a `<param>` (following the same pattern as the fileUpload interceptor):
+
+| Constant | Default | Controls |
+|----------|---------|----------|
+| `struts.json.maxElements` | `10000` | Maximum number of elements in a single 
JSON array or object |
+| `struts.json.maxDepth` | `64` | Maximum nesting depth of the JSON structure |
+| `struts.json.maxLength` | `2097152` (2 MB) | Maximum length of the JSON 
input |
+| `struts.json.maxStringLength` | `262144` (256 KB) | Maximum length of an 
individual JSON string value |
+| `struts.json.maxKeyLength` | `512` | Maximum length of a JSON object key |
+
+```xml
+<constant name="struts.json.maxLength" value="1048576"/>
+```
+
+The reader and writer implementations are also pluggable via
+`struts.json.reader` and `struts.json.writer` (both default to `struts`).
+
+### Parameter authorization
+
+JSON deserialization enforces the 
[`@StrutsParameter`](../../core-developers/struts-parameter-annotation.html)
+annotation **per property, during deserialization** — unauthorized fields are
+never set on the target object. Annotate the action properties that may be
+populated from the JSON request body.
+
+## JSON RPC
+````
+
+- [ ] **Step 2: Verify the content is present**
+
+Run: `grep -nE "struts.json.maxElements|per property, during deserialization" 
source/plugins/json/index.md`
+Expected: two matches (the limits table row and the authorization paragraph).
+
+- [ ] **Step 3: Commit**
+
+```bash
+git add source/plugins/json/index.md
+git commit -m "docs: document JSON deserialization limits and per-property 
authorization (WW-5618/5626)
+
+Co-Authored-By: Claude Opus 4.8 <[email protected]>"
+```
+
+---
+
+### Task 5: REST plugin — authorization-aware content type handlers (WW-5626)
+
+**Files:**
+- Modify: `source/plugins/rest/index.md` (append a paragraph to the end of the 
`### Custom ContentTypeHandlers` section, before `### Settings` at line 316)
+
+- [ ] **Step 1: Add the authorization note**
+
+Use Edit. `old_string`:
+
+```
+```xml
+<constant name="struts.rest.handlerOverride.xml" value="myXml"/>
+```
+
+### Settings
+```
+
+`new_string`:
+
+```
+```xml
+<constant name="struts.rest.handlerOverride.xml" value="myXml"/>
+```
+
+As of Struts 7.2.0 the built-in content type handlers enforce the
+[`@StrutsParameter`](../../core-developers/struts-parameter-annotation.html)
+annotation per property during deserialization. Custom handlers that need the
+same property-level authorization should implement
+`AuthorizationAwareContentTypeHandler` (which extends `ContentTypeHandler` with
+authorization callbacks) instead of `ContentTypeHandler` directly.
+
+### Settings
+```
+
+- [ ] **Step 2: Verify the content is present**
+
+Run: `grep -n "AuthorizationAwareContentTypeHandler" 
source/plugins/rest/index.md`
+Expected: one match in the `### Custom ContentTypeHandlers` section.
+
+- [ ] **Step 3: Commit**
+
+```bash
+git add source/plugins/rest/index.md
+git commit -m "docs: note AuthorizationAwareContentTypeHandler in REST plugin 
(WW-5626)
+
+Co-Authored-By: Claude Opus 4.8 <[email protected]>"
+```
+
+---
+
+### Task 6: Build verification
+
+**Files:** none (verification only)
+
+- [ ] **Step 1: Build the site**
+
+Run: `bundle exec jekyll build --trace`
+Expected: build completes with no errors; the five modified pages are present 
under `target/` (or the configured destination).
+
+If `bundle` is unavailable locally, instead run the Docker build per 
`CLAUDE.md`
+(`./docker-arm64-serve.sh`) and confirm the pages render. Note in the PR which
+method was used.
+
+- [ ] **Step 2: Confirm cross-links resolve**
+
+Run: `grep -rn "struts-parameter-annotation.html" 
source/core-developers/chaining-interceptor.md 
source/core-developers/cookie-interceptor.md`
+Expected: one match in each file.
+
+Run: `grep -rn "core-developers/struts-parameter-annotation.html" 
source/plugins/json/index.md source/plugins/rest/index.md`
+Expected: one match in each file.
+
+- [ ] **Step 3: No announcement files touched**
+
+Run: `git diff --name-only main...HEAD`
+Expected: only the five `source/...` doc files and the `docs/superpowers/` 
spec/plan files appear — **no** `_config.yml`, `announce-*`, or `releases.md`.
+
+---
+
+## Self-Review
+
+**Spec coverage:**
+- WW-5631 → Task 1 ✓
+- WW-5627 → Task 2 ✓
+- WW-5626 → Tasks 3 (hub), 4 (JSON), 5 (REST) ✓
+- WW-5618 → Task 4 ✓
+- Hub page (WW-5626/5631/5627) → Task 3 ✓
+- Out-of-scope items (WW-5576/5603/5635/5632 + internal) → intentionally 
excluded per spec ✓
+- Announcement mechanics excluded → verified in Task 6 Step 3 ✓
+
+**Placeholder scan:** No TBD/TODO; every edit shows the exact Markdown. ✓
+
+**Type/name consistency:** Constant names 
(`struts.chaining.requireAnnotations`,
+`struts.json.max*`, `struts.json.reader/writer`), the class
+`AuthorizationAwareContentTypeHandler`, and the cross-link target
+`struts-parameter-annotation.html` are used identically across all tasks. ✓
diff --git 
a/docs/superpowers/specs/2026-06-14-struts-720-content-audit-design.md 
b/docs/superpowers/specs/2026-06-14-struts-720-content-audit-design.md
new file mode 100644
index 000000000..e2daa421c
--- /dev/null
+++ b/docs/superpowers/specs/2026-06-14-struts-720-content-audit-design.md
@@ -0,0 +1,112 @@
+# Struts 7.2.0 Documentation Content Audit — Design
+
+**Date:** 2026-06-14
+**Scope:** Content documentation only. The release-announcement mechanics
+(`_config.yml` bump, `announce-YYYY.md`, `releases.md`, PR, `[ANN]` email) are
+explicitly out of scope — they are handled by the `announcing-struts-release` 
skill.
+
+## Background
+
+The 7.2.0 release notes were audited against the existing site content. Several
+items were already documented in earlier PRs:
+
+- WW-5444 (HTML5 theme) — `tag-developers/html5-theme.md`, linked from 
`themes-and-templates.md` (PR #287)
+- WW-5585 (dynamic `allowedTypes`/`allowedExtensions`) — 
`action-file-upload-interceptor.md` (PR #289)
+- WW-5588 (Preparable per-method `prepare*()`) — `prepare-interceptor.md` (PR 
#289)
+- WW-4291 (Spring bean name for type converter) — `type-conversion.md` + 
`plugins/spring/index.md` (PR #289)
+- WW-5621 (XML parser hardening) — `security/index.md` (PR #289)
+
+This design covers the **remaining gaps**: the `@StrutsParameter` authorization
+expansion to three new channels, and the new JSON deserialization 
configuration.
+
+## Source of truth
+
+Every fact below is taken from the JIRA issue and confirmed against the
+`STRUTS_7_2_0` git tag:
+
+- `core/src/main/resources/org/apache/struts2/default.properties` →
+  `struts.chaining.requireAnnotations=false`
+- `plugins/json/src/main/resources/struts-plugin.xml` →
+  `struts.json.maxElements=10000`, `struts.json.maxDepth=64`,
+  `struts.json.maxLength=2097152`, `struts.json.maxStringLength=262144`,
+  `struts.json.maxKeyLength=512`, `struts.json.writer=struts`,
+  `struts.json.reader=struts`
+
+## Changes by page
+
+### 1. `source/core-developers/chaining-interceptor.md` — WW-5631
+
+Add a **"Parameter Authorization"** subsection after the existing
+`struts.xwork.chaining.copy*` constants.
+
+- New global constant `struts.chaining.requireAnnotations` (default `false`).
+- When `true`, chaining copies only properties whose target setters carry
+  `@StrutsParameter`; rejected properties are skipped and logged at WARN.
+- Uses the same `ParameterAuthorizer` service as `ParametersInterceptor`.
+- **Fail-closed:** if the target action cannot be introspected, no properties 
are copied.
+- **Global-only:** no per-interceptor override.
+- Cross-link to `struts-parameter-annotation.md`.
+
+### 2. `source/core-developers/cookie-interceptor.md` — WW-5627
+
+Add a **"Parameter Authorization"** note (page last edited 2017).
+
+- Cookie values now flow through `@StrutsParameter` authorization instead of a
+  direct `stack.setValue`, aligning with `ParametersInterceptor`.
+- **Behavior-change callout:** applications relying on cookies populating
+  un-annotated setters must add `@StrutsParameter` to those setters (or drop 
the
+  `cookiesName=*` configuration).
+- Governed by the existing `struts.parameters.requireAnnotations` setting.
+- Cross-link to `struts-parameter-annotation.md`.
+
+### 3. `source/core-developers/struts-parameter-annotation.md` — hub 
(WW-5626/5631/5627)
+
+Add a **"Where authorization applies"** section listing the channels now 
enforced:
+
+- `ParametersInterceptor` (default, governed by 
`struts.parameters.requireAnnotations`)
+- `ChainingInterceptor` (opt-in via `struts.chaining.requireAnnotations`)
+- `CookieInterceptor`
+- JSON / REST deserialization (per-property, during deserialization)
+
+Each entry links to the relevant page. This makes the annotation page the hub
+for the authorization story.
+
+### 4. `source/plugins/json/index.md` — WW-5618 + WW-5626
+
+- New **"Deserialization limits"** subsection (placed under *Accepting JSON*)
+  documenting the five limit constants with defaults:
+  - `struts.json.maxElements` = `10000`
+  - `struts.json.maxDepth` = `64`
+  - `struts.json.maxLength` = `2097152` (2 MB)
+  - `struts.json.maxStringLength` = `262144` (256 KB)
+  - `struts.json.maxKeyLength` = `512`
+  - settable globally (constant) or per-interceptor (param), following the
+    fileUpload pattern.
+- Note the pluggable `struts.json.writer` / `struts.json.reader` (default 
`struts`).
+- Note that JSON deserialization now enforces `@StrutsParameter` 
**per-property**
+  (unauthorized fields are never set), cross-linking to 
`struts-parameter-annotation.md`.
+
+### 5. `source/plugins/rest/index.md` — WW-5626
+
+In the existing *Custom ContentTypeHandlers* section:
+
+- Note the new `AuthorizationAwareContentTypeHandler` interface (property-level
+  authorization callbacks extending `ContentTypeHandler`).
+- Note that the built-in handlers now enforce `@StrutsParameter` during
+  deserialization, matching `ParametersInterceptor` per-parameter semantics.
+
+## Out of scope (flag-only — no suitable doc home)
+
+- WW-5576 (Java 25 three-letter timezone deprecation) — internal handling.
+- WW-5603 (xwork-default.xml shown as framework config file) — internal 
labeling.
+- WW-5635 (TokenHelper logs session token) — internal logging.
+- WW-5632 (commons-fileupload2 binary hardening) — no user-facing doc.
+- Internal-only: WW-5256, WW-5560, WW-5563, WW-5589, WW-5617, WW-5622, WW-5587.
+
+## Success criteria
+
+- All five pages updated with accurate constant names, defaults, and behavior 
as
+  verified against the `STRUTS_7_2_0` tag.
+- The authorization story is discoverable from `struts-parameter-annotation.md`
+  with working cross-links to chaining, cookie, JSON, and REST docs.
+- No announcement-mechanics files touched (`_config.yml`, `announce-*`, 
`releases.md`).
diff --git a/source/core-developers/chaining-interceptor.md 
b/source/core-developers/chaining-interceptor.md
index 34d6d0139..be4c591d6 100644
--- a/source/core-developers/chaining-interceptor.md
+++ b/source/core-developers/chaining-interceptor.md
@@ -37,6 +37,27 @@ the below three constants in struts.properties or struts.xml:
 <constant name="struts.xwork.chaining.copyErrors" value="true"/>
 ```
 
+## Parameter Authorization
+
+By default the Chaining Interceptor copies **all** properties of the objects on
+the value stack into the target action, regardless of any `@StrutsParameter`
+annotation. To restrict copying to annotated properties only, set the global
+constant:
+
+```xml
+<constant name="struts.chaining.requireAnnotations" value="true"/>
+```
+
+When enabled (default is `false`):
+
+- Only properties whose target setters carry 
[`@StrutsParameter`](struts-parameter-annotation.html)
+  are copied; rejected properties are skipped and logged at `WARN`.
+- Authorization uses the same `ParameterAuthorizer` service as the
+  [Parameters Interceptor](parameters-interceptor.html), keeping semantics 
consistent.
+- The behaviour is **fail-closed**: if the target action cannot be 
introspected,
+  no properties are copied.
+- This is a **global** constant only — there is no per-interceptor override.
+
 ## Parameters
 
  - `excludes` (optional) - the list of parameter names to exclude from copying 
(all others will be included)
diff --git a/source/core-developers/cookie-interceptor.md 
b/source/core-developers/cookie-interceptor.md
index 6381b4f51..768e6bc27 100644
--- a/source/core-developers/cookie-interceptor.md
+++ b/source/core-developers/cookie-interceptor.md
@@ -23,6 +23,19 @@ into Struts' action.
 
 The action could implement `CookiesAware` in order to have a `Map` of filtered 
cookies set into it.
 
+## Parameter Authorization
+
+Cookie values are injected through the same `@StrutsParameter` authorization 
path
+as the [Parameters Interceptor](parameters-interceptor.html) (previously the
+interceptor wrote directly to the value stack and bypassed authorization).
+
+> **Behaviour change in 7.2.0:** when annotation enforcement is active (the
+> default `struts.parameters.requireAnnotations=true`), cookies will only 
populate
+> setters marked with [`@StrutsParameter`](struts-parameter-annotation.html).
+> Applications that relied on cookies populating un-annotated setters must 
either
+> add the annotation to those setters or stop using `cookiesName=*`.
+{:.alert .alert-warning}
+
 ## Parameters
 
  - `cookiesName` (mandatory) - Name of cookies to be injected into the action. 
If more than one cookie name is desired 
diff --git a/source/core-developers/struts-parameter-annotation.md 
b/source/core-developers/struts-parameter-annotation.md
index 1e043dcd6..95bb0d414 100644
--- a/source/core-developers/struts-parameter-annotation.md
+++ b/source/core-developers/struts-parameter-annotation.md
@@ -12,6 +12,19 @@ parent:
 
 Why it matters: by default (when annotations are required), Struts will only 
inject request parameters into fields or setter methods that have this 
annotation. This prevents attackers from setting values on fields you didn't 
intend to expose.
 
+## Where authorization applies
+
+As of Struts 7.2.0 the `@StrutsParameter` authorization is enforced across 
every
+channel that can populate an action from request data:
+
+- [Parameters Interceptor](parameters-interceptor.html) — request parameters
+  (default, governed by `struts.parameters.requireAnnotations`).
+- [Chaining Interceptor](chaining-interceptor.html) — value-stack copying 
during
+  action chaining (opt-in via `struts.chaining.requireAnnotations`).
+- [Cookie Interceptor](cookie-interceptor.html) — cookie values.
+- [JSON](../../plugins/json) and [REST](../../plugins/rest) plugins — 
per-property
+  authorization performed during deserialization, so unauthorized fields are 
never set.
+
 ## Usage
 
 The placement of the `@StrutsParameter` annotation is crucial and depends on 
how you want to populate your action properties.
diff --git a/source/plugins/json/index.md b/source/plugins/json/index.md
index dc4a3341d..cfa7cff04 100644
--- a/source/plugins/json/index.md
+++ b/source/plugins/json/index.md
@@ -562,6 +562,34 @@ and `jsonRpcContentType` params, see example:
 
 Please be aware that those are scoped params per stack, which means, once set 
it will be used by actions in scope of this stack.
 
+### Deserialization limits
+
+To guard against malicious or oversized payloads, JSON deserialization enforces
+the following limits. Each can be set globally as a constant or 
per-interceptor as
+a `<param>` (following the same pattern as the fileUpload interceptor):
+
+| Constant | Default | Controls |
+|----------|---------|----------|
+| `struts.json.maxElements` | `10000` | Maximum number of elements in a single 
JSON array or object |
+| `struts.json.maxDepth` | `64` | Maximum nesting depth of the JSON structure |
+| `struts.json.maxLength` | `2097152` (2 MB) | Maximum length of the JSON 
input |
+| `struts.json.maxStringLength` | `262144` (256 KB) | Maximum length of an 
individual JSON string value |
+| `struts.json.maxKeyLength` | `512` | Maximum length of a JSON object key |
+
+```xml
+<constant name="struts.json.maxLength" value="1048576"/>
+```
+
+The reader and writer implementations are also pluggable via
+`struts.json.reader` and `struts.json.writer` (both default to `struts`).
+
+### Parameter authorization
+
+JSON deserialization enforces the 
[`@StrutsParameter`](../../core-developers/struts-parameter-annotation.html)
+annotation **per property, during deserialization** — unauthorized fields are
+never set on the target object. Annotate the action properties that may be
+populated from the JSON request body.
+
 ## JSON RPC
 
 The json plugin can be used to execute action methods from javascript and 
return the output. This feature was developed 
diff --git a/source/plugins/rest/index.md b/source/plugins/rest/index.md
index 9528404fb..004d21c34 100644
--- a/source/plugins/rest/index.md
+++ b/source/plugins/rest/index.md
@@ -313,6 +313,13 @@ look like this:
 <constant name="struts.rest.handlerOverride.xml" value="myXml"/>
 ```
 
+As of Struts 7.2.0 the built-in content type handlers enforce the
+[`@StrutsParameter`](../../core-developers/struts-parameter-annotation.html)
+annotation per property during deserialization. Custom handlers that need the
+same property-level authorization should implement
+`AuthorizationAwareContentTypeHandler` (which extends `ContentTypeHandler` with
+authorization callbacks) instead of `ContentTypeHandler` directly.
+
 ### Settings
 
 The following settings can be customized. See the [developer 
guide](/core-developers/configuration-files).

Reply via email to