Skip to main content

adm-zip EUVDEUVD-2026-92493

| CVE-2026-102282 HIGH
Incorrect Permission Assignment for Critical Resource (CWE-732)
2026-09-29 https://github.com/cthackers/adm-zip GHSA-j5f4-cc29-5x44
7.1
CVSS 3.1 · Vendor: https://github.com/cthackers/adm-zip
View

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain

  1. Access
    Craft zip with 0o4755 setuid entry
  2. Delivery
    Deliver archive to build/upload path
  3. Exploit
    Root process extracts with keepOriginalPermission=true
  4. Execution
    Setuid file propagated into runtime image
  5. Persist
    Unprivileged user executes setuid binary
  6. Impact
    Attacker code runs as root

Vulnerability Assessment

Weakness
CWE
OWASP Top 10:2025
A01:2025 - Broken Access Control
ASVS 5.0
V13 - Configuration Permission assignment review
Exploitation Conditions

Exploitation requires ALL of: (1) the consuming application calls adm-zip's extractAllTo() or extractEntryTo() with keepOriginalPermission=true - a non-default flag; (2) that extraction process runs as root (the described Docker-build/CI-runner/privileged-install posture); (3) the extracted root-owned setuid file is preserved into an environment (e.g. via cp -a/rsync) where (4) a lower-privileged user later executes it. The attacker only needs to supply a zip whose entry external attributes encode the setuid/setgid bit (e.g. 0o4755 << 16), requiring no special access to produce. Default usage with the flag off, or non-root extraction, is NOT exploitable - non-root extraction yields only a harmless self-owned setuid file. This is a Unix/Linux-only concern (setuid semantics).

Impact

This is a genuine but conditional privilege-escalation issue, correctly rated as Medium severity despite the 7.1 CVSS. The vendor CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N is internally consistent with the mechanism: the attack vector is Local (the malicious setuid file must be executed on the host), and PR:L reflects that a lower-privileged local user ultimately runs the planted binary. There is no EPSS score, no CISA KEV listing, and no separately catalogued exploit, so there is no evidence of active exploitation; however, the GitHub Security Advisory (GHSA-j5f4-cc29-5x44) publishes a complete, tested, copy-paste reproduction (Python zipfile crafting + Node extraction + stat verification), so working exploit code is effectively public. The real-world risk is gated by a specific unsafe usage pattern rather than being universally exploitable: the code path only triggers when a consumer explicitly passes keepOriginalPermission=true AND runs extraction as root AND the resulting setuid file survives into a runtime executed by an unprivileged user. That materially narrows exposure versus the raw score, but the named target environments (Docker builds, CI runners, privileged install/deploy steps) are exactly where root extraction and permission-preservation flags are common, so affected deployments face a realistic root-compromise primitive. No signals conflict; the chief caveat is that CVSS treats this as a fully local chain while the initial malicious artifact can be delivered remotely (upload endpoint, fetched dependency archive).

Exploit ScenarioDerived

An attacker submits a crafted zip (via an upload feature, a poisoned dependency archive, or a build artifact) whose entry sets external attributes to 0o4755 << 16 for a shell script or binary. A CI pipeline or Docker build running as root extracts it with adm-zip's keepOriginalPermission=true, producing a root-owned setuid file that is then copied into the runtime image (e.g. by cp -a/rsync) and later executed by an unprivileged service account, running the attacker's code as root. A complete, tested proof-of-concept is published in the GHSA advisory.

This Week Schedule remediation this week. Why: HIGH severity (CVSS 7.0-8.9).
Patch available 0.1% exploitation probability (EPSS)

Get an e-mail when this CVE is exploited, patched or re-scored. Free account.

Alert me

AnalysisAIv1 – Sep 29, 2026

Local privilege escalation in the npm package adm-zip through version 0.6.0: when an application extracts an archive with the non-default keepOriginalPermission=true option, the library copies the Unix permission bits recorded in each zip entry's external file attributes straight to disk via fs.chmodSync() without stripping the setuid (0o4000), setgid (0o2000) or sticky (0o1000) bits. An attacker who can supply a zip - no special access needed to craft one - can therefore plant a 04755 root-owned binary whenever the extraction runs as root (the common Docker-build, CI-runner and privileged-install posture where this flag is used), and the attacker's code executes as root once a lower-privileged user later runs that file. The issue is correctly rated Medium despite a 7.1 CVSS score because it is highly conditional (flag enabled, root extraction, setuid file preserved and executed by another user); confirmed actively exploited: no - not in CISA KEV - but a working proof-of-concept (a Python-crafted zip with external_attr 0o4755 << 16) is documented in the vendor advisory. Default usage with the flag off, or extraction as a non-root user, is not exploitable.

