CVE-2025-64765: Astro middleware authentication checks based on url.pathname can be bypassed via url encoded values
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.
https://github.com/withastro/astro/blob/ebc4b1cde82c76076d5d673b5b70f94be2c066f3/packages/astro/src/vite-plugin-astro-server/request.ts#L40-L44
js / The main logic to route dev server requests to pages in Astro. / export async function handleRequest({ pipeline, routesList, controller, incomingRequest, incomingResponse, }: HandleRequest) { const { config, loader } = pipeline; const origin = ${loader.isHttps() ? 'https' : 'http'}://${ incomingRequest.headers[':authority'] ?? incomingRequest.headers.host };
const url = new URL(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.ts pathname = decodeURI(url.pathname); // here this url is for routing/rendering }
// Add config.base back to url before passing it to SSR url.pathname = removeTrailingForwardSlash(config.base) + url.pathname; // this is used for middleware context
Consider an application having the following middleware code:
js import { defineMiddleware } from "astro/middleware";
export const onRequest = defineMiddleware(async (context, next) => { const isAuthed = false; // simulate no auth if (context.url.pathname === "/admin" && !isAuthed) { return context.redirect("/"); } return next(); });
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
<img width="1920" height="1025" alt="image" src="https://github.com/user-attachments/assets/7e0eeecd-607a-4c73-b12e-5977a30c9bc4" />
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
diff 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 :)
Other sources
Astro is a web framework. Prior to version 5.15.8, 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 using encoded path variants that pass routing but bypass validation checks. This issue has been patched in version 5.15.8.
— MITRE
Affected Software
Remediation
Event History
Frequently Asked Questions
What is the severity of CVE-2025-64765?
CVE-2025-64765 is categorized as a high severity vulnerability due to its potential impact on routing and request processing.
How do I fix CVE-2025-64765?
To resolve CVE-2025-64765, you should upgrade to Astro version 5.15.8 or later.
What types of attacks can exploit CVE-2025-64765?
CVE-2025-64765 can be exploited through crafted requests that manipulate routing paths, potentially bypassing validation checks.
Which versions of Astro are affected by CVE-2025-64765?
CVE-2025-64765 affects all versions of Astro prior to version 5.15.8.
Is there a workaround for CVE-2025-64765 if I cannot upgrade?
There are no recommended workarounds for CVE-2025-64765; upgrading to a patched version is the best approach.