Skip to content

fix(deps): update dependency astro to ~6.4.0 [security]#3901

Open
renovate[bot] wants to merge 1 commit into
mainfrom
renovate-npm-astro-vulnerability
Open

fix(deps): update dependency astro to ~6.4.0 [security]#3901
renovate[bot] wants to merge 1 commit into
mainfrom
renovate-npm-astro-vulnerability

Conversation

@renovate

@renovate renovate Bot commented Apr 15, 2026

Copy link
Copy Markdown
Contributor

This PR contains the following updates:

Package Change Age Confidence
astro (source) ~6.3.8~6.4.0 age confidence

Astro: Host header SSRF in prerendered error page fetch

CVE-2026-54299 / GHSA-2pvr-wf23-7pc7

More information

Details

Summary

Astro SSR apps with prerendered error pages (/404 or /500 using export const prerender = true) fetch those pages over HTTP at runtime when an error occurs. The URL for this fetch is derived from request.url, which in turn gets its origin from the incoming Host header. When the Host header is not validated against allowedDomains, an attacker can point the fetch at an arbitrary host and read the response.

Who is affected

This affects SSR deployments that:

  1. Have a prerendered 404 or 500 page
  2. Use createRequestFromNodeRequest from astro/app/node with app.render() without overriding prerenderedErrorPageFetch — this includes custom servers built on the public API and third-party adapters

Not affected:

  • @astrojs/node >= 9.5.4 (reads error pages from disk)
  • @astrojs/cloudflare (uses the ASSETS binding)
  • The dev server (renders error pages in-process)
How it works

createRequestFromNodeRequest builds request.url from the raw Host / :authority header. The allowedDomains option is accepted but only gates X-Forwarded-For — it does not constrain the URL origin. (The public createRequest does fall back to localhost for unvalidated hosts; this internal builder did not.)

When app.render() encounters a 404 or 500 with a prerendered error route, default-handler.ts constructs the error page URL using the origin from request.url and fetches it via prerenderedErrorPageFetch, which defaults to global fetch. The response body is served to the client.

An attacker sends a request with Host: attacker-host:port, triggers an error (e.g., requesting a nonexistent path for a 404), and receives the response from the attacker-controlled host reflected back.

Remediation

The error page fetch origin is now validated against allowedDomains before use. When the host is validated, the original origin is preserved. Otherwise, it falls back to localhost. The fetch is also wrapped in a try/catch so that connection failures degrade gracefully to a plain error response.

Credit

5ud0 / Tarmo Technologies

Severity

  • CVSS Score: 7.5 / 10 (High)
  • Vector String: CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:L/A:N

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


Astro: XSS via Unescaped Attribute Names in Spread Props

CVE-2026-54298 / GHSA-jrpj-wcv7-9fh9

More information

Details

Summary

The spreadAttributes function in Astro's server-side rendering pipeline iterates over object keys and passes them directly to addAttribute, which interpolates the key into the HTML output without escaping. When a developer uses the spread syntax {...props} on an HTML element and the object keys come from an untrusted source (API, CMS, URL parameters), an attacker can inject arbitrary HTML attributes including event handlers like onmousemove, onclick, or break out of the attribute context entirely to inject new elements.

Details

The vulnerable function is addAttribute at packages/astro/src/runtime/server/render/util.ts:81-141:

export function addAttribute(value: any, key: string, shouldEscape = true, tagName = '') {
    if (value == null) {
        return '';
    }
    
    return markHTMLString(` ${key}="${toAttributeString(value, shouldEscape)}"`); //  key interpolated not escaped
}

This function is called from spreadAttributes at packages/astro/src/runtime/server/index.ts:91-92:

for (const [key, value] of Object.entries(values)) {
    output += addAttribute(value, key, true, _name);
}

The toAttributeString function escapes the attribute value, but the attribute name key is never validated or escaped. An attacker can craft a JSON object with a key containing " characters to break out of the attribute context and inject event handlers.

