
A Proof-of-Concept for CVE-2025-64512 using a polyglot file.
In the last weeks (in November 2025), an interesting vulnerability (CVE-2025-64512) was disclosed in pdfminer.six, a popular Python project to process PDF files, used in particular in AI pipelines. The vulnerability enables remote code execution by deserializing untrusted data via pickle.loads(), utilizing a PDF file as an attack vector. So far, so good: it's an important vulnerability in a popular Python package. What caught my attention was the exploitability 👀.
On Linux-like systems only files on the filesystem can be resolved. An attacker would need to provide the malicious PDF for processing and the malicious pickle file would need to be present on the target system in a location that the attacker already knows, since it needs to be set in the PDF itself. In many cases this will be difficult to exploit because even if the attacker provides both the PDF and the pickle file together, there would be no way to know in advance which full path to the pickle file to specify. [...] Overall, there is generally less risk on a Linux or Linux-like system.
So, apparently, for exploiting this vulnerability on a Linux-like system, the attacker should:
Can we create a valid PDF file that triggers the vulnerability without knowing the filepath of the malicious pickle file?
"Valid" means pdfminer.six doesn't refuse the file and starts to process it (because a PDF file is what a PDF reader opens).
The answer is Yes, creating a polyglot payload (a sort of). The idea is to create a file that is both a valid pickle.gz and a valid PDF file, so that pdf2txt.py can start to process a PDF file and then point to it to load the pickle code in GZIP format.
Often - but not always 🥲 - a file is a PDF file if it has %PDF- somewhere, in general in the first 1024 bytes (1 - 2). For pdfminer.six, a valid PDF file just must have a /Root object (pdfdocument.py#L752).
A GZIP file has specific initial bytes (RFC 1952 - Sec. 2.3.1), but it supports comments (FCOMMENT, RFC 1952 - Sec. 2.3.1).
So, this is the polyglot file design: create a valid GZIP containing the malicious pickle payload, and embed a valid PDF file in the GZIP FCOMMENT flag. Then use this file as a valid PDF with pdf2txt.py to trigger the vulnerability, and use the same file to execute the malicious pickle.
(2025.12.12) EDIT:
The only constraint we have is the filename: it must end with .pickle.gz (this is embedded in .pdfminer.six code, cmapdb.py#L235)
The two constraints we have are:
pdfminer.six code, cmapdb.py#L235);I am a little surprised this CVE is so underrated, considering the popularity of this project (6k ⭐️ on GitHub, but used by 34k projects, according to GitHub stats) and the use cases (command-line tools, AI workflows, pipelines, in short, all the kinds of infrastructure you don't want to update if they work fine).
For example, the Microsoft tool markitdown 0.1.3 (microsoft/markitdown, 84k ⭐️ on GitHub and used by 2k projects), installed before December 1st, is vulnerable to arbitrary code execution via pdfminer.six. Microsoft team released a patch on 1st December, 0.1.4, but no security alerts, so I don't think the update has been prioritized by other engineering teams.
Other projects could be affected by CVE-2025-64512, and it is quite easy to exploit.
An (incomplete) list of vulnerable projects:
docker build -t cve-2025-64512-poc .
docker run --rm -it cve-2025-64512-poc
pdf2txt.py payload.pickle.gz
docker build -t cve-2025-64512-poc .
docker run --rm -it cve-2025-64512-poc
markitdown markitdown-payload.pickle.gz -x pdf -o output.md
