CVE-2026-126363: Astro: Reflected XSS via unescaped slot names in @astrojs/solid-js
Summary
The @astrojs/solid-js renderer wraps named slot content passed to Solid 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:
astro --- import Tabs from '../components/Tabs.jsx'; const tab = Astro.url.searchParams.get('tab'); --- <Tabs client:load active={tab}><div slot={tab}>…</div></Tabs>
rendered with a Solid component that renders a slot by name:
jsx export default function Tabs(props) { return <div>{props[props.active]}</div>; }
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 Solid 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 Solid component renders the attacker-chosen slot, which in practice means accessing slot props by a dynamic name. Components that never render the slot only output Astro's already escaped fallback template.
This is the @astrojs/solid-js counterpart of GHSA-8hv8-536x-4wqp (CVE-2026-50146), which fixed the same issue in astro core.
Affected versions
@astrojs/solid-js >= 0.2.0, <= 7.1.1.
Patches
Fixed in @astrojs/solid-js 7.1.2. Slot names are now HTML-escaped in the server renderer.
Workarounds
Upgrade to @astrojs/solid-js 7.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.
Other sources
Astro is a web framework for content-driven websites. From 0.2.0 until 7.1.2, the @astrojs/solid-js renderer inserted a named slot into the quoted name attribute of an astro-slot wrapper without HTML escaping. A request-controlled slot name containing a quote could terminate the attribute and inject active HTML. Exploitation required a hydrated Solid component using a client: directive and dynamic access to the attacker-chosen slot property; a component that did not render that slot emitted only escaped fallback content. This issue is fixed in version 7.1.2.
— MITRE
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
npm/@astrojs/solid-jsto a version that resolves this vulnerability.Fixed in 7.1.2 - Upgrade
Upgrade
@astrojs/solid-jsto a version that resolves this vulnerability.Fixed in 7.1.2 - Compensating control
Before upgrading, do not use request-controlled input as a slot name; alternatively, map request-controlled input to a fixed set of known slot names before passing it to a Solid component.
Event History
Frequently Asked Questions
Which applications are exposed to exploitation?
Only applications that pass request-controlled input, such as a query parameter, into a slot name and render that slot through a Solid component hydrated with a client:* directive are exposed. Applications that do not use untrusted values as slot names are not affected by this attack path.
What does an attacker need to do?
An attacker needs to induce a user to open a crafted link or otherwise supply a malicious request-controlled slot name. The malicious value must contain characters such as a double quote that can terminate the generated name attribute and introduce HTML.
Does a non-hydrated Solid component have the same exposure?
No. For non-hydrated components, the slot wrapper is removed from the output along with its contents, so the described injection path requires hydration with a client:* directive.
What can be done before updating?
Do not use request-controlled values as slot names. If dynamic slot selection is required, restrict the value to an allowlist of expected slot names; removing the client:* hydration directive also prevents the described path where feasible.
How can I identify potentially affected code?
Review Astro pages for slot attributes whose values originate from request data, including Astro.url.searchParams, and determine whether the receiving Solid component uses client:* hydration. The advisory references the @astrojs/solid-js 7.1.2 release.