Public mode

No access to your tenant or devices. Every item links to its source. What this means

Some sources, documents or advisories need attention: 274/275 feeds/APIs · 469/469 docs · 8/9 advisories · checked 10:01 UTC Customize Public modeDiscuss ChangeIntel on Discord

Astro: URL manipulation via unsanitized headers leads to path-based middleware protections bypass, potential SSRF/cache-poisoning, CVE-2025-61925 bypass

Collected exploitation and prediction evidence

Risk source coverage

CISA KEV is observed exploitation evidence. FIRST EPSS is a dated prediction of exploitation in the next 30 days. Missing scores are unknown. This collector requests predictions only for explicit CVE aliases in the public NuGet archive; Microsoft release views retain their existing prediction scope.

No collected risk observation for these identifiers. This does not establish absence of exploitation or a zero probability.

cve-program · CVE-2025-64525

Published

Astro is a web framework. In Astro versions 2.16.0 up to but excluding 5.15.5 which utilizeon-demand rendering, request headers `x-forwarded-proto` and `x-forwarded-port` are insecurely used, without sanitization, to build the URL. This has several consequences, the most important of which are: middleware-based protected route bypass (only via `x-forwarded-proto`), DoS via cache poisoning (if a CDN is present), SSRF (only via `x-forwarded-proto`), URL pollution (potential SXSS, if a CDN is present), and WAF bypass. Version 5.15.5 contains a patch.

Source published
13 Nov 2025 15:58:16 UTC
Source modified
13 Nov 2025 16:15:18 UTC
Observed here
23 Oct 2026 15:48:27 UTC
Source terms
CVE Program Terms of Use

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: cve-program · CVE Program Terms of Use. Source text is retained; field grouping and change labels are provided by ChangeIntel.

CVSS 3.1 · 6.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:L

euvd · EUVD-2025-175298

Published

Astro is a web framework. In Astro versions 2.16.0 up to but excluding 5.15.5 which utilizeon-demand rendering, request headers `x-forwarded-proto` and `x-forwarded-port` are insecurely used, without sanitization, to build the URL. This has several consequences, the most important of which are: middleware-based protected route bypass (only via `x-forwarded-proto`), DoS via cache poisoning (if a CDN is present), SSRF (only via `x-forwarded-proto`), URL pollution (potential SXSS, if a CDN is present), and WAF bypass. Version 5.15.5 contains a patch.

EUVD source date text has no stated timezone and is retained without inventing a UTC instant. Related bulletin membership is not an alias, common cause or applicability claim. A missing vector with a zero score is treated as unrated. Complete vendor/product and underlying source evidence remains in the original JSON.

Original publisher date fields

datePublished: Nov 13, 2025, 3:58:16 PM

dateUpdated: Nov 13, 2025, 4:15:18 PM

Source published
Nov 13, 2025, 3:58:16 PM (timezone not stated)
Source modified
Nov 13, 2025, 4:15:18 PM (timezone not stated)
Observed here
11 Nov 2026 04:31:48 UTC
Source terms
ENISA EUVD · source terms and attribution apply

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: euvd · ENISA EUVD · source terms and attribution apply. Source text is retained; field grouping and change labels are provided by ChangeIntel.

EUVD CVSS 3.1 · 6.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:L

nvd · CVE-2025-64525

Published

Astro is a web framework. In Astro versions 2.16.0 up to but excluding 5.15.5 which utilizeon-demand rendering, request headers `x-forwarded-proto` and `x-forwarded-port` are insecurely used, without sanitization, to build the URL. This has several consequences, the most important of which are: middleware-based protected route bypass (only via `x-forwarded-proto`), DoS via cache poisoning (if a CDN is present), SSRF (only via `x-forwarded-proto`), URL pollution (potential SXSS, if a CDN is present), and WAF bypass. Version 5.15.5 contains a patch.

NVD analysis and CPE criteria are source context, not proof that a package or your environment is affected. Complete affected data, logical configurations and SSVC are retained in the original JSON.

Source analysis status: Analyzed

Weakness classifications: CWE-918

Original publisher date fields

published: 2025-11-13T16:15:56.447

lastModified: 2026-10-07T21:10:00.200

1 source CPE criteria · context only
  • cpe:2.3:a:astro:astro:*:*:*:*:*:node.js:*:*

The original JSON retains the logical configuration operators, exclusions and version bounds.

Source published
13 Nov 2025 16:15:56 UTC
Source modified
7 Oct 2026 21:10:00 UTC
Observed here
25 Oct 2026 03:17:29 UTC
Source terms
NIST NVD usage terms; underlying source attribution retained

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: nvd · NIST NVD usage terms; underlying source attribution retained. Source text is retained; field grouping and change labels are provided by ChangeIntel.