Execution flow: User controlled object keys (from API, CMS, URL params) are spread onto element via {...props}. The compiler generates spreadAttributes(props) which iterates with Object.entries() and calls addAttribute(value, key). The key is interpolated as ` ${key}="${escapedValue}"`. A malicious key breaks attribute context, resulting in XSS.

POC

Create an SSR Astro page (src/pages/index.astro):

---
const props = JSON.parse(Astro.url.searchParams.get('props') || '{}');
---
<html>
<body>
  <h1>Hello</h1>
  <div {...props}>Move mouse here</div>
</body>
</html>

Enable SSR in astro.config.mjs (for URL based demo):

export default defineConfig({
  output: 'server'
});

Note: SSR is not required for the vulnerability to exist. In static builds (default), the attack vector is compromised data sources at build time (API, CMS, database). SSR simply makes the PoC easier to demonstrate via URL parameters.

Start the dev server and visit:

http://localhost:4321/?props={"x\" onmousemove=\"alert(document.cookie)\" y":""}

URL encoded:

http://localhost:4321/?props=%7B%22x%5C%22%20onmousemove%3D%5C%22alert(document.cookie)%5C%22%20y%22%3A%22%22%7D

View the HTML source. The output contains:

<div x" onmousemove="alert(document.cookie)" y="">Move mouse here</div>

The key x" onmousemove="alert(document.cookie)" y breaks out of the attribute context. Moving the mouse over the div executes the JavaScript.

Captura de tela 2026-06-02 005906
Impact

An attacker can execute arbitrary JavaScript in the context of a victim's browser session on any Astro application that spreads object props from untrusted sources onto HTML elements. This is a common pattern when integrating with external APIs or CMS systems. Exploitation enables session hijacking via cookie theft, credential theft by injecting fake login forms or keyloggers, defacement of the rendered page, and redirection to attacker controlled domains.

The vulnerability affects all Astro versions that support spread syntax on HTML elements and is exploitable in SSR, SSG (if build time data is compromised), and hybrid deployments.

Severity

  • CVSS Score: 4.2 / 10 (Medium)
  • Vector String: CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


Release Notes

withastro/astro (astro)

v6.4.6

Compare Source

Patch Changes
  • #​16765 b10e86e Thanks @​fkatsuhiro! - Fixes an issue where renaming an image file while the dev server is running triggers a build error. Now Astro correctly hot-reloads the image without crashing.

  • #​17026 add3df1 Thanks @​matthewp! - Hardens addAttribute to drop attribute names containing characters that are invalid per the HTML spec (", ', >, /, =, whitespace)

  • #​17033 ffda27b Thanks @​matthewp! - Validates the request origin against allowedDomains before fetching prerendered error pages. When allowedDomains is configured and the Host header matches, the original origin is used. Otherwise, the fetch falls back to localhost.

v6.4.5

Compare Source

Patch Changes
  • #​16985 4ecff32 Thanks @​maximslo! - Fixes the experimental.logger destination not being used for the "Server listening on..." startup message. The logger is now resolved before the server starts listening, and adapterLogger re-creates itself when the underlying logger changes so the startup message uses the correct destination.

  • #​16947 e0703a6 Thanks @​ematipico! - Fixes Astro.request.url not reflecting validated X-Forwarded-Proto/X-Forwarded-Host headers when security.allowedDomains is configured. Previously, only Astro.url was updated with the forwarded origin while Astro.request.url retained the socket-derived URL, causing the two to diverge behind TLS-terminating proxies.

  • #​16997 dc45246 Thanks @​matthewp! - Reverts a change to isNode runtime detection that caused a significant build time regression for Cloudflare adapter users with large prerendered sites

v6.4.4

Compare Source

