Security
Aug 17, 2026

CVE-2026-73635 & CVE-2026-73633: Apache Struts Unauthenticated Denial of Service

How two unbounded memory reads in Struts, one in the core localized-text cache and one in the JSON plugin, let an unauthenticated client exhaust the Java heap and take the server down.

Give me the TL;DR
CVE-2026-73635 & CVE-2026-73633: Apache Struts Unauthenticated Denial of Service
For Qualys admins, NES for .NET directly resolves the EOL/Obsolete Software:   Microsoft .NET Version 6 Detected vulnerability, ensuring your systems remain secure and compliant. Fill out the form to get pricing details and learn more.

On August 14, 2026, the Apache Struts project disclosed two memory-exhaustion vulnerabilities in the same security batch: CVE-2026-73635 (bulletin S2-074) in struts2-core and CVE-2026-73633 (bulletin S2-072) in the struts2-json-plugin. Both are unauthenticated remote Denial of Service flaws. Apache rates each as Moderate; the CVSS 3.1 assessment recorded in the CVE records scores both 7.5 High (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H). CVE-2026-73635 (CWE-770) lets an unauthenticated client drive unbounded growth of Struts' internal localized-text caches when no fixed locale is configured, which is the default. CVE-2026-73633 (CWE-400) lets a client submit a JSON request body that the plugin reads into memory without bound. Both reach back into the end-of-life 2.3.x and 2.5.x lines. Struts 6.11.0 and 7.3.0 carry the upstream fixes; the EOL 2.x lines have no OSS fix available.

Affected and unsupported? See NES for Apache Struts.

What are these CVEs?

Both vulnerabilities are the same class of bug: an attacker-controlled input that Struts reads or caches without an upper bound, so a remote client can force the JVM to allocate memory until the heap is exhausted and the process stops serving requests. They live in different components and reach different version ranges, which is why they are worth covering together.

CVE-2026-73635 (S2-074): unbounded localized-text caches

This is an uncontrolled resource-allocation flaw (CWE-770) in struts2-core. Struts performs localized-text lookups to resolve messages such as type-conversion and validation errors. When no fixed locale is configured, the locale used for those lookups is taken from the incoming request. Under that default configuration, an unauthenticated remote client can send requests carrying a large number of distinct locale values, and each new locale creates new entries in Struts' internal localized-text caches. Those caches have no upper bound, so they grow without limit until the Java heap is exhausted and the server can no longer serve other users.

On the nes-2.5.x line, the unbounded structures sit in AbstractLocalizedTextProvider.java, where bundlesMap, messageFormats, and missingBundles are plain ConcurrentHashMap instances with no eviction policy. Every previously unseen locale adds keys that are never removed.

CVE-2026-73633 (S2-072): unbounded JSON request-body read

This is an uncontrolled resource-consumption flaw (CWE-400) in the optional struts2-json-plugin. When an application is configured to populate actions from a JSON request body, the plugin reads that body into memory without bounding how much it will accept. A single request can therefore cause the server to allocate memory in proportion to the size of the request, so one large body can exhaust the heap.

The critical detail for operators: the plugin's configurable limit on JSON input length does not bound this read. Teams who believe they have capped JSON input are still exposed, because that setting governs a different stage and never constrains the initial read. On the nes-2.5.x line, the unbounded read is in JSONUtil.java, where the request body is accumulated into a StringBuilder over successive readLine() calls with no size ceiling.

Severity and exploit conditions

Apache assigns both a maximum security rating of Moderate. Neither had completed NVD analysis at the time of writing (CVE-2026-73633 was Undergoing Analysis, CVE-2026-73635 was in Received status), so the authoritative numeric score is the CVSS 3.1 vector recorded in the CVE records via CISA's ADP enrichment, which is identical for both.

CVSS 3.1: 7.5 High, CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H (both CVEs)

The two CVEs differ sharply in their preconditions, and those preconditions decide whether you are actually exposed.

CVE-2026-73635 is exposed in the default configuration. Any Struts application that has not pinned a fixed locale uses the request-provided locale for message lookups, so the localized-text caches are reachable out of the box. This is the broader of the two.

CVE-2026-73633 requires the JSON plugin to be present and configured to populate actions from a JSON request body. That JSON-body population is not enabled by default. Applications that do not use the JSON plugin, or that use it only for JSON result rendering without enabling request-body population, are not exposed through this path.

Exploitation status

There is a proof-of-concept for CVE-2026-73633 circulating on public exploit aggregators as of mid-August 2026. We are not linking or reproducing it, and it is consistent with the mechanism the advisory already describes: a single oversized JSON request body against an endpoint that populates actions from JSON. The existence of a public PoC meaningfully lowers the bar for opportunistic scanning, so treat this as a patch-now item on exposed endpoints rather than a theoretical risk.

For CVE-2026-73635 we found no public proof-of-concept at the time of writing. The mechanism is straightforward to reason about (drive many distinct request locales), but no packaged exploit was observed.

Neither CVE is listed in the CISA Known Exploited Vulnerabilities catalog (catalog verified August 17, 2026), and there are no reports of active exploitation in the wild for either. Both are remote, unauthenticated, and low-complexity, so the absence of confirmed exploitation is not a reason to defer patching, especially on internet-facing Struts applications.

