← Reports xaferima.com Español →

XRef tables bypass configured limits

DoS CVSS 6.5 MEDIUM CWE-770: Allocation of Resources Without Limits pdfcpu/pdfcpu ≤ v0.15.0

GHSA-fjh6-rrhv-4g63 · CVE assignment pending

Summary

pdfcpu enforces configured cross-reference resource limits (MaxObjectCount, MaxXRefEntries) when parsing XRef streams (PDF 1.5+), but the legacy code path for traditional XRef tables (PDF 1.4 and earlier) never validates the subsection object count. A crafted PDF declaring a huge objCount with matching entries forces the cross-reference map to grow without bound, exhausting process memory and crashing any host application.

Impact

Root Cause

In pkg/pdfcpu/read.go, parseXRefTableSubSection() reads the subsection object count with strconv.Atoi and never checks it against the configured limits. Each valid xref entry then inserts into the cross-reference map, which grows unbounded:

// pkg/pdfcpu/read.go:445 — no limit check
objCount, err := strconv.Atoi(fields[1])

// read.go:424 — every entry grows the map
xRefTable.Table[objNr] = &entry

By contrast, XRef streams enforce MaxObjectCount = 10M in xRefStreamSize() (model/parse.go) — the traditional-table path simply lacks the equivalent check.

Proof of Concept

A crafted PDF with a traditional XRef table:

xref
0 100000000        ← objCount = 100M, never validated
0000000000 65535 f
0000000010 00000 n
...                ← attacker supplies matching entries
trailer << /Size 100000001 /Root 1 0 R >>

Each ~30-byte entry creates a map entry costing ~128 bytes of Go map overhead. 100M entries → multi-GB memory growth → OOM kill. Mitigating constraints: the loop stops on the first line without 3 fields, and the attacker must provide enough well-formed entries to match objCount, so the attack requires a large (GB-scale) file — but memory amplification is roughly 4×.

Disclosure Timeline

DateEvent
2026-09-18Report submitted via GitHub Private Vulnerability Reporting
2026-09-18Accepted by maintainer; retitled "Traditional cross-reference tables bypass configured XRef limits"
2026-09-28Advisory published — GHSA-fjh6-rrhv-4g63
Fixed inpdfcpu v0.16.0

Fix

Validate objCount against MaxObjectCount on the traditional-table path, mirroring the XRef-stream enforcement:

// After (safe):
objCount, err := strconv.Atoi(fields[1])
if err != nil {
    return "", err
}
if objCount > limits.MaxObjectCount {
    return "", fmt.Errorf("xref subsection objCount %d exceeds limit %d",
        objCount, limits.MaxObjectCount)
}

Fixed in pdfcpu v0.16.0. Advisory published 2026-09-28; CVE assignment pending.

← Back to all reports