网安资讯详情 - SecLens 情报雷达

网安资讯,一网打尽。汇集权威漏洞通告与行业要闻,结合分组浏览、智能过滤、RSS订阅 和 Webhook 推送,多通道拓展您的安全情报视野。

npm/astro: Astro: XSS via unescaped spread attribute names in renderHTMLElement (incomplete fix for CVE-2026-54298)

来源: github_advisory · 发布时间 2026-07-21 07:21 (UTC+08:00) · 抓取时间 2026-07-21 08:45 (UTC+08:00)

原文链接

摘要

Severity: MEDIUM | CVE: CVE-2026-59729 | Package: npm/astro | Affected: < 7.0.6 | Patched: 7.0.6

正文

## Summary The fix for CVE-2026-54298 (GHSA-jrpj-wcv7-9fh9) added an `INVALID_ATTR_NAME_CHAR` guard to `addAttribute()` so that spread-prop attribute names containing `"' >/=` or whitespace are dropped. A second attribute-rendering path, `renderHTMLElement()` in `packages/astro/src/runtime/server/render/dom.ts`, has its own inline attribute loop that does not go through `addAttribute()` 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 `renderHTMLElement` builds attributes directly: ```js for (const attr in props) { attrHTML += ` ${attr}="${toAttributeString(await props[attr])}"`; } ``` The attribute name (`attr`) is interpolated raw; only the value is escaped via `toAttributeString`. By contrast, the hardened `addAttribute` in `util.ts` rejects invalid names: ```js if (INVALID_ATTR_NAME_CHAR.test(key)) { return ''; } // /[\s"'>/=]/ ``` `renderHTMLElement` is reached from `component.ts` when the component is a native `HTMLElement` subclass: ```js if (!renderer && typeof HTMLElement === 'function' && componentIsHTMLElement(Component)) { const output = await renderHTMLElement(result, Component, _props, slots); } ``` where `_props` carries spread props verbatim. ### Reachability The branch only runs when `typeof HTMLElement === 'function'` at SSR time. In default Node SSR `HTMLElement` is `undefined`, so the branch is dead. It becomes reachable when the SSR runtime exposes a global `HTMLElement` (Deno, Bun with a DOM shim, or jsdom/happy-dom in Node) **and** a class extending `HTMLElement` is used directly as an Astro component that receives untrusted-keyed spread props. ## Proof of Concept Given malicious spread props: ```js const maliciousProps = { 'onmouseover=alert(document.domain) x': 'y', 'x><script>alert(1)</script>': 'z', }; ``` - `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`: ```astro --- import MyElement from '../MyElement.js'; // class MyElement extends HTMLElement {} const userInput = Astro.url.searchParams; // untrusted keys --- <MyElement {...Object.fromEntries(userInput)} /> ``` ## 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.

标签

扩展字段

{
  "credits": [
    {
      "login": "thientd",
      "type": "reporter"
    }
  ],
  "cve_id": "CVE-2026-59729",
  "cwe_ids": [
    "CWE-79"
  ],
  "cwe_names": [
    "Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')"
  ],
  "ghsa_id": "GHSA-f48w-9m4c-m7f5",
  "package": {
    "ecosystem": "npm",
    "name": "astro",
    "patched_version": "7.0.6",
    "vulnerable_range": "< 7.0.6"
  },
  "references": [
    "https://github.com/withastro/astro/security/advisories/GHSA-f48w-9m4c-m7f5",
    "https://github.com/withastro/astro/pull/17251",
    "https://github.com/withastro/astro/commit/5240e26c9dd91f9bc7140dcfacdb48d5a132830d",
    "https://github.com/withastro/astro/releases/tag/[email protected]",
    "https://github.com/advisories/GHSA-f48w-9m4c-m7f5"
  ],
  "source_code_location": "https://github.com/withastro/astro",
  "updated_at": "2026-07-20T23:22:00Z"
}