Back to Blog
critical SEVERITY6 min read

How Denial of Service via Crafted ZIP File Happens in Node.js and How to Fix It

A critical denial-of-service vulnerability (CVE-2026-39244) in adm-zip 0.5.10 allowed attackers to craft malicious ZIP files that triggered excessive memory allocation, potentially crashing the Node.js process. The fix upgrades adm-zip to version 0.6.0, which includes proper memory allocation limits when parsing ZIP entries. This vulnerability was discovered in the `solarIncidenceService.js` service, where uploaded ZIP files are processed without sandboxing.

O
By Orbis AppSec
Published August 9, 2026Reviewed August 9, 2026

Answer Summary

CVE-2026-39244 is a Denial of Service vulnerability in the adm-zip Node.js package (versions prior to 0.6.0) caused by excessive memory allocation when processing crafted ZIP files (CWE-400). The fix is to upgrade adm-zip from 0.5.10 to 0.6.0 in package.json and package-lock.json, which introduces proper bounds checking on ZIP entry decompression sizes.

Vulnerability at a Glance

cweCWE-400
fixUpgrade adm-zip from 0.5.10 to 0.6.0
riskApplication crash or resource exhaustion from malicious ZIP uploads
languageJavaScript (Node.js)
root causeadm-zip 0.5.10 lacks memory allocation limits when decompressing ZIP entries
vulnerabilityDenial of Service via Excessive Memory Allocation (ZIP Bomb)

Introduction

The services/solarIncidenceService.js file in this application handles solar incidence data processing, including the extraction of uploaded ZIP archives containing geospatial or configuration data. A critical vulnerability existed not in the application code itself, but in its dependency chain: adm-zip version 0.5.10 contained a flaw (CVE-2026-39244) that allowed crafted ZIP files to trigger unbounded memory allocation during decompression.

What makes this particularly dangerous is the context. The service processes ZIP files that may originate from user uploads or external data sources. Combined with the fact that plugins in this system execute with full Node.js runtime privileges—unrestricted access to the filesystem, network, and child processes—a denial-of-service attack could cascade into broader system instability, potentially affecting all co-hosted services.

The Vulnerability Explained

What Happens Under the Hood

adm-zip 0.5.10 reads ZIP file entries and allocates memory buffers based on metadata declared within the ZIP archive itself. A crafted ZIP file can declare decompressed sizes that are astronomically large, or use recursive compression techniques (a "ZIP bomb") to force the library to allocate gigabytes of memory from a tiny input file.

The vulnerable dependency was declared in package.json:

"adm-zip": "0.5.10"

When solarIncidenceService.js calls adm-zip to extract entries from an uploaded archive, the library trusts the size headers in the ZIP without imposing upper bounds. This means a 42-kilobyte ZIP file could decompress into 4.5 petabytes of data (the classic "42.zip" bomb pattern), though in practice the application would crash from memory exhaustion long before reaching that theoretical limit.

Attack Scenario

Consider this realistic attack path:

  1. An attacker identifies that the solar incidence service accepts ZIP file uploads (or processes ZIP files from an external data feed).
  2. The attacker crafts a malicious ZIP file where nested entries declare decompressed sizes of several gigabytes each.
  3. When solarIncidenceService.js processes this file using adm-zip 0.5.10, the library attempts to allocate memory proportional to the declared decompressed size.
  4. The Node.js process exhausts available heap memory and crashes with an out-of-memory error.
  5. Because plugins run with full Node.js runtime privileges without sandboxing, the crash affects the entire process—not just the ZIP handling code. Any other services sharing this process are also taken down.

Why the Lack of Sandboxing Amplifies the Risk

The vulnerability description notes that plugins execute with full Node.js runtime privileges without any sandboxing or permission restrictions. This means:

  • The ZIP processing code has unrestricted access to fs, net, and child_process modules
  • There's no memory limit enforced at the plugin level
  • A single malicious ZIP can take down the entire application, not just the solar incidence service
  • No manifest-based permission system exists to restrict what resources a plugin can consume

This is a textbook example of how a dependency vulnerability becomes exponentially more dangerous in an unsandboxed execution environment.

The Fix

What Changed

The fix upgrades adm-zip from version 0.5.10 to 0.6.0, which includes internal protections against excessive memory allocation during ZIP decompression.

Before (package.json):

"adm-zip": "0.5.10"

