A structured threat model for the Apache Struts framework — scope, adversary model, the security properties the framework provides vs. leaves to the application, and a triage-disposition guide for inbound reports and automated-scanner findings — is maintained in THREAT_MODEL.md. It is additive to this policy: this SECURITY.md and the security guidance remain canonical for the reporting process and configuration details.
Please visit the Releases page to see full information about each version and what potential vulnerability it can have:
| Version | Supported |
|---|---|
| 7.x | yes |
| 6.x.x | yes |
| 2.5.x | no |
| 2.3.x | no |
| 2.2.x | no |
| 2.1.x | no |
| 2.0.x | no |
(original)
The Apache Struts project takes a very active stance in eliminating security problems and denial of service attacks against applications using the Apache Struts framework.
We strongly encourage folks to report such security problems to our private security mailing list first, before disclosing them in a public forum.
We cannot accept regular bug reports or other queries at this address, we ask that you use our issue tracker (JIRA) for those.
All mail sent to this address that does not relate to security problems in the Apache Struts source code will be ignored
Note that all networked servers are subject to denial of service attacks, and we cannot promise magic workarounds to generic problems (such as a client streaming lots of data to your server or requesting the same URL repeatedly). In general, our philosophy is to avoid any attacks that can cause the server to consume resources in a non-linear relationship to the size of inputs.
To be clear about the linear cases: that philosophy describes what we design against, not a threshold a report has to clear before we will accept it. Framework code that reads or retains request-derived input without any bound is in scope even where the growth is merely linear, and we have assigned CVEs for exactly that. The reason is the control test below: THREAT_MODEL.md §8.7 promises that framework code reads and retains request-derived input under a limit, and that promise is a claimed control. What stays out of scope is the generic case above — where the cost to the server is proportionate, no framework limit is missing or ineffective, and the defence belongs to your servlet container, reverse proxy, or network.
The question we ask is not “can this input hurt a server” but “does the framework claim a control here, and does that control do what it says”. A control is claimed wherever the framework documents it: a setting, a limit, a filter, or one of the security properties in THREAT_MODEL.md §8.
@StrutsParameter control, new to the REST body path in 7.2.0, to the body properties it did not yet reach (WW-5642) is the precedent. Where the control is applied to a channel and does not hold there, the previous bullet applies.A consequence worth stating: adding a control moves the line. The same request that was a hardening report before a limit existed becomes a vulnerability report if the limit, once added, can be bypassed. The JSON plugin's input limits were added as hardening in WW-5618 (6.9.0 / 7.2.1) — at that point the plugin promised no bound and §8.7 had not yet been written, so no control was claimed; the later finding that the length limit could be bypassed was CVE-2026-73633 (S2-072). Those are two findings, not one, and they were credited separately.
The mailing address is: security@struts.apache.org
General network server security tips
A fix is a disclosure. Opening a public pull request, pushing a commit, branch, or fork, or filing a public Jira/GitHub issue that fixes, describes, or hints at a suspected vulnerability reveals where the weakness is — often with a working roadmap to exploit it — before a fixed release exists. This holds even if you never attach a proof-of-concept, and even if you believe the impact is low or you are “just hardening” the code.
If you have found, or suspect you have found, a security problem:
If you notice a possible security issue while working on an unrelated bug or PR, stop and email the private list before pushing the change. When in doubt, treat it as security-sensitive and email the list — a private report that turns out to be a non-issue costs far less than a public change that turns out to be exploitable.
Before sending a vulnerability report, run through the following checks. They exist to prevent duplicate reports, public disclosure of untriaged issues, and reports for behavior that is already documented as insecure configuration.
Confirm:
Review the Struts security guidance and determine whether the finding is already covered by documented secure configuration or application guidance, including but not limited to:
devMode is required to exploit the vulnerability,@StrutsParameter usage and parameter annotation requirements,If the behavior is caused by an application ignoring documented security guidance, that is not an Apache Struts framework vulnerability.
Compare the finding against already disclosed Struts vulnerabilities — affected versions, impact ratings, mitigations, and fixed versions:
If the finding overlaps with a known vulnerability, link to the existing bulletin, advisory, CVE, or release notes instead of drafting a new report.
Before drafting a report, confirm:
Only proceed with a private report when these answers still point to a likely new vulnerability in the framework.
A useful private report includes:
Do not speculate beyond what can be demonstrated. If severity is uncertain, say so explicitly.