CSIRTS // UNIFIED SECURITY ADVISORY FEEDSYS ● ONLINE · POWERED BY INTELFUSIONS.COM

GHSA-m8gf-v64p-gfmg: BabelDOC: Arbitrary Code Execution via CMap Pickle Deserialization in babeldoc/pdfminer/cmapdb.py

highCVSS 7.8CVE-2026-54071
Arbitrary Code Execution via CMap Pickle Deserialization in babeldoc/pdfminer/cmapdb.py Summary BabelDOC's vendored PDF parser (babeldoc/pdfminer/cmapdb.py) deserializes untrusted pickle data when loading CMap files. The _load_data() method strips only NUL bytes from a PDF-controlled CMap name, then passes it directly to os.path.join() and pickle.loads(). Because Python's os.path.join() discards all preceding path components when it encounters an absolute path segment, an attacker who embeds a hex-encoded absolute path in a crafted PDF's /Encoding name (e.g., /#2Ftmp#2Fattacker#2Fevil) can redirect deserialization to any attacker-writable .pickle.gz file on the local system. Processing such a PDF results in arbitrary Python code execution with the privileges of the BabelDOC process. Details The vulnerable function is CMapDB._load_data() at babeldoc/pdfminer/cmapdb.py:232–245: @classmethod def _load_data(cls, name: str) -> Any: name = name.replace("\0", "") # line 233 — only NUL is stripped filename = "%s.pickle.gz" % name # line 234 — attacker-controlled string ... for directory in cmap_paths: path = os.path.join(directory, filename) # line 241 — no realpath/canonical check if os.path.exists(path): gzfile = gzip.open(path) try: return type(str(name), (), pickle.loads(gzfile.read())) # line 245 — unconditional pickle Path injection via PDF name hex-encoding. The PDF specification allows name objects to encode arbitrary bytes as #xx. The pdfminer literal-name parser (psparser._parse_literal_hex) decodes these sequences before handing the string to higher layers. Consequently, the PDF literal /#2Ftmp#2Fattacker#2Fevil is decoded to the Python string /tmp/attacker/evil. Python os.path.join() absolute-path override. When the decoded name starts with / (i.e., it is an absolute path), Python's os.path.join(directory, name + ".pickle.gz") ignores directory entirely and returns the absolute path unchanged. The trusted cmap_paths directories (/usr/share/pdfminer/, the

Details

Source
GitHub Security Advisories (INTL · database · site)
Severity
high — CVSS 7.8
Published
2026-07-10
Last updated
2026-07-10
Exploitation
Not in CISA KEV at last sync

Original advisory: https://github.com/advisories/GHSA-m8gf-v64p-gfmg

Referenced CVEs

CVECSIRTS overviewExternal
CVE-2026-54071coverage & exploitation statusNVD · CVE.org

More from GitHub Security Advisories