GitHub Advisoryadvisory · npm
GHSA-5339-hvwr-7582 Unhead Vulnerable to Bypass of URI Scheme Sanitization in makeTagSafe via Case-Sensitivity
LOW
Official page ↗
- Aliases
- CVE-2026-31873
- Ecosystem
- npm
- Packages
- unhead
- Severity
- Low
- CVSS vector
- CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:N
- Weaknesses
- CWE-79
- Reviewed
- 2026-03-12
Affected packages
• npm unhead: < 2.1.11 → fixed in 2.1.11
Description
The `link.href` check in `makeTagSafe` (safe.ts, line 68-71) uses `String.includes()`, which is case-sensitive:
```typescript
if (key === 'href') {
if (val.includes('javascript:') || val.includes('data:')) {
return
}
next[key] = val
}
```
Browsers treat URI schemes case-insensitively. `DATA:text/css,...` is the same as `data:text/css,...` to the browser, but `'DATA:...'.includes('data:')` returns `false`.
PoC
```javascript
useHeadSafe({
link: [{
rel: 'stylesheet',
href: 'DATA:text/css,body{display:none}'
}]
})
```
SSR output:
```html
```
The browser loads this as a CSS stylesheet. An attacker can inject arbitrary CSS for UI redressing or data exfiltration via CSS attribute selectors with background-image callbacks.
Any case variation works: `DATA:`, `Data:`, `dAtA:`, `JAVASCRIPT:`, etc.
Suggested fix
```typescript
if (key === 'href') {
const lower = val.toLowerCase()
if (lower.includes('javascript:') || lower.includes('data:')) {
return
}
next[key] = val
}
```
Related
Alias · CVE (1)
- CVE-2026-31873 Unhead is a document head and template manager. vulnerability
Weakness · CWE (1)
- CWE-79 Improper Neutralization of Input During Web Page Generation weakness