Docling: Arbitrary local file read via draw:image xlink:href in the OpenDocument backend
MediumCVE-2026-105751 · Published Oct 5, 2026
## Summary The ODF backend resolves the `xlink:href` of a `draw:image` element as a filesystem path whenever the referenced part is not found inside the document archive. The value comes straight from `content.xml`, so it is document content, and it is used with no scheme check, no confinement to the extraction directory, and without consulting the `enable_local_fetch` / `enable_remote_fetch` controls that the other backends use for exactly this decision. Converting a crafted `.odt` therefore causes Docling to open an attacker-named absolute path on the converting host. Where the target decodes as an image, its complete contents are embedded in the resulting `DoclingDocument` and appear in the HTML, Markdown and JSON exports. Both the read and the disclosure are confirmed by execution. The trigger is a 452-byte archive containing two entries. ## Affected component `docling/backend/opendocument_backend.py`, in `_image_ref_from_odf_image`: ```python image_url = _odf_image_href(image) ... if image_data is None and odf_obj is not None and image_url: try: image_data = odf_obj.get_part(image_url) except Exception: image_data = None if image_data is None and...
Affected versions
| Package | Affected | Fixed in |
|---|---|---|
| docling PyPI | >= 2.107.0, < 2.120.3 | 2.120.3 |
Details and references
## Summary The ODF backend resolves the `xlink:href` of a `draw:image` element as a filesystem path whenever the referenced part is not found inside the document archive. The value comes straight from `content.xml`, so it is document content, and it is used with no scheme check, no confinement to the extraction directory, and without consulting the `enable_local_fetch` / `enable_remote_fetch` controls that the other backends use for exactly this decision. Converting a crafted `.odt` therefore causes Docling to open an attacker-named absolute path on the converting host. Where the target decodes as an image, its complete contents are embedded in the resulting `DoclingDocument` and appear in the HTML, Markdown and JSON exports. Both the read and the disclosure are confirmed by execution. The trigger is a 452-byte archive containing two entries. ## Affected component `docling/backend/opendocument_backend.py`, in `_image_ref_from_odf_image`: ```python image_url = _odf_image_href(image) ... if image_data is None and odf_obj is not None and image_url: try: image_data = odf_obj.get_part(image_url) except Exception: image_data = None if image_data is None and image_url: image_path = Path(image_url) if image_path.is_file(): image_data = image_path.read_bytes() ``` `_odf_image_href` returns the `xlink:href` attribute. The in-archive lookup is attempted first; when it fails, the same string is handed to `Path` and read from disk. The only filter on the way in is `_odf_image_can_be_bitmap`, which admits any path whose suffix is one of `.bmp`, `.gif`, `.jpeg`, `.jpg`, `.png`, `.tif`, `.tiff`, `.webp`, **or empty**. The empty-suffix case is what admits most paths of interest on a Unix host, `/etc/passwd` among them. ### The backend does not use the project's own fetch controls ``` $ grep -n "enable_local_fetch\|enable_remote_fetch\|image_resource_loader" \ docling/backend/opendocument_backend.py $ ``` Nothing. The HTML, Markdown, EPUB and XBRL backends all resolve image resources through `docling/backend/utils/image_resource_loader.py`, where `enable_local_fetch` and `enable_remote_fetch` both default to `False`. The ODF backend reimplements image loading and does not consult either, so the default of not fetching local resources is not applied on this path. That is the substance of the report: the control exists, it is off by default, and this backend does not reach it. ## Affected versions Introduced by commit `e2afe381`, "feat: Add OpenDocument backend support and improve ODF image/table handling" (#3480), 2026-06-24. First released in **v2.107.0**. **Affected: `docling` >= 2.107.0, up to and including 2.117.0 and current `main` (`52d8a6f24de7318a9ad4be2a7361ba93fc81a5c1`).** Subsequent commits touching this file , `2c3e55b3` (skip a `draw:object` with a missing embedded part), `b627ca91` (preserve content inside sections), `2ec33bc7` (guard backend imports) , address unrelated defects and leave the path resolution unchanged. Reproduced on two independent machines: | | | |---|---| | Python 3.12.3 | `docling-slim` 2.117.0, `docling-core` 2.88.0, `odfdo` 3.23.1 | | Python 3.14.4 | same releases, and again against `main` clones on `sys.path` | ## Proof of concept ### Trigger An `.odt` needs only `mimetype` and `content.xml`. No manifest, no styles, no embedded image part. ```python import zipfile CONTENT = ( '<?xml version="1.0"?><office:document-content ' 'xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" ' 'xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" ' 'xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" ' 'xmlns:xlink="http://www.w3.org/1999/xlink" office:version="1.2">' '<office:body><office:text><text:p>' '<draw:frame><draw:image xlink:href="{href}"/></draw:frame>' '</text:p></office:text></office:body></office:document-content>' ) def build(path, href): with zipf
- CVSS 4.0
- CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:H/VI:N/VA:N/SC:L/SI:N/SA:N
- Severity from
- GitHub (reviewed advisory)
- Weakness
- CWE-22
- Also known as
- CVE-2026-105751
More docling advisories
All docling| Date | Advisory | Severity | Fixed in |
|---|---|---|---|
| Oct 6 | Docling: `enable_local_fetch` is not enforced in HTML browser-rendering mode | Medium5.9 | 2.118.1 |
| Jun 3 | Docling: Unsafe URI and Path Handling in HTML Backend | High7.1 | 2.94.0 |
| Jun 3 | Docling: Potential Path Traversal via LaTeX \includegraphics and \input Commands | Medium5.5 | 2.91.0 |
| Jun 3 | Docling: Unsafe XML Entity Expansion in USPTO Patent Backend | High7.5 | 2.74.0 |
| Jun 3 | Docling: Unsafe Archive Extraction and XML Parsing in METS-GBS Backend | Medium5.5 | 2.91.0 |
| Jun 3 | Docling: Unsafe Playwright-based HTML Rendering | High8.2 | 2.91.0 |