opendatalab/MinerU · error · HTTPException

Publicly exposed API disables *-http-client backends and ser

Error message

Publicly exposed API disables *-http-client backends and server_url by default. Rebind to 127.0.0.1 or start with --allow-public-http-client if you understand the SSRF risk.

What it means

HTTP 400 (PUBLIC_HTTP_CLIENT_DISABLED_DETAIL) raised by validate_public_http_client_request in public_http_client_policy.py: the API is bound to a public interface (not 127.0.0.1/localhost) AND --allow-public-http-client was not passed, AND the request tried to use a backend ending in '-http-client' or a non-empty server_url. This is a deliberate SSRF guard: a publicly exposed endpoint that lets callers choose an arbitrary server_url could be used to probe/attack internal network services, so http-client backends are disabled until the operator explicitly opts in.

Source

Thrown at mineru/cli/public_http_client_policy.py:37

    *,
    public_bind_exposed: bool,
    allow_public_http_client: bool,
) -> None:
    app.state.public_bind_exposed = public_bind_exposed
    app.state.allow_public_http_client = allow_public_http_client


def validate_public_http_client_request(
    *,
    public_bind_exposed: bool,
    allow_public_http_client: bool,
    backend: str,
    server_url: str | None,
) -> None:
    if not public_bind_exposed or allow_public_http_client:
        return
    if backend.endswith("-http-client") or bool(server_url and server_url.strip()):
        raise HTTPException(status_code=400, detail=PUBLIC_HTTP_CLIENT_DISABLED_DETAIL)


def warn_if_public_http_client_policy(
    *,
    service_name: str,
    host: str,
    allow_public_http_client: bool,
) -> None:
    if not is_public_bind_host(host):
        return
    if allow_public_http_client:
        logger.warning(
            "MinerU {} is listening on {} with --allow-public-http-client enabled. "
            "Requests may supply remote HTTP inference endpoints and turn the service "
            "into an externally driven outbound request primitive, creating SSRF and "
            "internal network probing risk.",
            service_name,
            host,

View on GitHub (pinned to 4fe4bde114)

Solutions

  1. If you accept the SSRF risk and run in a trusted network, restart the API with --allow-public-http-client.
  2. Safer: bind to 127.0.0.1 and put an authenticating reverse proxy in front, so the policy never triggers.
  3. Drop server_url / '-http-client' backends from requests and use locally hosted models instead.
  4. Restrict at the network level (firewall/egress rules) if you must enable http-client backends publicly.

Example fix

# before
uvicorn mineru.cli.fast_api:app --host 0.0.0.0 --port 8000
# POST with server_url='http://10.0.0.5:8001/vlm' -> 400 SSRF guard

# after
uvicorn mineru.cli.fast_api:app --host 0.0.0.0 --port 8000 --allow-public-http-client
# (or) --host 127.0.0.1 behind an auth'd nginx proxy
Defensive patterns

Strategy: validation

Validate before calling

def request_allowed(public_bind_exposed: bool, allow_public_http_client: bool,
                  backend: str, server_url: str | None) -> bool:
    if not public_bind_exposed or allow_public_http_client:
        return True
    return not backend.endswith('-http-client') and not (server_url and server_url.strip())

Type guard

def uses_http_client(backend: str, server_url: str | None) -> bool:
    return backend.endswith('-http-client') or bool(server_url and server_url.strip())

Try / catch

r = requests.post(f'{base}/file_parse', json=payload)
if r.status_code == 400 and 'http-client' in r.text:
    raise RuntimeError('SSRF guard active: bind 127.0.0.1, or restart API with --allow-public-http-client')

Prevention

When it happens

Trigger: Starting the API with host 0.0.0.0 (or any LAN/public address) without --allow-public-http-client, then sending a request whose backend is e.g. 'vlm-http-client' or that carries a server_url pointing at a remote VLM service; Docker deployments binding 0.0.0.0; reverse-proxied setups where the bind looks public to the policy check.

Common situations: Containerizing the API (Docker defaults to 0.0.0.0) and wondering why server_url requests suddenly 400; exposing the service on a LAN for a team; moving from localhost dev to server deployment without re-reading the flags.

Related errors


AI-assisted analysis of opendatalab/MinerU@4fe4bde114 (2026-08-14). Data as JSON: /api/errors/39a4081388398e15. Report an issue: GitHub.