Action not permitted
Modal body text goes here.
Modal Title
Modal Body
Vulnerability from cleanstart
Package sqlpad version 7.5.7-r3 fixes 26 vulnerabilities: ghsa-2v35-w6hq-6mfw, ghsa-f6ww-3ggp-fr8h, ghsa-wh4c-j3r5-mjhp, ghsa-x6wf-f3px-wcqx, ghsa-j759-j44w-7fr8...
| URL | Type | |
|---|---|---|
{
"affected": [
{
"package": {
"ecosystem": "Alpine",
"name": "sqlpad"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "7.5.7-r3"
}
],
"type": "ECOSYSTEM"
}
],
"versions": [
"7.5.7-r3"
]
}
],
"credits": [],
"database_specific": {},
"details": "Package sqlpad version 7.5.7-r3 fixes 26 vulnerabilities: ghsa-2v35-w6hq-6mfw, ghsa-f6ww-3ggp-fr8h, ghsa-wh4c-j3r5-mjhp, ghsa-x6wf-f3px-wcqx, ghsa-j759-j44w-7fr8...",
"id": "CLEANSTART-2026-VJ19248",
"modified": "2026-08-14T05:57:24Z",
"published": "2026-08-13T12:10:09Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/sqlpad/sqlpad"
}
],
"related": [],
"schema_version": "1.7.3",
"summary": "Security fixes in sqlpad 7.5.7-r3",
"upstream": [
"ghsa-2v35-w6hq-6mfw",
"ghsa-f6ww-3ggp-fr8h",
"ghsa-wh4c-j3r5-mjhp",
"ghsa-x6wf-f3px-wcqx",
"ghsa-j759-j44w-7fr8",
"CVE-2026-34601",
"CVE-2026-41672",
"CVE-2026-41673",
"CVE-2026-41674",
"CVE-2026-41675",
"ghsa-xcpc-8h2w-3j85",
"CVE-2026-39244",
"ghsa-6457-6jrx-69cr",
"CVE-2026-30951",
"ghsa-378v-28hj-76wf",
"CVE-2026-2739",
"ghsa-v2v4-37r5-5v8g",
"CVE-2026-42338",
"ghsa-w5hq-g745-h8pq",
"CVE-2026-41907",
"ghsa-r5mx-6wc6-7h9w",
"CVE-2026-27837",
"ghsa-v422-hmwv-36x6",
"CVE-2026-12590",
"ghsa-vpq2-c234-7xj6",
"CVE-2026-3449"
]
}
GHSA-V422-HMWV-36X6
Vulnerability from github – Published: 2026-07-20 23:23 – Updated: 2026-07-20 23:23Impact
When body-parser is configured with an invalid limit option value, such as an unparseable string or NaN, bytes.parse() returns null and the request body size check is silently skipped. Applications that rely on limit as their primary safeguard against oversized request bodies will accept arbitrarily large payloads, leading to excessive memory and CPU usage and denial of service.
This issue affects applications that pass a programmatically computed or user-configurable value to the limit option without validating it first.
Patches
This issue is fixed in body-parser@2.3.0 and body-parser@1.20.6 via #698. After the fix, invalid limit values throw a clear error at parser construction time instead of silently disabling enforcement. null and undefined continue to fall back to the default limit (100kb).
Workarounds
Validate limit before passing it to body-parser. For example, parse the value with bytes.parse() at startup and reject any configuration where it returns null or a non-finite number.
References
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "body-parser"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.20.6"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "body-parser"
},
"ranges": [
{
"events": [
{
"introduced": "2.0.0"
},
{
"fixed": "2.3.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-12590"
],
"database_specific": {
"cwe_ids": [
"CWE-770"
],
"github_reviewed": true,
"github_reviewed_at": "2026-07-20T23:23:26Z",
"nvd_published_at": "2026-07-09T11:16:24Z",
"severity": "LOW"
},
"details": "### Impact\n\nWhen body-parser is configured with an invalid `limit` option value, such as an unparseable string or `NaN`, `bytes.parse()` returns `null` and the request body size check is silently skipped. Applications that rely on `limit` as their primary safeguard against oversized request bodies will accept arbitrarily large payloads, leading to excessive memory and CPU usage and denial of service.\n\nThis issue affects applications that pass a programmatically computed or user-configurable value to the `limit` option without validating it first.\n\n### Patches\n\nThis issue is fixed in [body-parser@2.3.0](https://github.com/expressjs/body-parser/releases/tag/v2.3.0) and [body-parser@1.20.6](https://github.com/expressjs/body-parser/releases/tag/v1.20.6) via [#698](https://github.com/expressjs/body-parser/pull/698). After the fix, invalid `limit` values throw a clear error at parser construction time instead of silently disabling enforcement. `null` and `undefined` continue to fall back to the default limit (`100kb`).\n\n### Workarounds\n\nValidate `limit` before passing it to body-parser. For example, parse the value with [`bytes.parse()`](https://github.com/visionmedia/bytes.js) at startup and reject any configuration where it returns `null` or a non-finite number.\n\n### References\n\n- [#698](https://github.com/expressjs/body-parser/pull/698): fix PR\n- [bytes.js](https://github.com/visionmedia/bytes.js): limit parser",
"id": "GHSA-v422-hmwv-36x6",
"modified": "2026-07-20T23:23:26Z",
"published": "2026-07-20T23:23:26Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/expressjs/body-parser/security/advisories/GHSA-v422-hmwv-36x6"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-12590"
},
{
"type": "WEB",
"url": "https://github.com/expressjs/body-parser/pull/698"
},
{
"type": "WEB",
"url": "https://github.com/expressjs/body-parser/pull/741"
},
{
"type": "WEB",
"url": "https://github.com/expressjs/body-parser/commit/2322e111cc321413ec2b7b76d01be533d3de9d7d"
},
{
"type": "WEB",
"url": "https://github.com/expressjs/body-parser/commit/3492672eee593d5c158f239b6e9115498a5dbeac"
},
{
"type": "WEB",
"url": "https://cna.openjsf.org/security-advisories.html"
},
{
"type": "PACKAGE",
"url": "https://github.com/expressjs/body-parser"
},
{
"type": "WEB",
"url": "https://github.com/expressjs/body-parser/releases/tag/1.20.6"
},
{
"type": "WEB",
"url": "https://github.com/expressjs/body-parser/releases/tag/v2.3.0"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L",
"type": "CVSS_V3"
}
],
"summary": "body-parser vulnerable to denial of service when invalid limit value silently disables size enforcement"
}
GHSA-VPQ2-C234-7XJ6
Vulnerability from github – Published: 2026-03-03 06:31 – Updated: 2026-05-21 16:55Versions of the package @tootallnate/once before 3.0.1 are vulnerable to Incorrect Control Flow Scoping in promise resolving when AbortSignal option is used. The Promise remains in a permanently pending state after the signal is aborted, causing any await or .then() usage to hang indefinitely. This can cause a control-flow leak that can lead to stalled requests, blocked workers, or degraded application availability.
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "@tootallnate/once"
},
"ranges": [
{
"events": [
{
"introduced": "3.0.0"
},
{
"fixed": "3.0.1"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "@tootallnate/once"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "2.0.1"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-3449"
],
"database_specific": {
"cwe_ids": [
"CWE-705"
],
"github_reviewed": true,
"github_reviewed_at": "2026-03-04T20:15:03Z",
"nvd_published_at": "2026-03-03T05:17:25Z",
"severity": "LOW"
},
"details": "Versions of the package @tootallnate/once before 3.0.1 are vulnerable to Incorrect Control Flow Scoping in promise resolving when AbortSignal option is used. The Promise remains in a permanently pending state after the signal is aborted, causing any await or .then() usage to hang indefinitely. This can cause a control-flow leak that can lead to stalled requests, blocked workers, or degraded application availability.",
"id": "GHSA-vpq2-c234-7xj6",
"modified": "2026-05-21T16:55:49Z",
"published": "2026-03-03T06:31:14Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-3449"
},
{
"type": "WEB",
"url": "https://github.com/TooTallNate/once/issues/8"
},
{
"type": "WEB",
"url": "https://github.com/TooTallNate/once/commit/b9f43cc5259bee2952d91ad3cdbd201a82df448a"
},
{
"type": "PACKAGE",
"url": "https://github.com/TooTallNate/once"
},
{
"type": "WEB",
"url": "https://github.com/TooTallNate/once/releases/tag/v2.0.1"
},
{
"type": "WEB",
"url": "https://security.snyk.io/vuln/SNYK-JS-TOOTALLNATEONCE-15250612"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:L",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:L/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N/E:P",
"type": "CVSS_V4"
}
],
"summary": "@tootallnate/once vulnerable to Incorrect Control Flow Scoping"
}
GHSA-W5HQ-G745-H8PQ
Vulnerability from github – Published: 2026-04-22 20:53 – Updated: 2026-05-21 18:25Summary
The v3(), v5(), and v6() API methods (not uuid release versions) accept external output buffers but do not reject out-of-range writes (small buf or large offset).
By contrast, v4(), v1(), and v7() API methods explicitly throw RangeError on invalid bounds.
This inconsistency allows silent partial writes into caller-provided buffers.
Affected code
src/v35.ts(v3()/v5()path) writesbuf[offset + i]without bounds validation.src/v6.tswritesbuf[offset + i]without bounds validation.
Reproducible PoC
cd /home/StrawHat/uuid
npm ci
npm run build
node --input-type=module -e "
import {v4,v5,v6} from './dist-node/index.js';
const ns='6ba7b810-9dad-11d1-80b4-00c04fd430c8';
for (const [name,fn] of [
['v4()',()=>v4({},new Uint8Array(8),4)],
['v5()',()=>v5('x',ns,new Uint8Array(8),4)],
['v6()',()=>v6({},new Uint8Array(8),4)],
]) {
try { fn(); console.log(name,'NO_THROW'); }
catch(e){ console.log(name,'THREW',e.name); }
}"
Observed:
v4() THREW RangeErrorv5() NO_THROWv6() NO_THROW
Example partial overwrite evidence captured during audit:
same true buf [
170, 170, 170, 170,
75, 224, 100, 63
]
v6 [
187, 187, 187, 187,
31, 19, 185, 64
]
Security impact
- Primary: integrity/robustness issue (silent partial output).
- If an application assumes full UUID writes into preallocated buffers, this can produce malformed/truncated/partially stale identifiers without error.
- In systems where caller-controlled offsets/buffer sizes are exposed indirectly, this may become a security-relevant logic flaw.
Suggested fix
Add the same guard used by v4()/v1()/v7():
if (offset < 0 || offset + 16 > buf.length) {
throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
}
Apply to:
src/v35.ts(coversv3()andv5())src/v6.ts
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "uuid"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "11.1.1"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "uuid"
},
"ranges": [
{
"events": [
{
"introduced": "12.0.0"
},
{
"fixed": "12.0.1"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "uuid"
},
"ranges": [
{
"events": [
{
"introduced": "13.0.0"
},
{
"fixed": "13.0.1"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-41907"
],
"database_specific": {
"cwe_ids": [
"CWE-1285",
"CWE-787"
],
"github_reviewed": true,
"github_reviewed_at": "2026-04-22T20:53:24Z",
"nvd_published_at": "2026-04-24T19:17:14Z",
"severity": "MODERATE"
},
"details": "### Summary\n\nThe `v3()`, `v5()`, and `v6()` [API methods](https://github.com/uuidjs/uuid#api-summary) (not `uuid` release versions) accept external output buffers but do not reject out-of-range writes (small `buf` or large `offset`). \nBy contrast, `v4()`, `v1()`, and `v7()` API methods explicitly throw `RangeError` on invalid bounds.\n\nThis inconsistency allows **silent partial writes** into caller-provided buffers.\n\n\n### Affected code\n\n- `src/v35.ts` (`v3()`/`v5()` path) writes `buf[offset + i]` without bounds validation.\n- `src/v6.ts` writes `buf[offset + i]` without bounds validation.\n\n### Reproducible PoC\n\n```bash\ncd /home/StrawHat/uuid\nnpm ci\nnpm run build\n\nnode --input-type=module -e \"\nimport {v4,v5,v6} from \u0027./dist-node/index.js\u0027;\nconst ns=\u00276ba7b810-9dad-11d1-80b4-00c04fd430c8\u0027;\nfor (const [name,fn] of [\n [\u0027v4()\u0027,()=\u003ev4({},new Uint8Array(8),4)],\n [\u0027v5()\u0027,()=\u003ev5(\u0027x\u0027,ns,new Uint8Array(8),4)],\n [\u0027v6()\u0027,()=\u003ev6({},new Uint8Array(8),4)],\n]) {\n try { fn(); console.log(name,\u0027NO_THROW\u0027); }\n catch(e){ console.log(name,\u0027THREW\u0027,e.name); }\n}\"\n```\n\nObserved:\n\n- `v4() THREW RangeError`\n- `v5() NO_THROW`\n- `v6() NO_THROW`\n\nExample partial overwrite evidence captured during audit:\n\n```text\nsame true buf [\n 170, 170, 170, 170,\n 75, 224, 100, 63\n]\nv6 [\n 187, 187, 187, 187,\n 31, 19, 185, 64\n]\n```\n\n### Security impact\n\n- **Primary**: integrity/robustness issue (silent partial output).\n- If an application assumes full UUID writes into preallocated buffers, this can produce malformed/truncated/partially stale identifiers without error.\n- In systems where caller-controlled offsets/buffer sizes are exposed indirectly, this may become a security-relevant logic flaw.\n\n### Suggested fix\n\nAdd the same guard used by `v4()`/`v1()`/`v7()`:\n\n```ts\nif (offset \u003c 0 || offset + 16 \u003e buf.length) {\n throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);\n}\n```\n\nApply to:\n\n- `src/v35.ts` (covers `v3()` and `v5()`)\n- `src/v6.ts`",
"id": "GHSA-w5hq-g745-h8pq",
"modified": "2026-05-21T18:25:56Z",
"published": "2026-04-22T20:53:24Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/uuidjs/uuid/security/advisories/GHSA-w5hq-g745-h8pq"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-41907"
},
{
"type": "WEB",
"url": "https://github.com/uuidjs/uuid/commit/32389c887c9e75f90442ee4cc95bbab0c4e8346e"
},
{
"type": "WEB",
"url": "https://github.com/uuidjs/uuid/commit/3d2c5b0342f0fcb52a5ac681c3d47c13e7444b34"
},
{
"type": "WEB",
"url": "https://github.com/uuidjs/uuid/commit/3d61d6ac1f782cf6b1dd8661c60f11722cd49a0d"
},
{
"type": "WEB",
"url": "https://github.com/uuidjs/uuid/commit/9d27ddf7046ce496ef39569ff84d948eeff9cb2a"
},
{
"type": "PACKAGE",
"url": "https://github.com/uuidjs/uuid"
},
{
"type": "WEB",
"url": "https://github.com/uuidjs/uuid/releases/tag/v11.1.1"
},
{
"type": "WEB",
"url": "https://github.com/uuidjs/uuid/releases/tag/v12.0.1"
},
{
"type": "WEB",
"url": "https://github.com/uuidjs/uuid/releases/tag/v13.0.1"
},
{
"type": "WEB",
"url": "https://github.com/uuidjs/uuid/releases/tag/v14.0.0"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "uuid: Missing buffer bounds check in v3/v5/v6 when buf is provided"
}
GHSA-WH4C-J3R5-MJHP
Vulnerability from github – Published: 2026-04-01 00:19 – Updated: 2026-04-24 23:17Summary
@xmldom/xmldom allows attacker-controlled strings containing the CDATA terminator ]]> to be inserted into a CDATASection node. During serialization, XMLSerializer emitted the CDATA content verbatim without rejecting or safely splitting the terminator. As a result, data intended to remain text-only became active XML markup in the serialized output, enabling XML structure
injection and downstream business-logic manipulation.
The sequence ]]> is not allowed inside CDATA content and must be rejected or safely handled during serialization. (MDN Web Docs)
Attack surface
Document.createCDATASection(data) is the most direct entry point, but it is not the only one. The WHATWG DOM spec intentionally does not validate ]]> in mutation methods — only createCDATASection carries that guard. The following paths therefore also allow ]]> to enter a CDATASection node and reach the serializer:
CharacterData.appendData()CharacterData.replaceData()CharacterData.insertData()- Direct assignment to
.data - Direct assignment to
.textContent
(Note: assigning to .nodeValue does not update .data in this implementation — the serializer reads .data directly — so .nodeValue is not an exploitable path.)
Parse path
Parsing XML that contains a CDATA section is not affected. The SAX parser's non-greedy CDSect regex stops at the first ]]>, so parsed CDATA data never contains the terminator.
Impact
If an application uses xmldom to generate "trusted" XML documents that embed untrusted user input inside CDATA (a common pattern in exports, feeds, SOAP/XML integrations, etc.), an attacker can inject additional XML elements/attributes into the generated document.
This can lead to:
- Integrity violation of generated XML documents.
- Business-logic injection in downstream consumers (e.g., injecting
<approved>true</approved>,<role>admin</role>, workflow flags, or other security-relevant elements). - Unexpected privilege/workflow decisions if downstream logic assumes injected nodes cannot appear.
This issue does not require malformed parsers or browser behavior; it is caused by serialization producing attacker-influenced XML markup.
Root Cause (with file + line numbers)
File: lib/dom.js
1. No validation in createCDATASection
createCDATASection: function (data) accepts any string and appends it directly.
- Lines 2216–2221 (0.9.8)
2. Unsafe CDATA serialization
Serializer prints CDATA sections as:
<![CDATA[ + node.data + ]]>
without handling ]]> in the data.
- Lines 2919–2920 (0.9.8)
Because CDATA content is emitted verbatim, an embedded ]]> closes the CDATA section early and the remainder of the attacker-controlled payload is interpreted as markup in the serialized XML.
Proof of Concept — Fix A: createCDATASection now throws
On patched versions, passing ]]> directly to createCDATASection throws InvalidCharacterError instead of silently accepting the payload:
const { DOMImplementation } = require('./lib');
const doc = new DOMImplementation().createDocument(null, 'root', null);
try {
doc.createCDATASection('SAFE]]><injected attr="pwn"/>');
console.log('VULNERABLE — no error thrown');
} catch (e) {
console.log('FIXED — threw:', e.name); // InvalidCharacterError
}
Expected output on patched versions:
FIXED — threw: InvalidCharacterError
Proof of Concept — Fix B: mutation vector now safe
On patched versions, injecting ]]> via a mutation method (appendData, replaceData, .data =, .textContent =) no longer produces injectable output. The serializer splits the terminator so the result round-trips as safe text:
const { DOMImplementation, XMLSerializer } = require('./lib');
const { DOMParser } = require('./lib');
const doc = new DOMImplementation().createDocument(null, 'root', null);
// Start with safe data, then mutate to include the terminator
const cdata = doc.createCDATASection('safe');
doc.documentElement.appendChild(cdata);
cdata.appendData(']]><injected attr="pwn"/><more>TEXT</more><![CDATA[');
const out = new XMLSerializer().serializeToString(doc);
console.log('Serialized:', out);
const reparsed = new DOMParser().parseFromString(out, 'text/xml');
const injected = reparsed.getElementsByTagName('injected').length > 0;
console.log('Injected element found in reparsed doc:', injected);
// VULNERABLE: true | FIXED: false
Expected output on patched versions:
Serialized: <root><![CDATA[safe]]]]><![CDATA[><injected attr="pwn"/><more>TEXT</more><![CDATA[]]></root>
Injected element found in reparsed doc: false
Fix Applied
Both mitigations were implemented:
Option A — Strict/spec-aligned: reject ]]> in createCDATASection()
Document.createCDATASection(data) now throws InvalidCharacterError (per the WHATWG DOM spec) when data contains ]]>. This closes the direct entry point.
Code that previously passed a string containing ]]> to createCDATASection and relied on the silent/unsafe behaviour will now receive InvalidCharacterError. Use a mutation method such as appendData if you intentionally need ]]> in a CDATASection node's data (the serializer split in Option B will keep the output safe).
Option B — Defensive serialization: split the terminator during serialization
XMLSerializer now replaces every occurrence of ]]> in CDATA section data with the split sequence ]]]]><![CDATA[> before emitting. This closes all mutation-vector paths that Option A alone cannot guard, and means the serialized output is always well-formed XML regardless of how ]]> entered the node.
Update — 2026-04-xx (0.9.10 / 0.8.13)
splitCDATASections is deprecated
The CDATA split behavior introduced as Option B of this fix (replacing ]]> with]]]]><![CDATA[> during serialization) is deprecated as of 0.9.10 / 0.8.13.
This release introduces a requireWellFormed option on XMLSerializer.serializeToString(). When { requireWellFormed: true } is passed as the second argument, the serializer throws InvalidStateError if CDATA section data contains ]]> — this is the spec-aligned behavior (W3C DOM Parsing and Serialization, require well-formed flag) and the recommended migration path going forward.
The split behavior is now controlled by an explicit splitCDATASections option (default true, preserving the current behavior). The three serialization behaviors are:
| requireWellFormed | splitCDATASections | Behavior ||---|---|---|| false (default) | true (default) | Split ]]> → ]]]]><![CDATA[> (current behavior, deprecated) || true | — (ignored) | Throw InvalidStateError — spec-aligned, recommended |\ false | false | Emit verbatim — same as pre-0.9.9 behavior |
requireWellFormed: true takes precedence: the split path is unreachable when it is set.
Migration
Replace any reliance on the default split behavior with an explicit opt-in: ```js// Before (implicit split, deprecated): const xml = new XMLSerializer().serializeToString(doc);
// After (explicit guard, spec-aligned): const xml = new XMLSerializer().serializeToString(doc, { requireWellFormed: true }); // Throws InvalidStateError if any CDATASection contains ']]>' ```
Removal timeline
Both the splitCDATASections option and the underlying ]]> → ]]]]><![CDATA[> split mechanics will be removed in the next breaking (0.10.0) release. After removal, the only behaviors will be verbatim (default) and requireWellFormed: true (throws).
Removal is tracked in xmldom/xmldom#999.
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "xmldom"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"last_affected": "0.6.0"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "@xmldom/xmldom"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.8.12"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "@xmldom/xmldom"
},
"ranges": [
{
"events": [
{
"introduced": "0.9.0"
},
{
"fixed": "0.9.9"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-34601"
],
"database_specific": {
"cwe_ids": [
"CWE-91"
],
"github_reviewed": true,
"github_reviewed_at": "2026-04-01T00:19:06Z",
"nvd_published_at": "2026-04-02T18:16:31Z",
"severity": "HIGH"
},
"details": "## Summary\n\n`@xmldom/xmldom` allows attacker-controlled strings containing the CDATA terminator `]]\u003e` to be inserted into a `CDATASection` node. During serialization, `XMLSerializer` emitted the CDATA content verbatim without rejecting or safely splitting the terminator. As a result, data intended to remain text-only became **active XML markup** in the serialized output, enabling XML structure\ninjection and downstream business-logic manipulation.\n\nThe sequence `]]\u003e` is not allowed inside CDATA content and must be rejected or safely handled during serialization. ([MDN Web Docs](https://developer.mozilla.org/))\n\n### Attack surface\n\n`Document.createCDATASection(data)` is the most direct entry point, but it is not the only one. The WHATWG DOM spec intentionally does not validate `]]\u003e` in mutation methods \u2014 only `createCDATASection` carries that guard. The following paths therefore also allow `]]\u003e` to enter a CDATASection node and reach the serializer:\n\n- `CharacterData.appendData()`\n- `CharacterData.replaceData()`\n- `CharacterData.insertData()`\n- Direct assignment to `.data`\n- Direct assignment to `.textContent`\n\n(Note: assigning to `.nodeValue` does **not** update `.data` in this implementation \u2014 the serializer reads `.data` directly \u2014 so `.nodeValue` is not an exploitable path.)\n\n### Parse path\n\nParsing XML that contains a CDATA section is **not** affected. The SAX parser\u0027s non-greedy `CDSect` regex stops at the first `]]\u003e`, so parsed CDATA data never contains the terminator.\n\n---\n\n## Impact\n\nIf an application uses `xmldom` to generate \"trusted\" XML documents that embed **untrusted user input** inside CDATA (a common pattern in exports, feeds, SOAP/XML integrations, etc.), an attacker can inject additional XML elements/attributes into the generated document.\n\nThis can lead to:\n\n- Integrity violation of generated XML documents.\n- Business-logic injection in downstream consumers (e.g., injecting `\u003capproved\u003etrue\u003c/approved\u003e`, `\u003crole\u003eadmin\u003c/role\u003e`, workflow flags, or other security-relevant elements).\n- Unexpected privilege/workflow decisions if downstream logic assumes injected nodes cannot appear.\n\nThis issue does **not** require malformed parsers or browser behavior; it is caused by serialization producing attacker-influenced XML markup.\n\n---\n\n## Root Cause (with file + line numbers)\n\n**File:** `lib/dom.js`\n\n### 1. No validation in `createCDATASection`\n\n`createCDATASection: function (data)` accepts any string and appends it directly.\n\n- **Lines 2216\u20132221** (0.9.8)\n\n### 2. Unsafe CDATA serialization\n\nSerializer prints CDATA sections as:\n\n```\n\u003c![CDATA[ + node.data + ]]\u003e\n```\n\nwithout handling `]]\u003e` in the data.\n\n- **Lines 2919\u20132920** (0.9.8)\n\nBecause CDATA content is emitted verbatim, an embedded `]]\u003e` closes the CDATA section early and the remainder of the attacker-controlled payload is interpreted as markup in the serialized XML.\n\n---\n\n## Proof of Concept \u2014 Fix A: `createCDATASection` now throws\n\nOn patched versions, passing `]]\u003e` directly to `createCDATASection` throws `InvalidCharacterError` instead of silently accepting the payload:\n\n```js\nconst { DOMImplementation } = require(\u0027./lib\u0027);\n\nconst doc = new DOMImplementation().createDocument(null, \u0027root\u0027, null);\ntry {\n doc.createCDATASection(\u0027SAFE]]\u003e\u003cinjected attr=\"pwn\"/\u003e\u0027);\n console.log(\u0027VULNERABLE \u2014 no error thrown\u0027);\n} catch (e) {\n console.log(\u0027FIXED \u2014 threw:\u0027, e.name); // InvalidCharacterError\n}\n```\n\nExpected output on patched versions:\n\n```\nFIXED \u2014 threw: InvalidCharacterError\n```\n\n---\n\n## Proof of Concept \u2014 Fix B: mutation vector now safe\n\nOn patched versions, injecting `]]\u003e` via a mutation method (`appendData`, `replaceData`, `.data =`, `.textContent =`) no longer produces injectable output. The serializer splits the terminator so the result round-trips as safe text:\n\n```js\nconst { DOMImplementation, XMLSerializer } = require(\u0027./lib\u0027);\nconst { DOMParser } = require(\u0027./lib\u0027);\n\nconst doc = new DOMImplementation().createDocument(null, \u0027root\u0027, null);\n\n// Start with safe data, then mutate to include the terminator\nconst cdata = doc.createCDATASection(\u0027safe\u0027);\ndoc.documentElement.appendChild(cdata);\ncdata.appendData(\u0027]]\u003e\u003cinjected attr=\"pwn\"/\u003e\u003cmore\u003eTEXT\u003c/more\u003e\u003c![CDATA[\u0027);\n\nconst out = new XMLSerializer().serializeToString(doc);\nconsole.log(\u0027Serialized:\u0027, out);\n\nconst reparsed = new DOMParser().parseFromString(out, \u0027text/xml\u0027);\nconst injected = reparsed.getElementsByTagName(\u0027injected\u0027).length \u003e 0;\nconsole.log(\u0027Injected element found in reparsed doc:\u0027, injected);\n// VULNERABLE: true | FIXED: false\n```\n\nExpected output on patched versions:\n\n```\nSerialized: \u003croot\u003e\u003c![CDATA[safe]]]]\u003e\u003c![CDATA[\u003e\u003cinjected attr=\"pwn\"/\u003e\u003cmore\u003eTEXT\u003c/more\u003e\u003c![CDATA[]]\u003e\u003c/root\u003e\nInjected element found in reparsed doc: false\n```\n\n---\n\n## Fix Applied\n\nBoth mitigations were implemented:\n\n### Option A \u2014 Strict/spec-aligned: reject `]]\u003e` in `createCDATASection()`\n\n`Document.createCDATASection(data)` now throws `InvalidCharacterError` (per the [WHATWG DOM spec](https://dom.spec.whatwg.org/#dom-document-createcdatasection)) when `data` contains `]]\u003e`. This closes the direct entry point.\n\nCode that previously passed a string containing `]]\u003e` to `createCDATASection` and relied on the silent/unsafe behaviour will now receive `InvalidCharacterError`. Use a mutation method such as `appendData` if you intentionally need `]]\u003e` in a CDATASection node\u0027s data (the serializer split in Option B will keep the output safe).\n\n### Option B \u2014 Defensive serialization: split the terminator during serialization\n\n`XMLSerializer` now replaces every occurrence of `]]\u003e` in CDATA section data with the split sequence `]]]]\u003e\u003c![CDATA[\u003e` before emitting. This closes all mutation-vector paths that Option A alone cannot guard, and means the serialized output is always well-formed XML regardless of how `]]\u003e` entered the node.\n\n## Update \u2014 2026-04-xx (0.9.10 / 0.8.13)\n\n### `splitCDATASections` is deprecated\n\nThe CDATA split behavior introduced as Option B of this fix (replacing `]]\u003e` with`]]]]\u003e\u003c![CDATA[\u003e` during serialization) is **deprecated** as of 0.9.10 / 0.8.13.\n\nThis release introduces a `requireWellFormed` option on `XMLSerializer.serializeToString()`. When `{ requireWellFormed: true }` is passed as the second argument, the serializer throws `InvalidStateError` if CDATA section data contains `]]\u003e` \u2014 this is the spec-aligned behavior (W3C DOM Parsing and Serialization, `require well-formed` flag) and the recommended migration path going forward.\nThe split behavior is now controlled by an explicit `splitCDATASections` option (default `true`, preserving the current behavior). The three serialization behaviors are:\n| `requireWellFormed` | `splitCDATASections` | Behavior ||---|---|---|| `false` (default) | `true` (default) | Split `]]\u003e` \u2192 `]]]]\u003e\u003c![CDATA[\u003e` (current behavior, deprecated) || `true` | \u2014 (ignored) | Throw `InvalidStateError` \u2014 spec-aligned, recommended |\\ `false` | `false` | Emit verbatim \u2014 same as pre-0.9.9 behavior |\n\n`requireWellFormed: true` takes precedence: the split path is unreachable when it is set.\n\n### Migration\nReplace any reliance on the default split behavior with an explicit opt-in:\n```js// Before (implicit split, deprecated): const xml = new XMLSerializer().serializeToString(doc);\n\n// After (explicit guard, spec-aligned): const xml = new XMLSerializer().serializeToString(doc, { requireWellFormed: true }); // Throws InvalidStateError if any CDATASection contains \u0027]]\u003e\u0027 ```\n\n### Removal timeline\nBoth the `splitCDATASections` option and the underlying `]]\u003e` \u2192 `]]]]\u003e\u003c.",
"id": "GHSA-wh4c-j3r5-mjhp",
"modified": "2026-04-24T23:17:44Z",
"published": "2026-04-01T00:19:06Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/xmldom/xmldom/security/advisories/GHSA-wh4c-j3r5-mjhp"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-34601"
},
{
"type": "WEB",
"url": "https://github.com/xmldom/xmldom/commit/2b852e836ab86dbbd6cbaf0537f584dd0b5ac184"
},
{
"type": "PACKAGE",
"url": "https://github.com/xmldom/xmldom"
},
{
"type": "WEB",
"url": "https://github.com/xmldom/xmldom/releases/tag/0.8.12"
},
{
"type": "WEB",
"url": "https://github.com/xmldom/xmldom/releases/tag/0.9.9"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N",
"type": "CVSS_V3"
}
],
"summary": "xmldom: XML injection via unsafe CDATA serialization allows attacker-controlled markup insertion"
}
GHSA-X6WF-F3PX-WCQX
Vulnerability from github – Published: 2026-04-22 20:17 – Updated: 2026-05-08 20:10Summary
The package allows attacker-controlled processing instruction data to be serialized into XML without validating or neutralizing the PI-closing sequence ?>. As a result, an attacker can terminate the processing instruction early and inject arbitrary XML nodes into the serialized output.
Details
The issue is in the DOM construction and serialization flow for processing instruction nodes.
When createProcessingInstruction(target, data) is called, the supplied data string is stored directly on the node without validation. Later, when the document is serialized, the serializer writes PI nodes by concatenating <?, the target, a space, node.data, and ?> directly.
That behavior is unsafe because processing instructions are a syntax-sensitive context. The closing delimiter ?> terminates the PI. If attacker-controlled input contains ?>, the serializer does not preserve it as literal PI content. Instead, it emits output where the remainder of the payload is treated as live XML markup.
The same class of vulnerability was previously addressed for CDATA sections (GHSA-wh4c-j3r5-mjhp / CVE-2026-34601), where ]]> in CDATA data was handled by splitting. The serializer applies no equivalent protection to processing instruction data.
Affected code
lib/dom.js — createProcessingInstruction (lines 2240–2246):
createProcessingInstruction: function (target, data) {
var node = new ProcessingInstruction(PDC);
node.ownerDocument = this;
node.childNodes = new NodeList();
node.nodeName = node.target = target;
node.nodeValue = node.data = data;
return node;
},
No validation is performed on data. Any string including ?> is stored as-is.
lib/dom.js — serializer PI case (line 2966):
case PROCESSING_INSTRUCTION_NODE:
return buf.push('<?', node.target, ' ', node.data, '?>');
node.data is emitted verbatim. If it contains ?>, that sequence terminates the PI in the output
stream and the remainder appears as active XML markup.
Contrast — CDATA (line 2945, patched):
case CDATA_SECTION_NODE:
return buf.push(g.CDATA_START, node.data.replace(/]]>/g, ']]]]><![CDATA[>'), g.CDATA_END);
PoC
Minimal (from @tlsbollei report, 2026-04-01)
const { DOMImplementation, XMLSerializer } = require('@xmldom/xmldom');
const doc = new DOMImplementation().createDocument(null, 'r', null);
doc.documentElement.appendChild(
doc.createProcessingInstruction('a', '?><z/><?q ')
);
console.log(new XMLSerializer().serializeToString(doc));
// <r><?a ?><z/><?q ?></r>
// ^^^^ injected <z/> element is active markup
With re-parse verification (from @tlsbollei report)
const assert = require('assert');
const { DOMParser, XMLSerializer } = require('@xmldom/xmldom');
const doc = new DOMParser().parseFromString('<r/>', 'application/xml');
doc.documentElement.appendChild(doc.createProcessingInstruction('a', '?><z/><?q '));
const xml = new XMLSerializer().serializeToString(doc);
assert.strictEqual(new DOMParser().parseFromString(xml, 'application/xml')
.getElementsByTagName('z').length, 1); // passes — z is a real element
Impact
An application that uses the package to build XML from untrusted input can be made to emit attacker-controlled elements outside the intended PI boundary. That allows the attacker to alter the meaning and structure of generated XML documents.
In practice, this can affect any workflow that generates XML and then stores it, forwards it, signs it, or hands it to another parser. Realistic targets include XML-based configuration, policy documents, and message formats where downstream consumers trust the serialized structure.
As noted by @tlsbollei: this is the same delimiter-driven XML injection bug class previously addressed by GHSA-wh4c-j3r5-mjhp for createCDATASection(). Fixing CDATA while leaving PI creation and PI serialization unguarded leaves the same standards-constrained issue open for another node type.
Disclosure
This vulnerability was publicly disclosed at 2026-04-06T11:25:07Z via xmldom/xmldom#987, which was subsequently closed without being merged.
Fix Applied
⚠ Opt-in required. Protection is not automatic. Existing serialization calls remain vulnerable unless
{ requireWellFormed: true }is explicitly passed. Applications that pass untrusted data tocreateProcessingInstruction()or mutate PI nodes with untrusted input (via.data =orCharacterDatamutation methods) should audit allserializeToString()call sites and add the option.
XMLSerializer.serializeToString() now accepts an options object as a second argument. When { requireWellFormed: true } is passed, the serializer throws InvalidStateError before emitting any ProcessingInstruction node whose .data contains ?>. This check applies regardless of how ?> entered the node — whether via createProcessingInstruction directly or a subsequent mutation (.data =, CharacterData methods).
On @xmldom/xmldom ≥ 0.9.10, the serializer additionally applies the full W3C DOM Parsing §3.2.1.7 checks when requireWellFormed: true:
- Target check: throws
InvalidStateErrorif the PI target contains a:character or is an ASCII case-insensitive match for"xml". - Data Char check: throws
InvalidStateErrorif the PI data contains characters outside the XML Char production. - Data sequence check: throws
InvalidStateErrorif the PI data contains?>.
On @xmldom/xmldom ≥ 0.8.13 (LTS), only the ?> data check (check 3) is applied. The target and XML Char checks are not included in the LTS fix.
PoC — fixed path
const { DOMImplementation, XMLSerializer } = require('@xmldom/xmldom');
const doc = new DOMImplementation().createDocument(null, 'r', null);
doc.documentElement.appendChild(doc.createProcessingInstruction('a', '?><z/><?q '));
// Default (unchanged): verbatim — injection present
const unsafe = new XMLSerializer().serializeToString(doc);
console.log(unsafe);
// <r><?a ?><z/><?q ?></r>
// Opt-in guard: throws InvalidStateError before serializing
try {
new XMLSerializer().serializeToString(doc, { requireWellFormed: true });
} catch (e) {
console.log(e.name, e.message);
// InvalidStateError: The ProcessingInstruction data contains "?>"
}
The guard catches ?> regardless of when it was introduced:
// Post-creation mutation: also caught at serialization time
const pi = doc.createProcessingInstruction('target', 'safe data');
doc.documentElement.appendChild(pi);
pi.data = 'safe?><injected/>';
new XMLSerializer().serializeToString(doc, { requireWellFormed: true });
// InvalidStateError: The ProcessingInstruction data contains "?>"
Why the default stays verbatim
The W3C DOM Parsing and Serialization spec §3.2.1.3 defines a require well-formed flag whose default value is false. With the flag unset, the spec explicitly permits serializing PI data verbatim. This matches browser behavior: Chrome, Firefox, and Safari all emit ?> in PI data verbatim by default without error.
Unconditionally throwing would be a behavioral breaking change with no spec justification. The opt-in requireWellFormed: true flag allows applications that require injection safety to enable strict mode without breaking existing code.
Residual limitation
createProcessingInstruction(target, data) does not validate data at creation time. The WHATWG DOM spec (§4.5 step 2) mandates an InvalidCharacterError when data contains ?>; enforcing this check unconditionally at creation time is a breaking change and is deferred to a future breaking release.
When the default serialization path is used (without requireWellFormed: true), PI data containing ?> is still emitted verbatim. Applications that do not pass requireWellFormed: true remain exposed.
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "@xmldom/xmldom"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.8.13"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "@xmldom/xmldom"
},
"ranges": [
{
"events": [
{
"introduced": "0.9.0"
},
{
"fixed": "0.9.10"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "xmldom"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"last_affected": "0.6.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-41675"
],
"database_specific": {
"cwe_ids": [
"CWE-91"
],
"github_reviewed": true,
"github_reviewed_at": "2026-04-22T20:17:58Z",
"nvd_published_at": "2026-05-07T04:16:33Z",
"severity": "HIGH"
},
"details": "## Summary\n\nThe package allows attacker-controlled processing instruction data to be serialized into XML without validating or neutralizing the PI-closing sequence `?\u003e`. As a result, an attacker can terminate the processing instruction early and inject arbitrary XML nodes into the serialized output.\n\n---\n\n## Details\n\nThe issue is in the DOM construction and serialization flow for processing instruction nodes.\n\nWhen `createProcessingInstruction(target, data)` is called, the supplied `data` string is stored directly on the node without validation. Later, when the document is serialized, the serializer writes PI nodes by concatenating `\u003c?`, the target, a space, `node.data`, and `?\u003e` directly.\n\nThat behavior is unsafe because processing instructions are a syntax-sensitive context. The closing delimiter `?\u003e` terminates the PI. If attacker-controlled input contains `?\u003e`, the serializer does not preserve it as literal PI content. Instead, it emits output where the remainder of the payload is treated as live XML markup.\n\nThe same class of vulnerability was previously addressed for CDATA sections (GHSA-wh4c-j3r5-mjhp / CVE-2026-34601), where `]]\u003e` in CDATA data was handled by splitting. The serializer applies no equivalent protection to processing instruction data.\n\n---\n\n## Affected code\n\n**`lib/dom.js` \u2014 `createProcessingInstruction` (lines 2240\u20132246):**\n\n```js\ncreateProcessingInstruction: function (target, data) {\n var node = new ProcessingInstruction(PDC);\n node.ownerDocument = this;\n node.childNodes = new NodeList();\n node.nodeName = node.target = target;\n node.nodeValue = node.data = data;\n return node;\n},\n```\n\nNo validation is performed on `data`. Any string including `?\u003e` is stored as-is.\n\n**`lib/dom.js` \u2014 serializer PI case (line 2966):**\n\n```js\ncase PROCESSING_INSTRUCTION_NODE:\n return buf.push(\u0027\u003c?\u0027, node.target, \u0027 \u0027, node.data, \u0027?\u003e\u0027);\n```\n\n`node.data` is emitted verbatim. If it contains `?\u003e`, that sequence terminates the PI in the output\nstream and the remainder appears as active XML markup.\n\n**Contrast \u2014 CDATA (line 2945, patched):**\n\n```js\ncase CDATA_SECTION_NODE:\n return buf.push(g.CDATA_START, node.data.replace(/]]\u003e/g, \u0027]]]]\u003e\u003c, which was subsequently closed\nwithout being merged.\n\n---\n\n## Fix Applied\n\n\u003e **\u26a0 Opt-in required.** Protection is not automatic. Existing serialization calls remain\n\u003e vulnerable unless `{ requireWellFormed: true }` is explicitly passed. Applications that pass\n\u003e untrusted data to `createProcessingInstruction()` or mutate PI nodes with untrusted input\n\u003e (via `.data =` or `CharacterData` mutation methods) should audit all `serializeToString()`\n\u003e call sites and add the option.\n\n`XMLSerializer.serializeToString()` now accepts an options object as a second argument. When `{ requireWellFormed: true }` is passed, the serializer throws `InvalidStateError` before emitting any ProcessingInstruction node whose `.data` contains `?\u003e`. This check applies regardless of how `?\u003e` entered the node \u2014 whether via `createProcessingInstruction` directly or a subsequent mutation (`.data =`, `CharacterData` methods).\n\nOn `@xmldom/xmldom` \u2265 0.9.10, the serializer additionally applies the full W3C DOM Parsing \u00a73.2.1.7 checks when `requireWellFormed: true`:\n\n1. **Target check**: throws `InvalidStateError` if the PI target contains a `:` character or is an ASCII case-insensitive match for `\"xml\"`.\n2. **Data Char check**: throws `InvalidStateError` if the PI data contains characters outside the XML Char production.\n3. **Data sequence check**: throws `InvalidStateError` if the PI data contains `?\u003e`.\n\nOn `@xmldom/xmldom` \u2265 0.8.13 (LTS), only the `?\u003e` data check (check 3) is applied. The target and XML Char checks are not included in the LTS fix.\n\n### PoC \u2014 fixed path\n\n```js\nconst { DOMImplementation, XMLSerializer } = require(\u0027@xmldom/xmldom\u0027);\n\nconst doc = new DOMImplementation().createDocument(null, \u0027r\u0027, null);\ndoc.documentElement.appendChild(doc.createProcessingInstruction(\u0027a\u0027, \u0027?\u003e\u003cz/\u003e\u003c?q \u0027));\n\n// Default (unchanged): verbatim \u2014 injection present\nconst unsafe = new XMLSerializer().serializeToString(doc);\nconsole.log(unsafe);\n// \u003cr\u003e\u003c?a ?\u003e\u003cz/\u003e\u003c?q ?\u003e\u003c/r\u003e\n\n// Opt-in guard: throws InvalidStateError before serializing\ntry {\n new XMLSerializer().serializeToString(doc, { requireWellFormed: true });\n} catch (e) {\n console.log(e.name, e.message);\n // InvalidStateError: The ProcessingInstruction data contains \"?\u003e\"\n}\n```\n\nThe guard catches `?\u003e` regardless of when it was introduced:\n\n```js\n// Post-creation mutation: also caught at serialization time\nconst pi = doc.createProcessingInstruction(\u0027target\u0027, \u0027safe data\u0027);\ndoc.documentElement.appendChild(pi);\npi.data = \u0027safe?\u003e\u003cinjected/\u003e\u0027;\nnew XMLSerializer().serializeToString(doc, { requireWellFormed: true });\n// InvalidStateError: The ProcessingInstruction data contains \"?\u003e\"\n```\n\n### Why the default stays verbatim\n\nThe W3C DOM Parsing and Serialization spec \u00a73.2.1.3 defines a `require well-formed` flag whose **default value is `false`**. With the flag unset, the spec explicitly permits serializing PI data verbatim. This matches browser behavior: Chrome, Firefox, and Safari all emit `?\u003e` in PI data verbatim by default without error.\n\nUnconditionally throwing would be a behavioral breaking change with no spec justification. The opt-in `requireWellFormed: true` flag allows applications that require injection safety to enable strict mode without breaking existing code.\n\n### Residual limitation\n\n`createProcessingInstruction(target, data)` does not validate `data` at creation time. The WHATWG DOM spec (\u00a74.5 step 2) mandates an `InvalidCharacterError` when `data` contains `?\u003e`; enforcing this check unconditionally at creation time is a breaking change and is deferred to a future breaking release.\n\nWhen the default serialization path is used (without `requireWellFormed: true`), PI data containing `?\u003e` is still emitted verbatim. Applications that do not pass `requireWellFormed: true` remain exposed.",
"id": "GHSA-x6wf-f3px-wcqx",
"modified": "2026-05-08T20:10:13Z",
"published": "2026-04-22T20:17:58Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/xmldom/xmldom/security/advisories/GHSA-x6wf-f3px-wcqx"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-41675"
},
{
"type": "WEB",
"url": "https://github.com/xmldom/xmldom/commit/7207a4b0e0bcc228868075ed991665ef9f73b1c2"
},
{
"type": "PACKAGE",
"url": "https://github.com/xmldom/xmldom"
},
{
"type": "WEB",
"url": "https://github.com/xmldom/xmldom/releases/tag/0.8.13"
},
{
"type": "WEB",
"url": "https://github.com/xmldom/xmldom/releases/tag/0.9.10"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "xmldom has XML node injection through unvalidated processing instruction serialization"
}
GHSA-XCPC-8H2W-3J85
Vulnerability from github – Published: 2026-07-10 18:32 – Updated: 2026-07-17 21:50adm-zip before 0.5.18 is vulnerable to denial of service via a crafted ZIP file with a manipulated uncompressed size header field. In zipEntry.js line 103, Buffer.alloc(_centralHeader.size) allocates memory based on the declared uncompressed size from the ZIP central directory header without validating it against the actual compressed data size or imposing any upper bound. The size value is read directly from the binary header at entryHeader.js line 266 with no bounds check. An attacker can craft a ~120-byte ZIP file that declares ~4GB uncompressed size, causing a memory allocation amplification ratio of over 33 million to 1. The allocation occurs before CRC validation, so the malicious payload cannot be rejected early. All extraction and read methods are affected: readFile(), readAsText(), extractEntryTo(), extractAllTo(), extractAllToAsync(), test(), and entry.getData(). Any application accepting untrusted ZIP files via adm-zip is vulnerable to immediate process crash.
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "adm-zip"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.6.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-39244"
],
"database_specific": {
"cwe_ids": [
"CWE-400",
"CWE-789"
],
"github_reviewed": true,
"github_reviewed_at": "2026-07-17T21:50:08Z",
"nvd_published_at": "2026-07-10T17:16:57Z",
"severity": "HIGH"
},
"details": "adm-zip before 0.5.18 is vulnerable to denial of service via a crafted ZIP file with a manipulated uncompressed size header field. In zipEntry.js line 103, Buffer.alloc(_centralHeader.size) allocates memory based on the declared uncompressed size from the ZIP central directory header without validating it against the actual compressed data size or imposing any upper bound. The size value is read directly from the binary header at entryHeader.js line 266 with no bounds check. An attacker can craft a ~120-byte ZIP file that declares ~4GB uncompressed size, causing a memory allocation amplification ratio of over 33 million to 1. The allocation occurs before CRC validation, so the malicious payload cannot be rejected early. All extraction and read methods are affected: readFile(), readAsText(), extractEntryTo(), extractAllTo(), extractAllToAsync(), test(), and entry.getData(). Any application accepting untrusted ZIP files via adm-zip is vulnerable to immediate process crash.",
"id": "GHSA-xcpc-8h2w-3j85",
"modified": "2026-07-17T21:50:08Z",
"published": "2026-07-10T18:32:19Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-39244"
},
{
"type": "WEB",
"url": "https://github.com/cthackers/adm-zip/issues/568"
},
{
"type": "WEB",
"url": "https://github.com/cthackers/adm-zip/commit/2450dcf417aa29df49270237d18c5245794da3e2"
},
{
"type": "PACKAGE",
"url": "https://github.com/cthackers/adm-zip"
},
{
"type": "WEB",
"url": "https://github.com/cthackers/adm-zip/releases"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
],
"summary": "adm-zip: Crafted ZIP file triggers 4GB memory allocation"
}
Sightings
| Author | Source | Type | Date | Other |
|---|
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.
The approach is described in our paper Mapping CVEs to MITRE ATT&CK Techniques: A Curated Gold-Set Classifier and the Limits of LLM-Assisted Label Expansion.