What an attacker can do

A remote, unauthenticated attacker who can reach an affected Struts application can:

  • Exhaust the Java heap through CVE-2026-73635 by sending a stream of requests carrying distinct locale values, each of which adds permanent entries to the unbounded localized-text caches, until the process runs out of memory and stops serving all users. No application feature beyond default message resolution is required.
  • Exhaust the Java heap through CVE-2026-73633 with a single large JSON request body against an endpoint that populates actions from JSON, since the read is not bounded and the JSON input-length limit does not constrain it. One request can be enough.
  • Take down every user on the process, not just the attacker's session. Both bugs exhaust a shared resource (the JVM heap), so a single successful attack denies service to every tenant and request served by that process.
  • Bypass application-layer input validation. Both triggers act before or outside the application's own request-size and content checks: the locale path is part of core message resolution, and the JSON body is consumed at the read stage before the plugin's configured length limit applies.
  • Repeat on reconnect. There is no credential check or request budget in either path, so a supervisor that restarts the crashed process simply provides a fresh target. Sustained repetition holds the service down.

For internet-facing Struts applications, and for any Struts service reachable by untrusted clients, both of these are straightforward remote Denial of Service.

Who is affected?

Both CVEs affect the actively supported 6.x and 7.x lines up to the fix releases, and both reach back into the end-of-life 2.3.x and 2.5.x lines. CVE-2026-73633 additionally requires the JSON plugin, which earlier 2.0.x releases did not bundle, so its lower bound starts at 2.1.8.

Apache Struts version support dates are published on the Apache Struts End-of-Life Versions page. Struts 2.5.x reached end of life on October 30, 2023, and Struts 2.3.x reached end of life on September 12, 2019. Both are well past end of life and receive no upstream security patches.

CVE-2026-73635 (localized-text caches)

CVE-2026-73633 (JSON request-body read)

Earlier 2.0.x releases do not bundle the JSON plugin and are not affected by CVE-2026-73633.

What we validated on end-of-life lines

The upstream bulletins list the 2.3.x and 2.5.x ranges as affected but do not ship fixes for them, because those lines are past end of life. We confirmed the vulnerable code is present on the nes-2.5.x line for both CVEs. For CVE-2026-73635, AbstractLocalizedTextProvider.java holds the localized-text state in unbounded ConcurrentHashMap structures (bundlesMap, messageFormats, missingBundles) with no eviction. For CVE-2026-73633, JSONUtil.java accumulates the request body into an unbounded StringBuilder across readLine() calls. If you are running Struts 2.3.x or 2.5.x, treat both as real and unpatched rather than as absent from a fix table.

Mitigation guidance

Upgrading within a supported major line is a maintenance-release change. Moving from an end-of-life 2.x line to a supported 6.x or 7.x release is a larger exercise: Struts 6.x requires a Servlet API baseline and Struts 7.x requires Java 17 and Jakarta EE, which can surface javax-to-jakarta namespace changes and dependency conflicts. That migration cost is exactly the gap remediated end-of-life builds are meant to close for teams that cannot move yet.

Related CVEs

These two were disclosed alongside three other Struts issues in the same August 2026 batch. The siblings are lower priority for end-of-life users, but worth tracking:

  • CVE-2026-73634 (S2-073): an unbounded read of a Content Security Policy violation report in struts2-core, also a 7.5 High DoS. It affects only 6.x and 7.x, because the CSP report-collection feature does not exist in the 2.x lines, and it is inert unless an application explicitly maps a report-collection endpoint.
  • CVE-2026-73631 (S2-070) and CVE-2026-73632 (S2-071): shared per-request parsing and serialization state in the JSON plugin, both introduced in and affecting only Struts 7.2.1. Neither reaches the end-of-life lines.

For the broader end-of-life picture, see our overview of Apache Struts vulnerabilities in 2026 and our analysis of why CVE-2025-68493 is a bigger warning sign for EOL Struts users.

Taking action

If you run Struts 7.x, upgrade to 7.3.0. If you run Struts 6.x, upgrade to 6.11.0. Both releases carry the fixes for CVE-2026-73635 and CVE-2026-73633, and 7.3.0 also resolves the three sibling CVEs from the same batch, so it is worth taking the release whole rather than cherry-picking.

The harder decision belongs to teams on Struts 2.3.x and 2.5.x. Those lines reached end of life on September 12, 2019 and October 30, 2023, and they will never receive an upstream fix for either CVE. We confirmed the unbounded localized-text caches and the unbounded JSON body read are both present in the final 2.5.x releases, so an internet-facing Struts 2.x application is a single unauthenticated request sequence away from a heap-exhaustion outage with no vendor advisory to point at. The public PoC already circulating for CVE-2026-73633 makes that gap more urgent, not less.

NES for Apache Struts delivers drop-in replacement builds that resolve these vulnerabilities on end-of-life Struts lines without forcing the migration to Jakarta EE and Java 17 that a jump to supported Struts would require. See NES for Apache Struts to confirm coverage for your version, or talk to our team about scoping an end-of-life Struts estate.

Table of Contents
Author
Greg Allen
Chief Technology Officer
Open Source Insights Delivered Monthly