fix(deps): update dependency astro to v7 [security]#80
Open
renovate[bot] wants to merge 1 commit into
Open
Conversation
renovate
Bot
force-pushed
the
renovate/npm-astro-vulnerability
branch
2 times, most recently
from
July 20, 2026 21:48
bdff2f7 to
9ddead7
Compare
renovate
Bot
force-pushed
the
renovate/npm-astro-vulnerability
branch
2 times, most recently
from
July 24, 2026 22:54
9ddead7 to
a958762
Compare
Wiz Scan Summary
To detect these findings earlier in the dev lifecycle, try using Wiz Code VS Code Extension. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR contains the following updates:
^6.0.0→^7.0.0Astro: Reflected XSS via unescaped slot name
CVE-2026-50146 / GHSA-8hv8-536x-4wqp
More information
Details
Summary
When a component uses a
client:*directive, Astro inserts named slot content into adata-astro-templateattribute without HTML escaping the slot name allowing an attacker to break out of the attribute context and inject arbitrary HTML, resulting in reflected XSS during SSR.This is similar to GHSA-wrwg-2hg8-v723 but exploits a different injection point.
Vulnerable Code
packages/astro/src/runtime/server/render/component.ts:371:376I found that key is interpolated directly into the attribute value without proper escaping.
Proof of Concept
For the PoC, I set up with a minimal repository with Astro 6.3.1, Node.js: v26.0.0.
astro.config.mjssrc/pages/index.astrosrc/components/Wrapper.jsxPayload:
Accessing this URL will trigger the popup.
http://localhost:4321/?tab=abc%22%3E%3C%2Ftemplate%3E%3C%2Fastro-island%3E%3Cimg+src%3Dx+onerror%3Dconfirm(document.domain)%3E%3C!--
This will render in html.
Fix
I suggest leveraging the existing escape function on the slot name.
Severity
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:H/A:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Astro: Host header SSRF in prerendered error page fetch
CVE-2026-54299 / GHSA-2pvr-wf23-7pc7
More information
Details
Summary
Astro SSR apps with prerendered error pages (
/404or/500usingexport const prerender = true) fetch those pages over HTTP at runtime when an error occurs. The URL for this fetch is derived fromrequest.url, which in turn gets its origin from the incomingHostheader. When theHostheader is not validated againstallowedDomains, an attacker can point the fetch at an arbitrary host and read the response.Who is affected
This affects SSR deployments that:
createRequestFromNodeRequestfromastro/app/nodewithapp.render()without overridingprerenderedErrorPageFetch— this includes custom servers built on the public API and third-party adaptersNot affected:
@astrojs/node>= 9.5.4 (reads error pages from disk)@astrojs/cloudflare(uses the ASSETS binding)How it works
createRequestFromNodeRequestbuildsrequest.urlfrom the rawHost/:authorityheader. TheallowedDomainsoption is accepted but only gatesX-Forwarded-For— it does not constrain the URL origin. (The publiccreateRequestdoes fall back tolocalhostfor unvalidated hosts; this internal builder did not.)When
app.render()encounters a 404 or 500 with a prerendered error route,default-handler.tsconstructs the error page URL using the origin fromrequest.urland fetches it viaprerenderedErrorPageFetch, which defaults to globalfetch. The response body is served to the client.An attacker sends a request with
Host: attacker-host:port, triggers an error (e.g., requesting a nonexistent path for a 404), and receives the response from the attacker-controlled host reflected back.Remediation
The error page fetch origin is now validated against
allowedDomainsbefore use. When the host is validated, the original origin is preserved. Otherwise, it falls back tolocalhost. The fetch is also wrapped in a try/catch so that connection failures degrade gracefully to a plain error response.Credit
5ud0 / Tarmo Technologies
Severity
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:L/A:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Astro: XSS via Unescaped Attribute Names in Spread Props
CVE-2026-54298 / GHSA-jrpj-wcv7-9fh9
More information
Details
Summary
The
spreadAttributesfunction in Astro's server-side rendering pipeline iterates over object keys and passes them directly toaddAttribute, 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 likeonmousemove,onclick, or break out of the attribute context entirely to inject new elements.Details
The vulnerable function is
addAttributeatpackages/astro/src/runtime/server/render/util.ts:81-141:This function is called from
spreadAttributesatpackages/astro/src/runtime/server/index.ts:91-92:The
toAttributeStringfunction escapes the attribute value, but the attribute namekeyis 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 generatesspreadAttributes(props)which iterates withObject.entries()and callsaddAttribute(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):Enable SSR in
astro.config.mjs(for URL based demo):Note: SSR is not required for the vulnerability to exist. In static builds (default), the attack vector is compromised data sources at build time (API, CMS, database). SSR simply makes the PoC easier to demonstrate via URL parameters.
Start the dev server and visit:
URL encoded:
View the HTML source. The output contains:
The key
x" onmousemove="alert(document.cookie)" ybreaks out of the attribute context. Moving the mouse over the div executes the JavaScript.Impact
An attacker can execute arbitrary JavaScript in the context of a victim's browser session on any Astro application that spreads object props from untrusted sources onto HTML elements. This is a common pattern when integrating with external APIs or CMS systems. Exploitation enables session hijacking via cookie theft, credential theft by injecting fake login forms or keyloggers, defacement of the rendered page, and redirection to attacker controlled domains.
The vulnerability affects all Astro versions that support spread syntax on HTML elements and is exploitable in SSR, SSG (if build time data is compromised), and hybrid deployments.
Severity
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Astro: Reflected XSS via unescaped View Transition animation properties
GHSA-4g3v-8h47-v7g6
More information
Details
Summary
Astro's server-side View Transition CSS generator interpolates animation properties into an inline
<style>element without escaping them for the CSS and HTML contexts.An attacker-controlled value passed to an animation property such as
durationcan contain a</style>sequence, terminate the generated style element, and inject arbitrary HTML or JavaScript.This is similar to GHSA-8hv8-536x-4wqp, but exploits a different injection point: unescaped View Transition animation values in a server-generated
<style>element rather than an unescaped slot name in a hydration template.Like GHSA-8hv8-536x-4wqp, exploitation requires an application to pass attacker-controlled data to an Astro API. However, the value is subsequently inserted into the HTML response without context-appropriate escaping by Astro.
Details
packages/astro/src/runtime/server/transition.tsThe generated stylesheet is wrapped in a
<style>element and marked as HTML-safe:Animation properties are added to the stylesheet without escaping:
For string values,
toTimeValue()returns the input unchanged:As a result, a
durationvalue containing</style>can escape from the generated style element.Other
TransitionAnimationproperties, includingeasing,direction,delay,fillMode, andname, are serialized by the same animation builder. The following PoC only relies on the officialfade()helper and itsdurationoption.PoC
Using:
astro@7.0.9@astrojs/node@11.0.2astro.config.mjssrc/pages/index.astroPayload:
open:
The browser interprets
</style>as the end of the generated style element and executes the injected script. An alert dialog is displayed when the page is opened.Impact
An attacker who can control a View Transition animation value can execute arbitrary JavaScript in the origin of the affected Astro application.
The query-based reflected XSS scenario affects on-demand/server-rendered routes, such as:
output: "server";export const prerender = false;Successful exploitation may allow access to sensitive page data and authenticated actions available to the victim.
Suggested Fix
Animation values should be serialized using context-appropriate CSS escaping or validation before being added to the generated stylesheet.
Additionally, content inserted into a raw
<style>element must not be able to contain an HTML end-tag sequence such as</style>. The final generated CSS should be made safe for the HTML raw-text context before it is passed tomarkHTMLString().Severity
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:N/VA:N/SC:L/SI:L/SA:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Astro: Cross-site scripting via unescaped transition:* directive values on hydrated islands
CVE-2026-59727 / GHSA-7pw4-f3q4-r2p2
More information
Details
Summary
When a
transition:persist,transition:scope, ortransition:persist-propsdirective is applied to a client-hydrated (client:*) component, Astro copied the directive value onto the rendered<astro-island>element without HTML-escaping it. If a developer reflects attacker-controlled input into one of these directives, an attacker can break out of the attribute and inject arbitrary HTML/JavaScript into the server-rendered output, resulting in reflected cross-site scripting (XSS).Severity
Although a generic reflected XSS scores in the Medium range, exploitation here requires the application developer to have written a non-idiomatic pattern — passing untrusted, request-derived input directly into a transition directive. Astro applications that do not route untrusted input into these directives are unaffected. This mitigating precondition places the real-world severity at Low.
Details
In
generateHydrateScript()(packages/astro/src/runtime/server/hydration.ts), every island property is HTML-escaped before serialization — theattrs,props, andoptsassignments all pass throughescapeHTML(). The transition directives, however, were copied verbatim:The
<astro-island>element is serialized viarenderElement('astro-island', island, false)withshouldEscape=false, andtoAttributeString()returns the value unchanged in that mode. As a result there is no downstream re-escaping, and the raw directive value reaches the HTML response. This is the same output sink previously addressed for slot names in GHSA-8hv8-536x-4wqp.The affected directives are:
data-astro-transition-scope(transition:scope)data-astro-transition-persist(transition:persist)data-astro-transition-persist-props(transition:persist-props)Note that
transition:persistis typedboolean | string, so passing a string value is a supported use of the API.Proof of Concept
A component that reflects a query parameter into a transition directive:
Request:
Rendered output (before the fix):
The
"closes the attribute and the injected<img onerror=…>executes in the victim's browser.Impact
Reflected XSS. An attacker who can induce a victim to visit a crafted URL can execute arbitrary script in the victim's session on the origin, subject to the requirement that the target application reflects untrusted input into one of the affected transition directives.
Affected Versions
astro >= 3.10.0, < 7.0.4(introduced in 3.10.0, PR #7861).Patched Versions
astro >= 7.0.4. Fixed in PR #17212 by HTML-escaping transition directive values before they are rendered onto the island element.Workarounds
Do not pass untrusted or request-derived input into
transition:persist,transition:scope, ortransition:persist-props. If such input is required, HTML-escape or strictly validate it before passing it to the directive. Upgrading toastro@7.0.4or later removes the need for manual mitigation.Credits
Reported by @jlgore.
Severity
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:A/VC:N/VI:N/VA:N/SC:L/SI:L/SA:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Astro: XSS via unescaped spread attribute names in renderHTMLElement (incomplete fix for CVE-2026-54298)
CVE-2026-59729 / GHSA-f48w-9m4c-m7f5
More information
Details
Summary
The fix for CVE-2026-54298 (GHSA-jrpj-wcv7-9fh9) added an
INVALID_ATTR_NAME_CHARguard toaddAttribute()so that spread-prop attribute names containing"' >/=or whitespace are dropped. A second attribute-rendering path,renderHTMLElement()inpackages/astro/src/runtime/server/render/dom.ts, has its own inline attribute loop that does not go throughaddAttribute()and was not updated. It interpolates the attribute name unescaped and only escapes the value, so untrusted prop keys spread onto a native-HTMLElement-subclass component can still break out of the attribute context, resulting in XSS.Details
renderHTMLElementbuilds attributes directly:The attribute name (
attr) is interpolated raw; only the value is escaped viatoAttributeString. By contrast, the hardenedaddAttributeinutil.tsrejects invalid names:renderHTMLElementis reached fromcomponent.tswhen the component is a nativeHTMLElementsubclass:where
_propscarries spread props verbatim.Reachability
The branch only runs when
typeof HTMLElement === 'function'at SSR time. In default Node SSRHTMLElementisundefined, so the branch is dead. It becomes reachable when the SSR runtime exposes a globalHTMLElement(Deno, Bun with a DOM shim, or jsdom/happy-dom in Node) and a class extendingHTMLElementis used directly as an Astro component that receives untrusted-keyed spread props.Proof of Concept
Given malicious spread props:
addAttribute(post-fix) →<my-el></my-el>(key stripped — safe)renderHTMLElement→<my-el onmouseover=alert(document.domain) x="y" x><script>alert(1)</script>="z"></my-el>(handler +<script>injected — XSS)Equivalent Astro template, served by an SSR runtime that defines a global
HTMLElement:Impact
Cross-site scripting (CWE-79) via attribute-name breakout — the same vulnerability class as CVE-2026-54298, in a code path its fix did not cover. An attacker who controls the keys of an object spread onto a native-
HTMLElement-subclass component can inject arbitrary event-handler attributes or sibling elements (including<script>) into the SSR output. Reachability is constrained by the runtime and component preconditions described above.Severity
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:N/VA:N/SC:L/SI:L/SA:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Astro: Reflected XSS via unescaped slot name
CVE-2026-50146 / GHSA-8hv8-536x-4wqp
More information
Details
Summary
When a component uses a
client:*directive, Astro inserts named slot content into adata-astro-templateattribute without HTML escaping the slot name allowing an attacker to break out of the attribute context and inject arbitrary HTML, resulting in reflected XSS during SSR.This is similar to GHSA-wrwg-2hg8-v723 but exploits a different injection point.
Vulnerable Code
packages/astro/src/runtime/server/render/component.ts:371:376I found that key is interpolated directly into the attribute value without proper escaping.
Proof of Concept
For the PoC, I set up with a minimal repository with Astro 6.3.1, Node.js: v26.0.0.
astro.config.mjssrc/pages/index.astrosrc/components/Wrapper.jsxPayload:
Accessing this URL will trigger the popup.
http://localhost:4321/?tab=abc%22%3E%3C%2Ftemplate%3E%3C%2Fastro-island%3E%3Cimg+src%3Dx+onerror%3Dconfirm(document.domain)%3E%3C!--
This will render in html.
Fix
I suggest leveraging the existing escape function on the slot name.
Severity
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:H/A:NReferences
This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).
Astro: Host header SSRF in prerendered error page fetch
CVE-2026-54299 / GHSA-2pvr-wf23-7pc7
More information
Details
Summary
Astro SSR apps with prerendered error pages (
/404or/500usingexport const prerender = true) fetch those pages over HTTP at runtime when an error occurs. The URL for this fetch is derived fromrequest.url, which in turn gets its origin from the incomingHostheader. When theHostheader is not validated againstallowedDomains, an attacker can point the fetch at an arbitrary host and read the response.Who is affected
This affects SSR deployments that:
createRequestFromNodeRequestfromastro/app/nodewithapp.render()without overridingprerenderedErrorPageFetch— this includes custom servers built on the public API and third-party adaptersNot affected:
@astrojs/node>= 9.5.4 (reads error pages from disk)@astrojs/cloudflare(uses the ASSETS binding)How it works
createRequestFromNodeRequestbuildsrequest.urlfrom the rawHost/:authorityheader. TheallowedDomainsoption is accepted but only gatesX-Forwarded-For— it does not constrain the URL origin. (The publiccreateRequestdoes fall back tolocalhostfor unvalidated hosts; this internal builder did not.)When
app.render()encounters a 404 or 500 with a prerendered error route,default-handler.tsconstructs the error page URL using the origin fromrequest.urland fetches it viaprerenderedErrorPageFetch, which defaults to globalfetch. The response body is served to the client.An attacker sends a request with
Host: attacker-host:port, triggers an error (e.g., requesting a nonexistent path for a 404), and receives the response from the attacker-controlled host reflected back.Remediation
The error page fetch origin is now validated against
allowedDomainsbefore use. When the host is validated, the original origin is preserved. Otherwise, it falls back tolocalhost. The fetch is also wrapped in a try/catch so that connection failures degrade gracefully to a plain error response.Credit
5ud0 / Tarmo Technologies
Severity
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:L/A:NReferences
This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).
Astro: XSS via Unescaped Attribute Names in Spread Props
CVE-2026-54298 / GHSA-jrpj-wcv7-9fh9
More information
Details
Summary
The
spreadAttributesfunction in Astro's server-side rendering pipeline iterates over object keys and passes them directly toaddAttribute, 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 likeonmousemove,onclick, or break out of the attribute context entirely to inject new elements.Details
The vulnerable function is
addAttributeatpackages/astro/src/runtime/server/render/util.ts:81-141:This function is called from
spreadAttributesatpackages/astro/src/runtime/server/index.ts:91-92:The
toAttributeStringfunction escapes the attribute value, but the attribute namekeyis 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 generatesspreadAttributes(props)which iterates withObject.entries()and callsaddAttribute(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):Enable SSR in
astro.config.mjs(for URL based demo):Note: SSR is not required for the vulnerability to exist. In static builds (default), the attack vector is compromised data sources at build time (API, CMS, database). SSR simply makes the PoC easier to demonstrate via URL parameters.
Start the dev server and visit:
URL encoded:
View the HTML source. The output contains:
The key
x" onmousemove="alert(document.cookie)" ybreaks out of the attribute context. Moving the mouse over the div executes the JavaScript.Impact
An attacker can execute arbitrary JavaScript in the context of a victim's browser session on any Astro application that spreads object props from untrusted sources onto HTML elements. This is a common pattern when integrating with external APIs or CMS systems. Exploitation enables session hijacking via cookie theft, credential theft by injecting fake login forms or keyloggers, defacement of the rendered page, and redirection to attacker controlled domains.
The vulnerability affects all Astro versions that support spread syntax on HTML elements and is exploitable in SSR, SSG (if build time data is compromised), and hybrid deployments.
Severity
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:NReferences
This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).
Astro: Cross-site scripting via unescaped transition:* directive values on hydrated islands
CVE-2026-59727 / GHSA-7pw4-f3q4-r2p2
More information
Details
Summary
When a
transition:persist,transition:scope, ortransition:persist-propsdirective is applied to a client-hydrated (client:*) component, Astro copied the directive value onto the rendered<astro-island>element without HTML-escaping it. If a developer reflects attacker-controlled input into one of these directives, an attacker can break out of the attribute and inject arbitrary HTML/JavaScript into the server-rendered output, resulting in reflected cross-site scripting (XSS).Severity
Although a generic reflected XSS scores in the Medium range, exploitation here requires the application developer to have written a non-idiomatic pattern — passing untrusted, request-derived input directly into a transition directive. Astro applications that do not route untrusted input into these directives are unaffected. This mitigating precondition places the real-world severity at Low.
Details
In
generateHydrateScript()(packages/astro/src/runtime/server/hydration.ts), every island property is HTML-escaped before serialization — theattrs,props, andoptsassignments all pass throughescapeHTML(). The transition directives, however, were copied verbatim:The
<astro-island>element is serialized viarenderElement('astro-island', island, false)withshouldEscape=false, andtoAttributeString()returns the value unchanged in that mode. As a result there is no downstream re-escaping, and the raw directive value reaches the HTML response. This is the same output sink previously addressed for slot names in GHSA-8hv8-536x-4wqp.The affected directives are:
data-astro-transition-scope(transition:scope)data-astro-transition-persist(transition:persist)data-astro-transition-persist-props(transition:persist-props)Note that
transition:persistis typedboolean | string, so passing a string value is a supported use of the API.Proof of Concept
A component that reflects a query parameter into a transition directive:
Request:
Rendered output (before the fix):
The
"closes the attribute and the injected<img onerror=…>executes in the victim's browser.Impact
Reflected XSS. An attacker who can induce a victim to visit a crafted URL can execute arbitrary script in the victim's session on the origin, subject to the requirement that the target application reflects untrusted input into one of the affected transition directives.
Affected Versions
astro >= 3.10.0, < 7.0.4(introduced in 3.10.0, PR #7861).Patched Versions
astro >= 7.0.4. Fixed in PR #17212 by HTML-escaping transition directive values before they are rendered onto the island element.Workarounds
Do not pass untrusted or request-derived input into
transition:persist,transition:scope, ortransition:persist-props. If such input is required, HTML-escape or strictly validate it before passing it to the directive. Upgrading toastro@7.0.4or later removes the need for manual mitigation.Credits
Reported by @jlgore.
Severity
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:A/VC:N/VI:N/VA:N/SC:L/SI:L/SA:NReferences
This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).
Astro: XSS via unescaped spread attribute names in renderHTMLElement (incomplete fix for CVE-2026-54298)
CVE-2026-59729 / GHSA-f48w-9m4c-m7f5
More information
Details
Summary
The fix for CVE-2026-54298 (GHSA-jrpj-wcv7-9fh9) added an
INVALID_ATTR_NAME_CHARguard toaddAttribute()so that spread-prop attribute names containing"' >/=or whitespace are dropped. A second attribute-rendering path,renderHTMLElement()inpackages/astro/src/runtime/server/render/dom.ts, has its own inline attribute loop that does not go throughaddAttribute()and was not updated. It interpolates the attribute name unescaped and only escapes the value, so untrusted prop keys spread onto a native-HTMLElement-subclass component can still break out of the attribute context, resulting in XSS.Details
renderHTMLElementbuilds attributes directly:The attribute name (
attr) is interpolated raw; only the value is escaped viatoAttributeString. By contrast, the hardenedaddAttributeinutil.tsrejects invalid names:renderHTMLElementis reached fromcomponent.tswhen the component is a nativeHTMLElementsubclass:where
_propscarries spread props verbatim.Reachability
The branch only runs when
typeof HTMLElement === 'function'at SSR time. In default Node SSRHTMLElementisundefined, so the branch is dead. It becomes reachable when the SSR runtime exposes a globalHTMLElement(Deno, Bun with a DOM shim, or jsdom/happy-dom in Node) and a class extendingHTMLElementis used directly as an Astro component that receives untrusted-keyed spread props.Proof of Concept
Given malicious spread props:
addAttribute(post-fix) →<my-el></my-el>(key stripped — safe)renderHTMLElement→<my-el onmouseover=alert(document.domain) x="y" x><script>alert(1)</script>="z"></my-el>(handler +<script>injected — XSS)Equivalent Astro template, served by an SSR runtime that defines a global
HTMLElement:Impact
Cross-site scripting (CWE-79) via attribute-name breakout — the same vulnerability class as CVE-2026-54298, in a code path its fix did not cover. An attacker who controls the keys of an object spread onto a native-
HTMLElement-subclass component can inject arbitrary event-handler attributes or sibling elements (including<script>) into the SSR output. Reachability is constrained by the runtime and component preconditions described above.Severity
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:N/VA:N/SC:L/SI:L/SA:NReferences
This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).
Astro: Reflected XSS via unescaped View Transition animation properties
GHSA-4g3v-8h47-v7g6
More information
Details
Summary
Astro's server-side View Transition CSS generator interpolates animation properties into an inline
<style>element without escaping them for the CSS and HTML contexts.An attacker-controlled value passed to an animation property such as
durationcan contain a</style>sequence, terminate the generated style element, and inject arbitrary HTML or JavaScript.This is similar to GHSA-8hv8-536x-4wqp, but exploits a different injection point: unescaped View Transition animation values in a server-generated
<style>element rather than an unescaped slot name in a hydration template.Like GHSA-8hv8-536x-4wqp, exploitation requires an application to pass attacker-controlled data to an Astro API. However, the value is subsequently inserted into the HTML response without context-appropriate escaping by Astro.
Details
packages/astro/src/runtime/server/transition.tsThe generated stylesheet is wrapped in a
<style>element and marked as HTML-safe:Animation properties are added to the stylesheet without escaping:
For string values,
toTimeValue()returns the input unchanged:As a result, a
durationvalue containing</style>can escape from the generated style element.Other
TransitionAnimationproperties, includingeasing,direction,delay,fillMode, andname, are serialized by the same animation builder. The following PoC only relies on the officialfade()helper and itsdurationoption.PoC
Using:
astro@7.0.9@astrojs/node@11.0.2astro.config.mjssrc/pages/index.astroPayload:
open:
The browser interprets
</style>as the end of the generated style element and executes the injected script. An alert dialog is displayed when the page is opened.Impact
An attacker who can control a View Transition animation value can execute arbitrary JavaScript in the origin of the affected Astro application.
The query-based reflected XSS scenario affects on-demand/server-rendered routes, such as:
output: "server";export const prerender = false;Successful exploitation may allow access to sensitive page data and authenticated actions available to the victim.
Suggested Fix
Animation values should be serialized using context-appropriate CSS escaping or validation before being added to the generated stylesheet.
Additionally, content inserted into a raw
<style>element must not be able to contain an HTML end-tag sequence such as</style>. The final generated CSS should be made safe for the HTML raw-text context before it is passed tomarkHTMLString().Severity
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:N/VA:N/SC:L/SI:L/SA:NReferences
This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).
Release Notes
withastro/astro (astro)
v7.1.0Compare Source
Minor Changes
#17302
5f4dc03Thanks @astrobot-houston! - Adds a newdeferRenderoption to theglob()content loaderWhen set to
true, renderable entries (such as Markdown) are not rendered during content sync. Instead, rendering is deferred until the entry is actually rendered in a page, using the same on-demand path that.mdxfiles already use.This reduces memory usage during
astro buildfor large collections whose rendered output is much larger than the source — for example, Markdown that uses heavy rehype plugins likerehype-katex. Such builds could previously run out of memory while storing the eagerly-rendered HTML for every entry.By default
deferRenderisfalse, preserving the existing behavior of rendering entries eagerly during sync so their rendered HTML can be cached across builds.#17296
30698a2Thanks @ematipico! - Adds a new experimentalcollectionStorageoption for controlling how the content layer persists its data storeBy default, Astro serializes the entire content layer data store to a single file (
.astro/data-store.json). For very large content collections, this file can grow large enough to hit platform file-size limits.Set
experimental.collectionStorage: 'chunked'to instead split the data store across many smaller, content-addressed files inside a.astro/data-store/directory, described by a manifest:Because each part file is named by a hash of its contents, unchanged parts keep the same name across builds and are not rewritten, and identical parts are deduplicated. The default value is
'single-file', which preserves the current behavior.#17214
44c4989Thanks @ematipico! - Adds support for the more specific CSP directivesscript-src-elem,script-src-attr,style-src-elem, andstyle-src-attrthrough a newkindoption.Previously,
CSPwas only scoped to genericscript-src/style-srcdirectives. Now each source or hash can be scoped to a narrower directive — for example, to allow inlinestyleattributes (such as those fromdefine:varsor Shiki) without loosening the policy for your<style>and<link>elements.Scoping sources and hashes in your config
Each entry in
resourcesandhashescan be an object with akindproperty. Depending on whether you usescriptDirectiveorstyleDirective,"element"targetsscript-src-elemorstyle-src-elem,"attribute"targetsscript-src-attrorstyle-src-attr, and"default"(the same as a bare string or hash) targetsscript-srcorstyle-src.Scoping at runtime
The same
kindoption is available on the runtime CSP API, where the existing methods now also accept an object:84814d4Thanks @astrobot-houston! - Adds a newformat()option to the [paginate](https://docs.astro.build/en/refConfiguration
📅 Schedule: (UTC)
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR was generated by Mend Renovate. View the repository job log.