The Safe, Deterministic
ZIP Engine

100 % TypeScript. Zero runtime dependencies. One API across Node ≥ 22, browsers, Deno, Bun and Workers — for modern apps and the agents that operate them.

Get Started → GitHub
CI status CodeQL security scan OpenSSF Scorecard npm version npm monthly downloads Minified + gzipped bundle size Zero runtime dependencies TypeScript strict mode 93.9 percent statement coverage npm provenance signed MIT License
npm install zipnative

1.0 — stable: the API surface, the 39-code error vocabulary and the deterministic bytes are frozen under semver.

385+
Tests
93.9%
Coverage
0
Dependencies
6
Foreign interop tools
39
Frozen error codes
GitHub Stars

What only zipnative does

Not a faster deflate — a safer, reproducible, streaming archive engine built for scenarios the incumbents cannot do.

Random access

Read one entry of a 4 GB archive with three range reads — the central directory is parsed lazily, payloads are zero-copy views. No “extract everything first”.

Safe by default

Zip-slip, symlinks, duplicate names, decompression bombs, overlapping entries, Zip64 spoofing and EOCD ambiguity are all rejected unless you explicitly opt out. Every parser loop runs under a named, CWE-tagged bound.

Deterministic

Reproducible-build mode with a written contract: identical inputs, identical SHA-256, on every runtime — via a pure-TS deflate encoder whose constants are frozen public API.

Incremental modification

Replace, add, remove or rename entries and save without recompressing the untouched 99 % — the append-only model proven in pdfnative's PDF incremental updates.

True streaming

Create archives in fixed-size chunks with bounded memory, and read unseekable streams forward — data-descriptor entries included, thanks to a resumable pure-TS inflater.

Worker parallelism

zipnative/worker fans per-entry compression across a real pool (worker_threads and Web Workers) — byte-identical output, graceful degradation, never an infra failure.

Ninety seconds of API

Sync-first, no classes, every error carries a stable machine-readable code.

import { openZip, extractZip } from 'zipnative';

const zip = openZip(bytes);              // lazy — nothing decompressed
const manifest = zip.readEntry('manifest.json'); // one entry, CRC-verified

const files = extractZip(bytes);         // traversal/bombs rejected by default
import { createZip } from 'zipnative';

const zip = createZip({ compression: { deterministic: true } });
zip.add('data.json', payload);
const bytes = zip.toBytes();             // same inputs → same SHA-256, anywhere
import { createZipModifier, openZip } from 'zipnative';

const mod = createZipModifier(openZip(bytes));
mod.replaceEntry('word/document.xml', updated);
const saved = mod.save();                // untouched entries never recompressed

Full quickstart →

The honest comparison

fflate keeps the raw-deflate crown and we do not chase it — zipnative wins on scenarios, not drag races.

Compared 2026-09-01 against fflate 0.8.x, jszip 3.10.x, yauzl/yazl, adm-zip 0.6.x.
zipnativefflatejszipyauzl/yazladm-zip
Zero runtime dependencies
Random access (1 entry, no full parse)yauzl
Streaming read + writepartialone per lib
Safe-extract defaults (slip/bomb/ambiguity)DIYDIYDIYhistorical CVEs
Deterministic output (written contract)DIY
Modify in place, no recompressionrewrite-allpartial
Stable machine-readable error codes
Browser + Node + Deno + Bun + WorkersNode-onlyNode-only
Raw deflate throughputgood (platform zlib)bestslowgoodpoor

Benchmarks

Measured scenarios, security checks always on — including the one we lose.

Create 1000 small entries (deflate) — fflate's home turf
fflate
15.2 op/s
adm-zip
14.3 op/s
zipnative
7.2 op/s
jszip
5.4 op/s
Inventory a 10 000-entry archive (no decompression)
zipnative
fastest
fflate
1.25×
jszip
3.39×
adm-zip
14.8×
Random access: read 1 entry out of 10 000
zipnative
fastest
fflate
1.04×
jszip
3.37×
adm-zip
11.8×

Windows 11, Node v22.17, tiny-entry corpus — the worst case for the random-access rows (with megabyte entries the gap becomes orders of magnitude). zipnative numbers include the always-on security checks. Full methodology: bench/RESULTS.md.

Security model

Every archive is untrusted input; the default code path is the safe one.

Extraction refuses traversal (../, absolute paths, drive letters, NTFS streams), symlink entries and bombs; the reader refuses overlapping entries, parser-differential headers and ambiguous end-of-central-directory records. Bounds are named, CWE-tagged, documented and caller-configurable — raising one is always an explicit decision. Every refusal throws a stable machine-readable error code.

Read the full threat model

Determinism as a contract

Identical inputs, identical SHA-256 — on any runtime.

compression: { deterministic: true } pins the pure-TS encoder: the mode for content addressing, caching, signatures and reproducible builds. The contract is written down and golden-tested; changing the emitted bytes is a semver-major event.

Read the determinism contract

Architecture

Five strict layers, one direction of imports, zero reverse edges — and one write path with two byte-identical consumers.

Built for AI agents

Machine-readable ground truth at every level — never guessed, always verified.

Stable error codes (errors.json), a structured diagnostics channel, executable recipes, and the mechanically extracted export surface in api.json — plus llms.txt and llms-full.txt for context ingestion, with byte and approximate token budgets for every artefact in llms-index.json so an agent can decide what to fetch before spending the tokens. Developed under a human-in-the-loop AI governance policy.

Agent brief →

Origin

zipnative is the sibling of pdfnative: the same doctrine — zero dependencies, closure factories, strict layers, sync-first, security by default — applied to the ZIP format. The incremental-update model, the AI governance policy and this documentation pipeline were extracted from pdfnative and hardened here.