PoC Archive PoC Archive
High CVE-2026-24009 unpatched

docling-core Unsafe YAML Deserialization Leading to Code Execution — CVE-2026-24009

by Biran Perez (BiranPeretz) · 2026-07-05

Severity
High
CVE
CVE-2026-24009
Category
misc
Affected product
docling-core (Python library)
Affected versions
docling-core >= 2.21.0 and < 2.48.4, combined with PyYAML < 5.4
Disclosed
2026-07-05
Patch status
unpatched

Metadata

FieldValue
Date Added2026-07-05
Last Updated2026-02
Author / ResearcherBiran Perez (BiranPeretz)
CVE / AdvisoryCVE-2026-24009
Categorymisc
SeverityHigh
CVSS ScoreNot specified in source
StatusPoC
Tagsdocling-core, yaml-deserialization, pyyaml, unsafe-loader, rce, python, cwe-502
RelatedN/A

Affected Target

FieldValue
Software / Systemdocling-core (Python library)
Versions Affecteddocling-core >= 2.21.0 and < 2.48.4, combined with PyYAML < 5.4
Language / PlatformPython
Authentication RequiredNo (depends on how the host application exposes YAML loading)
Network Access RequiredNo (local file / library-level PoC; exploitability depends on the consuming application)

Summary

docling-core’s DoclingDocument.load_from_yaml() deserializes YAML using yaml.load(f, Loader=yaml.FullLoader) rather than a safe loader. When paired with a vulnerable PyYAML version (< 5.4, related to CVE-2020-14343), a crafted YAML document can trigger code execution during parsing, before any DoclingDocument schema validation even runs. The repository provides check_loader.py to confirm which loader a given docling-core version uses, repro_docling_load.py to actually trigger execution via a malicious YAML payload (malicious.yaml), and a scanner/ helper to check whether an installed environment’s resolved dependency versions fall into the vulnerable range. The fix is to upgrade docling-core to >= 2.48.4 (which switches to yaml.SafeLoader) or upgrade PyYAML to >= 5.4.


Vulnerability Details

Root Cause

DoclingDocument.load_from_yaml() uses PyYAML’s yaml.FullLoader instead of yaml.SafeLoader; combined with a PyYAML version still affected by CVE-2020-14343-era unsafe constructor behavior, attacker-controlled YAML can instantiate arbitrary Python objects/constructors during deserialization.

Attack Vector

  1. Identify an application that calls docling_core.DoclingDocument.load_from_yaml() on untrusted/attacker-supplied YAML input, running a vulnerable docling-core + PyYAML combination.
  2. Craft a malicious YAML document (see malicious.yaml) containing a YAML tag/constructor payload that executes code as a side effect of parsing.
  3. Supply the YAML to load_from_yaml(); code execution occurs during the yaml.load() call, before Pydantic schema validation of the resulting DoclingDocument can reject the malformed structure.
  4. Confirm execution via a side effect (the PoC creates a marker file at /tmp/docling_cve_poc_marker).

Impact

Arbitrary code execution in the context of the process parsing the YAML, if an application passes untrusted YAML to load_from_yaml() while running the vulnerable dependency combination.


Environment / Lab Setup

Target:   docling-core==2.48.3 + PyYAML==5.3.1, Python 3.12 on Ubuntu 24.04
Attacker: Python 3 virtualenv, pip

Proof of Concept

PoC Script

See repro_docling_load.py, check_loader.py, malicious.yaml, and scanner/scan_cve_2026_24009.py in this folder.

1
2
3
4
python3 -m venv .venv && source .venv/bin/activate
pip install "docling-core==2.48.3" "PyYAML==5.3.1"
python check_loader.py
python repro_docling_load.py

check_loader.py prints which YAML loader load_from_yaml() resolves to; repro_docling_load.py loads the crafted malicious.yaml payload, raises an expected ValidationError from Pydantic, but still leaves behind /tmp/docling_cve_poc_marker, proving code executed during parsing before validation failed. scanner/scan_cve_2026_24009.py performs a dependency-based check for the vulnerable version combination in an environment.


Detection & Indicators of Compromise

/tmp/docling_cve_poc_marker created without corresponding legitimate action

Signs of compromise:

  • Unexpected marker files, spawned subprocesses, or network connections occurring during document/YAML ingestion.
  • Application logs showing ValidationError from DoclingDocument.model_validate() immediately following YAML load calls, especially from unexpected/attacker-supplied sources.
  • Presence of docling-core < 2.48.4 combined with PyYAML < 5.4 in dependency lockfiles.

Remediation

ActionDetail
Primary fixUpgrade docling-core to >= 2.48.4 (switches to yaml.SafeLoader).
Interim mitigationUpgrade PyYAML to >= 5.4, or avoid calling load_from_yaml() on untrusted YAML; enforce yaml.SafeLoader explicitly when deserializing untrusted input.

References


Notes

Mirrored from https://github.com/BiranPeretz/docling-core-CVE-2026-24009 on 2026-07-05.

check_loader.py
1
2
3
4
5
6
7
8
import yaml
from docling_core.types.doc import DoclingDocument
import inspect

print("PyYAML version:", yaml.__version__)
print("Method signature:", inspect.signature(DoclingDocument.load_from_yaml))
print("\nload_from_yaml source:\n")
print(inspect.getsource(DoclingDocument.load_from_yaml))