docling-project/docling · error · ValueError

Access to restricted IP address not allowed: {ip}

Error message

Access to restricted IP address not allowed: {ip}

What it means

ValueError raised at the end of validate_url_safety when the resolved IP fails the allowlist: it must be is_global and must not be private, loopback, link-local, reserved, multicast, or unspecified. This blocks SSRF attempts (and accidental internal requests) toward 127.0.0.1, 10.x, 192.168.x, 169.254.x (cloud metadata), ::1, etc., including hostnames that resolve to those ranges.

Source

Thrown at docling/backend/utils/image_resource_loader.py:76

    except ValueError:
        try:
            ip_str = socket.gethostbyname(hostname)
            ip = ipaddress.ip_address(ip_str)
        except (socket.gaierror, socket.herror) as e:
            raise ValueError(f"Cannot resolve hostname: {hostname}") from e

    if not (
        ip.is_global
        and not (
            ip.is_private
            or ip.is_loopback
            or ip.is_link_local
            or ip.is_reserved
            or ip.is_multicast
            or ip.is_unspecified
        )
    ):
        raise ValueError(f"Access to restricted IP address not allowed: {ip}")


class ImageResourceLoader:
    """Resolve and load image resources for declarative document backends.

    The ``base_path`` against which relative locations are resolved is supplied
    per call rather than stored, so a backend that mutates its base path between
    calls always uses the current value.
    """

    def __init__(
        self,
        *,
        enable_local_fetch: bool = False,
        enable_remote_fetch: bool = False,
        max_image_data_base64_bytes: int = 20 * 1024 * 1024,
        max_remote_image_bytes: int = 20 * 1024 * 1024,
        max_redirects: int = 5,

View on GitHub (pinned to 61d76f1ff3)

Solutions

  1. Do not fetch internal resources remotely: pre-download the images and enable local loading with a base_path instead.
  2. Expose the internal image host through a public, proxied URL that the runner can reach legitimately.
  3. If you truly need internal fetches, mirror the images to a location with a global IP rather than disabling the guard.
  4. Treat this error on user-uploaded documents as a suspected SSRF attempt and log/alert.

Example fix

# before
loader = ImageResourceLoader(enable_remote_fetch=True)
data = loader.load_image_data('http://169.254.169.254/latest/meta-data', base)
# ValueError: restricted IP

# after (pre-mirror assets locally)
loader = ImageResourceLoader(enable_local_fetch=True)
data = loader.load_image_data('images/chart.png', '/srv/mirror/report.html')
Defensive patterns

Strategy: validation

Validate before calling

import ipaddress, socket
from urllib.parse import urlparse
host = urlparse(url).hostname
ip = ipaddress.ip_address(host) if ':' in host else ipaddress.ip_address(socket.gethostbyname(host))
assert ip.is_global and not (ip.is_private or ip.is_loopback or ip.is_link_local or ip.is_reserved or ip.is_multicast or ip.is_unspecified), 'restricted IP'

Try / catch

try:
    data = loader.load_image_data(src, base)
except ValueError as e:
    if 'restricted IP' in str(e):
        alert_security(f'possible SSRF attempt: {src}')
        data = None
    else:
        raise

Prevention

When it happens

Trigger: A document image URL points to a private/internal address: http://10.0.0.5/chart.png, http://localhost:8080/x.png, a hostname resolving into RFC1918 space, or the cloud metadata IP 169.254.169.254. Requires enable_remote_fetch=True to be reached.

Common situations: Converting intranet HTML on a host where image hosts resolve privately; penetration-test payloads in uploaded HTML; localhost dev servers referenced as image sources.

Related errors


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