
Technical write-up and PoC for CVE-2026-24009, demonstrating unsafe YAML loading in docling-core and practical mitigation paths.
This repo contains a proof-of-concept (PoC) and a simple scanner demonstrating CVE-2026-24009, where docling-core can enable code execution when loading attacker-controlled YAML under specific dependency conditions.
Impact: potential RCE during YAML parsing Vulnerable chain (all required):
docling-core >= 2.21.0 and < 2.48.4PyYAML < 5.4 (upstream behavior associated with CVE-2020-14343)DoclingDocument.load_from_yaml(...) on untrusted YAMLFix: upgrade docling-core to >= 2.48.4 (switches to yaml.SafeLoader)
upgrade to
PyYAMLDoclingDocument.load_from_yaml() deserializes a YAML-serialized DoclingDocument. In vulnerable versions, it loads YAML using an unsafe loader (yaml.FullLoader) when PyYAML is vulnerable, allowing malicious YAML constructors to execute code during parsing (see CVE-2020-14343 for more information).
docling-core: 2.48.3 (vulnerable)PyYAML: 5.3.1 (vulnerable)python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install "docling-core==2.48.3" "PyYAML==5.3.1"
Run:
python check_loader.py
In vulnerable versions, load_from_yaml() uses:
data = yaml.load(f, Loader=yaml.FullLoader)
python repro_docling_load.py
Expected behavior:
repro_docling_load.py raises a ValidationError (expected)/tmp/docling_cve_poc_markerThis demonstrates execution occurred during YAML parsing, before DoclingDocument.model_validate(...) fails.
docling-core (recommended)python -m pip install --upgrade "docling-core==2.48.4"
python check_loader.py
python repro_docling_load.py
Expected:
check_loader.py shows yaml.SafeLoaderPyYAMLUpgrading PyYAML to >= 5.4 mitigates the upstream behavior associated with CVE-2020-14343.
If upgrading is not possible, avoid loading untrusted YAML with unsafe loaders. Enforce yaml.SafeLoader when deserializing untrusted YAML.
docling exposure (dependency mapping)While this CVE is in docling-core, the most common consumer is docling. A broad dependency range in docling does not prove vulnerability by itself; what matters is the resolved environment (lockfiles / installed packages) and whether YAML import paths are used.
This repo includes collect_versions.py, which maps:
docling-core constraints from pyproject.tomldocling-core versions from uv.lock (or poetry.lock in older tags)From the extracted data, the potentially vulnerable docling versions (constraint allows vulnerable + lock pins vulnerable) are:
>= v2.27.0 and <= v2.57.0This is a dependency-resolution indicator, not a proof that default
doclingworkflows reachload_from_yaml()on untrusted input.
repro_docling_load.py — minimal PoC runnercheck_loader.py — prints the YAML loader used by load_from_yaml()scanner/ — a simple dependency-based scanner (optional direct sink check)collect_versions.py — helper to map docling tags to pinned docling-core versions