CVE-2026-126362 — @astrojs/svelte
Fix: withastro/astro@5e47636CVE-2026-126362 is a security vulnerability in @astrojs/svelte. A fix is available for @astrojs/svelte — see the affected versions and patch details below.
Astro: Reflected XSS via unescaped slot names in @astrojs/svelte
Real-World Exposure
How broadly this vulnerability is actually deployed: weekly install volume shows current usage, and reverse-dependency count shows how many other packages break if it stays unpatched.
@astrojs/sveltenpmDescription
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:
---
import Tabs from '../components/Tabs.svelte';
const tab = Astro.url.searchParams.get('tab');
---
<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 itsnameattribute. - 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.
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 📦npm | @astrojs/svelte | ≥ 5.7.3&&< 9.1.2 | 9.1.2npm install @astrojs/svelte@9.1.2 |
Detection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for @astrojs/svelte, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
Fix
Update @astrojs/svelte to 9.1.2 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-126362 is resolved across your whole dependency graph.
Workarounds
Escape or sanitise the affected output on the server side rather than relying on client-side filtering, and add a Content-Security-Policy that blocks inline script execution so injected markup cannot run even if it reaches the page.
Frequently Asked Questions
Is CVE-2026-126362 in your dependencies?
Find it across npm, including transitive dependencies.