{"record":{"id":"b477f3f1dad0252c","repo":"docling-project/docling","slug":"fetching-local-resources-is-only-allowed-when-set","errorCode":null,"errorMessage":"Fetching local resources is only allowed when set explicitly. Set options.enable_local_fetch=True.","messagePattern":"Fetching local resources is only allowed when set explicitly\\. Set options\\.enable_local_fetch=True\\.","errorType":"exception","errorClass":"OperationNotAllowed","httpStatus":null,"severity":"warning","filePath":"docling/backend/utils/image_resource_loader.py","lineNumber":260,"sourceCode":"                    total_size += len(chunk)\n                    if total_size > max_size:\n                        raise ValueError(\"Downloaded data exceeds size limit\")\n                    chunks.append(chunk)\n\n            return b\"\".join(chunks)\n        elif src_loc.startswith(\"data:\"):\n            encoded_data = re.sub(r\"^data:image/.+;base64,\", \"\", src_loc)\n            decoded_data = base64.b64decode(encoded_data)\n\n            if len(decoded_data) > self.max_image_data_base64_bytes:\n                raise ValueError(\n                    f\"Decoded image exceeds size limit of {self.max_image_data_base64_bytes} bytes.\"\n                )\n\n            return decoded_data\n\n        if not self.enable_local_fetch:\n            raise OperationNotAllowed(\n                \"Fetching local resources is only allowed when set explicitly. \"\n                \"Set options.enable_local_fetch=True.\"\n            )\n\n        # Require base_path for directory confinement (validation done in resolve_relative_path)\n        if not base_path:\n            raise OperationNotAllowed(\n                f\"Local file access requires base_path for directory confinement: '{src_loc}'\"\n            )\n\n        if os.path.isfile(src_loc) and os.access(src_loc, os.R_OK):\n            with open(src_loc, \"rb\") as f:\n                return f.read()\n        else:\n            raise ValueError(\"File does not exist or it is not readable.\")\n","sourceCodeStart":242,"sourceCodeEnd":276,"githubUrl":"https://github.com/docling-project/docling/blob/61d76f1ff3f8428065465889f7b4577da7df704c/docling/backend/utils/image_resource_loader.py#L242-L276","documentation":"The image resource loader was asked to fetch a local filesystem path (from an <img src> or Markdown image reference), but enable_local_fetch defaults to False, so docling raises OperationNotAllowed. This is an SSRF/local-file-read guard: documents come from untrusted parties, so reading arbitrary local paths referenced inside them is opt-in.","triggerScenarios":"Converting HTML/Markdown with relative or absolute local image paths while pipeline options leave enable_local_fetch=False (the default). The loader's resolve_relative_path produced a local path and load_image_data reached the local branch.","commonSituations":"First-time users converting a local .html with sibling images and expecting them to be embedded; batch pipelines processing downloaded HTML; migrating from a version/looser config that auto-fetched.","solutions":["Opt in explicitly: set options.enable_local_fetch=True on the pipeline options for that conversion.","Also pass a base_path (the directory containing the document) so relative src values resolve and stay confined.","If you don't need local images, ignore it — create_image_ref catches OperationNotAllowed, warns, and continues without the image.","For remote-hosted images instead, enable enable_remote_fetch=True and fix the src URLs."],"exampleFix":"# before\nhtml_opts = HtmlPipelineOptions()\nresult = converter.convert(html_path)\n\n# after\nhtml_opts = HtmlPipelineOptions()\nhtml_opts.enable_local_fetch = True\nconverter = DocumentConverter(\n    format_options={InputFormat.HTML: HtmlFormatOptions(pipeline_options=html_opts)}\n)\nresult = converter.convert(html_path)","handlingStrategy":"validation","validationCode":"from urllib.parse import urlparse\n\ndef will_local_fetch_be_attempted(src: str, enable_local_fetch: bool) -> bool:\n    p = urlparse(src)\n    is_local = not p.netloc and (not p.scheme or (len(p.scheme) == 1 and p.scheme.isalpha()))\n    return is_local and not enable_local_fetch  # True -> error [83] imminent","typeGuard":null,"tryCatchPattern":"try:\n    img = loader.load_image_ref(src, base_path)\nexcept OperationNotAllowed as e:\n    logger.info(\"local image skipped (enable_local_fetch=False): %s\", src)","preventionTips":["Default conversions of local HTML/Markdown with images: always set enable_local_fetch=True plus a base_path.","Never blanket-enable local fetch for untrusted documents; confine with base_path.","Know that via create_image_ref this is a warning, not a crash."],"tags":["security","images","local-files","html","markdown","configuration"],"backgroundTag":null,"analyzedSha":"61d76f1ff3f8428065465889f7b4577da7df704c","analyzedAt":"2026-08-14T23:53:18.727Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}