Mar 24, 2026·7 min read·1 visit
Unbounded JSON parsing in the Astro Server Islands endpoint allows unauthenticated attackers to exhaust Node.js heap memory, resulting in a remote Denial of Service condition.
A critical resource exhaustion vulnerability exists in the Astro web framework versions prior to 10.0.0. The Server Islands endpoint fails to enforce size limits on incoming POST request bodies, allowing an unauthenticated attacker to cause a Denial of Service (DoS) by sending a crafted JSON payload that triggers massive V8 heap memory allocation.
CVE-2026-29772 describes a resource exhaustion vulnerability within the Astro web framework, specifically affecting applications running in Server-Side Rendering (SSR) mode prior to version 10.0.0. The flaw resides in the handling of incoming HTTP POST requests directed at the Server Islands component, a feature introduced in Astro 4.12. The underlying issue is classified as CWE-770, Allocation of Resources Without Limits or Throttling, because the framework accepts and processes request bodies of arbitrary size.
The vulnerability exposes a direct path for unauthenticated attackers to induce a Denial of Service (DoS) condition against the hosting server. Astro automatically registers the /_server-islands/[name] route for all SSR applications using the Node standalone adapter. This automated registration occurs regardless of whether the application explicitly utilizes the server:defer directive associated with Server Islands, broadly expanding the attack surface.
Exploitation relies on transmitting a specifically structured JSON payload that manipulates the memory allocation behavior of the V8 JavaScript engine. Upon receiving the payload, the framework buffers the entire request into memory and attempts to parse it synchronously. This unbounded operation rapidly consumes the available heap space, leading to an Out of Memory (OOM) fatal error and the subsequent termination of the Node.js process.
The root cause originates in the getRequestData function located within packages/astro/src/core/server-islands/endpoint.ts. When processing a POST request, the endpoint handler invokes await request.text() to buffer the entire incoming request body into a single string. The handler then immediately passes this untrusted string directly to JSON.parse(). Crucially, these operations occur before the framework applies any size validation, structural checks, or authentication requirements.
The vulnerability relies heavily on the specific memory management mechanics of the V8 JavaScript engine. When JSON.parse() processes a serialized string, it must allocate heap memory for every distinct element, key, and object required to construct the resulting JavaScript object tree. Parsing a deeply nested or highly repetitive structure consisting of minimal byte-size objects forces V8 to allocate internal overhead structures for each entity.
This behavior creates a significant memory amplification effect. Security research demonstrates an approximate 15x amplification factor between the size of the network payload and the resulting heap allocation. For example, an 8.6 MB crafted JSON payload translates to over 180 MB of heap memory consumption. By submitting a payload sized slightly below standard reverse proxy limits but large enough to exceed the --max-old-space-size configuration of the Node.js runtime, the parsing operation deterministically crashes the server.
In vulnerable versions, the endpoint handles incoming POST requests by blindly reading the full text stream and passing it to the JSON parser. The vulnerable implementation pattern is straightforward and lacks defensive constraints:
// Pre-patch implementation in packages/astro/src/core/server-islands/endpoint.ts
export async function getRequestData(request: Request): Promise<Response | RenderOptions> {
// ...
case 'POST': {
try {
const raw = await request.text(); // Buffers entire body without limit
const data = JSON.parse(raw); // Parses untrusted body
// Validation occurs only after parsing completes
return data as RenderOptions;
} catch (e) {
// Error handling logic
}
}
}The official patch (commit f9ee8685dd26e9afeba3b48d41ad6714f624b12f) addresses the flaw by introducing a configurable size limit and implementing a stream reader utility. The framework now defaults to a 1MB payload limit defined by security.serverIslandBodySizeLimit. The patched implementation uses a new utility function, readBodyWithLimit, which actively monitors the stream size.
// Post-patch logic utilizing readBodyWithLimit
const bodyString = await readBodyWithLimit(request, serverIslandBodySizeLimit);
const data = JSON.parse(bodyString);The readBodyWithLimit function inspects the Content-Length header for early rejection and then tracks byte chunks as they stream into memory. If the accumulated byte count exceeds the configured limit at any point during the stream processing, the function immediately throws a BodySizeLimitError. This structural change guarantees that unbounded inputs cannot reach the vulnerable JSON.parse() sink.
Exploitation of CVE-2026-29772 requires minimal preparation and no specialized tooling. The attacker first identifies a target application running Astro in Server-Side Rendering (SSR) mode with the Node adapter. The presence of the /_server-islands/ route confirms the attack surface is active. The endpoint accepts arbitrary identifiers in the path, such as /_server-islands/any-target, making route discovery trivial.
The attacker constructs a JSON payload optimized to maximize V8 object allocation overhead while minimizing wire size. A standard payload involves generating a vast array containing empty objects, such as {"a":[{},{},{},...]}. The attacker duplicates these empty objects millions of times to generate a payload ranging from 10 MB to 50 MB, depending on the anticipated reverse proxy configuration.
The payload is delivered via an unauthenticated POST request with the Content-Type: application/json header. Upon receipt, the target server attempts to parse the payload synchronously. The parsing blocks the event loop while simultaneously driving rapid heap allocations. The Node.js process rapidly exceeds its maximum heap size limit, generating a fatal memory error and crashing the application. Successive requests prevent the application from remaining online following process restarts.
The vulnerability carries a CVSS v3.1 base score of 5.9, reflecting a medium severity rating driven primarily by the high complexity requirement. While the exploit requires zero authentication or user interaction, the target environment must explicitly run the Node standalone adapter in SSR mode. Applications operating as static sites or utilizing entirely different deployment adapters are unaffected.
The technical impact is isolated entirely to system availability. The vulnerability does not permit unauthorized data disclosure, state modification, or arbitrary code execution. However, the availability impact is absolute. A single HTTP request reliably halts the Node.js process, severing service for all concurrent users and halting application operations.
> [!NOTE] > Process managers such as PM2 or systemd will typically restart the crashed Node.js process automatically. However, an attacker can maintain a persistent Denial of Service state by submitting the exploit payload in an automated loop, continuously crashing newly spawned worker processes faster than they can serve legitimate traffic.
The definitive remediation for CVE-2026-29772 requires updating the Astro framework and its associated Node adapter. Development and operations teams must upgrade the astro and @astrojs/node packages to version 10.0.0 or later. This upgrade installs the readBodyWithLimit stream validator and enforces the new 1MB default body size limit for the Server Islands endpoint.
Organizations that require larger payload capacities for their specific Server Islands implementations can safely modify the default limit. This requires adding the security.serverIslandBodySizeLimit parameter to the astro.config.mjs configuration file. The value is defined in bytes, allowing administrators to establish an exact ceiling that accommodates legitimate application traffic while preventing unbounded memory consumption.
In scenarios where immediate patching is unfeasible, administrators can apply mitigation controls at the network edge. Web Application Firewalls (WAF) or reverse proxies (such as Nginx or HAProxy) should be configured to strictly limit the client_max_body_size specifically for POST requests targeting the /_server-islands/.* path. Enforcing a strict 1MB limit at the proxy layer replicates the patch behavior and neutralizes the exploitation vector.
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
Astro withastro | < 10.0.0 | 10.0.0 |
| Attribute | Detail |
|---|---|
| CWE | CWE-770 |
| Attack Vector | Network |
| CVSS | 5.9 (Medium) |
| Impact | High (Denial of Service) |
| Exploit Status | Proof of Concept |
The software allocates a reusable resource or group of resources on behalf of an actor without any limits, which can lead to resource exhaustion.