CVSS 3.1 · [email protected] · Secondary · 6.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:L

osv · GHSA-hr2q-hp5q-x767

Published

## Summary In impacted versions of Astro using [on-demand rendering](https://docs.astro.build/en/guides/on-demand-rendering/), request headers `x-forwarded-proto` and `x-forwarded-port` are insecurely used, without sanitization, to build the URL. This has several consequences the most important of which are: - Middleware-based protected route bypass (only via `x-forwarded-proto`) - DoS via cache poisoning (if a CDN is present) - SSRF (only via `x-forwarded-proto`) - URL pollution (potential SXSS, if a CDN is present) - WAF bypass ## Details The `x-forwarded-proto` and `x-forwarded-port` headers are used without sanitization in two parts of the Astro server code. The most important is in the `createRequest()` function. Any configuration, including the default one, is affected: [https://github.com/withastro/astro/blob/970ac0f51172e1e6bff4440516a851e725ac3097/packages/astro/src/core/app/node.ts#L97](https://github.com/withastro/astro/blob/970ac0f51172e1e6bff4440516a851e725ac3097/packages/astro/src/core/app/node.ts#L97) [https://github.com/withastro/astro/blob/970ac0f51172e1e6bff4440516a851e725ac3097/packages/astro/src/core/app/node.ts#L121](https://github.com/withastro/astro/blob/970ac0f51172e1e6bff4440516a851e725ac3097/packages/astro/src/core/app/node.ts#L121) These header values are then used directly to construct URLs. By injecting a payload at the protocol level during URL creation (via the `x-forwarded-proto` header), the entire URL can be rewritten, including the host, port and path, and then pass the rest of the URL, the real hostname and path, as a query so that it doesn't affect (re)routing. If the following header value is injected when requesting the path `/ssr`: ``` x-forwarded-proto: https://www.malicious-url.com/?tank= ``` The complete URL that will be created is: `https://www.malicious-url.com/?tank=://localhost/ssr` As a reminder, URLs are created like this: ``` url = new URL(`${protocol}://${hostnamePort}${req.url}`); ``` The value is injected at the beginning of the string (`${protocol}`), and ends with a query `?tank=` whose value is the rest of the string, `://${hostnamePort}${req.url}`. This way there is control over the routing without affecting the path, and the URL can be manipulated arbitrarily. This behavior can be exploited in various ways, as will be seen in the PoC section. The same logic applies to `x-forwarded-port`, with a few differences. > [!NOTE] > The `createRequest` function is called every time a non-static page is requested. Therefore, all non-static pages are exploitable for reproducing the attack. ## PoC The PoC will be tested with a minimal repository: - Latest Astro version at the time (`2.16.0`) - The Node adapter - Two simple pages, one SSR (`/ssr`), the other simulating an admin page (`/admin`) protected by a middleware - A middleware example copied and pasted from the official Astro documentation to protect the admin page based on the path [Download the PoC repository](https://github.com/zhero-web-sec/astro-app) ### Middleware-based protected route bypass - x-forwarded-proto only The middleware has been configured to protect the `/admin` route based on [the official documentation](https://docs.astro.build/en/guides/authentication/): ```ts // src/middleware.ts import { defineMiddleware } from "astro/middleware"; export const onRequest = defineMiddleware(async (context, next) => { const isAuthed = false; // auth logic if (context.url.pathname === "/admin" && !isAuthed) { return context.redirect("/"); } return next(); }); ``` 1. When tryint to access `/admin` the attacker is naturally redirected : ```sh curl -i http://localhost:4321/admin ``` <img width="620" height="102" alt="image" src="https://github.com/user-attachments/assets/15a7bffc-ee56-4ed9-84b2-091cf4d78351" /> 2. The attackr can bypass the middleware path check using a malicious header value: ```sh curl -i -H "x-forwarded-proto: x:admin?" http://localhost:4321/admin ``` <img width="1348" height="159" alt="image" src="https://github.com/user-attachments/assets/d9d9ac1a-5efa-452b-981e-efea8a08d089" /> #### How ​​is this possible? Here, with the payload `x:admin?`, the attacker can use the URL API parser to their advantage: - `x:` is considered the protocol - Since there is no `//`, the parser considers there to be no authority, and everything before the `?` character is therefore considered part of the path: `admin` During a path-based middleware check, the *path* value begins with a `/`: `context.url.pathname === "/admin"`. However, this is not the case with this payload; `context.url.pathname === "admin"`, the absence of a slash satisfies both the middleware check and the router and consequently allows us to bypass the protection and access the page. ### SSRF As seen, the request URL is built from untrusted input via the `x-forwarded-protocol` header, if it turns out that this URL is subsequently used to perform external network calls, for an API for example, this allows an attacker to supply a malicious URL that the server will fetch, resulting in server-side request forgery (SSRF). Example of code reusing the "origin" URL, concatenating it to the API endpoint : <img width="601" height="418" alt="image" src="https://github.com/user-attachments/assets/9c374b2c-841c-48d6-98f1-3b3f5b060802" /> ### DoS via cache poisoning If a CDN is present, it is possible to force the caching of bad pages/resources, or 404 pages on the application routes, rendering the application unusable. A `404` cab be forced, causing an error on the `/ssr` page like this : `curl -i -H "x-forwarded-proto: https://localhost/vulnerable?" http://localhost:4321/ssr` <img width="998" height="108" alt="image" src="https://github.com/user-attachments/assets/4bab58e5-3045-4e25-9aa2-2f72a0832d86" /> Same logic applies to `x-forwarded-port` : `curl -i -H "x-forwarded-port: /vulnerable?" http://localhost:4321/ssr` #### How ​​is this possible? The router sees the request for the path `/vulnerable`, which does not exist, and therefore returns a `404`, while the potential CDN sees `/ssr` and can then cache the `404` response, consequently serving it to all users requesting the path `/ssr`. ### URL pollution The exploitability of the following is also contingent on the presence of a CDN, and is therefore cache poisoning. If the value of `request.url` is used to create links within the page, this can lead to Stored XSS with `x-forwarded-proto` and the following value: ``` x-forwarded-proto: javascript:alert(document.cookie)// ``` results in the following URL object: <img width="444" height="202" alt="image" src="https://github.com/user-attachments/assets/c2990626-da5b-4868-9093-dbb9b34780ba" /> It is also possible to inject any link, always, if the value of `request.url` is used on the server side to create links. ``` x-forwarded-proto: https://www.malicious-site.com/bad? ``` **The attacker is more limited with `x-forwarded-port`** If the value of `request.url` is used to create links within the page, this can lead to broken links, with the header and the following value: ``` X-Forwarded-Port: /nope? ``` Example of an Astro website: <img width="1627" height="298" alt="Capture d’écran 2025-11-03 à 22 07 14" src="https://github.com/user-attachments/assets/02de5e67-f48d-4bf4-810d-6b0714ad2c12" /> ### WAF bypass For this section, Astro invites users to read previous research on the React-Router/Remix framework, in the section "Exploitation - WAF bypass and escalations". This research deals with a similar case, the difference being that the vulnerable header was `x-forwarded-host` in their case: [https://zhero-web-sec.github.io/research-and-things/react-router-and-the-remixed-path](https://zhero-web-sec.github.io/research-and-things/react-router-and-the-remixed-path) Note: A section addressing DoS attacks via cache poisoning using the same vector was also included there. ### CVE-2025-61925 complete bypass It is possible to completely bypass the vulnerability patch related to the `X-Forwarded-Host` header. By sending `x-forwarded-host` with an empty value, the `forwardedHostname` variable is assigned an empty string. Then, during [the subsequent check](https://github.com/withastro/astro/blob/7a5f28006e9b1f6ad77c7884991ba551ca9ff35b/packages/astro/src/core/app/node.ts#L107), the condition fails because `forwardedHostname ` returns `false`, its value being an empty string: ``` if (forwardedHostname && !App.validateForwardedHost(...)) ``` Consequently, the implemented check is bypassed. From this point on, since the request has no `host` (*its value being an empty string*), the path value is retrieved by the URL parser to set it as the `host`. This is because the `http/https` schemes are considered special schemes by the [WHATWG URL Standard Specification](https://url.spec.whatwg.org/#scheme-state), requiring an `authority state`. From there, the following request on the example SSR application (astro repo) yields an SSRF: <img width="1878" height="456" alt="Capture d’écran 2025-11-06 à 21 18 26" src="https://github.com/user-attachments/assets/c5cca89c-9c65-46f6-bf70-cd7a90a9e0d9" /> *empty `x-forwarded-host` + the target `host` in the path* ## Credits - Allam Rachid ([zhero;](https://zhero-web-sec.github.io/research-and-things/)) - Allam Yasser (inzo)

Source published
13 Nov 2025 22:46:24 UTC
Source modified
13 Nov 2025 22:46:24 UTC
Observed here
24 Oct 2026 13:17:17 UTC
Source terms
GitHub Advisory Database · CC-BY-4.0

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: osv · GitHub Advisory Database · CC-BY-4.0. Source text is retained; field grouping and change labels are provided by ChangeIntel.

CVSS_V3 · CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:L

Publisher rating · MODERATE

ChangeIntel

An IT change radar: releases, security, known issues, retirements, documentation changes, and service status from public sources. Every item links to supporting evidence; dates and statuses can change after they are read.

Sources read 11 Nov 10:01 UTC · 274 of 275 readable · 273 fully read · documentation 469/469 current