MEDIUM SEVERITYCONFIRMED
resolve_source_to_stream() reads arbitrary OS paths — no base-directory guard
Package
docling-core
Version
HEAD
Verified
2026-03-28
Description
docling-core's `resolve_source_to_stream()` and `resolve_file_source()` in `docling_core/utils/file.py` cast any non-URL string directly to `pathlib.Path` and call `.read_bytes()` with no path restriction. There is no `Path.resolve()` call, no base-directory containment check, and no symlink resolution. If user-controlled input flows into this function (e.g., from a document ingestion API), an attacker can read arbitrary files on the server.
Reproduction
from docling_core.utils.file import resolve_source_to_stream
# If the target file exists and is readable:
stream = resolve_source_to_stream('../../etc/passwd')
# Returns the file contents as a BytesIO stream — no error raised