Vulnerability GHSA-f4j9-crrj-867q

Low Risk
LOW RISK
CVSS Score: 3.0
Score Range: < 4.0
Low severity vulnerabilities (CVSS < 4.0). Hygiene issues that can accumulate but pose lower immediate risk.
18 hours ago
November 12, 2026 at 10:34 PM UTC
Astro: Reflected XSS via unescaped slot names in @astrojs/svelte
>=5.7.3 <9.1.2
>=5.7.3 <9.1.2

Summary

Astro: Reflected XSS via unescaped slot names in @astrojs/svelte

Details

Summary

The @astrojs/svelte renderer wraps slotted content passed to Svelte components in an <astro-slot> element, and writes the slot name into its name attribute without HTML escaping. A slot name containing " could end the attribute and inject arbitrary HTML into the page.

For example, a page that takes a slot name from the request:

<Tabs client:load active={tab}><div slot={tab}>…</div></Tabs>

rendered with a Svelte 5 component that renders its snippets by name:

<script>
	let { active, ...snippets } = $props();
</script>
{@render snippets[active]?.()}

would output a tab value such as x"><img src=x onerror=alert(1)> as live HTML.

Impact

Reflected cross-site scripting. An attacker who gets a user to open a crafted link can run JavaScript on the site's origin, but only in applications where all of the following are true:

  • The page passes request-controlled input (such as a query parameter) as a slot name.
  • The Svelte component is hydrated with a client:* directive. For non-hydrated components the slot wrapper is removed from the output, together with its name attribute.
  • The Svelte component renders the attacker-chosen slot, which in practice means a Svelte 5 component that renders snippets by a dynamic name. Components that never render the slot only output Astro's already escaped fallback template.

This is the @astrojs/svelte counterpart of GHSA-8hv8-536x-4wqp (CVE-2026-50146), which fixed the same issue in astro core. The same unescaped value was also used when hydrating the component in the browser.

Affected versions

@astrojs/svelte >= 5.7.3, <= 9.1.1.

Patches

Fixed in @astrojs/svelte 9.1.2. Slot names are now HTML-escaped in the server renderer and in the client-side hydration code.

Workarounds

Upgrade to @astrojs/svelte 9.1.2 or later. Before upgrading, do not use request-controlled input as a slot name, or map it to a fixed set of known slot names before passing it to a component.

Credits

Reported by @manus-pi.

Impacted packages

Timeline

Published
18 hours ago
November 12, 2026 at 10:34 PM UTC
Fixed (9.1.2)
16 days ago
October 28, 2026 at 02:50 PM UTC
Last Modified
18 hours ago
November 12, 2026 at 10:45 PM UTC