docling-project/docling · error · ValueError
Path traversal blocked: '{loc}' resolves outside base direct
Error message
Path traversal blocked: '{loc}' resolves outside base directory What it means
ValueError raised after resolving (base_dir / loc).resolve() when the result escapes base_dir (checked with Path.is_relative_to). It blocks '../' traversal: a relative image reference that walks out of the document's directory is rejected before any file read.
Source
Thrown at docling/backend/utils/image_resource_loader.py:151
abs_loc = loc
if base_path:
if loc.startswith("//"):
abs_loc = "https:" + loc
elif not loc.startswith(("http://", "https://", "data:", "#")):
if ImageResourceLoader.is_remote_url(base_path):
abs_loc = urljoin(base_path, loc)
elif ImageResourceLoader.is_local_path(base_path):
if ImageResourceLoader.is_absolute_path(loc):
raise ValueError(
f"Absolute paths are not allowed with local base_path: '{loc}'"
)
base_dir = Path(base_path).parent.resolve()
resolved_path = (base_dir / loc).resolve()
if not resolved_path.is_relative_to(base_dir):
raise ValueError(
f"Path traversal blocked: '{loc}' resolves outside base directory"
)
abs_loc = str(resolved_path)
else:
raise ValueError(f"Invalid base_path format: '{base_path}'")
_log.debug(f"Resolved location {loc} to {abs_loc}")
return abs_loc
def create_image_ref(
self, src_url: str, base_path: Optional[str]
) -> Optional[ImageRef]:
try:
img_data = self.load_image_data(src_url, base_path)
if img_data:
img = Image.open(BytesIO(img_data))
return ImageRef.from_pil(img, dpi=int(img.info.get("dpi", (72,))[0]))
except (View on GitHub (pinned to 61d76f1ff3)
Solutions
- Move/copy referenced assets under the document's directory (or a subdirectory of it) and fix the srcs.
- Set base_path to the true common root of documents and assets so traversal resolves inside it.
- For untrusted input, keep the guard and treat the hit as malicious content (log and skip the image).
Example fix
# before <img src="../../shared/logo.png"> # base_path='/data/clients/a/doc.html' -> blocked # after # copy logo.png under /data/clients/a/assets/ and use: <img src="assets/logo.png">
Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
base_dir = Path(base_path).parent.resolve()
candidate = (base_dir / loc).resolve()
if not candidate.is_relative_to(base_dir):
raise ValueError(f'{loc} escapes document directory') Try / catch
try:
loc = loader.resolve_relative_path(src, base)
except ValueError as e:
if 'Path traversal' in str(e):
log_security_event(src); loc = None
else:
raise Prevention
- Package assets inside the document's directory before conversion
- Set base_path to the true common root when assets legitimately live above the document
- Treat traversal hits in untrusted documents as malicious input
When it happens
Trigger: A document at /data/doc.html references <img src="../../etc/passwd.png"> or '../../../home/user/secret.png'; the resolved absolute path no longer sits under the parent of base_path, so the guard fires.
Common situations: Untrusted HTML with traversal payloads, symlinked relative targets, or legitimately-shared parent directories when documents are served from a nested folder but assets live above it.
Related errors
- Fetching local resources is only allowed when set explicitly
- Local file access requires base_path for directory confineme
- ZIP slip attempt: {info.filename}
- Access to restricted IP address not allowed: {ip}
- Absolute paths are not allowed with local base_path: '{loc}'
AI-assisted analysis of docling-project/docling@61d76f1ff3 (2026-08-14).
Data as JSON: /api/errors/03d2bdfe04df5c63.
Report an issue: GitHub.