vLLM container is published on all interfaces (-p {port}:8000 ignores SURYA_INFERENCE_HOST)
Summary: surya publishes its auto-spawned vLLM container with -p {port}:8000 — no host address — so Docker binds it to all host interfaces. On any machine that isn't behind a host firewall, an ordinary local OCR call opens an unauthenticated GPU inference endpoint to the LAN (and to a tailnet/VPN, if present).
Where: surya/inference/backends/vllm.py (0.22.1), the docker run argument construction:
"-p",
f"{port}:8000",Why this binds publicly: Docker's own documentation states that when a container's ports are mapped without a specific host address, the daemon publishes to all host addresses (0.0.0.0 and [::]), and that publishing is "insecure by default" — https://docs.docker.com/engine/network/port-publishing/
Observed (surya 0.22.1, Docker 29.7.2, Windows 11 + WSL2, RTX 4090). Three ordinary read-only OCR calls, default config, no explicit server configured — each spawned a container reachable off-box:
docker inspect -> ports {"8000/tcp":[{"HostIp":"0.0.0.0","HostPort":"58677"},
{"HostIp":"::","HostPort":"58677"}]}
http://<lan-ip>:58677/health -> 200
http://<tailnet-ip>:58677/health -> 200 (off-LAN)
http://127.0.0.1:58677/v1/models -> 200, unauthenticatedSURYA_INFERENCE_AUTOSTART defaults to True, so this is the default path, not an opt-in one.
Why it's surprising: settings.py already carries SURYA_INFERENCE_HOST = "127.0.0.1". That value is the client dial address; the publish binding ignores it. A reader of the settings would reasonably conclude the server is loopback-scoped — it isn't.
Suggested fix — honour the existing host setting in the publish mapping:
"-p",
f"{settings.SURYA_INFERENCE_HOST}:{port}:8000",That keeps the current behaviour for anyone who deliberately sets SURYA_INFERENCE_HOST=0.0.0.0, and makes the default local-only, matching what the setting already implies.
Prior art for the same remediation: googledatalab/datalab#786 changed run.sh to -p 127.0.0.1:host_port:container_port for exactly this reason.
Notes / non-claims:
- This is a default-exposure report, not an exploit report. I'm not claiming a vulnerability in vLLM itself; the concern is that a private inference dependency is reachable off-host without the operator choosing that.
- Workaround for anyone hitting this now: run your own server bound to loopback (
docker run -p 127.0.0.1:PORT:8000 ...), then setSURYA_INFERENCE_URLandSURYA_INFERENCE_AUTOSTART=False. Verified working — attaches in seconds and spawns nothing. - Separately, and this one is our bug rather than surya's: a client killed by a caller-side timeout orphans the container that surya would otherwise tear down on exit. Worth knowing that fixing the bind narrows the exposure but doesn't remove orphans caused by the caller.
Source: datalab-to/surya