Skip to content

Host exposure

The agent scans the machine it runs on for services listening on a wildcard address (0.0.0.0 / ::) that are not in the allowlist. Ephemeral sandboxes never run this scan; it exists for the long-lived agent host.

Docker-published ports bypass ufw: docker-proxy inserts its DNAT rules before ufw’s rules run, so docker run -p 5432:5432 is reachable from the network even when ufw status shows only SSH. A dev database, Redis, or a Docker API socket published that way stays internet-exposed until someone notices.

  • Reads /proc/net/tcp and /proc/net/tcp6 — no root, no ss.
  • Flags LISTEN sockets on a wildcard address.
  • Ignores the allowlist and the agent’s own listeners.
  • Explicit binds (loopback, LAN, tailnet) are the operator’s call.

The first scan runs at agent startup, then every host_exposure_minutes (default 60; 0 disables). A finding is logged and sent to the Discord webhook once per change: a persistent exposure does not repeat, and clearing it sends an all-clear.

  1. Bind the service to loopback. For a published container port use -p 127.0.0.1:5432:5432 (Compose: "127.0.0.1:5432:5432").
  2. If the service must be reachable publicly (a reverse proxy, a Kubernetes node port), add it to the allowlist, e.g. host_exposure_allow_ports=22,80,443,10250.
  3. The next scan reports the exposure cleared.
KeyDefaultEffect
host_exposure_minutes60Scan interval in minutes. 0 disables.
host_exposure_allow_ports22,80,443Public TCP ports the host is expected to serve.