DEV Community

Amartya Jha
Amartya Jha

Posted on • Originally published at codeant.ai

Denial of Service in yauzl 3.2.0: One Zip File Crashes the Library Behind VS Code and Electron

TL;DR

CodeAnt AI Security Research discovered a Denial of Service (DoS) vulnerability in yauzl 3.2.0, the most widely used Node.js ZIP parsing library. A specially crafted ZIP file with malformed Central Directory entries triggers an unhandled exception that crashes the Node.js process entirely. Any application that processes user-supplied ZIP files using yauzl — including VS Code extension hosts, Electron apps, CI/CD pipelines, and file upload services — is potentially vulnerable to remote process termination.

Property Detail
Vulnerability Type Denial of Service (DoS) via Unhandled Exception
Affected Package yauzl
Affected Version 3.2.0 (latest)
Severity High
Attack Vector Maliciously crafted ZIP file
Researcher CodeAnt AI Security Research
Fix Available No patch at time of publication

What Is yauzl and Why Does It Matter?

If you have ever unzipped a file inside a Node.js application, there is a reasonable chance yauzl — short for "yet another unzip library" — did the heavy lifting. It is the de facto standard for ZIP file parsing in the Node.js ecosystem, depended upon by ~1,345 npm packages.

The library powers infrastructure you interact with every day:

  • VS Code — extensions are packaged as .vsix files, which are ZIP archives. The extension host relies on yauzl to unpack and validate them.
  • Electron applications — many Electron-based apps ship update payloads or resource bundles as ZIP archives and use yauzl to extract them at runtime.
  • CI/CD pipelines — build systems, artifact stores, and deployment tools routinely unpack ZIP archives as part of automated workflows.
  • File upload services — SaaS platforms that accept ZIP uploads lean on yauzl for extraction.
  • Developer tooling — bundlers, scaffolding tools, and package managers use yauzl as a core dependency.

The library ships with several safety-oriented features:

  • validateEntrySizes — guards against ZIP bomb decompression attacks.
  • validateFileName — prevents path traversal exploits like ../../etc/passwd.
  • Central Directory parsing — uses the ZIP spec's authoritative file index rather than local file headers.

Design principle #4 in the yauzl README explicitly states a commitment to Robustness — the idea that malformed ZIP files should never crash the host application. As we demonstrate below, that guarantee does not hold in version 3.2.0.


The Vulnerability

How yauzl Parses ZIP Files

ZIP files have a two-part structure. Each file entry has a Local File Header near the compressed data, but the authoritative index lives in the Central Directory at the end of the archive. yauzl reads the Central Directory first to enumerate entries.

const yauzl = require('yauzl');

yauzl.open('archive.zip', { lazyEntries: true }, (err, zipfile) => {
  if (err) throw err;

  zipfile.readEntry();

  zipfile.on('entry', (entry) => {
    zipfile.openReadStream(entry, (err, readStream) => {
      if (err) throw err;
      readStream.pipe(someWritableDestination);
      readStream.on('end', () => zipfile.readEntry());
    });
  });

  zipfile.on('end', () => console.log('Done'));
});
Enter fullscreen mode Exit fullscreen mode

This is almost exactly the pattern shown in the official README — and the pattern most real-world consumers follow.

The Crash

A specially crafted ZIP file can embed a Central Directory entry where a critical numeric field contains an unexpected value that yauzl's parser does not defensively validate before using it in a downstream operation. When yauzl processes this entry, it passes the malformed value into a code path that does not guard against the anomaly, resulting in an unhandled exception thrown synchronously inside an asynchronous callback chain.

Because the exception is thrown outside a try/catch boundary and is not forwarded to the library's own error callback, the Node.js process receives an uncaught exception. Unless the host application has registered a global process.on('uncaughtException', ...) handler — which most production applications deliberately avoid — the process terminates immediately.

/path/to/node_modules/yauzl/index.js:NNN
  throw new Error("...");
        ^

Error: [internal yauzl error triggered by malformed field]
    at ...

Node.js process exited with code 1
Enter fullscreen mode Exit fullscreen mode

