Skip to content
← All posts

Your AI agent is probably reachable from the internet

Self-hosted agent gateways default to convenient bindings, not safe ones. Here is how the exposure happens, why nothing warns you, and how to check yours in a few minutes.

6 min read securityself-hosting

Nothing breaks when you expose an agent to the internet. That is the whole problem.

A misconfigured database throws connection errors. A broken deploy returns 500s. An agent gateway listening on 0.0.0.0 with no authentication behaves exactly like a correctly configured one — right up until someone else starts talking to it. There is no error, no alert, no degraded response time. The failure mode is silence.

This post is about how that happens, why it is so easy to miss, and how to check your own deployment.

How a laptop project becomes a public endpoint

Almost nobody decides to expose their agent. It happens in three steps that each look reasonable.

Step one: you develop locally. The gateway binds to localhost, or you set it to 0.0.0.0 because you want to hit it from your phone on the same wifi. On a laptop behind a home router, 0.0.0.0 is harmless — nothing outside your network can route to it. You learn that this setting works and move on.

Step two: you move it to a server. The agent is useful, so it should not die when your laptop sleeps. You copy the config to a VPS. That config still says 0.0.0.0. On a VPS, 0.0.0.0 means every network interface, and one of those interfaces has a public IP address with no router in front of it.

Step three: nothing happens. Your agent works. You use it for weeks. Nothing in the logs looks unusual, because a stranger sending your agent a message produces exactly the same log line as you sending it a message.

The gap between step two and step three is where deployments live for months.

Why the defaults point this way

It is tempting to blame the software, but the defaults are the way they are for a defensible reason: a gateway that binds to localhost only is annoying to develop against, and every project that ships that default gets a stream of “I can’t connect from my other machine” issues.

The result is that agent runtimes optimise their defaults for the laptop case, which is where the software is first run, rather than the server case, which is where it ends up. That is a reasonable choice for a project and a bad outcome for you specifically.

It is also worth being honest about scale. Reports of exposed agent and LLM-adjacent deployments — open Ollama endpoints, unauthenticated vector databases, agent gateways — turn up regularly in internet-wide scan data, and the numbers run to tens of thousands. Whatever the exact figure this month, the shape is consistent: a lot of people are in step three and do not know it.

What an exposed agent actually costs you

“Someone can talk to my agent” undersells it. An agent is not a chatbot; it is a chatbot with hands.

Your model credits. The most common outcome is the cheapest one to describe and the most annoying to receive: someone finds an open endpoint and uses it as free inference. You pay for their tokens. This is the good case.

Your tools. Agents are configured with tools — shell access, file operations, HTTP requests, sometimes credentials for other services. Whoever can send messages to the agent can, within the limits of your tool configuration and your prompt, ask it to use those tools. The blast radius is not the conversation; it is everything the agent is allowed to touch.

Your data. Session history, workspace files, whatever context the agent has been given. If the agent can read it, a caller can usually get it to repeat it.

Your reputation, eventually. An agent with outbound network access that is under someone else’s control is a machine sending traffic on your behalf, from your IP.

The severity is set by your tool configuration, not by the exposure itself. Which is exactly why “is it exposed” and “what can it do” need to be checked together.

Check yours

This takes a few minutes. Do it on the machine the agent runs on.

1. What is it actually listening on?

ss -tlnp | grep -E 'LISTEN'

You are looking for the port your agent gateway uses. If the local address column shows 0.0.0.0:PORT or *:PORT, it is bound to every interface. 127.0.0.1:PORT is bound to localhost only, which is what you want unless you have deliberately decided otherwise.

2. Is that port reachable from outside?

Bound to 0.0.0.0 does not always mean reachable — a firewall or cloud security group may still be in front of it. Check from a machine that is not the server, and not on the same network:

curl -m 5 -sv http://YOUR_SERVER_IP:PORT/ 2>&1 | tail -20

If you get a connection refused or a timeout, something is blocking it. If you get an HTTP response, it is open to the internet.

3. Does it ask who you are?

This is the question that matters most, and the one people skip. An open port with solid authentication in front of it is a different situation from an open port without. If the response to an unauthenticated request is anything other than a rejection, you have no authentication.

4. What could a caller reach?

Look at your agent’s tool configuration and workspace scope. Assume for a moment that an untrusted person is sending it messages. What are they able to make it do? Anything on that list that makes you uncomfortable is a finding, whether or not the endpoint turns out to be exposed today.

Fixing it

In rough order of how much they buy you:

Bind to localhost. If you access the agent from the same machine, 127.0.0.1 closes the entire class of problem. Everything else on this list is mitigation; this is elimination.

Put a reverse proxy with authentication in front. If you need remote access, do not expose the gateway directly. Terminate TLS and authenticate at nginx or Caddy, and have it forward to the gateway on localhost.

Use a private network instead of the public internet. WireGuard or Tailscale gives you remote access without a publicly routable port. For a single-user setup this is usually less work than it sounds and strictly better than a password on a public endpoint.

Set a firewall rule. Cloud security groups and ufw are a coarse but effective backstop, and they protect you when a config change re-opens something you thought was closed.

Reduce the tool surface. Separately from access control: an agent that cannot run arbitrary shell commands is a smaller problem when something does get through. Scope the workspace. Remove tools you are not using.

Set a spending limit at your provider. Not a security control, but it caps the cost of the most likely outcome.

The part that does not fix itself

Every item above is a one-time action, and every one of them can be silently undone: a config restore, a container rebuild from an older image, a well-meaning change to make something work from a phone. The check is not hard. Remembering to repeat it is the hard part, and that is a bad thing to leave to memory.

This is the reason the security audit exists in GambaOS: it runs the same class of checks — gateway binding, authentication, channel exposure, workspace scope — scores the result, and links each finding to the page that fixes it. A default deployment usually scores in the fifties the first time, which is a more useful number than it sounds: it means the gap between “it works” and “it is safe” is normal, not a personal failing.

If you run an agent on a server, go and run step one now. It takes thirty seconds, and there is a real chance it tells you something you did not expect.

Get GambaOS when it launches

The panel this article talks about opens for download soon. Leave an email and be first in.

One email when it launches. Unsubscribe anytime.