You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When running Astro in on-demand rendering mode using a adapter such as the node adapter it is possible to maliciously send an X-Forwarded-Host header that is reflected when using the recommended Astro.url property as there is no validation that the value is safe.
Details
Astro reflects the value in X-Forwarded-Host in output when using Astro.url without any validation.
It is common for web servers such as nginx to route requests via the Host header, and forward on other request headers. As such as malicious request can be sent with both a Host header and an X-Forwarded-Host header where the values do not match and the X-Forwarded-Host header is malicious. Astro will then return the malicious value.
This could result in any usages of the Astro.url value in code being manipulated by a request. For example if a user follows guidance and uses Astro.url for a canonical link the canonical link can be manipulated to another site. It is not impossible to imagine that the value could also be used as a login/registration or other form URL as well, resulting in potential redirecting of login credentials to a malicious party.
As this is a per-request attack vector the surface area would only be to the malicious user until one considers that having a caching proxy is a common setup, in which case any page which is cached could persist the malicious value for subsequent users.
Many other frameworks have an allowlist of domains to validate against, or do not have a case where the headers are reflected to avoid such issues.
Observe that the response reflects the malicious X-Forwarded-Host header
For the more advanced / dangerous attack vector deploy the application behind a caching proxy, e.g. Cloudflare, set a non-zero cache time, perform the above curl request a few times to establish a cache, then perform the request without the malicious headers and observe that the malicious data is persisted.
Impact
This could affect anyone using Astro in an on-demand/dynamic rendering mode behind a caching proxy.
A Reflected Cross-Site Scripting (XSS) vulnerability exists in Astro's development server error pages when the trailingSlash configuration option is used. An attacker can inject arbitrary JavaScript code that executes in the victim's browser context by crafting a malicious URL. While this vulnerability only affects the development server and not production builds, it could be exploited to compromise developer environments through social engineering or malicious links.
The vulnerability was introduced in commit 536175528 (PR #12994) , as part of a feature to "redirect trailing slashes on on-demand rendered pages." The feature added a helpful 404 error page in development mode to alert developers of trailing slash mismatches.
Issue: The corrected variable, which is derived from the user-controlled pathname parameter, is directly interpolated into the HTML without proper escaping. While the pathname variable itself is escaped elsewhere in the same file (line 114: escape(pathname)), the corrected variable is not sanitized before being inserted into both the href attribute and the link text.
Attack Vector
When a developer has configured trailingSlash to 'always' or 'never' and visits a URL with a mismatched trailing slash, the development server returns a 404 page containing the vulnerable template. An attacker can craft a URL with JavaScript payloads that will be executed when the page is rendered.
PoC
Local Testing (localhost)
Basic vulnerability verification in local development environment
Show details
astro.config.mjs:
import{defineConfig}from'astro/config';exportdefaultdefineConfig({trailingSlash: 'never',// or 'always'server: {port: 3000,host: true}});
In impacted versions of Astro using 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:
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:
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
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 :
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
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:
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:
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:
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, 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, requiring an authority state.
From there, the following request on the example SSR application (astro repo) yields an SSRF: empty x-forwarded-host + the target host in the path
A vulnerability has been identified in the Astro framework's development server that allows arbitrary local file read access through the image optimization endpoint. The vulnerability affects Astro development environments and allows remote attackers to read any image file accessible to the Node.js process on the host system.
Details
Title: Arbitrary Local File Read in Astro Development Image Endpoint
Type: CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
Affected Versions: Astro v5.x development builds (confirmed v5.13.3)
Attack Vector: Network (HTTP GET request)
Authentication Required: None
The vulnerability exists in the Node.js image endpoint handler used during development mode. The endpoint accepts an href parameter that specifies the path to an image file. In development mode, this parameter is processed without adequate path validation, allowing attackers to specify absolute file paths.
// Vulnerable code in development modeif(import.meta.env.DEV){fileUrl=pathToFileURL(removeQueryString(replaceFileSystemReferences(src)));}else{// Production has proper path validation// ... security checks omitted in dev mode}
The development branch bypasses the security checks that exist in the production code path, which validates that file paths are within the allowed assets directory.
PoC
Attack Prerequisites
Astro development server must be running (astro dev)
The /_image endpoint must be accessible to the attacker
Target image files must be readable by the Node.js process
Exploit Steps
Start Astro Development Server:
astro dev # Typically runs on http://localhost:4321
Craft Malicious Request:
GET /_image?href=/[ABSOLUTE_PATH_TO_IMAGE]&w=100&h=100&f=png HTTP/1.1Host: localhost:4321
After some research it appears that it is possible to obtain a reflected XSS when the server islands feature is used in the targeted application, regardless of what was intended by the component template(s).
Details
Server islands run in their own isolated context outside of the page request and use the following pattern path to hydrate the page: /_server-islands/[name]. These paths can be called via GET or POST and use three parameters:
e: component to export
p: the transmitted properties, encrypted
s: for the slots
Slots are placeholders for external HTML content, and therefore allow, by default, the injection of code if the component template supports it, nothing exceptional in principle, just a feature.
This is where it becomes problematic: it is possible, independently of the component template used, even if it is completely empty, to inject a slot containing an XSS payload, whose parent is a tag whose name is is the absolute path of the island file. Enabling reflected XSS on any application, regardless of the component templates used, provided that the server islands is used at least once.
How ?
By default, when a call is made to the endpoint /_server-islands/[name], the value of the parameter e is default, pointing to a function exported by the component's module.
Upon further investigation, we find that two other values are possible for the component export (param e) in a typical configuration: url and file. file returns a string value corresponding to the absolute path of the island file. Since the value is of type string, it fulfills the following condition and leads to this code block:
An entire template is created, completely independently, and then returned:
the absolute path name is sanitized and then injected as the tag name
childSlots, the value provided to the s parameter, is injected as a child
All of this is done using markHTMLString. This allows the injection of any XSS payload, even if the component template intended by the application is initially empty or does not provide for the use of slots.
Proof of concept
For our Proof of Concept (PoC), we will use a minimal repository:
Latest Astro version at the time (5.15.6)
Use of Island servers, with a completely empty component, to demonstrate what we explained previously
The value of the parameter s must be in JSON format and the payload must be injected at the value level, not the key level :
Despite the initial template being empty, it is created because the value of the URL parameter e is set to file, as explained earlier. The parent tag is the name of the component's internal route, and its child is the value of the key "zhero" (the name doesn't matter) of the URL parameter s.
A mismatch exists between how Astro normalizes request paths for routing/rendering and how the application’s middleware reads the path for validation checks. Astro internally applies decodeURI() to determine which route to render, while the middleware uses context.url.pathname without applying the same normalization (decodeURI).
This discrepancy may allow attackers to reach protected routes (e.g., /admin) using encoded path variants that pass routing but bypass validation checks.
/** The main logic to route dev server requests to pages in Astro. */exportasyncfunctionhandleRequest({
pipeline,
routesList,
controller,
incomingRequest,
incomingResponse,}: HandleRequest){const{ config, loader }=pipeline;constorigin=`${loader.isHttps() ? 'https' : 'http'}://${incomingRequest.headers[':authority']??incomingRequest.headers.host}`;consturl=newURL(origin+incomingRequest.url);
let pathname: string;if(config.trailingSlash==='never'&&!incomingRequest.url){pathname='';}else{// We already have a middleware that checks if there's an incoming URL that has invalid URI, so it's safe// to not handle the error: packages/astro/src/vite-plugin-astro-server/base.tspathname=decodeURI(url.pathname);// here this url is for routing/rendering}// Add config.base back to url before passing it to SSRurl.pathname=removeTrailingForwardSlash(config.base)+url.pathname;// this is used for middleware context
Consider an application having the following middleware code:
import{defineMiddleware}from"astro/middleware";exportconstonRequest=defineMiddleware(async(context,next)=>{constisAuthed=false;// simulate no authif(context.url.pathname==="/admin"&&!isAuthed){returncontext.redirect("/");}returnnext();});
context.url.pathname is validated , if it's equal to /admin the isAuthed property must be true for the next() method to be called. The same example can be found in the official docs https://docs.astro.build/en/guides/authentication/
context.url.pathname returns the raw version which is /%61admin while pathname which is used for routing/rendering /admin, this creates a path normalization mismatch.
By sending the following request, it's possible to bypass the middleware check
GET /%61dmin HTTP/1.1
Host: localhost:3000
Remediation
Ensure middleware context has the same normalized pathname value that Astro uses internally, because any difference could allow it to bypass such checks. In short maybe something like this
pathname = decodeURI(url.pathname);
}
// Add config.base back to url before passing it to SSR
- url.pathname = removeTrailingForwardSlash(config.base) + url.pathname;+ url.pathname = removeTrailingForwardSlash(config.base) + decodeURI(url.pathname);
Thank you, let @Sudistark know if any more info is needed. Happy to help :)
Summary
A Cross-Site Scripting (XSS) vulnerability exists in Astro when using the @astrojs/cloudflare adapter with output: 'server'. The built-in image optimization endpoint (/_image) uses isRemoteAllowed() from Astro’s internal helpers, which unconditionally allows data: URLs. When the endpoint receives a valid data: URL pointing to a malicious SVG containing JavaScript, and the Cloudflare-specific implementation performs a 302 redirect back to the original data: URL, the browser directly executes the embedded JavaScript. This completely bypasses any domain allow-listing (image.domains / image.remotePatterns) and typical Content Security Policy mitigations.
Affected Versions
@astrojs/cloudflare ≤ 12.6.10 (and likely all previous versions)
Astro ≥ 4.x when used with output: 'server' and the Cloudflare adapter
Root Cause – Vulnerable Code
File: node_modules/@​astrojs/internal-helpers/src/remote.ts
exportfunctionisRemoteAllowed(src: string, ...): boolean{if(!URL.canParse(src)){returnfalse;}consturl=newURL(src);// Data URLs are always allowed if(url.protocol==='data:'){returntrue;}// Non-http(s) protocols are never allowedif(!['http:','https:'].includes(url.protocol)){returnfalse;}// ... further http/https allow-list checks}
In the Cloudflare adapter, the /_image endpoint contains logic similar to:
consthref=ctx.url.searchParams.get('href');if(!href){// return error }if(isRemotePath(href)){if(isRemoteAllowed(href,imageConfig)===false){// return error}else{//redirect to return the image returnResponse.redirect(href,302);}}
Because data: URLs are considered “allowed”, a request such as: https://example.com/_image?href=data:image/svg+xml;base64,PHN2Zy... (base64-encoded malicious SVG)
triggers a 302 redirect directly to the data: URL, causing the browser to render and execute the malicious JavaScript inside the SVG.
Proof of Concept (PoC)
Create a minimal Astro project with Cloudflare adapter (output: 'server').
Deploy to Cloudflare Pages or Workers.
Request the image endpoint with the following payload:
Safe vs Vulnerable Behavior
Other Astro adapters (Node, Vercel, etc.) typically proxy and rasterize SVGs, stripping JavaScript. The Cloudflare adapter currently redirects to remote resources (including data: URLs), making it uniquely vulnerable.
A double URL encoding bypass allows any unauthenticated attacker to bypass path-based authentication checks in Astro middleware, granting unauthorized access to protected routes. While the original CVE-2025-64765 (single URL encoding) was fixed in v5.15.8, the fix is insufficient as it only decodes once. By using double-encoded URLs like /%2561dmin instead of /%61dmin, attackers can still bypass authentication and access protected resources such as /admin, /api/internal, or any route protected by middleware pathname checks.
Fix
A more secure fix is just decoding once, then if the request has a %xx format, return a 400 error by using something like :
if (containsEncodedCharacters(pathname)) {
// Multi-level encoding detected - reject request
return new Response(
'Bad Request: Multi-level URL encoding is not allowed',
{
status: 400,
headers: { 'Content-Type': 'text/plain' }
}
);
}
#14786758a891 Thanks @mef! - Add handling of invalid encrypted props and slots in server islands.
#14783504958f Thanks @florian-lefebvre! - Improves the experimental Fonts API build log to show the number of downloaded files. This can help spotting excessive downloading because of misconfiguration
#147919e9c528 Thanks @Princesseuh! - Changes the remote protocol checks for images to require explicit authorization in order to use data URIs.
In order to allow data URIs for remote images, you will need to update your astro.config.mjs file to include the following configuration:
#147870f75f6b Thanks @matthewp! - Fixes wildcard hostname pattern matching to correctly reject hostnames without dots
Previously, hostnames like localhost or other single-part names would incorrectly match patterns like *.example.com. The wildcard matching logic has been corrected to ensure that only valid subdomains matching the pattern are accepted.
#147763537876 Thanks @ktym4a! - Fixes the behavior of passthroughImageService so it does not generate webp.
#1477200c579a Thanks @matthewp! - Improves the security of Server Islands slots by encrypting them before transmission to the browser, matching the security model used for props. This improves the integrity of slot content and prevents injection attacks, even when component templates don't explicitly support slots.
Slots continue to work as expected for normal usage—this change has no breaking changes for legitimate requests.
Middleware now receives normalized pathname values, ensuring that encoded paths like /%61dmin are properly decoded to /admin before middleware checks. This prevents potential security issues where middleware checks might be bypassed through URL encoding.
#14690ae7197d Thanks @fredriknorlin! - Fixes a bug where Astro's i18n fallback system with fallbackType: 'rewrite' would not generate fallback files for pages whose filename started with a locale key.
#1475118c55e1 Thanks @delucis! - Fixes hydration of client components when running the dev server and using a barrel file that re-exports both Astro and UI framework components.
#1475035122c2 Thanks @florian-lefebvre! - Updates the experimental Fonts API to log a warning if families with a conflicting cssVariable are provided
#1473774c8852 Thanks @Arecsu! - Fixes an error when using transition:persist with components that use declarative Shadow DOM. Astro now avoids re-attaching a shadow root if one already exists, preventing "Unable to re-attach to existing ShadowDOM" navigation errors.
#1475035122c2 Thanks @florian-lefebvre! - Updates the experimental Fonts API to allow for more granular configuration of remote font families
A font family is defined by a combination of properties such as weights and styles (e.g. weights: [500, 600] and styles: ["normal", "bold"]), but you may want to download only certain combinations of these.
For greater control over which font files are downloaded, you can specify the same font (ie. with the same cssVariable, name, and provider properties) multiple times with different combinations. Astro will merge the results and download only the required files. For example, it is possible to download normal 500 and 600 while downloading only italic 500:
#14743dafbb1b Thanks @matthewp! - Improves X-Forwarded header validation to prevent cache poisoning and header injection attacks. Now properly validates X-Forwarded-Proto, X-Forwarded-Host, and X-Forwarded-Port headers against configured allowedDomains patterns, rejecting malformed or suspicious values. This is especially important when running behind a reverse proxy or load balancer.
The getContainerRenderer() function is exported by Astro framework integrations to simplify the process of rendering framework components when using the experimental Container API inside a Vite or Vitest environment. This update adds the client hydration entrypoint to the returned object, enabling client-side interactivity for components rendered using this function. Previously this required users to manually call container.addClientRenderer() with the appropriate client renderer entrypoint.
#14711a4d284d Thanks @deining! - Fixes typos in documenting our error messages and public APIs.
#147019be54c7 Thanks @florian-lefebvre! - Fixes a case where the experimental Fonts API would filter available font files too aggressively, which could prevent the download of woff files when using the google provider
#14623c5fe295 Thanks @delucis! - Fixes a leak of server runtime code when importing SVGs in client-side code. Previously, when importing an SVG file in client code, Astro could end up adding code for rendering SVGs on the server to the client bundle.
#1461218552c7 Thanks @ematipico! - Fixes a regression introduced in Astro v5.14.7 that caused ?url imports to not work correctly. This release reverts #14142.
#145439b3241d Thanks @matthewp! - Adds two new adapter configuration options assetQueryParams and internalFetchHeaders to the Adapter API.
Official and community-built adapters can now use client.assetQueryParams to specify query parameters that should be appended to asset URLs (CSS, JavaScript, images, fonts, etc.). The query parameters are automatically appended to all generated asset URLs during the build process.
Adapters can also use client.internalFetchHeaders to specify headers that should be included in Astro's internal fetch calls (Actions, View Transitions, Server Islands, Prefetch).
This enables features like Netlify's skew protection, which requires the deploy ID to be sent with both internal requests and asset URLs to ensure client and server versions match during deployments.
#14489add4277 Thanks @dev-shetty! - Adds a new Copy to Clipboard button to the error overlay stack trace.
When an error occurs in dev mode, you can now copy the stack trace with a single click to more easily share it in a bug report, a support thread, or with your favorite LLM.
Running astro add cloudflare will now emit wrangler.jsonc and public/.assetsignore, allowing your Astro project to work out of the box as a worker.
Patch Changes
#145913e887ec Thanks @matthewp! - Adds TypeScript support for the components prop on MDX Content component when using await render(). Developers now get proper IntelliSense and type checking when passing custom components to override default MDX element rendering.
#145987b45c65 Thanks @delucis! - Reduces terminal text styling dependency size by switching from kleur to picocolors
#138268079482 Thanks @florian-lefebvre! - Adds the option to specify in the preload directive which weights, styles, or subsets to preload for a given font family when using the experimental Fonts API:
Variable weight font files will be preloaded if any weight within its range is requested. For example, a font file for font weight 100 900 will be included when 400 is specified in a preload object.
#14590577d051 Thanks @matthewp! - Fixes image path resolution in content layer collections to support bare filenames. The image() helper now normalizes bare filenames like "cover.jpg" to relative paths "./cover.jpg" for consistent resolution behavior between markdown frontmatter and JSON content collections.
#1456794500bb Thanks @matthewp! - Fixes the actions endpoint to return 404 for non-existent actions instead of throwing an unhandled error
#14566946fe68 Thanks @matthewp! - Fixes handling malformed cookies gracefully by returning the unparsed value instead of throwing
When a cookie with an invalid value is present (e.g., containing invalid URI sequences), Astro.cookies.get() now returns the raw cookie value instead of throwing a URIError. This aligns with the behavior of the underlying cookie package and prevents crashes when manually-set or corrupted cookies are encountered.
#1414273c5de9 Thanks @P4tt4te! - Updates handling of CSS for hydrated client components to prevent duplicates
#145762af62c6 Thanks @aprici7y! - Fixes a regression that caused Astro.site to always be undefined in getStaticPaths()
DeepSource reviewed changes in the commit range 242a5a8...15f3667 on this pull request. Below is the summary for the review, and you can see the individual issues we found as review comments.
Administrators can configure which issue categories are reported and cause analysis to be marked as failed when detected. This helps prevent bad and insecure code from being introduced in the codebase. If you're an administrator, you can modify this in the repository's settings.
renovatebot
changed the title
chore(monorepo): update pnpm.catalog.default astro to ^5.14.3 [security]
chore(monorepo): update pnpm.catalog.default astro to ^5.14.7 [security]
Oct 21, 2025
renovatebot
changed the title
chore(monorepo): update pnpm.catalog.default astro to ^5.14.7 [security]
chore(monorepo): update pnpm.catalog.default astro to ^5.14.3 [security]
Oct 22, 2025
renovatebot
changed the title
chore(monorepo): update pnpm.catalog.default astro to ^5.14.3 [security]
chore(monorepo): update pnpm.catalog.default astro to ^5.15.4 [security]
Nov 10, 2025
renovatebot
changed the title
chore(monorepo): update pnpm.catalog.default astro to ^5.15.4 [security]
chore(monorepo): update pnpm.catalog.default astro to ^5.14.3 [security]
Nov 11, 2025
renovatebot
changed the title
chore(monorepo): update pnpm.catalog.default astro to ^5.14.3 [security]
chore(monorepo): update pnpm.catalog.default astro to ^5.15.6 [security]
Nov 13, 2025
renovatebot
changed the title
chore(monorepo): update pnpm.catalog.default astro to ^5.15.6 [security]
chore(monorepo): update pnpm.catalog.default astro to ^5.15.9 [security]
Nov 18, 2025
renovatebot
changed the title
chore(monorepo): update pnpm.catalog.default astro to ^5.15.9 [security]
chore(monorepo): update pnpm.catalog.default astro to ^5.15.6 [security]
Nov 19, 2025
renovatebot
changed the title
chore(monorepo): update pnpm.catalog.default astro to ^5.15.6 [security]
chore(monorepo): update pnpm.catalog.default astro to ^5.15.8 [security]
Nov 19, 2025
renovatebot
changed the title
chore(monorepo): update pnpm.catalog.default astro to ^5.15.8 [security]
chore(monorepo): update pnpm.catalog.default astro to ^5.15.9 [security]
Nov 20, 2025
renovatebot
changed the title
chore(monorepo): update pnpm.catalog.default astro to ^5.15.9 [security]
chore(monorepo): update pnpm.catalog.default astro to ^5.16.4 [security]
Dec 3, 2025
renovatebot
changed the title
chore(monorepo): update pnpm.catalog.default astro to ^5.16.7 [security]
chore(monorepo): update pnpm.catalog.default astro to ^5.15.9 [security]
Jan 8, 2026
renovatebot
changed the title
chore(monorepo): update pnpm.catalog.default astro to ^5.15.9 [security]
chore(monorepo): update pnpm.catalog.default astro to ^5.16.11 [security]
Jan 19, 2026
renovatebot
changed the title
chore(monorepo): update pnpm.catalog.default astro to ^5.16.11 [security]
chore(monorepo): update pnpm.catalog.default astro to ^5.15.9 [security]
Jan 19, 2026
renovatebot
changed the title
chore(monorepo): update pnpm.catalog.default astro to ^5.15.9 [security]
chore(monorepo): update pnpm.catalog.default astro to ^5.16.15 [security]
Jan 23, 2026
renovatebot
changed the title
chore(monorepo): update pnpm.catalog.default astro to ^5.16.15 [security]
chore(monorepo): update pnpm.catalog.default astro to ^5.15.9 [security]
Jan 23, 2026
renovatebot
changed the title
chore(monorepo): update pnpm.catalog.default astro to ^5.15.9 [security]
chore(monorepo): update pnpm.catalog.default astro to ^5.17.1 [security]
Feb 2, 2026
renovatebot
changed the title
chore(monorepo): update pnpm.catalog.default astro to ^5.17.1 [security]
chore(monorepo): update pnpm.catalog.default astro to ^5.15.9 [security]
Feb 2, 2026
renovatebot
changed the title
chore(monorepo): update pnpm.catalog.default astro to ^5.15.9 [security]
chore(monorepo): update pnpm.catalog.default astro to ^5.17.2 [security]
Feb 12, 2026
renovatebot
changed the title
chore(monorepo): update pnpm.catalog.default astro to ^5.17.2 [security]
chore(monorepo): update pnpm.catalog.default astro to ^5.15.9 [security]
Feb 12, 2026
renovatebot
changed the title
chore(monorepo): update pnpm.catalog.default astro to ^5.15.9 [security]
chore(monorepo): update pnpm.catalog.default astro to ^5.17.2 [security]
Feb 16, 2026
renovatebot
changed the title
chore(monorepo): update pnpm.catalog.default astro to ^5.17.2 [security]
chore(monorepo): update pnpm.catalog.default astro to ^5.15.9 [security]
Feb 16, 2026
renovatebot
changed the title
chore(monorepo): update pnpm.catalog.default astro to ^5.15.9 [security]
chore(monorepo): update pnpm.catalog.default astro to ^5.17.2 [security]
Feb 17, 2026
renovatebot
changed the title
chore(monorepo): update pnpm.catalog.default astro to ^5.17.2 [security]
chore(monorepo): update pnpm.catalog.default astro to ^5.15.9 [security]
Feb 17, 2026
renovatebot
changed the title
chore(monorepo): update pnpm.catalog.default astro to ^5.15.9 [security]
chore(monorepo): update pnpm.catalog.default astro to ^5.17.3 [security]
Feb 20, 2026
renovatebot
changed the title
chore(monorepo): update pnpm.catalog.default astro to ^5.17.3 [security]
chore(monorepo): update pnpm.catalog.default astro to ^5.15.9 [security]
Feb 20, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
dependenciesUpgrade or downgrade of project dependencies.
0 participants
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR contains the following updates:
^5.13.5→^5.15.9GitHub Vulnerability Alerts
CVE-2025-61925
Summary
When running Astro in on-demand rendering mode using a adapter such as the node adapter it is possible to maliciously send an
X-Forwarded-Hostheader that is reflected when using the recommendedAstro.urlproperty as there is no validation that the value is safe.Details
Astro reflects the value in
X-Forwarded-Hostin output when usingAstro.urlwithout any validation.It is common for web servers such as nginx to route requests via the
Hostheader, and forward on other request headers. As such as malicious request can be sent with both aHostheader and anX-Forwarded-Hostheader where the values do not match and theX-Forwarded-Hostheader is malicious. Astro will then return the malicious value.This could result in any usages of the
Astro.urlvalue in code being manipulated by a request. For example if a user follows guidance and usesAstro.urlfor a canonical link the canonical link can be manipulated to another site. It is not impossible to imagine that the value could also be used as a login/registration or other form URL as well, resulting in potential redirecting of login credentials to a malicious party.As this is a per-request attack vector the surface area would only be to the malicious user until one considers that having a caching proxy is a common setup, in which case any page which is cached could persist the malicious value for subsequent users.
Many other frameworks have an allowlist of domains to validate against, or do not have a case where the headers are reflected to avoid such issues.
PoC
nvm useyarn run buildnode ./dist/server/entry.mjscurl --location 'http://localhost:4321/' --header 'X-Forwarded-Host: www.evil.com' --header 'Host: www.example.com'X-Forwarded-HostheaderFor the more advanced / dangerous attack vector deploy the application behind a caching proxy, e.g. Cloudflare, set a non-zero cache time, perform the above
curlrequest a few times to establish a cache, then perform the request without the malicious headers and observe that the malicious data is persisted.Impact
This could affect anyone using Astro in an on-demand/dynamic rendering mode behind a caching proxy.
CVE-2025-64745
Summary
A Reflected Cross-Site Scripting (XSS) vulnerability exists in Astro's development server error pages when the
trailingSlashconfiguration option is used. An attacker can inject arbitrary JavaScript code that executes in the victim's browser context by crafting a malicious URL. While this vulnerability only affects the development server and not production builds, it could be exploited to compromise developer environments through social engineering or malicious links.Details
Vulnerability Location
https://github.com/withastro/astro/blob/5bc37fd5cade62f753aef66efdf40f982379029a/packages/astro/src/template/4xx.ts#L133-L149
Root Cause
The vulnerability was introduced in commit
536175528(PR #12994) , as part of a feature to "redirect trailing slashes on on-demand rendered pages." The feature added a helpful 404 error page in development mode to alert developers of trailing slash mismatches.Issue: The
correctedvariable, which is derived from the user-controlledpathnameparameter, is directly interpolated into the HTML without proper escaping. While thepathnamevariable itself is escaped elsewhere in the same file (line 114:escape(pathname)), thecorrectedvariable is not sanitized before being inserted into both thehrefattribute and the link text.Attack Vector
When a developer has configured
trailingSlashto'always'or'never'and visits a URL with a mismatched trailing slash, the development server returns a 404 page containing the vulnerable template. An attacker can craft a URL with JavaScript payloads that will be executed when the page is rendered.PoC
Local Testing (localhost)
Basic vulnerability verification in local development environment
Show details
astro.config.mjs:package.json:{ "name": "astro-xss-poc-victim", "version": "0.1.0", "scripts": { "dev": "astro dev" }, "dependencies": { "astro": "5.15.5" } }Start the development server:
Access the following malicious URL depending on your configuration:
For
trailingSlash: 'never'(requires trailing slash):For
trailingSlash: 'always'(no trailing slash):When accessing the malicious URL:
alert(document.domain)) executes in the browserRemote Testing (ngrok)
Reproduce realistic attack scenario via external malicious link
Show details
Prerequisites: ngrok account and authtoken configured (
ngrok config add-authtoken <key>)Setup and Execution:
When a remote user accesses either of the generated attack URLs:
alert(document.domain)) executes in the user's browserBoth URL patterns work depending on your
trailingSlashconfiguration ('never' or 'always').Impact
This only affects the development server. Risk depends on how and where the dev server is exposed.
Security impact
localhostendpoints or dev tools depending on browser policies.Attack scenarios
CVE-2025-64525
Summary
In impacted versions of Astro using on-demand rendering, request headers
x-forwarded-protoandx-forwarded-portare insecurely used, without sanitization, to build the URL. This has several consequences the most important of which are:x-forwarded-proto)x-forwarded-proto)Details
The
x-forwarded-protoandx-forwarded-portheaders are used without sanitization in two parts of the Astro server code. The most important is in thecreateRequest()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#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-protoheader), 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:The complete URL that will be created is:
https://www.malicious-url.com/?tank=://localhost/ssrAs a reminder, URLs are created like this:
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
createRequestfunction 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:
2.16.0)/ssr), the other simulating an admin page (/admin) protected by a middlewareDownload the PoC repository
Middleware-based protected route bypass - x-forwarded-proto only
The middleware has been configured to protect the
/adminroute based on the official documentation:When tryint to access
/adminthe attacker is naturally redirected :The attackr can bypass the middleware path check using a malicious header value:
curl -i -H "x-forwarded-proto: x:admin?" http://localhost:4321/adminHow 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//, the parser considers there to be no authority, and everything before the?character is therefore considered part of the path:adminDuring 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-protocolheader, 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 :
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

404cab be forced, causing an error on the/ssrpage like this :curl -i -H "x-forwarded-proto: https://localhost/vulnerable?" http://localhost:4321/ssrSame logic applies to
x-forwarded-port:curl -i -H "x-forwarded-port: /vulnerable?" http://localhost:4321/ssrHow is this possible?
The router sees the request for the path
/vulnerable, which does not exist, and therefore returns a404, while the potential CDN sees/ssrand can then cache the404response, 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.urlis used to create links within the page, this can lead to Stored XSS withx-forwarded-protoand the following value:results in the following URL object:
It is also possible to inject any link, always, if the value of
request.urlis used on the server side to create links.The attacker is more limited with
x-forwarded-portIf the value of
request.urlis used to create links within the page, this can lead to broken links, with the header and the following value:Example of an Astro website:

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-hostin their case: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-Hostheader.By sending
x-forwarded-hostwith an empty value, theforwardedHostnamevariable is assigned an empty string. Then, during the subsequent check, the condition fails becauseforwardedHostnamereturnsfalse, its value being an empty string: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 thehost. This is because thehttp/httpsschemes are considered special schemes by the WHATWG URL Standard Specification, requiring anauthority state.From there, the following request on the example SSR application (astro repo) yields an SSRF:

empty
x-forwarded-host+ the targethostin the pathCredits
CVE-2025-64757
Summary
A vulnerability has been identified in the Astro framework's development server that allows arbitrary local file read access through the image optimization endpoint. The vulnerability affects Astro development environments and allows remote attackers to read any image file accessible to the Node.js process on the host system.
Details
/packages/astro/src/assets/endpoint/node.tsThe vulnerability exists in the Node.js image endpoint handler used during development mode. The endpoint accepts an
hrefparameter that specifies the path to an image file. In development mode, this parameter is processed without adequate path validation, allowing attackers to specify absolute file paths.Vulnerable Code Location:
packages/astro/src/assets/endpoint/node.tsThe development branch bypasses the security checks that exist in the production code path, which validates that file paths are within the allowed assets directory.
PoC
Attack Prerequisites
astro dev)/_imageendpoint must be accessible to the attackerExploit Steps
Start Astro Development Server:
astro dev # Typically runs on http://localhost:4321Craft Malicious Request:
Example Attack:
curl "http://localhost:4321/_image?href=/%2FSystem%2FLibrary%2FImage%20Capture%2FAutomatic%20Tasks%2FMakePDF.app%2FContents%2FResources%2F0blank.jpg&w=100&h=100&f=png" -o stolen.pngDemonstration Results
Test Environment: macOS with Astro v5.13.3
Successful Exploitation:
/System/Library/Image Capture/Automatic Tasks/MakePDF.app/Contents/Resources/0blank.jpgstolen-image.pngcontaining processed system imageAttack Payload:
Server Response:
Impact
Confidentiality Impact: HIGH
Integrity Impact: NONE
Availability Impact: NONE
Affected Components
Primary Component
packages/astro/src/assets/endpoint/node.tsloadLocalImage()Secondary Components
packages/astro/src/assets/endpoint/generic.tsCVE-2025-64764
Summary
After some research it appears that it is possible to obtain a reflected XSS when the server islands feature is used in the targeted application, regardless of what was intended by the component template(s).
Details
Server islands run in their own isolated context outside of the page request and use the following pattern path to hydrate the page:
/_server-islands/[name]. These paths can be called via GET or POST and use three parameters:e: component to exportp: the transmitted properties, encrypteds: for the slotsSlots are placeholders for external HTML content, and therefore allow, by default, the injection of code if the component template supports it, nothing exceptional in principle, just a feature.
This is where it becomes problematic: it is possible, independently of the component template used, even if it is completely empty, to inject a slot containing an XSS payload, whose parent is a tag whose name is is the absolute path of the island file. Enabling reflected XSS on any application, regardless of the component templates used, provided that the server islands is used at least once.
How ?
By default, when a call is made to the endpoint
/_server-islands/[name], the value of the parametereisdefault, pointing to a function exported by the component's module.Upon further investigation, we find that two other values are possible for the component export (param
e) in a typical configuration:urlandfile.filereturns a string value corresponding to the absolute path of the island file. Since the value is of typestring, it fulfills the following condition and leads to this code block:An entire template is created, completely independently, and then returned:
childSlots, the value provided to thesparameter, is injected as a childAll of this is done using
markHTMLString. This allows the injection of any XSS payload, even if the component template intended by the application is initially empty or does not provide for the use of slots.Proof of concept
For our Proof of Concept (PoC), we will use a minimal repository:
Download the PoC repository
Access the following URL and note the opening of the popup, demonstrating the reflected XSS:
http://localhost:4321/_server-islands/ServerTime?e=file&p=&s={%22zhero%22:%22%3Cimg%20src=x%20onerror=alert(0)%3E%22}
The value of the parameter
smust be in JSON format and the payload must be injected at the value level, not the key level :Despite the initial template being empty, it is created because the value of the URL parameter
eis set tofile, as explained earlier. The parent tag is the name of the component's internal route, and its child is the value of the key "zhero" (the name doesn't matter) of the URL parameters.Credits
CVE-2025-64765
A mismatch exists between how Astro normalizes request paths for routing/rendering and how the application’s middleware reads the path for validation checks. Astro internally applies
decodeURI()to determine which route to render, while the middleware usescontext.url.pathnamewithout applying the same normalization (decodeURI).This discrepancy may allow attackers to reach protected routes (e.g., /admin) using encoded path variants that pass routing but bypass validation checks.
https://github.com/withastro/astro/blob/ebc4b1cde82c76076d5d673b5b70f94be2c066f3/packages/astro/src/vite-plugin-astro-server/request.ts#L40-L44
Consider an application having the following middleware code:
context.url.pathnameis validated , if it's equal to/admintheisAuthedproperty must be true for the next() method to be called. The same example can be found in the official docs https://docs.astro.build/en/guides/authentication/context.url.pathnamereturns the raw version which is/%61adminwhile pathname which is used for routing/rendering/admin, this creates a path normalization mismatch.By sending the following request, it's possible to bypass the middleware check
Remediation
Ensure middleware context has the same normalized pathname value that Astro uses internally, because any difference could allow it to bypass such checks. In short maybe something like this
pathname = decodeURI(url.pathname); } // Add config.base back to url before passing it to SSR - url.pathname = removeTrailingForwardSlash(config.base) + url.pathname; + url.pathname = removeTrailingForwardSlash(config.base) + decodeURI(url.pathname);Thank you, let @Sudistark know if any more info is needed. Happy to help :)
CVE-2025-65019
Summary
A Cross-Site Scripting (XSS) vulnerability exists in Astro when using the @astrojs/cloudflare adapter with
output: 'server'. The built-in image optimization endpoint (/_image) usesisRemoteAllowed()from Astro’s internal helpers, which unconditionally allowsdata:URLs. When the endpoint receives a validdata:URL pointing to a malicious SVG containing JavaScript, and the Cloudflare-specific implementation performs a 302 redirect back to the originaldata:URL, the browser directly executes the embedded JavaScript. This completely bypasses any domain allow-listing (image.domains/image.remotePatterns) and typical Content Security Policy mitigations.Affected Versions
@astrojs/cloudflare≤ 12.6.10 (and likely all previous versions)output: 'server'and the Cloudflare adapterRoot Cause – Vulnerable Code
File:
node_modules/@​astrojs/internal-helpers/src/remote.tsIn the Cloudflare adapter, the
/_imageendpoint contains logic similar to:Because
data:URLs are considered “allowed”, a request such as:https://example.com/_image?href=data:image/svg+xml;base64,PHN2Zy... (base64-encoded malicious SVG)triggers a 302 redirect directly to the
data:URL, causing the browser to render and execute the malicious JavaScript inside the SVG.Proof of Concept (PoC)
output: 'server').(Base64 decodes to:
<svg xmlns="http://www.w3.org/2000/svg"><script>alert('zomasec')</script></svg>)data:URL → browser executes the<script>→alert()fires.Impact
image.domains/image.remotePatternsconfiguration entirelySafe vs Vulnerable Behavior
Other Astro adapters (Node, Vercel, etc.) typically proxy and rasterize SVGs, stripping JavaScript. The Cloudflare adapter currently redirects to remote resources (including
data:URLs), making it uniquely vulnerable.References
data:URL bypass in WordPress: CVE-2025-2575CVE-2025-66202
Authentication Bypass via Double URL Encoding in Astro
Bypass for CVE-2025-64765 / GHSA-ggxq-hp9w-j794
Summary
A double URL encoding bypass allows any unauthenticated attacker to bypass path-based authentication checks in Astro middleware, granting unauthorized access to protected routes. While the original CVE-2025-64765 (single URL encoding) was fixed in v5.15.8, the fix is insufficient as it only decodes once. By using double-encoded URLs like
/%2561dmininstead of/%61dmin, attackers can still bypass authentication and access protected resources such as/admin,/api/internal, or any route protected by middleware pathname checks.Fix
A more secure fix is just decoding once, then if the request has a %xx format, return a 400 error by using something like :
Release Notes
withastro/astro (astro)
v5.15.9Compare Source
Patch Changes
#14786
758a891Thanks @mef! - Add handling of invalid encrypted props and slots in server islands.#14783
504958fThanks @florian-lefebvre! - Improves the experimental Fonts API build log to show the number of downloaded files. This can help spotting excessive downloading because of misconfiguration#14791
9e9c528Thanks @Princesseuh! - Changes the remote protocol checks for images to require explicit authorization in order to use data URIs.In order to allow data URIs for remote images, you will need to update your
astro.config.mjsfile to include the following configuration:#14787
0f75f6bThanks @matthewp! - Fixes wildcard hostname pattern matching to correctly reject hostnames without dotsPreviously, hostnames like
localhostor other single-part names would incorrectly match patterns like*.example.com. The wildcard matching logic has been corrected to ensure that only valid subdomains matching the pattern are accepted.#14776
3537876Thanks @ktym4a! - Fixes the behavior ofpassthroughImageServiceso it does not generate webp.Updated dependencies [
9e9c528,0f75f6b]:v5.15.8Compare Source
Patch Changes
#14772
00c579aThanks @matthewp! - Improves the security of Server Islands slots by encrypting them before transmission to the browser, matching the security model used for props. This improves the integrity of slot content and prevents injection attacks, even when component templates don't explicitly support slots.Slots continue to work as expected for normal usage—this change has no breaking changes for legitimate requests.
#14771
6f80081Thanks @matthewp! - Fix middleware pathname matching by normalizing URL-encoded pathsMiddleware now receives normalized pathname values, ensuring that encoded paths like
/%61dminare properly decoded to/adminbefore middleware checks. This prevents potential security issues where middleware checks might be bypassed through URL encoding.v5.15.7Compare Source
Patch Changes
#14765
03fb47cThanks @florian-lefebvre! - Fixes a case whereprocess.envwouldn't be properly populated during the build#14690
ae7197dThanks @fredriknorlin! - Fixes a bug where Astro's i18n fallback system withfallbackType: 'rewrite'would not generate fallback files for pages whose filename started with a locale key.v5.15.6Compare Source
Patch Changes
#14751
18c55e1Thanks @delucis! - Fixes hydration of client components when running the dev server and using a barrel file that re-exports both Astro and UI framework components.#14750
35122c2Thanks @florian-lefebvre! - Updates the experimental Fonts API to log a warning if families with a conflictingcssVariableare provided#14737
74c8852Thanks @Arecsu! - Fixes an error when usingtransition:persistwith components that use declarative Shadow DOM. Astro now avoids re-attaching a shadow root if one already exists, preventing"Unable to re-attach to existing ShadowDOM"navigation errors.#14750
35122c2Thanks @florian-lefebvre! - Updates the experimental Fonts API to allow for more granular configuration of remote font familiesA font family is defined by a combination of properties such as weights and styles (e.g.
weights: [500, 600]andstyles: ["normal", "bold"]), but you may want to download only certain combinations of these.For greater control over which font files are downloaded, you can specify the same font (ie. with the same
cssVariable,name, andproviderproperties) multiple times with different combinations. Astro will merge the results and download only the required files. For example, it is possible to download normal500and600while downloading only italic500:v5.15.5Compare Source
Patch Changes
#14712
91780cfThanks @florian-lefebvre! - Fixes a case where build'sprocess.envwould be inlined in the server output#14713
666d5a7Thanks @florian-lefebvre! - Improves fallbacks generation when using the experimental Fonts API#14743
dafbb1bThanks @matthewp! - ImprovesX-Forwardedheader validation to prevent cache poisoning and header injection attacks. Now properly validatesX-Forwarded-Proto,X-Forwarded-Host, andX-Forwarded-Portheaders against configuredallowedDomainspatterns, rejecting malformed or suspicious values. This is especially important when running behind a reverse proxy or load balancer.v5.15.4Compare Source
Patch Changes
#14703
970ac0fThanks @ArmandPhilippot! - Adds missing documentation for some public utilities exported fromastro:i18n.#14715
3d55c5dThanks @ascorbic! - Adds support for client hydration ingetContainerRenderer()The
getContainerRenderer()function is exported by Astro framework integrations to simplify the process of rendering framework components when using the experimental Container API inside a Vite or Vitest environment. This update adds the client hydration entrypoint to the returned object, enabling client-side interactivity for components rendered using this function. Previously this required users to manually callcontainer.addClientRenderer()with the appropriate client renderer entrypoint.See the
container-with-vitestdemo for a usage example, and the Container API documentation for more information on using framework components with the experimental Container API.#14711
a4d284dThanks @deining! - Fixes typos in documenting our error messages and public APIs.#14701
9be54c7Thanks @florian-lefebvre! - Fixes a case where the experimental Fonts API would filter available font files too aggressively, which could prevent the download of woff files when using the google providerv5.15.3Compare Source
Patch Changes
#14627
b368de0Thanks @matthewp! - Fixes skew protection support for images and font URLsAdapter-level query parameters (
assetQueryParams) are now applied to all image and font asset URLs, including:/_imageendpoint#14631
3ad33f9Thanks @KurtGokhan! - Adds theastro/jsx-dev-runtimeexport as an alias forastro/jsx-runtimev5.15.2Compare Source
Patch Changes
#14623
c5fe295Thanks @delucis! - Fixes a leak of server runtime code when importing SVGs in client-side code. Previously, when importing an SVG file in client code, Astro could end up adding code for rendering SVGs on the server to the client bundle.#14621
e3175d9Thanks @GameRoMan! - Updatesviteversion to fix CVEv5.15.1Compare Source
Patch Changes
18552c7Thanks @ematipico! - Fixes a regression introduced in Astro v5.14.7 that caused?urlimports to not work correctly. This release reverts #14142.v5.15.0Compare Source
Minor Changes
#14543
9b3241dThanks @matthewp! - Adds two new adapter configuration optionsassetQueryParamsandinternalFetchHeadersto the Adapter API.Official and community-built adapters can now use
client.assetQueryParamsto specify query parameters that should be appended to asset URLs (CSS, JavaScript, images, fonts, etc.). The query parameters are automatically appended to all generated asset URLs during the build process.Adapters can also use
client.internalFetchHeadersto specify headers that should be included in Astro's internal fetch calls (Actions, View Transitions, Server Islands, Prefetch).This enables features like Netlify's skew protection, which requires the deploy ID to be sent with both internal requests and asset URLs to ensure client and server versions match during deployments.
#14489
add4277Thanks @dev-shetty! - Adds a new Copy to Clipboard button to the error overlay stack trace.When an error occurs in dev mode, you can now copy the stack trace with a single click to more easily share it in a bug report, a support thread, or with your favorite LLM.
#14564
5e7cebbThanks @florian-lefebvre! - Updatesastro add cloudflareto scaffold more configuration filesRunning
astro add cloudflarewill now emitwrangler.jsoncandpublic/.assetsignore, allowing your Astro project to work out of the box as a worker.Patch Changes
#14591
3e887ecThanks @matthewp! - Adds TypeScript support for thecomponentsprop on MDXContentcomponent when usingawait render(). Developers now get proper IntelliSense and type checking when passing custom components to override default MDX element rendering.#14598
7b45c65Thanks @delucis! - Reduces terminal text styling dependency size by switching fromkleurtopicocolors#13826
8079482Thanks @florian-lefebvre! - Adds the option to specify in thepreloaddirective which weights, styles, or subsets to preload for a given font family when using the experimental Fonts API:Variable weight font files will be preloaded if any weight within its range is requested. For example, a font file for font weight
100 900will be included when400is specified in apreloadobject.v5.14.8Compare Source
Patch Changes
577d051Thanks @matthewp! - Fixes image path resolution in content layer collections to support bare filenames. Theimage()helper now normalizes bare filenames like"cover.jpg"to relative paths"./cover.jpg"for consistent resolution behavior between markdown frontmatter and JSON content collections.v5.14.7Compare Source
Patch Changes
#14582
7958c6bThanks @florian-lefebvre! - Fixes a regression that caused Actions to throw errors while loading#14567
94500bbThanks @matthewp! - Fixes the actions endpoint to return 404 for non-existent actions instead of throwing an unhandled error#14566
946fe68Thanks @matthewp! - Fixes handling malformed cookies gracefully by returning the unparsed value instead of throwingWhen a cookie with an invalid value is present (e.g., containing invalid URI sequences),
Astro.cookies.get()now returns the raw cookie value instead of throwing a URIError. This aligns with the behavior of the underlyingcookiepackage and prevents crashes when manually-set or corrupted cookies are encountered.#14142
73c5de9Thanks @P4tt4te! - Updates handling of CSS for hydrated client components to prevent duplicates#14576
2af62c6Thanks @aprici7y! - Fixes a regression that causedAstro.siteto always beundefinedingetStaticPaths()v5.14.6Compare Source
Patch Changes
#14562
722bba0Thanks @erbierc! - Fixes a bug where the behavior of the "muted" HTML attribute was inconsistent with that of other attributes.#14538
51ebe6aThanks @florian-lefebvre! - Improves how Actions are implemented#14548
6cdade4Thanks @ascorbic! - Removes support for themaxAgeproperty in `cachConfiguration
📅 Schedule: Branch creation - "" in timezone America/New_York, Automerge - At any time (no schedule defined).
🚦 Automerge: Enabled.
♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about these updates again.
This PR was generated by Mend Renovate. View the repository job log.