After (package.json):

"adm-zip": "^0.6.0"

Before (package-lock.json):

"node_modules/adm-zip": {
  "version": "0.5.10",
  "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.10.tgz",
  "integrity": "sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==",
  "engines": {
    "node": ">=6.0"
  }
}

After (package-lock.json):

"node_modules/adm-zip": {
  "version": "0.6.0",
  "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.6.0.tgz",
  "integrity": "sha512-XleryMhbuksdKtofnWZ9Sk+4CUTbms4Mb/EU32SZwToAyZ5RgVos/ki8n+yr0LWHOGKuakbXTuuYNHLQjhddgg==",
  "engines": {
    "node": ">=14.0"
  }
}

How the Fix Works

adm-zip 0.6.0 introduces several key improvements:

  1. Memory allocation bounds: The library now validates declared decompression sizes against configurable limits before allocating buffers.
  2. Incremental decompression: Rather than allocating the full declared size upfront, the library decompresses in chunks, detecting anomalous expansion ratios.
  3. Minimum Node.js version bump: The engine requirement moved from >=6.0 to >=14.0, allowing the library to leverage modern Node.js APIs for safer memory management (including Buffer.alloc with explicit size checks).

Why Both Files Changed

  • package.json: Updates the declared dependency so that npm install pulls the correct version. The ^0.6.0 semver range ensures future patch releases (0.6.x) are automatically included.
  • package-lock.json: Locks the exact resolved version, integrity hash, and registry URL, ensuring reproducible builds and preventing supply-chain attacks through tampered packages.

Prevention & Best Practices

1. Dependency Scanning in CI/CD

Integrate tools like Trivy, Snyk, or npm audit into your CI pipeline to catch vulnerable dependencies before they reach production:

# Example: Run Trivy on your project
trivy fs --scanners vuln .

2. Implement Upload Size Limits

Even with a patched library, enforce server-side limits on uploaded file sizes:

// Express middleware example
app.use('/upload', express.raw({ limit: '10mb' }));

3. Validate ZIP Contents Before Extraction

Check declared sizes in ZIP entries before attempting full decompression:

const AdmZip = require('adm-zip');
const MAX_ENTRY_SIZE = 100 * 1024 * 1024; // 100MB

const zip = new AdmZip(buffer);
for (const entry of zip.getEntries()) {
  if (entry.header.size > MAX_ENTRY_SIZE) {
    throw new Error(`ZIP entry ${entry.entryName} exceeds size limit`);
  }
}

4. Sandbox Plugin Execution

The broader architectural issue—plugins running with full Node.js privileges—should be addressed with:
- Worker threads with resource limits (--max-old-space-size)
- A manifest-based permission system restricting fs, net, and child_process access
- Node.js experimental permissions API (--experimental-permission)

5. Keep Dependencies Updated

Use tools like Dependabot or Renovate to automate dependency updates and receive alerts for security advisories.

Key Takeaways

  • adm-zip 0.5.10's lack of decompression size limits made solarIncidenceService.js vulnerable to ZIP bomb attacks that could crash the entire Node.js process.
  • The absence of plugin sandboxing amplified a library-level DoS into a full application crash—a single malicious ZIP could take down all co-hosted services.
  • Upgrading from adm-zip 0.5.10 to 0.6.0 is a minimal, low-risk change (only package.json and package-lock.json modified) that eliminates CVE-2026-39244.
  • The Node.js engine requirement bump from >=6.0 to >=14.0 signals that the new version uses modern, safer APIs—ensure your runtime meets this requirement.
  • Dependency scanning tools like Trivy caught this vulnerability automatically, demonstrating the value of continuous security monitoring in the development pipeline.

How Orbis AppSec Detected This

  • Source: Uploaded or externally sourced ZIP file data entering the application through solarIncidenceService.js
  • Sink: adm-zip library's ZIP decompression routines that allocate memory based on untrusted ZIP header metadata
  • Missing control: No bounds checking on declared decompression sizes in adm-zip 0.5.10; no application-level validation of ZIP entry sizes before extraction; no sandboxing to limit memory consumption
  • CWE: CWE-400 (Uncontrolled Resource Consumption)
  • Fix: Upgraded adm-zip from 0.5.10 to 0.6.0, which introduces internal memory allocation limits during ZIP decompression

Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.

Conclusion