The exit is abrupt and immediate. No graceful shutdown, no error forwarded to the application, no opportunity to log, alert, or recover.

Why the Existing Safeguards Do Not Help

  • validateEntrySizes protects against decompression bombs — it checks during stream reading, not during Central Directory parsing, so it is never reached.
  • validateFileName checks for path traversal patterns in the file name field. The malformed field triggering this vulnerability is a different field entirely.
  • strictFileNames sanitizes file name characters. Unrelated to the affected field.

The vulnerability lives in parsing logic that runs before any of these guards are evaluated.


Impact Analysis

Who Is Affected

Any Node.js process that:

  1. Accepts ZIP files from untrusted or semi-trusted sources, and
  2. Opens them with yauzl.open() or yauzl.fromBuffer(), and
  3. Calls readEntry() to enumerate the archive contents

...is vulnerable to process termination via a single crafted upload.

Attack Scenario Exploitable? Notes
File upload endpoint (HTTP) Yes Single request terminates server process
CI/CD artifact ingestion Yes Poisoned build artifact crashes runner
VS Code extension installation Yes Crafted .vsix crashes extension host
Electron app auto-update Yes Malicious update payload crashes app
Email attachment processing Yes Triggered on message receipt
Offline ZIP processing No Attacker cannot supply the file

CVSS Snapshot

Metric Value
Attack Vector Network
Attack Complexity Low
Privileges Required None
User Interaction None (server-side) / Required (client-side)
Availability Impact High
Confidentiality Impact None
Integrity Impact None
Estimated CVSS Score 7.5 (High)

Remediation and Workarounds

Until an official patch is released:

1. Isolate ZIP Processing in a Child Process

const { fork } = require('child_process');

function safeExtract(zipPath, callback) {
  const worker = fork('./zip-worker.js', [zipPath]);
  worker.on('message', (msg) => callback(null, msg));
  worker.on('error', (err) => callback(err));
  worker.on('exit', (code) => {
    if (code !== 0) {
      callback(new Error(`ZIP worker exited with code ${code}`));
    }
  });
}
Enter fullscreen mode Exit fullscreen mode

By processing ZIP files in a forked child process, a crash terminates only the worker — not your main server.

2. Validate ZIP Files Before Processing

const ZIP_MAGIC = Buffer.from([0x50, 0x4b, 0x03, 0x04]);

function looksLikeZip(buffer) {
  return buffer.slice(0, 4).equals(ZIP_MAGIC);
}
Enter fullscreen mode Exit fullscreen mode

3. Ensure Process Supervision

Ensure your Node.js processes are managed by a process supervisor (PM2, systemd, Kubernetes) with automatic restart policies.

4. Consider Alternative Libraries

  • unzipper — actively maintained, streams-based
  • jszip — pure JavaScript, in-memory
  • adm-zip — synchronous API, different trade-offs

Key Takeaways

  1. "Robustness" guarantees require adversarial testing. Security properties need to be tested with fuzzers, not just stated in documentation.
  2. Unhandled exceptions in async callbacks are process-killers. Libraries processing untrusted data must wrap every parsing operation defensively.
  3. Process isolation is a practical defense. Handle untrusted file formats in a child process to contain the blast radius.
  4. Audit your dependency tree. Run npm ls yauzl to understand your exposure.
  5. ZIP is not a simple format. Treat ZIP ingestion with the same scrutiny you apply to SQL queries or HTML rendering.

Disclosure Timeline

Date Event
2026-02-XX Vulnerability discovered by CodeAnt AI Security Research
2026-02-XX Initial disclosure sent to yauzl maintainer
2026-03-12 Public disclosure
TBD Patch released

About CodeAnt AI

CodeAnt AI builds AI-powered code quality and security tools that help engineering teams ship safer software faster. Our security research team investigates vulnerabilities in widely used open-source libraries to help the broader developer community stay informed and protected.


Responsible disclosure is a core value at CodeAnt AI. We follow coordinated disclosure practices and work with maintainers to provide reasonable remediation timelines before public disclosure.

Top comments (0)