docling-project/docling · error · ArtifactDownloadError

Resource bundle contains an unsafe path: {member!r}

Error message

Resource bundle contains an unsafe path: {member!r}

What it means

Raised as ArtifactDownloadError when extracting a downloaded resource bundle ZIP: one of its member paths (e.g. '../../etc/passwd') would resolve outside the extraction directory. This is a zip-slip containment guard applied even though bundles nominally come from the trusted docling-serve service. Per the exception docstring it is normally caught internally and surfaced as a FAILURE ConversionResult rather than propagated.

Source

Thrown at docling/service_client/client.py:1796

            except zipfile.BadZipFile as exc:
                raise ArtifactDownloadError(
                    f"Downloaded resource bundle is not a valid ZIP: {exc}"
                ) from exc
            json_path = self._find_bundle_json(base_dir)
            document = DoclingDocument.load_from_json(json_path)
            # Embed while the extracted artifacts are still on disk, then let the
            # temp dir be removed: the returned document is fully in-memory.
            self._embed_referenced_images(document, base_dir)
            return document

    @staticmethod
    def _safe_extract_zip(bundle_zip: zipfile.ZipFile, base_dir: Path) -> None:
        # Guard against zip-slip even though bundles originate from our service.
        base_resolved = base_dir.resolve()
        for member in bundle_zip.namelist():
            target = (base_dir / member).resolve()
            if target != base_resolved and base_resolved not in target.parents:
                raise ArtifactDownloadError(
                    f"Resource bundle contains an unsafe path: {member!r}"
                )
        bundle_zip.extractall(base_dir)

    @staticmethod
    def _find_bundle_json(base_dir: Path) -> Path:
        # The server writes the document files at the bundle root and the
        # referenced images under artifacts/, so the document JSON is the
        # top-level *.json file.
        candidates = sorted(base_dir.glob("*.json"))
        if not candidates:
            raise ArtifactDownloadError(
                "Resource bundle does not contain a top-level JSON document."
            )
        return candidates[0]

    def _embed_referenced_images(
        self, document: DoclingDocument, base_dir: Path

View on GitHub (pinned to 61d76f1ff3)

Solutions

  1. Check the resulting ConversionResult.status/errors — the failure is attached to that document's result, and other documents in the batch still succeed
  2. Verify the docling-serve deployment version and that the artifact store is not tampering with bundle contents
  3. If images are not needed, request images='embedded' or omit image export so no bundle ZIP is downloaded

Example fix

// before
result = client.convert(Path('doc.pdf'), options=options_with_referenced_images)

// after (inspect per-document result instead of expecting an exception)
results = list(client.convert_all([Path('doc.pdf')], options=options))
for res in results:
    if res.status == ConversionStatus.FAILURE:
        print(res.errors)  # ArtifactDownloadError details appear here
Defensive patterns

Strategy: try-catch

Type guard

def is_artifact_download_error(exc: BaseException) -> bool:
    return isinstance(exc, ArtifactDownloadError)

Try / catch

try:
    results = list(client.convert_all(sources))
except ArtifactDownloadError:
    ...  # rare: only when the error escapes internal handling
# preferred: inspect per-document results
for res in results:
    if res.status == ConversionStatus.FAILURE:
        handle(res.errors)

Prevention

When it happens

Trigger: Calling convert()/convert_all() with images='referenced' (bundle mode) against a service that returns a ZIP whose member names contain absolute paths or '../' traversal segments that resolve beyond the temp extraction dir.

Common situations: A compromised or buggy docling-serve version writes member names with leading slashes or traversal; a proxy/CDN rewrites the artifact; a hand-crafted bundle is served from a misconfigured object store presigned URL.

Related errors


AI-assisted analysis of docling-project/docling@61d76f1ff3 (2026-08-14). Data as JSON: /api/errors/532f72937cd5fb05. Report an issue: GitHub.