One command answers in plain English, ranks what it found, puts the exact fix under each item — and applies the fixes if you say yes. No account, no cloud, nothing installed but a 50 KB Python package.
pipx install llm-host-guard && llm-host-guard
llm-host-guard v0.3.4 — studio-pc (Linux, 192.168.1.20)
🔴 2 thing(s) to fix NOW, 2 this week score 2/10
CRITICAL Ollama on *:11434 reachable from LAN with no auth (7 models listed)
fix: OLLAMA_HOST=127.0.0.1 … or ufw allow from 192.168.1.0/24 to any port 11434
CRITICAL container open-webui publishes 0.0.0.0:8080 — bypasses host firewall
HIGH sshd PasswordAuthentication yes
HIGH 3 pickle-format weight file(s) — execute code on load
OK ufw active, default deny incoming
OK 2 LLM server(s): children as expected, no public outbound
next: preview the fixes → llm-host-guard --fix --dry-run
apply them → sudo llm-host-guard --fix
Ollama, LM Studio, vLLM and llama.cpp have no password by default. Many bind to every network interface, so anyone on your Wi-Fi — a guest, a smart bulb, a phone with a bad app — can run prompts, list and delete your models, or poke at known parser bugs. Tens of thousands of open Ollama servers are already indexed on Shodan.
Model files add a second problem: .pt / .bin weights run code the moment they load, and a crafted GGUF can crash or hijack the server. Existing tools cover coding agents (agent-firewall, mcp-sentinel) or generic hardening (lynis). None look at the LLM host specifically. This one does, and it changes nothing unless you ask.
Each finding comes with the exact command that fixes it. Run with sudo and rules that already protect a port get credited — a LAN-scoped Ollama drops from CRITICAL to MED.
Finds 14 LLM servers by process and port, then actually calls the API from your LAN address to prove it answers without a password.
ufw, firewalld, nftables, macOS pf, Windows Firewall — missing, off, not default-deny, or letting an LLM port in from Anywhere.
A container published on 0.0.0.0 skips your firewall entirely. Most people don't know this.
Public IP on an interface; cloudflared / ngrok / frp tunnels running. Opt-in --internet adds Shodan and a router UPnP scan.
Pickle weights that execute on load, malformed GGUF / safetensors headers, world-writable model folders.
Ollama, vLLM, llama.cpp, Open WebUI versions against a bundled advisory table.
OLLAMA_ORIGINS=* (any website can drive your LLM from your browser), missing API keys, open signup, SSH password login.
Your inference server just spawned a shell, or is talking to a public IP with no download running. That's what a poisoned model looks like.
Claude Code, Cursor, Codex, MCP configs on the box — flagged so you know, with a pointer to the right tool for that layer.
Wide open right now. Anyone on your network (or the internet) can use or damage your LLM today. Fix first.
A real hole, but an attacker needs one more thing — be on your Wi-Fi, or get you to open a file. Fix this week.
Exposed on purpose but wider than it needs to be. Tighten when convenient.
Looks exposed but something else already blocks it. Just be aware.
Not a problem, just something you should know exists.
Checked, nothing wrong.
Score starts at 10. CRITICAL costs 3, HIGH 2, MED 1.
Python 3.9 or newer is the only requirement. Linux and macOS first-class; Windows works with py -m llm_host_guard.
pipx keeps it isolated; plain pip works too. No pipx? git clone the repo and run python3 llm_host_guard.py.
pipx install llm-host-guardRead-only. sudo is optional but gives the accurate score because firewall rules become readable.
sudo llm-host-guardPreview first. Then each fix shows its exact command, asks y/N, and prints the undo. Fixes only add firewall rules or drop-in files; they never edit an existing config, and SSH password login is only disabled if you already have a key installed.
llm-host-guard --fix --dry-run
sudo llm-host-guard --fixPrefer a page? llm-host-guard --open writes a self-contained HTML report and opens it in your browser. --json for scripts.
Watch mode re-checks on a schedule and messages you only when a new exposure appears — a container that started on 0.0.0.0, a firewall rule that vanished, your LLM server spawning a shell. Silence means nothing changed.
In Telegram, open @BotFather, send /newbot, pick a name and a username ending in bot. BotFather replies with a token like 123456789:AAH…. Keep it private.
Open the bot's chat and press Start (or send any message). Bots can't message you until you do this once.
Paste this into a browser, with your token in place of TOKEN. In the reply, look for "chat":{"id":…} — that number is your chat id.
https://api.telegram.org/botTOKEN/getUpdatesTwo environment variables. Put them in your shell profile, or a systemd EnvironmentFile, so they never appear on a command line.
export LLM_HOST_GUARD_TELEGRAM_BOT_TOKEN=123456789:AAH…
export LLM_HOST_GUARD_TELEGRAM_CHAT_ID=987654321You should get a message within a second.
llm-host-guard --telegram-testEvery 30 minutes, root so firewall rules are credited, HTML report refreshed alongside. A ready systemd unit is in the repo; on a Mac use launchd, or a cron line with --once.
sudo llm-host-guard --watch 30 --telegram --html ~/llm-host-report.htmlAlready have a bot for something else? Reuse it — the same token works for any number of tools. Prefer a webhook? --webhook URL posts the same JSON anywhere.
Add two words to the command and each machine also reports to a fleet dashboard: all hosts sorted worst-first, history per host, alerts when any of them goes red or goes quiet. Laptops are understood — they sleep, so their "gone silent" threshold is 12 hours instead of 90 minutes. Works on laptops, desktops and servers running Linux, macOS or Windows. Not phones — phone LLM apps don't open network ports, and a phone on your Wi-Fi is one of the things the guard protects your laptop from.
llm-host-guard --report-to https://fleet.yourcompany.example --enrol-key lhg_…
Fleet is in private beta. Free for up to 3 machines when it opens. Ask for access.
It tells you when you're missing one and writes the rule if you ask. The rule still runs in ufw.
Server behaviour is detected and reported with the pid. Blocking lives in agent-firewall.
No prompt-injection scanning, no content inspection. Ports, files, config, process behaviour — that's the scope.