CVE-2026-31860 (GCVE-0-2026-31860)
Vulnerability from cvelistv5 – Published: 2026-03-12 17:18 – Updated: 2026-03-13 16:26
VLAI?
Title
Unhead has a XSS bypass in `useHeadSafe` via attribute name injection and case-sensitive protocol check
Summary
Unhead is a document head and template manager. Prior to 2.1.11, useHeadSafe() can be bypassed to inject arbitrary HTML attributes, including event handlers, into SSR-rendered <head> tags. This is the composable that Nuxt docs recommend for safely handling user-generated content. The acceptDataAttrs function (safe.ts, line 16-20) allows any property key starting with data- through to the final HTML. It only checks the prefix, not whether the key contains spaces or other characters that break HTML attribute parsing. This vulnerability is fixed in 2.1.11.
Severity ?
CWE
- CWE-79 - Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
Assigner
References
| URL | Tags | ||||
|---|---|---|---|---|---|
|
|||||
{
"containers": {
"adp": [
{
"metrics": [
{
"other": {
"content": {
"id": "CVE-2026-31860",
"options": [
{
"Exploitation": "poc"
},
{
"Automatable": "no"
},
{
"Technical Impact": "partial"
}
],
"role": "CISA Coordinator",
"timestamp": "2026-03-13T16:26:47.686961Z",
"version": "2.0.3"
},
"type": "ssvc"
}
}
],
"providerMetadata": {
"dateUpdated": "2026-03-13T16:26:51.670Z",
"orgId": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
"shortName": "CISA-ADP"
},
"references": [
{
"tags": [
"exploit"
],
"url": "https://github.com/unjs/unhead/security/advisories/GHSA-g5xx-pwrp-g3fv"
}
],
"title": "CISA ADP Vulnrichment"
}
],
"cna": {
"affected": [
{
"product": "unhead",
"vendor": "unjs",
"versions": [
{
"status": "affected",
"version": "\u003c 2.1.11"
}
]
}
],
"descriptions": [
{
"lang": "en",
"value": "Unhead is a document head and template manager. Prior to 2.1.11, useHeadSafe() can be bypassed to inject arbitrary HTML attributes, including event handlers, into SSR-rendered \u003chead\u003e tags. This is the composable that Nuxt docs recommend for safely handling user-generated content. The acceptDataAttrs function (safe.ts, line 16-20) allows any property key starting with data- through to the final HTML. It only checks the prefix, not whether the key contains spaces or other characters that break HTML attribute parsing. This vulnerability is fixed in 2.1.11."
}
],
"metrics": [
{
"cvssV4_0": {
"attackComplexity": "LOW",
"attackRequirements": "NONE",
"attackVector": "NETWORK",
"baseScore": 5.3,
"baseSeverity": "MEDIUM",
"privilegesRequired": "NONE",
"subAvailabilityImpact": "NONE",
"subConfidentialityImpact": "LOW",
"subIntegrityImpact": "LOW",
"userInteraction": "PASSIVE",
"vectorString": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N",
"version": "4.0",
"vulnAvailabilityImpact": "NONE",
"vulnConfidentialityImpact": "NONE",
"vulnIntegrityImpact": "NONE"
}
}
],
"problemTypes": [
{
"descriptions": [
{
"cweId": "CWE-79",
"description": "CWE-79: Improper Neutralization of Input During Web Page Generation (\u0027Cross-site Scripting\u0027)",
"lang": "en",
"type": "CWE"
}
]
}
],
"providerMetadata": {
"dateUpdated": "2026-03-12T17:18:20.452Z",
"orgId": "a0819718-46f1-4df5-94e2-005712e83aaa",
"shortName": "GitHub_M"
},
"references": [
{
"name": "https://github.com/unjs/unhead/security/advisories/GHSA-g5xx-pwrp-g3fv",
"tags": [
"x_refsource_CONFIRM"
],
"url": "https://github.com/unjs/unhead/security/advisories/GHSA-g5xx-pwrp-g3fv"
}
],
"source": {
"advisory": "GHSA-g5xx-pwrp-g3fv",
"discovery": "UNKNOWN"
},
"title": "Unhead has a XSS bypass in `useHeadSafe` via attribute name injection and case-sensitive protocol check"
}
},
"cveMetadata": {
"assignerOrgId": "a0819718-46f1-4df5-94e2-005712e83aaa",
"assignerShortName": "GitHub_M",
"cveId": "CVE-2026-31860",
"datePublished": "2026-03-12T17:18:20.452Z",
"dateReserved": "2026-03-09T19:02:25.012Z",
"dateUpdated": "2026-03-13T16:26:51.670Z",
"state": "PUBLISHED"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2",
"vulnerability-lookup:meta": {
"epss": {
"cve": "CVE-2026-31860",
"date": "2026-04-23",
"epss": "0.00017",
"percentile": "0.04238"
},
"nvd": "{\"cve\":{\"id\":\"CVE-2026-31860\",\"sourceIdentifier\":\"security-advisories@github.com\",\"published\":\"2026-03-12T18:16:24.227\",\"lastModified\":\"2026-03-16T17:56:34.140\",\"vulnStatus\":\"Analyzed\",\"cveTags\":[],\"descriptions\":[{\"lang\":\"en\",\"value\":\"Unhead is a document head and template manager. Prior to 2.1.11, useHeadSafe() can be bypassed to inject arbitrary HTML attributes, including event handlers, into SSR-rendered \u003chead\u003e tags. This is the composable that Nuxt docs recommend for safely handling user-generated content. The acceptDataAttrs function (safe.ts, line 16-20) allows any property key starting with data- through to the final HTML. It only checks the prefix, not whether the key contains spaces or other characters that break HTML attribute parsing. This vulnerability is fixed in 2.1.11.\"},{\"lang\":\"es\",\"value\":\"Unhead es un gestor de cabecera de documento y plantillas. Antes de la 2.1.11, se puede eludir useHeadSafe() para inyectar atributos HTML arbitrarios, incluyendo manejadores de eventos, en etiquetas renderizadas por SSR. Este es el composable que la documentaci\u00f3n de Nuxt recomienda para manejar de forma segura contenido generado por el usuario. La funci\u00f3n acceptDataAttrs (safe.ts, l\u00ednea 16-20) permite cualquier clave de propiedad que comience con \u0027data-\u0027 hasta el HTML final. Solo verifica el prefijo, no si la clave contiene espacios u otros caracteres que rompen el an\u00e1lisis de atributos HTML. Esta vulnerabilidad est\u00e1 corregida en la 2.1.11.\"}],\"metrics\":{\"cvssMetricV40\":[{\"source\":\"security-advisories@github.com\",\"type\":\"Secondary\",\"cvssData\":{\"version\":\"4.0\",\"vectorString\":\"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X\",\"baseScore\":5.3,\"baseSeverity\":\"MEDIUM\",\"attackVector\":\"NETWORK\",\"attackComplexity\":\"LOW\",\"attackRequirements\":\"NONE\",\"privilegesRequired\":\"NONE\",\"userInteraction\":\"PASSIVE\",\"vulnConfidentialityImpact\":\"NONE\",\"vulnIntegrityImpact\":\"NONE\",\"vulnAvailabilityImpact\":\"NONE\",\"subConfidentialityImpact\":\"LOW\",\"subIntegrityImpact\":\"LOW\",\"subAvailabilityImpact\":\"NONE\",\"exploitMaturity\":\"NOT_DEFINED\",\"confidentialityRequirement\":\"NOT_DEFINED\",\"integrityRequirement\":\"NOT_DEFINED\",\"availabilityRequirement\":\"NOT_DEFINED\",\"modifiedAttackVector\":\"NOT_DEFINED\",\"modifiedAttackComplexity\":\"NOT_DEFINED\",\"modifiedAttackRequirements\":\"NOT_DEFINED\",\"modifiedPrivilegesRequired\":\"NOT_DEFINED\",\"modifiedUserInteraction\":\"NOT_DEFINED\",\"modifiedVulnConfidentialityImpact\":\"NOT_DEFINED\",\"modifiedVulnIntegrityImpact\":\"NOT_DEFINED\",\"modifiedVulnAvailabilityImpact\":\"NOT_DEFINED\",\"modifiedSubConfidentialityImpact\":\"NOT_DEFINED\",\"modifiedSubIntegrityImpact\":\"NOT_DEFINED\",\"modifiedSubAvailabilityImpact\":\"NOT_DEFINED\",\"Safety\":\"NOT_DEFINED\",\"Automatable\":\"NOT_DEFINED\",\"Recovery\":\"NOT_DEFINED\",\"valueDensity\":\"NOT_DEFINED\",\"vulnerabilityResponseEffort\":\"NOT_DEFINED\",\"providerUrgency\":\"NOT_DEFINED\"}}],\"cvssMetricV31\":[{\"source\":\"nvd@nist.gov\",\"type\":\"Primary\",\"cvssData\":{\"version\":\"3.1\",\"vectorString\":\"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N\",\"baseScore\":6.1,\"baseSeverity\":\"MEDIUM\",\"attackVector\":\"NETWORK\",\"attackComplexity\":\"LOW\",\"privilegesRequired\":\"NONE\",\"userInteraction\":\"REQUIRED\",\"scope\":\"CHANGED\",\"confidentialityImpact\":\"LOW\",\"integrityImpact\":\"LOW\",\"availabilityImpact\":\"NONE\"},\"exploitabilityScore\":2.8,\"impactScore\":2.7}]},\"weaknesses\":[{\"source\":\"security-advisories@github.com\",\"type\":\"Secondary\",\"description\":[{\"lang\":\"en\",\"value\":\"CWE-79\"}]}],\"configurations\":[{\"nodes\":[{\"operator\":\"OR\",\"negate\":false,\"cpeMatch\":[{\"vulnerable\":true,\"criteria\":\"cpe:2.3:a:unjs:unhead:*:*:*:*:*:*:*:*\",\"versionEndExcluding\":\"2.1.11\",\"matchCriteriaId\":\"67F3AFEA-7DE2-46CC-AC50-D8B49F57C37E\"}]}]}],\"references\":[{\"url\":\"https://github.com/unjs/unhead/security/advisories/GHSA-g5xx-pwrp-g3fv\",\"source\":\"security-advisories@github.com\",\"tags\":[\"Exploit\",\"Mitigation\",\"Vendor Advisory\"]},{\"url\":\"https://github.com/unjs/unhead/security/advisories/GHSA-g5xx-pwrp-g3fv\",\"source\":\"134c704f-9b21-4f2e-91b3-4a467353bcc0\",\"tags\":[\"Exploit\",\"Mitigation\",\"Vendor Advisory\"]}]}}",
"vulnrichment": {
"containers": "{\"adp\": [{\"title\": \"CISA ADP Vulnrichment\", \"metrics\": [{\"other\": {\"type\": \"ssvc\", \"content\": {\"id\": \"CVE-2026-31860\", \"role\": \"CISA Coordinator\", \"options\": [{\"Exploitation\": \"poc\"}, {\"Automatable\": \"no\"}, {\"Technical Impact\": \"partial\"}], \"version\": \"2.0.3\", \"timestamp\": \"2026-03-13T16:26:47.686961Z\"}}}], \"references\": [{\"url\": \"https://github.com/unjs/unhead/security/advisories/GHSA-g5xx-pwrp-g3fv\", \"tags\": [\"exploit\"]}], \"providerMetadata\": {\"orgId\": \"134c704f-9b21-4f2e-91b3-4a467353bcc0\", \"shortName\": \"CISA-ADP\", \"dateUpdated\": \"2026-03-13T16:26:40.074Z\"}}], \"cna\": {\"title\": \"Unhead has a XSS bypass in `useHeadSafe` via attribute name injection and case-sensitive protocol check\", \"source\": {\"advisory\": \"GHSA-g5xx-pwrp-g3fv\", \"discovery\": \"UNKNOWN\"}, \"metrics\": [{\"cvssV4_0\": {\"version\": \"4.0\", \"baseScore\": 5.3, \"attackVector\": \"NETWORK\", \"baseSeverity\": \"MEDIUM\", \"vectorString\": \"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N\", \"userInteraction\": \"PASSIVE\", \"attackComplexity\": \"LOW\", \"attackRequirements\": \"NONE\", \"privilegesRequired\": \"NONE\", \"subIntegrityImpact\": \"LOW\", \"vulnIntegrityImpact\": \"NONE\", \"subAvailabilityImpact\": \"NONE\", \"vulnAvailabilityImpact\": \"NONE\", \"subConfidentialityImpact\": \"LOW\", \"vulnConfidentialityImpact\": \"NONE\"}}], \"affected\": [{\"vendor\": \"unjs\", \"product\": \"unhead\", \"versions\": [{\"status\": \"affected\", \"version\": \"\u003c 2.1.11\"}]}], \"references\": [{\"url\": \"https://github.com/unjs/unhead/security/advisories/GHSA-g5xx-pwrp-g3fv\", \"name\": \"https://github.com/unjs/unhead/security/advisories/GHSA-g5xx-pwrp-g3fv\", \"tags\": [\"x_refsource_CONFIRM\"]}], \"descriptions\": [{\"lang\": \"en\", \"value\": \"Unhead is a document head and template manager. Prior to 2.1.11, useHeadSafe() can be bypassed to inject arbitrary HTML attributes, including event handlers, into SSR-rendered \u003chead\u003e tags. This is the composable that Nuxt docs recommend for safely handling user-generated content. The acceptDataAttrs function (safe.ts, line 16-20) allows any property key starting with data- through to the final HTML. It only checks the prefix, not whether the key contains spaces or other characters that break HTML attribute parsing. This vulnerability is fixed in 2.1.11.\"}], \"problemTypes\": [{\"descriptions\": [{\"lang\": \"en\", \"type\": \"CWE\", \"cweId\": \"CWE-79\", \"description\": \"CWE-79: Improper Neutralization of Input During Web Page Generation (\u0027Cross-site Scripting\u0027)\"}]}], \"providerMetadata\": {\"orgId\": \"a0819718-46f1-4df5-94e2-005712e83aaa\", \"shortName\": \"GitHub_M\", \"dateUpdated\": \"2026-03-12T17:18:20.452Z\"}}}",
"cveMetadata": "{\"cveId\": \"CVE-2026-31860\", \"state\": \"PUBLISHED\", \"dateUpdated\": \"2026-03-13T16:26:51.670Z\", \"dateReserved\": \"2026-03-09T19:02:25.012Z\", \"assignerOrgId\": \"a0819718-46f1-4df5-94e2-005712e83aaa\", \"datePublished\": \"2026-03-12T17:18:20.452Z\", \"assignerShortName\": \"GitHub_M\"}",
"dataType": "CVE_RECORD",
"dataVersion": "5.2"
}
}
}
Loading…
Loading…
Sightings
| Author | Source | Type | Date |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
Loading…
Loading…