GHSA-p634-w6r4-rjp2: adm-zip Duplicate ZIP Entry Names: GetEntry() Vulnerability
MODERATEGHSA-p634-w6r4-rjp2 is a MODERATE (CVSS 5.9) duplicate zip entry names: getentry() vulnerability (CWE-436: Interpretation Conflict) affecting adm-zip libraries in the npm ecosystem. The issue involves duplicate zip entry names: getentry() and extractallto() resolve to different content. Remediation is available by upgrading affected packages to version 0.6.1.
GHSA-p634-w6r4-rjp2 at a Glance
Security Impact
CVSS: 5.9
The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:H/A:N).
How to Fix GHSA-p634-w6r4-rjp2
To remediate this vulnerability, upgrade all affected adm-zip dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
npm install adm-zip@0.6.1
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
npm ls adm-zip
How to Check if You Are Affected
To determine whether your Node.js application is affected by GHSA-p634-w6r4-rjp2, inspect your project dependencies using npm:
npm ls adm-zip
Analyze the terminal output to locate any version of adm-zip in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 0.6.1), your application is affected.
Note: The npm ls adm-zip command inspects dependencies declared in your package.json and lockfile; it does not perform automated runtime dynamic scanning.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-436: Interpretation Conflict, where product a handles inputs or steps differently than product b, which causes a to perform incorrect actions based on its perception of b's state. In adm-zip, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
GHSA-p634-w6r4-rjp2 Affected adm-zip Versions
1 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
adm-zip
|
npm |
< 0.6.1
|
0.6.1
|
References
Frequently Asked Questions
What is GHSA-p634-w6r4-rjp2?
Which adm-zip versions are affected?
What version fixes GHSA-p634-w6r4-rjp2?
Is adm-zip affected?
What is the CVSS score of GHSA-p634-w6r4-rjp2?
What CWE is associated with GHSA-p634-w6r4-rjp2?
How can I check npm dependencies for GHSA-p634-w6r4-rjp2?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-p634-w6r4-rjp2",
"modified" : "2026-09-29T23:11:01Z",
"published" : "2026-09-29T23:11:01Z",
"aliases" : [ ],
"summary" : "adm-zip: Duplicate ZIP entry names: getEntry() and extractAllTo() resolve to different content",
"details" : "### Summary\n\nA ZIP file can contain two entries with the identical name. adm-zip keeps both in its internal entry list, but its name-lookup table only retains the last one written. `getEntry(name)` and `extractAllTo()` walk these two different internal structures, so they can each resolve a duplicate name to a *different* entry. An application that validates a named entry's contents via `getEntry()` before trusting an archive, then extracts the whole archive, can end up approving one file's content while a different file's bytes are what actually land on disk under that name.\n\n### Details\n- `zipFile.js:58-83` retains both entries in `entryList` but overwrites `entryTable[name]` with only the last one written.\n- `adm-zip.js:83-95,658-663` uses `entryTable` for `getEntry()` lookups — returns the *last* duplicate.\n- `adm-zip.js:769-914` iterates `entryList` for extraction — writes the *first* duplicate (sync, default overwrite policy).\n\n\n### PoC\n```js\nconst AdmZip = require('adm-zip');\nconst z = new AdmZip({ noSort: true });\nz.addFile('a.txt', Buffer.from('FIRST'));\nz.addFile('b.txt', Buffer.from('SECOND'));\nconst raw = Buffer.from(z.toBuffer());\n// rename the a.txt entry to b.txt directly in the raw bytes\nfor (let at = raw.indexOf('a.txt'); at >= 0; at = raw.indexOf('a.txt', at + 5)) {\n raw.write('b.txt', at);\n}\nconst parsed = new AdmZip(raw, { noSort: true });\nconst validated = parsed.getEntry('b.txt').getData().toString();\nparsed.extractAllTo(outDir, false);\n// validated === \"SECOND\", but the file written to disk === \"FIRST\"\n```\n\nReproduced on the pinned commit (`2b4d84087d45344643e0183756e19191d52815cc`)\n\n### Impact\nAn application that checks a named entry's content before trusting an untrusted ZIP, then extracts it, can be made to approve different bytes than what actually gets written to disk — the classic check/use split that this kind of validate-then-extract pattern relies on.",
"severity" : [ {
"type" : "CVSS_V3",
"score" : "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:H/A:N"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "npm",
"name" : "adm-zip"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "0"
}, {
"fixed" : "0.6.1"
} ]
} ],
"database_specific" : {
"last_known_affected_version_range" : "<= 0.6.0"
}
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/cthackers/adm-zip/security/advisories/GHSA-p634-w6r4-rjp2"
}, {
"type" : "WEB",
"url" : "https://github.com/cthackers/adm-zip/commit/05101d47b3b983b705cc3e66fc34366118ba7b99"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/cthackers/adm-zip"
}, {
"type" : "WEB",
"url" : "https://github.com/cthackers/adm-zip/releases/tag/v0.6.1"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-436", "CWE-696" ],
"severity" : "MODERATE",
"github_reviewed" : true,
"github_reviewed_at" : "2026-09-29T23:11:01Z",
"nvd_published_at" : null
}
}