Skip to content
RESEARCH INDEX BREACHROAD / INTELLIGENCE NOTE

Apache Struts CVE-2026-73634 and 73635: two inputs, one heap DoS

Unbounded CSP reports and request-driven locale caches can exhaust the Java heap. We analyse S2-073, S2-074, mitigations and fixed releases.

PUBLIC RESEARCH
AUTHOR
/ Breachroad CEO · OSCP · PNPT
PUBLISHED
15 August 2026
READING TIME
15 min read
TOPIC
Vulnerabilities and CVEs
Apache Struts CVE-2026-73634 and 73635: two inputs, one heap DoS

CVE-2026-73634 and CVE-2026-73635 for Apache Struts were published on 15 August 2026. Both vulnerabilities enable remote exhaustion of a Java process, but consume different resources. The first lets an unbounded Content Security Policy violation report enter memory. The second drives unbounded growth of localised-text caches with a request-controlled locale.

Apache documents the issues in S2-073 and S2-074. Both CVE records carry a 7.5 CVSS 3.1 score. Fixes are available in Struts 6.11.0 and 7.3.0. Although the project labels the maximum severity moderate, an unauthenticated client can still disrupt an entire public service.

CVE-2026-73634: a CSP report without a boundary

Content Security Policy can tell a browser to report violations, such as an attempt to load a script from a forbidden domain. Struts provides an optional facility for collecting those reports. The endpoint is normally public because a user’s browser submits the request automatically rather than an authenticated administrator.

Affected releases read the report into memory without a limit. Allocation therefore grew with request content. A client could submit an exceptionally large body and force the JVM into high heap consumption, expensive garbage collection and ultimately OutOfMemoryError or loss of responsiveness.

There is an important exposure constraint: Struts core does not map a reporting endpoint by default, and merely enabling CSP support does not publish one. Applications are affected when they explicitly configure a route that collects reports. Version alone does not prove reachability, but the absence of a visible form proves nothing either; the mapping may exist only in deployment configuration.

Fixed releases read reports up to a limit. The default is 8,192 characters, adjustable through struts.csp.report.maxSize between 1 and 1,048,576. An oversized report is discarded and logged as a warning. The boundary is enforced in the layer that understands the feature, before unbounded allocation.

CVE-2026-73635: request-controlled cache growth

The second issue needs no giant request. Struts looks up localised text for validation, type-conversion messages and other elements. When an application does not set a fixed locale, the framework may take the locale from the client request.

Affected releases did not effectively bound the internal cache cardinality. An attacker can generate many distinct locale values and cause more cache combinations to be created. Every request can be small while memory grows cumulatively. Instead of one giant body, this DoS uses a sequence of cheap inputs that leave persistent state on the heap.

The version range is broad: Struts 2.0.0–2.3.37, 2.5.0–2.5.33, 6.0.0–6.10.0 and 7.0.0–7.2.1. The 2.3 and 2.5 lines are end of life, so a configuration workaround is not a sustainable solution.

In 6.11.0 and 7.3.0 the caches are bounded, with size configurable through struts.i18n.cacheMaxSize. struts.locale.validateRequestLocale can also restrict request locales to the set available in the runtime. Request-locale validation is disabled by default, so teams should choose the setting deliberately.

Two resource-exhaustion models

The first vulnerability is proportional to input size: the attacker sends many bytes and the server allocates memory. A reverse-proxy body limit can materially reduce exposure when it applies to the correct route and traffic cannot bypass the proxy.

The second is proportional to input diversity. Each request can fit a small body limit, but a new value creates new cache state. Body-size controls do not help. Defenders need cardinality limits, validation against a known set, bounded caches or a fixed locale.

This difference matters in threat modelling. Rate limiting slows both attacks without removing the cause. A large burst can be stopped by throughput controls, while slow cache filling may fit normal request volume and become visible only after hours.

Who should respond first

Every Apache Struts team should identify the exact production version. For CVE-2026-73634, inspect action mappings for CSP reporting and public reachability. For CVE-2026-73635, determine whether struts.locale is fixed to a supported value.

Priority goes to Internet-facing applications with a small heap, shared JVM components, or automatic restarts without loop protection. In a cluster, an attacker can repeat the pressure across pods, while autoscaling may only increase incident cost.

Do not rely solely on a Server header or an external scanner. Struts is often packaged in a WAR behind a proxy. Review the SBOM, Maven or Gradle dependencies, image contents and classes actually loaded at runtime.

Upgrades and workarounds

Users on 6.x should move to at least 6.11.0, while 7.x users need 7.3.0. End-of-life lines require migration to a supported release. Before production rollout, test validation, message localisation, CSP reporting and custom classes extending the reporting action.

If the CVE-2026-73634 update must wait, remove the CSP-report endpoint mapping. Where the feature is required, enforce a request-body limit at the reverse proxy or servlet container. Apache notes that struts.csp.report.maxSize exists only in fixed releases and is not a workaround for an affected framework.

For CVE-2026-73635, configure a fixed struts.locale. Localised lookups then stop using the request locale, removing the vulnerable route. This is effective for a genuinely single-language application. A multilingual service should move to bounded caches and allow only required locales.

Observability and detection

For CSP reports, monitor request size, body-read time, 413/500 responses and memory growth without corresponding business traffic. Exceptionally large POST requests to the report route are a strong indicator. Logging full bodies may double resource use and expose data, so retain metadata rather than content.

For locale abuse, track distinct-value count over time, cache size and allocation rate. Separate supported values such as pl-PL and en-US from random combinations. Correlate JVM old-generation occupancy, full-GC frequency, pause time and restarts with routes and input metadata.

An alert on OutOfMemoryError is too late. Earlier signals include a rising heap baseline after successive GC cycles, degrading response time and failure to return to the previous memory level. In Kubernetes, review OOMKilled events but remember that the container limit may terminate the process before JVM diagnostics complete.

Engineering lesson: every input needs a budget

Every untrusted input consumes a resource: memory bytes, cache entries, threads, descriptors or CPU time. A secure design sets both the maximum cost of one request and the maximum state retained after many requests. These two CVEs demonstrate both dimensions.

A cache needs a size limit, eviction policy and constrained key set. A body parser must stop once the boundary is crossed, rather than accepting everything and checking length afterwards. Controls should exist at several layers: the edge protects platform capacity while the framework protects feature semantics.

Performance tests should include hostile but safe test-environment inputs: growing bodies, many distinct keys, client disconnects and slow requests. The goal is not only average latency, but proof that cost has a hard upper bound.

Facts and Breachroad conclusions

CVE-2026-73634 affects only applications mapping a CSP-report endpoint on Struts 6.0.0–6.10.0 and 7.0.0–7.2.1. CVE-2026-73635 spans more releases, while applications with a fixed locale are not affected. Fixes are available in 6.11.0 and 7.3.0. The bulletins do not establish widespread exploitation.

Breachroad’s conclusion is that teams should use these findings to audit resource governance, not merely add two WAF signatures. If an endpoint can expand a body or cache without a boundary, similar defects may exist in uploads, parsers, sessions and telemetry. The upgrade closes known paths; a budget review removes the broader class.

If you need to assess application and API resilience against resource abuse, see our web application and API penetration testing. Java, platform and operations teams can also use cybersecurity training for organisations focused on safe limits and degradation detection.

SHARE / COPY