In short: a Docker host that exposes its management API on port 2375 without authentication can be taken over, and the Carbonato botnet scans for exactly that. Check every Docker host you run and close that port.
Table of Contents
Every five minutes, somewhere on the internet, a compromised Docker host finishes scanning its own local network for other Docker hosts before moving on. That’s the propagation cycle security researchers at ThreatDown documented for a botnet they’ve named Carbonato: find an unauthenticated Docker daemon, break in, scan the neighborhood, repeat. No phishing email, no stolen password, just a daemon that was left listening on a port with no authentication required.
The entry point is mundane and well-documented: Docker’s API can be exposed over TCP on port 2375, and unlike the local Unix socket Docker uses by default, that TCP listener has no built-in authentication. If it’s reachable from the internet, anyone who finds it has root-equivalent control over that host, because that’s what Docker API access means. Carbonato’s operators aren’t exploiting a new flaw here; they’re exploiting a configuration choice that’s been a known risk for years and keeps showing up anyway. (Source: The Hacker News)
What Makes This One Different
Botnets built on exposed Docker daemons aren’t new. What’s notable about Carbonato is what it installs once it’s in: instead of a conventional command-and-control client, it deploys the open-source Hermes Agent framework running a custom AI persona. According to the researchers, the persona file is a 39-line prompt that gives the deployed agent a fictional identity, “GH0ST,” described as a senior hacker and exploit developer with no ethical restrictions, and instructs it to execute tasks it receives through Telegram, maintain persistence, and collect credentials.
That’s a meaningfully different operating model from a botnet whose infected hosts wait passively for a hardcoded command list. An agent that can interpret instructions and act on a live shell means the operator can adapt in real time, ask it to check for specific software, pivot toward a new target, or respond to whatever it finds on a given host, without pushing a new binary update to the whole botnet first. Whether that makes Carbonato meaningfully more dangerous than a well-run conventional botnet or is mostly a proof of concept for the technique remains to be seen.
Either way, it’s a real, currently active use of an AI agent framework for exactly the kind of hands-on-keyboard work that operators used to have to do themselves or hardcode in advance.
How It Spreads and Stays
Once inside a host, Carbonato launches privileged containers, essentially containers granted access to the underlying host system rather than being properly isolated, which gives it a foothold to run commands directly on the server itself, not just inside a sandboxed container. From there it installs SSH servers with operator-controlled keys and sets up reverse SSH tunnels back to infrastructure researchers traced to Costa Rica, giving the operator a durable, encrypted channel back into the compromised machine even after the initial entry point is noticed and closed. Cron jobs and watchdog scripts restart the malware if a defender kills the process, which is standard persistence tradecraft but effective enough that a single manual process kill won’t resolve an infection.
The propagation mechanism is the part worth taking seriously if you run any Docker infrastructure at all, even infrastructure you’re confident is locked down: the five-minute network scan means a single exposed Docker host on a shared network segment can become the pivot point that finds every other exposed host nearby, including ones an administrator assumed were internal-only and therefore safe.
Checking Whether Your Own Docker Host Is Exposed
This is a five-minute check worth running today, not filing away for later, and it doesn’t require deep Docker expertise. From outside your server’s own network, run a port scan against your server’s public IP address on port 2375 (a simple nc -zv your-server-ip 2375 or an online port checker works). If nothing responds, or the connection is refused, that port isn’t reachable from the internet and this specific attack vector doesn’t apply to your host. If it does respond, and especially if docker -H tcp://your-server-ip:2375 info returns real output from outside your network, that daemon is exposed exactly the way Carbonato is scanning for.
A second, quieter way this happens: firewall or cloud security group rules configured to allow traffic on 2375 “for testing” and never tightened back up afterward. Reviewing whatever inbound rule set applies to a VPS, whether that’s ufw, iptables, or a cloud provider’s security group console, for any rule permitting 2375 from 0.0.0.0/0 (any source) catches this even when Docker’s own configuration file looks fine.
Signs a Docker Host May Already Be Compromised
If a Docker host has ever been exposed, even briefly, it’s worth checking for the specific traces this campaign leaves behind rather than assuming closing the port after the fact undoes any damage already done. Worth checking: docker ps for any privileged container you don’t recognize starting it; the ~/.ssh/authorized_keys file for a server-level or container-level SSH key that wasn’t added by anyone on the team; crontab -l and any systemd timers for jobs referencing unfamiliar scripts or restart loops; and outbound network connections (ss -tnp or equivalent) to unfamiliar IP addresses, particularly persistent SSH-looking connections that don’t correspond to any admin’s own remote access.
None of these checks require specialized tooling, and finding any one of them is a strong enough signal to treat the host as compromised and rebuild rather than trying to manually clean an active infection.
What to Actually Do About It
The fix Docker’s own documentation recommends, and the one security researchers keep repeating because it keeps not being followed, is straightforward: never expose the Docker daemon on an unauthenticated TCP port to the internet, full stop. If remote API access is genuinely needed, either tunnel it over SSH to the Unix socket rather than opening a TCP listener at all, or, if TCP access is unavoidable, enable TLS with mutual authentication (client certificates issued by your own CA) so the daemon only accepts connections that present a valid cert, not just any connection on the right port.
For most small businesses running a handful of containerized applications on a VPS, the simplest fix is also the most complete one: there usually isn’t a real business need for the Docker API to be reachable from outside the box at all. Managing containers through SSH into the server directly, rather than exposing an API to be managed remotely, removes the entire attack surface this botnet depends on rather than trying to secure a door that didn’t need to be open in the first place.
Why This Matters Even If You’ve Never Touched Docker
A server that isn’t running Docker at all isn’t a target for this specific botnet, but the underlying pattern is worth understanding regardless of your own stack: automated scanning for known misconfiguration classes runs continuously and doesn’t discriminate by the size of the business behind a given IP address. Carbonato’s five-minute scan cycle against neighboring networks means the practical risk to any given host isn’t really about whether it looks like an interesting target, it’s about whether a scan happens to reach it before anyone notices the door was left open.
That’s as true for a database left open on a default port as it is for a Docker daemon on 2375, and it’s the reason routine configuration audits matter more than trying to guess in advance which specific service an attacker will target next.
Related reading: A New Linux Botnet Is Turning Unpatched Routers and Servers Into Proxy Networks and An AI Found This File-Server Flaw. Attackers Used It Within a Day.

