GHSA-jrpj-wcv7-9fh9: Astro: XSS via Unescaped Attribute Names in Spread Props
Summary
The spreadAttributes function in Astro's server-side rendering pipeline iterates over object keys and passes them directly to addAttribute, which interpolates the key into the HTML output without escaping. When a developer uses the spread syntax {...props} on an HTML element and the object keys come from an untrusted source (API, CMS, URL parameters), an attacker can inject arbitrary HTML attributes including event handlers like onmousemove, onclick, or break out of the attribute context entirely to inject new elements.
Details
The vulnerable function is addAttribute at packages/astro/src/runtime/server/render/util.ts:81-141:
export function addAttribute(value: any, key: string, shouldEscape = true, tagName = '') {
if (value == null) {
return '';
}
return markHTMLString( ${key}="${toAttributeString(value, shouldEscape)}"); // key interpolated not escaped
}
This function is called from spreadAttributes at packages/astro/src/runtime/server/index.ts:91-92:
for (const [key, value] of Object.entries(values)) {
output += addAttribute(value, key, true, _name);
}
The toAttributeString function escapes the attribute value, but the attribute name key is never validated or escaped. An attacker can craft a JSON object with a key containing " characters to break out of the attribute context and inject event handlers.
Execution flow: User controlled object keys (from API, CMS, URL params) are spread onto element via {...props}. The compiler generates spreadAttributes(props) which iterates with Object.entries() and calls addAttribute(value, key). The key is interpolated as ${key}="${escapedValue}" . A malicious key breaks attribute context, resulting in XSS.
POC
Create an SSR Astro page (src/pages/index.astro):
const props = JSON.parse(Astro.url.searchParams.get('props') || '{}');
<html>
<body>
<h1>Hello</h1>
<div {...props}>Move mouse here</div>
</body>
</html>
Enable SSR in astro.config.mjs (for URL based demo):
export default defineConfig({
output: 'serve
Details
Original advisory: https://github.com/advisories/GHSA-jrpj-wcv7-9fh9
Exploitation outlook
EPSS (FIRST.org) estimates each CVE’s probability of exploitation in the next 30 days — here is the CSIRTS.com read on those numbers.
- Low exploitation riskCVE-2026-542980.23% 30-day exploitation probability — currently an unlikely target, but scores change as exploit code circulates. Riskier than 14% of all scored CVEs.
Referenced CVEs
| CVE | CSIRTS overview | External |
|---|---|---|
| CVE-2026-54298 | coverage & exploitation status | NVD · CVE.org |
More from GitHub Security Advisories
- mediumGHSA-xm43-3m56-w3wf: Ghost: Paid gift memberships obtainable at minimal cost via the donations feature2026-08-04
- mediumGHSA-chgm-3698-jm42: Ghost: Member existence leak via magic link sign-in response2026-08-04
- highGHSA-xpp7-93x6-v29m: XSS in Ghost's ActivityPub client2026-08-04
- mediumGHSA-7mpp-r37j-x5wh: Ghost: Session Fixation in Ghost Admin2026-08-04
- mediumGHSA-cjc9-q5gf-327p: Ghost: Theme Upload Path Traversal2026-08-04