Patch Changes
  • #​16926 1b39ae8 Thanks @​narendraio! - Prevents App.match() from throwing on request paths that contain an invalid percent-sequence.

  • #​16924 2c0bc94 Thanks @​astrobot-houston! - Fixes an issue where editing a client-side component (e.g. with client:idle, client:load, etc.) caused an unnecessary full program reload of the backend during development.

  • #​16958 2c1d50f Thanks @​fkatsuhiro! - Fixes a bug where static file endpoints using getStaticPaths with .html in dynamic param values (e.g. { path: 'file.html' }) would fail with a NoMatchingStaticPathFound error during build. The .html suffix is no longer incorrectly stripped from endpoint route pathnames.

  • #​16855 c610cda Thanks @​astrobot-houston! - Fixes dynamic routes returning 500 "TypeError: Missing parameter" when using domain-based i18n routing in SSR.

  • #​16946 606c37b Thanks @​ematipico! - Fixes Astro.routePattern to preserve original casing of dynamic parameter names from filenames. Previously, a file at src/pages/blog/[postId].astro would return /blog/[postid] for Astro.routePattern due to an internal .toLowerCase() call. It now correctly returns /blog/[postId].

  • #​16720 16d49b6 Thanks @​thomas-callahan-collibra! - Fix an issue where dynamic routes would return the string [object Object] instead of the expected content, in certain runtimes.

  • #​16703 17390a6 Thanks @​henrybrewer00-dotcom! - Fixes styles being stripped when the project root is started with a path whose case differs from the actual filesystem case (e.g. running astro dev from d:\dev\app while the folder on disk is D:\dev\app).

  • #​16855 c610cda Thanks @​astrobot-houston! - Fixes Astro.currentLocale returning the default locale instead of the domain's locale on dynamic routes served from a mapped domain.

v6.4.3

Compare Source

Patch Changes
  • #​16900 17a0fbd Thanks @​ocavue! - Bumps devalue dependency to v5.8.1

  • #​16016 0d85e1b Thanks @​felmonon! - Fix a false positive in the dev toolbar accessibility audit for anchors with text inside closed <details> elements.

  • #​16911 79c6c46 Thanks @​astrobot-houston! - Fixes a bug where experimental.advancedRouting with astro/hono handlers threw TypeError: Cannot read properties of undefined (reading 'route') for unmatched routes instead of rendering the custom 404 page.

  • #​16899 239c469 Thanks @​matthewp! - Fixes a false "does not call the middleware() handler" warning when using astro() in a custom src/app.ts and the first request is a redirect route.

  • #​16887 493acdb Thanks @​astrobot-houston! - Fixes redirectToDefaultLocale not working after the Advanced Routing refactoring.

  • #​16908 ef53ab9 Thanks @​florian-lefebvre! - Improves optimized fallbacks generation when using the Fonts API by using better metrics for bold variants

v6.4.2

Patch Changes
  • #​16889 b94bcfd Thanks @​Princesseuh! - Fixes a plugins is not iterable crash when using a pre-6.0 @astrojs/mdx alongside integrations (e.g. Starlight) that set markdown.remarkPlugins, markdown.rehypePlugins, or markdown.remarkRehype.

  • #​16878 b9f6bb9 Thanks @​fkatsuhiro! - Fixes an issue where on-demand (SSR) dynamic routes would return 404 when a prerendered dynamic route with the same URL pattern was sorted first alphabetically. In production builds with @astrojs/node adapter, if [a_prebuild].astro (prerender=true) came before [b_ssr].astro alphabetically, requests to URLs not in the prerendered route's static paths would 404 instead of falling through to the SSR route. The fix adds fallthrough logic so that when a prerendered dynamic route matches but can't serve the request, Astro tries subsequent matching routes.

v6.4.1

Patch Changes
  • #​16883 eeb064c Thanks @​Princesseuh! - Restores the astro/jsx/rehype.js entry point so that older versions of @astrojs/mdx continue to work when used with Astro 6.x. This entry point will be removed in Astro 7.0.

v6.4.0

Compare Source

