@vue/server-renderer: XSS via missing CR in attribute-name blacklist
## Description `@vue/server-renderer` was investigated specifically because it's the one place in Vue where template rendering output becomes a real HTTP response body -- a genuine server-side trust boundary, unlike client-side rendering which only ever affects the same browser session that's already running the app's own JS. `ssrRenderAttrs()` (in `packages/server-renderer/src/helpers/ssrRenderAttrs.ts`) is what compiled SSR output calls for something like ``. It loops over the object's own keys and, for each one, renders it as an HTML attribute: ```ts export function ssrRenderDynamicAttr( key: string, value: unknown, tag?: string, ): string { if (!isRenderableAttrValue(value)) { return `` } const attrKey = ... if (isBooleanAttr(attrKey) || ...) { return includeBooleanAttr(value) ? ` ${attrKey}` : `` } else if (isSSRSafeAttrName(attrKey)) { return value === '' ? ` ${attrKey}` : ` ${attrKey}="${escapeHtml(value)}"` } else { console.warn(`[@vue/server-renderer] Skipped rendering unsafe attribute name: ${attrKey}`) return `` } } ``` The value always goes through `escapeHtml()` -- that part is correctly and consistently applied everywhere in this file. But the attribute name (`attrKey`) is only checked against a character blacklist, then spliced directly into the output with no escaping of its own: ```ts // packages/shared/src/domAttrConfig.ts const unsafeAttrCharRE = /[>/="'\u0009\u000a\u000c\u0020]/ export function isSSRSafeAttrName(name: string): boolean { if (attrValidationC
GHSA-g2v6-rqmx-r4w6
Primary source · Revision 1
Imported from structured advisory data. Source references identify upstream records or fields; verify affected versions and your deployed configuration.
Security context
Source reference: osv:GHSA-g2v6-rqmx-r4w6
@vue/server-renderer
Source reference: /affected/0/package/name
- Affected versions
- Not stated in this record
- Fixed versions
- 3.5.42
Source reference:
/affected/0/ranges - Prerequisites
- Not stated in this record
@vue/server-renderer
Source reference: /affected/1/package/name
- Affected versions
- Not stated in this record
- Fixed versions
- 3.6.0-rc.6
Source reference:
/affected/1/ranges - Prerequisites
- Not stated in this record
Structured affected-version data
Original package identities and version rules from this source.
[
{
"ranges": [
{
"type": "SEMVER",
"events": [
{
"introduced": "0"
},
{
"fixed": "3.5.42"
}
]
}
],
"package": {
"name": "@vue/server-renderer",
"purl": "pkg:npm/%40vue/server-renderer",
"ecosystem": "npm"
},
"database_specific": {
"source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/10/GHSA-g2v6-rqmx-r4w6/GHSA-g2v6-rqmx-r4w6.json"
}
},
{
"ranges": [
{
"type": "SEMVER",
"events": [
{
"introduced": "3.6.0-rc.0"
},
{
"fixed": "3.6.0-rc.6"
}
]
}
],
"package": {
"name": "@vue/server-renderer",
"purl": "pkg:npm/%40vue/server-renderer",
"ecosystem": "npm"
},
"database_specific": {
"source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/10/GHSA-g2v6-rqmx-r4w6/GHSA-g2v6-rqmx-r4w6.json"
}
}
]Publisher severity
high
Source reference: /database_specific/severity
- Event
- #85865 · Revision 1
- Added to Heist Feed
- Publisher date