Integer overflow in XRef stream /W array
GHSA-w2hj-54mc-76r4 · CVE assignment pending
Summary
An integer overflow in the cross-reference stream /W array sum calculation allows any unauthenticated attacker to crash any application using pdfcpu by providing a crafted PDF file. The overflow produces a small positive entry length that bypasses the modulo integrity check, after which out-of-bounds slice reads trigger an unrecovered panic: runtime error: slice bounds out of range. The panic escapes the public API and kills the host process.
Impact
- Denial of Service — unrecovered runtime panic terminates the process.
- Attack vector: network — malicious PDF via upload, email attachment, or any processing pipeline.
- No authentication required; user interaction limited to the victim processing the file.
- Scope: any application embedding pdfcpu (CLI, HTTP services, libraries) and downstream Go projects.
Root Cause
In pkg/pdfcpu/read.go, extractXRefTableEntriesFromXRefStream() computes the cross-reference entry length by summing three attacker-controlled values from the /W array with no overflow check:
// pkg/pdfcpu/read.go:710
i1 := xsd.W[0]
i2 := xsd.W[1]
i3 := xsd.W[2]
xrefEntryLen := i1 + i2 + i3 // ← no overflow check
The values are validated only for non-negativity at parse time (pkg/pdfcpu/model/parse.go). When the sum overflows int64 to a small positive value (e.g. 1), the modulo validation passes but the individual W values remain huge, so later slice operations read far beyond the buffer:
// read.go:763-766 — bufToInt64(buf[i : i+i1]) with i1 ≈ 6.1e18
Proof of Concept
Craft an XRef stream whose /W values overflow when summed:
W = [6148914691236517205, 6148914691236517205, 6148914691236517207]
mathematical sum: 18446744073709551617
int64 overflow: 1 → passes modulo check
actual slices: buf[i : i+6148914691236517205] → PANIC
Confirmed with a unit test against the vulnerable function:
=== RUN TestXRefWArrayOverflow/overflow_to_one
PANIC: runtime error: slice bounds out of range
[:6148914691236517205] with capacity 3
A minimal PDF embedding such an XRef stream crashes pdfcpu validate, pdfcpu merge, and any api.ReadContext() call on the file.
Disclosure Timeline
| Date | Event |
|---|---|
| 2026-09-13 | Report submitted via GitHub Private Vulnerability Reporting |
| 2026-09-14 | Accepted by maintainer (hhrutter) |
| 2026-09-28 | Advisory published — GHSA-w2hj-54mc-76r4 |
| Fixed in | pdfcpu v0.16.0 |
Fix
Use the codebase's existing safemath.AddInt for the W array sum and reject overflows:
// After (safe):
xrefEntryLen, err := safemath.AddInt(i1, i2)
if err != nil {
return errInvalidXRefStreamWArray
}
xrefEntryLen, err = safemath.AddInt(xrefEntryLen, i3)
if err != nil {
return errInvalidXRefStreamWArray
}
Fixed in pdfcpu v0.16.0. Advisory published 2026-09-28; CVE assignment pending.