Minor Changes
  • #​16468 4cff3a1 Thanks @​matthewp! - Adds a new preserveBuildServerDir adapter feature

    Adapters can now set preserveBuildServerDir: true in their adapter features to keep the dist/server/ directory structure for static builds, mirroring the existing preserveBuildClientDir option. This is useful for adapters that require a consistent dist/client/ and dist/server/ layout regardless of build output type.

    setAdapter({
      name: 'my-adapter',
      adapterFeatures: {
        buildOutput,
        preserveBuildClientDir: true,
        preserveBuildServerDir: true,
      },
    });
  • #​16848 f732f3c Thanks @​Princesseuh! - Adds a new markdown.processor configuration option, allowing you to choose an alternative Markdown processor.

    Websites with many Markdown/MDX files tend to be slow to build because the unified ecosystem (e.g., remark, rehype) is slow to process. This feature introduces the ability to replace this part of the build pipeline with another processor.

    The default processor is unified(). This means that existing configurations remain unchanged and your remark/rehype plugins continue to work.

    // astro.config.mjs
    import { defineConfig } from 'astro/config';
    import { unified } from '@&#8203;astrojs/markdown-remark';
    import remarkToc from 'remark-toc';
    
    export default defineConfig({
      markdown: {
        processor: unified({
          remarkPlugins: [remarkToc],
        }),
      },
    });

    In addition to this new configuration option, Astro provides a new alternative processor based on Rust: Sätteri. You can choose to use it now by installing @astrojs/markdown-satteri, importing the satteri() processor, and adapting your existing configuration:

    // astro.config.mjs
    import { defineConfig } from 'astro/config';
    import { satteri } from '@&#8203;astrojs/markdown-satteri';
    
    export default defineConfig({
      markdown: {
        processor: satteri({
          features: { directive: true },
        }),
      },
    });

    This processor does not support the remark and rehype plugins. This means you may need to convert them to MDAST or HAST plugins to retain your current functionality.

    The existing top-level markdown.remarkPlugins, markdown.rehypePlugins, markdown.remarkRehype, markdown.gfm, and markdown.smartypants options still work, but are now deprecated and will be removed in a future major update. The matching remarkPlugins, rehypePlugins, and remarkRehype options on the MDX integration are also deprecated for the same reason. To anticipate their removal, move them onto unified({...}) (or your preferred plugin processor) :

    // astro.config.mjs
    import { defineConfig } from 'astro/config';
    import remarkToc from 'remark-toc';
    import rehypeSlug from 'rehype-slug';
    + import { unified } from '@&#8203;astrojs/markdown-remark';
    
    export default defineConfig({
      markdown: {
    +    processor: unified({
    +      remarkPlugins: [remarkToc],
    +      rehypePlugins: [rehypeSlug],
    +      remarkRehype: true,
    +      gfm: true,
    +      smartypants: true,
    +    }),
    -    remarkPlugins: [remarkToc],
    -    rehypePlugins: [rehypeSlug],
    -    remarkRehype: true,
    -    gfm: true,
    -    smartypants: true,
      },
    });

    For more information on enabling and using this feature in your project, see our Markdown guide. To give feedback on this new Rust processor, see the Native Markdown / MDX parsing and processing RFC.

Patch Changes
  • #​16468 4cff3a1 Thanks @​matthewp! - Skips the static preview server when an adapter provides its own previewEntrypoint, allowing the adapter to handle both static and dynamic routes

  • #​16811 e0e26db Thanks @​matthewp! - Fixes X-Forwarded-Host and X-Forwarded-Proto headers being ignored when set in a custom src/app.ts fetch handler before creating FetchState

  • #​16468 4cff3a1 Thanks @​matthewp! - Fixes the static preview server to respect preserveBuildClientDir, serving files from build.client instead of outDir when the adapter requires it

  • #​16770 1e2aa11 Thanks @​matthewp! - Fixes a race condition where the Vite dep optimizer could lose React dependencies in dev mode when using Astro Actions

  • #​16468 4cff3a1 Thanks @​matthewp! - Exempts internal routes (e.g. server islands) from getStaticPaths() validation, fixing server island rendering on static sites

  • #​16468 4cff3a1 Thanks @​matthewp! - Fixes preview for static sites that contain non-prerendered routes. Previously, the preview command ignored SSR routes discovered during route scanning and always used the static preview server.

  • Updated dependencies [f732f3c, f732f3c]:


Configuration

📅 Schedule: (UTC)

  • Branch creation
    • At any time (no schedule defined)
  • 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 label Apr 15, 2026