RemediationAI

Vendor-released patch: upgrade adm-zip to 0.6.1 or later, which changes the entryHeader fileAttr getter to mask with 0o777 instead of 0xfff and thereby discards attacker-controlled setuid/setgid/sticky bits (fix commit 6a63c339b83c52915483efacda517660a7a7bf87, GHSA-j5f4-cc29-5x44, release https://github.com/cthackers/adm-zip/releases/tag/v0.6.1); pin and audit transitive dependencies since adm-zip is frequently pulled in indirectly. If an immediate upgrade is not possible, stop passing keepOriginalPermission=true - this is the single enabler and the default (false) path yields mode 0666 with no setuid bit, at the cost of losing intended permission preservation for deployment flows; alternatively, run all archive extraction as an unprivileged user (for example a dedicated non-root user inside Docker builds or CI runners), which reduces the extracted setuid file to a harmless self-owned artifact but requires restructuring build stages that currently rely on root for package installation. Additional compensating controls with trade-offs: mount build/CI workspaces and extraction targets with the nosuid option so any setuid bit on files in those trees is ignored at execution time (side effect: legitimate setuid tooling in those mounts also stops working); strip setuid/setgid bits after extraction and before artifacts leave the build, e.g. a recursive chmod -R a-s or find -perm /6000 -exec chmod -s on the output tree (side effect: strips legitimate special bits and must be applied consistently to all copies, since cp -a and rsync would otherwise reintroduce the mode); and treat attacker-supplied archives as untrusted input in code review so any future use of keepOriginalPermission requires an explicit, root-context justification.

Affected VersionsENISA

adm-zip < 0.6.1

Affected Packages

npm adm-zip fix: 0.6.1

Source: OSV (Open Source Vulnerabilities)

Affects your stack

Affects 1 package in npm

Checking this CVE against your own stacks and servers is part of the Basic plan and up.

Technical ContextAI · show details

adm-zip parses the ZIP central-directory/entry header and exposes the Unix mode encoded in the high 16 bits of the external file attributes through an entryHeader getter. The vulnerable implementation masks with 0xfff (0o7777), which faithfully retain the special permission bits setuid, setgid and sticky in addition to the rwxrwxrwx bits; the correct mask is 0o777. That value flows from adm-zip.js (extractEntryTo and extractAllTo) into util/utils.js, which calls fs.chmodSync(path, attr || 0o666) with no filtering, so untrusted archive metadata directly determines the mode of a file the library creates on disk - including directory entries, where a setgid bit propagates group inheritance to subsequently created files. This is a textbook CWE-732 (Incorrect Permission Assignment for Critical Resource): a privileged attribute (the setuid bit) is sourced from attacker-controlled input and applied without validation. Building, parsing and extracting ZIP archives is core to npm tooling, artifact downloaders, installer scripts and container build layers, which is why the affected code path sits in exactly the environments (root-owned CI and Docker builds) where setuid bits translate into privilege escalation. The affected package is identified by CPE pkg:npm/adm-zip, and the issue is Unix/Linux-specific because setuid semantics do not exist on Windows.

Know when Docker gets its next vulnerability

  • Watch products and get an email when something new is published
  • Check this CVE against your own stack and servers
  • Exploit and PoC references, threat intelligence from 22 sources

No credit card · 7-day full trial

Severity by source

Vendor (https://github.com/cthackers/adm-zip) PRIMARY 7.1 HIGH
AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N
vuln.today AI 7.1 HIGH

Local because the planted setuid binary must be executed on-host; PR:L as a low-privileged local user runs it; C:H/I:H from full root code execution, A:N as availability is not the primary impact.

3.1 AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N
4.0 AV:L/AC:L/AT:P/PR:L/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N
Red Hat 7.1 HIGH

Primary rating from Vendor (https://github.com/cthackers/adm-zip).

CVSS VectorVendor: https://github.com/cthackers/adm-zip

Attack Vector
Local
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
High
Availability
None

DescriptionCVE.org

Summary

adm-zip applies the Unix permission bits stored in a zip entry directly to the extracted file via fs.chmodSync() when keepOriginalPermission=true is passed to extractAllTo()/extractEntryTo() - and it never filters the setuid/setgid/sticky bits out of those bits. A zip crafted by an attacker can therefore produce an extracted binary with mode 04755. When extraction runs as root (the default posture in Docker builds, CI runners, and privileged install steps - the exact environments where this flag is used), the resulting root-owned setuid file is executed later by a lesser-privileged user, turning the attacker's code into a root execution.

Details

The mode a zip entry wants is read back from the external file attributes in the header, and the mask used keeps every special bit:

js
// headers/entryHeader.js:187
get fileAttr() {
    return (_attr || 0) >> 16 & 0xfff;
}

0xfff is 0o7777 - it preserves setuid (0o4000), setgid (0o2000) and the sticky bit (0o1000) along with the rwx bits. Shifting by 16 is the standard Unix convention for where zip stores the mode; the mask is the problem.

When the flag is on, that value goes straight to the write:

js
// adm-zip.js:726-727 (extractEntryTo, and identically in extractAllTo)
const fileAttr = keepOriginalPermission ? entry.header.fileAttr : undefined;
filetools.writeFileTo(target, content, overwrite, fileAttr);
js
// util/utils.js:94
self.fs.chmodSync(path, attr || 0o666);

No & 0o777, no stripping of 0o7000. Attacker-controlled bytes in the zip decide the final mode of a file the library creates on disk. Directory entries are affected too (adm-zip.js:855), so a setgid bit on a directory entry also carries over and gives new files inside it group inheritance.

PoC

Tested against adm-zip@0.6.0 (latest as of 2026-08-01), Node 22, Linux.

  1. Craft a zip with a setuid binary using standard tooling (this is the

realistic attacker path - no adm-zip APIs involved in creating it):

bash
python3 -c "
import zipfile
zi = zipfile.ZipInfo('pysuidbin')
zi.external_attr = 0o4755 << 16
with zipfile.ZipFile('evil.zip', 'w') as z:
    z.writestr(zi, '#!/bin/sh\nid\n')
"
  1. Extract with the flag enabled:
js
const AdmZip = require('adm-zip');
new AdmZip('evil.zip').extractAllTo('/tmp/out', true, true);

const fs = require('fs');
const st = fs.statSync('/tmp/out/pysuidbin');
console.log((st.mode & 0o7777).toString(8));
// => 4755   (setuid bit set - the file is root-owned if the extractor runs as root)
  1. Control - same zip, default extraction (keepOriginalPermission=false):

mode comes out 0666, no setuid. The flag is the enabler.

Alternative supply path, if the zip is built in-process with adm-zip's own API:

js
const zip = new AdmZip();
zip.addFile('suidbin', Buffer.from('#!/bin/sh\nid\n'), '', 0o4755);
zip.writeZip('evil.zip');
new AdmZip('evil.zip').extractAllTo('/tmp/out', true, true);
// same result: stat mode & 0o7777 === 0o4755

Impact

Privilege escalation. The vulnerability class is CWE-732 (incorrect permission assignment): permission bits taken from untrusted input are applied with no filtering.

Realistic chain:

  1. Attacker supplies a zip (upload endpoint, fetched dependency archive, artifact in a build script - no special access needed to produce the file).
  2. A pipeline or service extracts it as root with keepOriginalPermission=true. Docker builds run as root by default and CI/install steps commonly do too; this flag is specifically the tooling used in permission-preserving deploy flows.
  3. The root-owned setuid file leaves the build, typically preserved by cp -a/rsync mode-bit propagation, into the runtime environment.
  4. An unprivileged app user or service account executes it (the standard build-as-root/run-as-user model) - the attacker's code runs as root.

Who is impacted: applications and pipelines that extract untrusted archives with keepOriginalPermission=true while running as root. Default-usage deployments (flag off) are not affected; non-root extraction results in a harmless self-owned setuid file. Severity: Medium

Suggested fix, one line in the getter:

js
get fileAttr() {
    return (_attr >> 16) & 0o777;
}

Blast Radius

ecosystem impact
† from your stack dependencies † transitive graph · vuln.today resolves 4-path depth
  • 4,625 npm packages depend on adm-zip (683 direct, 3,970 indirect)

Ecosystem-wide dependent count for version 0.6.1.

Technical POC Analysis

CWE-732 (Incorrect Permission Assignment for Critical Resource): permission bits taken verbatim from untrusted archive metadata.

Full technical POC analysis - root cause, step-by-step exploitation and patch breakdown - is part of the Pro and Business plans.

Executive ViewAI

Why It Matters

Adm-zip, a widely used npm archive library, can enable local privilege escalation in versions through 0.6.0 when applications extract archives as root with the non-default keepOriginalPermission=true option, allowing a crafted ZIP to plant a setuid root binary. This primarily affects CI/CD runners, Docker build environments, and privileged installers that process untrusted archives, where a successful attack could yield root-level control of build infrastructure. Patch available per vendor advisory, and publicly available exploit code exists, but no confirmed active exploitation (CISA KEV) has been reported.

Business Impact: Medium
Compensating Controls

Apply vendor patch.

Threat Intelligence Overview

EPSS Score
0.1%
Top 96% exploitable
Prevalence
High
adm-zip is an extremely popular Node.js zip library with millions of weekly npm downloads
Threat Intel
1
1 source
Data Quality
5 sources
Confidence: Medium

How this decision was reached

The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.

SignalValue
Severity HIGH
CISA KEV No
Public POC No
EPSS 0.1%
Patch available Yes
Active threat No
Deciding rule
HIGH severity (CVSS 7.0-8.9)
What every action level means
Emergency Immediate action required. Criteria: CRITICAL + in CISA KEV (actively exploited) without patch, OR CRITICAL + EPSS > 30% without patch, OR CRITICAL + active threat signals without patch.
Act Now Prioritize within 24-48h. Criteria: in KEV with patch available, OR CRITICAL + public POC, OR HIGH + EPSS > 10%, OR CRITICAL + active threat, OR any CRITICAL severity.
This Week Schedule remediation this week. Criteria: HIGH severity (CVSS 7.0-8.9). Patch within normal change window.
This Month Plan within 30 days. Criteria: MEDIUM severity (CVSS 4.0-6.9), lower exploitation probability. Include in regular patch cycle.
Monitor Track and reassess. Criteria: LOW severity (CVSS 0.1-3.9), minimal exploitation risk. No immediate action needed.

SSVC AssessmentENISA

SSVC Decision· derived
Defer
Exploitation· derived
None
System Exposure· derived
Small
Automatable· derived
No
Human Impact
Medium

Priority Score

36
Low Medium High Critical
KEV: 0
EPSS: 0
CVSS: +36
PoC: 0
Weaponized: 0
Threat intel: 0
Gov advisory: 0

Attack Technique

Privilege escalation occurs when an attacker leverages flaws in access control mechanisms to gain permissions beyond what they were originally granted.

More in Docker

View all
CVE-2024-55964 CRITICAL POC
9.8 Mar 26

An issue was discovered in Appsmith before 1.52. Rated critical severity (CVSS 9.8), this vulnerability is remotely expl

CVE-2019-5736 HIGH POC
8.6 Feb 11

runc through version 1.0-rc6 (used in Docker before 18.09.2) contains a container escape vulnerability that allows attac

CVE-2023-32077 HIGH POC
7.5 Aug 24

Netmaker makes networks with WireGuard. Rated high severity (CVSS 7.5), this vulnerability is remotely exploitable, no a

CVE-2026-39987 CRITICAL POC
9.3 Apr 08

Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/

CVE-2023-5815 HIGH POC
8.1 Nov 22

The News & Blog Designer Pack - WordPress Blog Plugin - (Blog Post Grid, Blog Post Slider, Blog Post Carousel, Blog Post

CVE-2026-66384 MEDIUM POC
5.3 Aug 12

Path traversal in JFrog Artifactory (CWE-22) enables an authenticated low-privilege user to write data outside the inten

CVE-2014-9357 CRITICAL
10.0 Dec 16

Docker 1.3.2 allows remote attackers to execute arbitrary code with root privileges via a crafted (1) image or (2) build

CVE-2026-52806 CRITICAL POC
9.9 Jun 23

Remote code execution in Gogs through 0.14.2 allows authenticated users (and unauthenticated attackers on default-config

CVE-2025-14707 HIGH POC
8.9 Dec 15

Unauthenticated remote command injection in SGWBOX N3 firmware 2.0.25 lets attackers execute arbitrary operating-system

CVE-2026-56274 HIGH POC
8.7 Jun 23

Remote code execution in Flowise before 3.1.2 allows any authenticated user (or API caller with chatflow view/update per

CVE-2026-34156 CRITICAL POC
9.9 Mar 30

Remote code execution in NocoBase Workflow Script Node (npm @nocobase/plugin-workflow-javascript) allows authenticated l

CVE-2019-15752 HIGH POC
7.8 Aug 28

Docker Desktop Community Edition before 2.1.0.1 allows local users to gain privileges by placing a Trojan horse docker-c

Vendor StatusVendor

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy