Commit fd2abee
authored
chore(deps): update dependency astro to v5.15.9 [security] (#1158)
This PR contains the following updates:
| Package | Change | Age | Confidence |
|---|---|---|---|
| [astro](https://astro.build)
([source](https://redirect.github.com/withastro/astro/tree/HEAD/packages/astro))
| [`5.15.6` ->
`5.15.9`](https://renovatebot.com/diffs/npm/astro/5.15.6/5.15.9) |
[](https://docs.renovatebot.com/merge-confidence/)
|
[](https://docs.renovatebot.com/merge-confidence/)
|
### GitHub Vulnerability Alerts
####
[CVE-2025-64764](https://redirect.github.com/withastro/astro/security/advisories/GHSA-wrwg-2hg8-v723)
## 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 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](https://redirect.github.com/withastro/astro/blob/190106149908ef6826899459146ef9f0ead602ab/packages/astro/src/runtime/server/render/component.ts#L279):
<img width="804" height="571" alt="image"
src="https://github.com/user-attachments/assets/25ea6c16-fc27-477a-a1ad-e5edf0819b31"
/>
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
[Download the PoC
repository](https://redirect.github.com/zhero-web-sec/astro-app-2)
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}
<img width="1781" height="529" alt="image"
src="https://github.com/user-attachments/assets/92f8134a-d1c7-4d3f-818e-214842c239c8"
/>
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 :
<img width="3273" height="1840" alt="for_respected_patron"
src="https://github.com/user-attachments/assets/8ac0079a-3dee-49e8-b639-322f77c84b83"
/>
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`.
## Credits
- Allam Rachid
([zhero;](https://zhero-web-sec.github.io/research-and-things/))
- Allam Yasser (inzo)
####
[CVE-2025-64765](https://redirect.github.com/withastro/astro/security/advisories/GHSA-ggxq-hp9w-j794)
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);
```
Thankyou, let me know if any more info is needed happy to help :)
####
[CVE-2025-65019](https://redirect.github.com/withastro/astro/security/advisories/GHSA-fvmw-cj7j-j39q)
## Summary
When using Astro's Cloudflare adapter (@​astrojs/cloudflare) with
`output: 'server'`, the image optimization endpoint (`/_image`) contains
a critical vulnerability in the `isRemoteAllowed()` function that
unconditionally allows `data:` protocol URLs. This enables Cross-Site
Scripting (XSS) attacks through malicious SVG payloads, bypassing domain
restrictions and Content Security Policy protections.
## Details
On-demand rendered sites built with Astro include an `/_image` endpoint
for image optimization. While this endpoint is designed to restrict
processing to local images and authorized remote domains (configured via
`image.domains` or `image.remotePatterns`), a critical vulnerability
exists in the underlying validation logic.
The `isRemoteAllowed()` function in
[packages/internal-helpers/src/remote.ts](https://redirect.github.com/withastro/astro/blob/b8ca69b97149becefaf89bf21853de9c905cdbb7/packages/internal-helpers/src/remote.ts)
(lines 128-131) unconditionally allows ALL `data:` protocol URLs without
any validation or sanitization. When combined with SVG images containing
JavaScript, this creates a vector for XSS attacks.
**Vulnerable Code:**
```JavaScript
/packages/ packages/internal-helpers/src/remote.ts lines 128-131
if (url.protocol === 'data:') {
return true; // ← Unconditionally allows ALL data: URLs!
}
```
The vulnerability manifests differently depending on the image endpoint
implementation:
- **Safe implementation**: Server processes SVG and converts to raster
format (PNG/JPEG), removing JavaScript
- **Vulnerable implementation**: Server redirects browser to raw SVG
data URL, allowing JavaScript execution
### PoC
1. Create a new minimal Astro project (astro@latest)
2. Configure it to use the Cloudflare adapter
(@​astrojs/[email protected])
3. Deploy to Cloudflare Pages or Workers.
4. Write page to load SVG Image like : [SVG XSS
Payload](https://gist.github.com/rudSarkar/76f1ce7a65c356a5cd71d058ab76a344)
5. Open directly the SVG file to show an alert (in read scenarios, the
apps that use the framework will use CDN for example, to load SVG,
depending that the framework is secure)
### Impact
1. **Stored XSS**: Malicious URLs can be crafted to execute JavaScript
in victim's browser
2. **Session Hijacking**: JavaScript can access cookies and session
tokens
3. **Account Takeover**: Combined with CSRF, can perform unauthorized
actions
4. **Data Exfiltration**: Sensitive information can be stolen and sent
to attacker-controlled servers
### References
- **Vulnerable Function**:
[packages/internal-helpers/src/remote.ts](https://redirect.github.com/withastro/astro/blob/b8ca69b97149becefaf89bf21853de9c905cdbb7/packages/internal-helpers/src/remote.ts)
lines 128-131
- **Similar Vulnerability**::
https://dailycve.com/wordpress-stored-xss-via-svg-upload-cve-2025-2575-medium/
---
### Release Notes
<details>
<summary>withastro/astro (astro)</summary>
###
[`v5.15.9`](https://redirect.github.com/withastro/astro/blob/HEAD/packages/astro/CHANGELOG.md#5159)
[Compare
Source](https://redirect.github.com/withastro/astro/compare/[email protected]@5.15.9)
##### Patch Changes
-
[#​14786](https://redirect.github.com/withastro/astro/pull/14786)
[`758a891`](https://redirect.github.com/withastro/astro/commit/758a891112839a108479fd0489a1785640b31ecf)
Thanks [@​mef](https://redirect.github.com/mef)! - Add handling of
invalid encrypted props and slots in server islands.
-
[#​14783](https://redirect.github.com/withastro/astro/pull/14783)
[`504958f`](https://redirect.github.com/withastro/astro/commit/504958fe7fccd7bffc177a1f4b1bf4e22989470e)
Thanks
[@​florian-lefebvre](https://redirect.github.com/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](https://redirect.github.com/withastro/astro/pull/14791)
[`9e9c528`](https://redirect.github.com/withastro/astro/commit/9e9c528191b6f5e06db9daf6ad26b8f68016e533)
Thanks [@​Princesseuh](https://redirect.github.com/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:
```js
// astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
images: {
remotePatterns: [
{
protocol: 'data',
},
],
},
});
```
-
[#​14787](https://redirect.github.com/withastro/astro/pull/14787)
[`0f75f6b`](https://redirect.github.com/withastro/astro/commit/0f75f6bc637d547e07324e956db21d9f245a3e8e)
Thanks [@​matthewp](https://redirect.github.com/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.
-
[#​14776](https://redirect.github.com/withastro/astro/pull/14776)
[`3537876`](https://redirect.github.com/withastro/astro/commit/3537876fde3bdb2a0ded99cc9b00d53f66160a7f)
Thanks [@​ktym4a](https://redirect.github.com/ktym4a)! - Fixes the
behavior of `passthroughImageService` so it does not generate webp.
- Updated dependencies
\[[`9e9c528`](https://redirect.github.com/withastro/astro/commit/9e9c528191b6f5e06db9daf6ad26b8f68016e533),
[`0f75f6b`](https://redirect.github.com/withastro/astro/commit/0f75f6bc637d547e07324e956db21d9f245a3e8e)]:
-
[@​astrojs/internal-helpers](https://redirect.github.com/astrojs/internal-helpers)@​0.7.5
-
[@​astrojs/markdown-remark](https://redirect.github.com/astrojs/markdown-remark)@​6.3.9
###
[`v5.15.8`](https://redirect.github.com/withastro/astro/blob/HEAD/packages/astro/CHANGELOG.md#5158)
[Compare
Source](https://redirect.github.com/withastro/astro/compare/[email protected]@5.15.8)
##### Patch Changes
-
[#​14772](https://redirect.github.com/withastro/astro/pull/14772)
[`00c579a`](https://redirect.github.com/withastro/astro/commit/00c579a23322d92459e4ccad0ec365c4d1980a5d)
Thanks [@​matthewp](https://redirect.github.com/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](https://redirect.github.com/withastro/astro/pull/14771)
[`6f80081`](https://redirect.github.com/withastro/astro/commit/6f800813516b07bbe12c666a92937525fddb58ce)
Thanks [@​matthewp](https://redirect.github.com/matthewp)! - Fix
middleware pathname matching by normalizing URL-encoded paths
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.
###
[`v5.15.7`](https://redirect.github.com/withastro/astro/blob/HEAD/packages/astro/CHANGELOG.md#5157)
[Compare
Source](https://redirect.github.com/withastro/astro/compare/[email protected]@5.15.7)
##### Patch Changes
-
[#​14765](https://redirect.github.com/withastro/astro/pull/14765)
[`03fb47c`](https://redirect.github.com/withastro/astro/commit/03fb47c0106fda823e4dc89ed98d282ecb5258a0)
Thanks
[@​florian-lefebvre](https://redirect.github.com/florian-lefebvre)!
- Fixes a case where `process.env` wouldn't be properly populated during
the build
-
[#​14690](https://redirect.github.com/withastro/astro/pull/14690)
[`ae7197d`](https://redirect.github.com/withastro/astro/commit/ae7197d35676b3745dc9ca71aecbcf3bbbfffb30)
Thanks
[@​fredriknorlin](https://redirect.github.com/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.
</details>
---
### Configuration
📅 **Schedule**: Branch creation - "" (UTC), Automerge - At any time (no
schedule defined).
🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/yorukot/superfile).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNzMuMSIsInVwZGF0ZWRJblZlciI6IjQyLjE2LjEiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbXX0=-->
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>1 parent e6aa7da commit fd2abee
1 file changed
+133
-133
lines changed
0 commit comments