@netlify

netlify Bot commented Apr 15, 2026

Copy link
Copy Markdown

Deploy Preview for brilliant-pasca-3e80ec ready!

Name Link
🔨 Latest commit c03a76f
🔍 Latest deploy log https://app.netlify.com/projects/brilliant-pasca-3e80ec/deploys/6a5c08c7d66faf0008c0eea9
😎 Deploy Preview https://deploy-preview-3901--brilliant-pasca-3e80ec.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@github-actions

github-actions Bot commented Apr 15, 2026

Copy link
Copy Markdown

🚀 Performance Test Results

Test Configuration:

  • VUs: 4
  • Duration: 1m0s

Test Metrics:

  • Requests/s: 42.49
  • Iterations/s: 14.16
  • Failed Requests: 0.00% (0 of 2557)
📜 Logs

> performance@1.0.0 run-tests:testenv /home/runner/work/rafiki/rafiki/test/performance
> ./scripts/run-tests.sh -e test -k -q --vus 4 --duration 1m

Cloud Nine GraphQL API is up: http://localhost:3101/graphql
Cloud Nine Wallet Address is up: http://localhost:3100/
Happy Life Bank Address is up: http://localhost:4100/
cloud-nine-wallet-test-backend already set
cloud-nine-wallet-test-auth already set
happy-life-bank-test-backend already set
happy-life-bank-test-auth already set
     data_received..................: 923 kB 15 kB/s
     data_sent......................: 2.0 MB 33 kB/s
     http_req_blocked...............: avg=7.8µs    min=1.66µs   med=5.79µs   max=1.83ms   p(90)=7.21µs   p(95)=7.9µs   
     http_req_connecting............: avg=416ns    min=0s       med=0s       max=315.94µs p(90)=0s       p(95)=0s      
     http_req_duration..............: avg=93.41ms  min=8.96ms   med=76.47ms  max=481.79ms p(90)=160.85ms p(95)=184.11ms
       { expected_response:true }...: avg=93.41ms  min=8.96ms   med=76.47ms  max=481.79ms p(90)=160.85ms p(95)=184.11ms
     http_req_failed................: 0.00%  ✓ 0         ✗ 2557
     http_req_receiving.............: avg=109.79µs min=28.49µs  med=91.82µs  max=2.21ms   p(90)=131.96µs p(95)=183.01µs
     http_req_sending...............: avg=41.58µs  min=9.21µs   med=28.33µs  max=2.72ms   p(90)=43.88µs  p(95)=62.55µs 
     http_req_tls_handshaking.......: avg=0s       min=0s       med=0s       max=0s       p(90)=0s       p(95)=0s      
     http_req_waiting...............: avg=93.26ms  min=8.77ms   med=76.24ms  max=481.69ms p(90)=160.68ms p(95)=183.99ms
     http_reqs......................: 2557   42.487079/s
     iteration_duration.............: avg=282.1ms  min=197.43ms med=269.36ms max=940.06ms p(90)=344.44ms p(95)=375.88ms
     iterations.....................: 852    14.156821/s
     vus............................: 4      min=4       max=4 
     vus_max........................: 4      min=4       max=4 

@renovate renovate Bot changed the title chore(deps): update dependency astro to v5.18.1 [security] chore(deps): update dependency astro to v6.1.10 [security] Jun 3, 2026
@renovate
renovate Bot force-pushed the renovate-npm-astro-vulnerability branch 3 times, most recently from 881c844 to 3ae0c29 Compare June 7, 2026 19:57
@renovate
renovate Bot force-pushed the renovate-npm-astro-vulnerability branch from 3ae0c29 to c03a76f Compare July 18, 2026 23:14
@renovate renovate Bot changed the title chore(deps): update dependency astro to v6.1.10 [security] fix(deps): update dependency astro to ~6.4.0 [security] Jul 18, 2026
@github-actions github-actions Bot added the pkg: documentation Changes in the documentation package. label Jul 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency pkg: documentation Changes in the documentation package.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants