lopdf has a stack overflow via deeply nested PDF objects
GHSA-6fj4-rcr3-r7rr · RUSTSEC-2026-0187 · published 21 Jun 2026
How serious is it
- Severity: high, CVSS score 7.5 out of 10.
- No exploit prediction (EPSS) score yet.
- Not on the CISA list of exploited vulnerabilities.
- No public exploit in Exploit-DB.
Is your app affected by GHSA-6fj4-rcr3-r7rr?
Paste this prompt into Claude Code, Cursor or any AI coding tool: it runs a free Shippable scan of your project and fixes what it finds. Built with Lovable, Bolt or v0? Scan your live app. Or upload your package file.
Who is affected
lopdf(crates.io) < 0.42.0
How to check
- Run
cargo tree -i lopdfin your project to see the installed version, including copies pulled in by other packages. - Or paste your lockfile into the checker: it lists every package with a known vulnerability, this one included.
How to fix
Copies a prompt for Claude Code, Cursor or Codex: it checks your lockfiles for this and upgrades it.
- Upgrade
lopdfto 0.42.0 or later, commit the lockfile and redeploy. - If a vulnerable version was live, check your logs and rotate the secrets that server could read.
The advisory
`lopdf::Document::load_mem` (and the other `load*` entry points) parses nested PDF arrays and dictionaries with unbounded recursion. A small crafted PDF whose Catalog contains a deeply nested array (`/X [[[ … ]]]`, on the order of 10,000 levels) exhausts the call stack and aborts the process with `SIGABRT`.
Because this is a stack-overflow abort rather than a `panic!`, it cannot be caught with `catch_unwind`: any service that parses untrusted PDF input with lopdf can be crashed by a ~21 KB file, resulting in a denial of service.
Confirmed on lopdf 0.41.0 and earlier; fixed in 0.42.0. Default configuration, no features changed.
## Proof of concept
```rust
fn main() {
let bytes = std::fs::read("poc.pdf").unwrap(); // ~10,380-deep nested array in the Catalog
let _ = lopdf::Document::load_mem(&bytes); // stack overflow -> SIGABRT
}
```
An equivalent PoC is a minimal PDF whose Catalog `/X` value is `"[" * 10380 + "]" * 10380`.
## Suggested fix
Enforce a maximum object-nesting depth in the parser and return an `Err` instead of recursing without bound.
Check your whole app
Dependencies are only half of it. Free and read-only: before you push, run npx shippable-dev scan localhost:3000 in your project folder, no account needed. For your live app, you prove it's yours with a one-line tag first.
References
- github.com/J-F-Liu/lopdf/issues/502
- github.com/J-F-Liu/lopdf/pull/503
- github.com/J-F-Liu/lopdf/commit/c755394ad7dd651ccfe77c618f90ab779da1dfd9
- rustsec.org/advisories/RUSTSEC-2026-0187.html
- github.com/advisories/GHSA-6fj4-rcr3-r7rr
- crates.io/crates/lopdf
- github.com/J-F-Liu/lopdf/commit/c755394
- github.com/J-F-Liu/lopdf
Merged from GitHub Advisory Database, OSV. Last updated 23 Oct 2026. All vulnerabilities · RSS · JSON