Management interfaces not internet-exposed
What this checks
Scans open ports for common management services SSH (22), Docker API (2375/2376), dev/admin servers (4000, 5000), HTTP proxy/admin (8080), HTTPS admin (8443), Jupyter/admin (8888), management consoles (9000), and Prometheus/admin (9090) to check whether they are bound to public interfaces rather than localhost. Management interfaces exposed to the internet are the primary vector for host-level compromise of self-hosted AI setups.
Why it matters
An unauthenticated Docker API on port 2375 gives an attacker full root access to the host. An SSH service with password auth on port 22 is scanned and brute-forced within minutes of exposure. An admin dashboard on port 8080 with no auth is an open door. These are not theoretical risks they are the most common cause of self-hosted server compromise.
How to fix it
SSH (port 22)
Restrict SSH to key-based auth only and consider changing to a non-standard port:
# /etc/ssh/sshd_config
PasswordAuthentication no
PubkeyAuthentication yes
# Optional: change port
Port 2222
Or, if you don't need remote SSH at all:
sudo systemctl stop ssh && sudo systemctl disable ssh # Linux
sudo systemsetup -setremotelogin off # macOS
Docker API (port 2375/2376)
The Docker daemon should never listen on a TCP port unless you have a specific remote management need. Ensure /etc/docker/daemon.json does NOT contain "hosts": ["tcp://0.0.0.0:2375"]. If remote access is needed, use TLS mutual auth (port 2376) or tunnel over SSH instead:
export DOCKER_HOST=ssh://user@remote-host
docker ps # Docker commands tunnel over SSH no exposed TCP port needed
Admin dashboards and dev servers (ports 8080, 8443, 8888, 9000, 9090, 4000, 5000, etc.)
Bind admin interfaces to localhost, then access via SSH port forwarding if needed remotely:
# Bind to localhost:
./dashboard --host 127.0.0.1 --port 8080
# Access remotely via SSH tunnel:
ssh -L 8080:localhost:8080 user@your-server
# Then open http://localhost:8080 in your browser
Technical details
| Field | Value |
|---|---|
| Control ID | NC-NET-001 |
| Domain | NETWORK |
| Severity | Critical |
| Status | Expanded (Plugin only) |
| Data source | lsof -i :<port> -sTCP:LISTEN per port, with ss fallback on Linux |
| Ports checked | 22, 2375, 2376, 4000, 5000, 8080, 8443, 8888, 9000, 9090 |
| Mode | Mode 2 (System-level requires plugin expanded mode) |
| Introduced in | Library v0.2.0 |
False positive notes
SSH on port 22 is flagged only if accessible beyond localhost. If your setup uses a VPN or Tailscale for SSH access (not direct internet exposure), this may be a false positive exclude with a reason.
Suppress this finding
clawvitals exclude NC-NET-001 reason "SSH access via Tailscale only, not internet-exposed"
Custom port list
Add extra ports to scan
NC-NET-001 scans 10 default ports. To scan additional services on non-standard ports, add an extra_ports list to your plugin config. Extra ports are merged with the defaults they do not replace them.
Config file: ~/.openclaw/plugins/clawvitals/config.json
{
"network": {
"extra_ports": [
{ "port": 3001, "service": "Slack server" },
{ "port": 8888, "service": "Jupyter notebook" }
]
}
}
After saving the config, run run clawvitals --expanded the extra ports will be included in the scan.