CVE-2026-39244 demonstrates how a single vulnerable dependency can expose an entire application to denial-of-service attacks—especially when the execution environment lacks proper sandboxing. The fix was straightforward: a version bump in two files. But the lesson extends beyond this specific CVE.

Applications that process untrusted archive files should implement defense in depth: keep dependencies updated, validate input sizes before processing, enforce resource limits on processing threads, and adopt a least-privilege execution model for plugins and services. The combination of automated dependency scanning and architectural safeguards like sandboxing creates a resilient security posture that can withstand both known and zero-day vulnerabilities.

References

Frequently Asked Questions

What is a ZIP bomb denial of service?

A ZIP bomb is a maliciously crafted ZIP archive that, when decompressed, expands to an enormous size, consuming all available memory and causing the application to crash or become unresponsive.

How do you prevent ZIP-based DoS in Node.js?

Use up-to-date ZIP parsing libraries with built-in decompression limits, validate file sizes before extraction, implement memory usage caps, and consider processing ZIP files in isolated worker threads with resource constraints.

What CWE is excessive memory allocation?

CWE-400: Uncontrolled Resource Consumption. This covers scenarios where an application does not properly restrict the amount of resources (memory, CPU, disk) that can be consumed by an attacker.

Is simply upgrading adm-zip enough to prevent this vulnerability?

Upgrading to adm-zip 0.6.0 addresses CVE-2026-39244 specifically, but defense-in-depth practices like file size validation, upload limits, and sandboxed processing provide additional protection against future ZIP-related attacks.

Can static analysis detect ZIP bomb vulnerabilities?

Yes, tools like Trivy can detect known vulnerable library versions through dependency scanning, and SAST tools can flag patterns where ZIP extraction occurs without size validation.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #870

Related Articles

critical

How Sensitive Data Exposure in Error Logging happens in TypeScript/Deno and how to fix it

A critical vulnerability in Supabase Edge Functions allowed sensitive authentication errors and API credentials to leak through verbose error logging. The `cancel-subscription/index.ts` function logged full error objects to the console, potentially exposing Paddle API keys and auth tokens in deployment logs. The fix sanitizes all error messages to log only safe error text while preserving debugging capability.

critical

How HTTP Header Injection Happens in Go and How to Fix It

A critical vulnerability in the file upload handler allowed attackers to inject CRLF sequences into HTTP response headers through crafted filenames. The fix sanitizes user-supplied filenames before using them in Content-Disposition headers, preventing header injection attacks that could lead to cache poisoning, session fixation, or XSS.

high

How Path Traversal and Security Policy Bypass Happens in Node.js Dependencies and How to Fix It

A high-severity vulnerability in the fast-uri package (CVE-2026-6321) allowed attackers to bypass security policies through improper Unicode hostname canonicalization and path traversal. This issue affected the @apralabs/apra-fleet project through its dependency tree, and was resolved by upgrading fast-uri from version 3.1.0 to 4.1.2 using npm overrides.

high

How Command Injection happens in Node.js child_process calls and how to fix it

A high-severity command injection vulnerability was discovered in `tools/utils/lang/helpers.ts` where the `prettier()` function passed a user-controllable `fileName` argument directly into a shell command string via `exec()`. By replacing `exec()` with `execFile()` and passing arguments as an array, the fix eliminates shell interpolation entirely, preventing attackers from injecting arbitrary shell commands through malicious filenames.

high

How Quadratic CPU Consumption in YAML Parsing happens in JavaScript and how to fix it

A high-severity vulnerability in js-yaml versions 3.x and 4.x allowed attackers to cause quadratic CPU consumption through specially crafted YAML documents using the `!!omap` type. This denial-of-service vulnerability (GHSA-5p4m-2wfm-xmqj) was fixed by upgrading from js-yaml 4.3.0 to 4.3.1, protecting applications from algorithmic complexity attacks during YAML parsing.

high

How Arbitrary HTTP Header Injection via Prototype Pollution happens in JavaScript and how to fix it

A high-severity vulnerability (CVE-2026-42035) in axios version 1.13.5 allowed attackers to inject arbitrary HTTP headers through prototype pollution. The fix upgrades axios to version 1.18.0 in the frontend's dependency tree, which includes proper prototype chain validation when constructing HTTP request headers. This prevents attackers from manipulating outgoing requests to perform SSRF, session hijacking, or cache poisoning attacks.