Skip to content
ThreatDown researchers note

ThreatDown researchers note

www.threatdown.com • September 24, 2026

​ThreatDown​ ​researchers​ ​uncovered​ ​CARBONATO,​ ​a​ ​Docker​ ​botnet​ ​built​ ​around​ ​an​ ​AI​ ​agent​ ​that​ ​compromises​ ​exposed​ ​Docker​ ​daemons,​ ​spreads​ ​across​ ​reachable​ ​hosts,​ ​and​ ​gives​ ​operators​ ​a​ ​Telegram-controlled​ ​tool​​ for​ ​post-compromise activity.​

In August 2026, we found an unauthenticated Docker registry that had been publicly exposed since May. Over one day of passive, read-only collection, we recovered 59 repositories, 234 image tags, 605 verified blobs, and 4.3 GB of image data.

The archive spans October 2024 through August 2026. It documents two linked product lines: a factory distributing trojanized cryptocurrency wallet apps, and a botnet that compromises Docker daemons exposed on port 2375.

At the center of the botnet is Hermes Agent, an MIT-licensed open-source agent framework. The implant installs the framework unchanged, then overwrites its SOUL.md persona file. The 39-line prompt directs it to execute tasks received through Telegram, maintain persistence, and collect credentials.

​During ​​routine ​​threat hunting,​​ we​​ scanned​​ the​​ internet ​​for ​​exposed​​ Docker​ ​services​ ​and​ ​found​ ​a​ ​US-based​ ​server​ ​running​ ​a​ ​Docker​ ​Registry​ ​on​ ​port​ 5000​​.​ ​Two​ ​read-only​ ​GET​ ​requests​ ​confirmed​ ​that​ ​the​ ​registry​ ​allowed​ ​unauthenticated access:​

​The ​​response ​​listed ​​59 ​​repositories,​​ including ​​backdoor​​, ​​fsociety/agent​​,​​ gh0st/c2​​,​ ​and​ ​system/resolved​​.​ ​One​ ​day​ ​of​ ​passive​ ​collection​ ​recovered​ ​4.3​ ​GB,​ ​234​ ​image tags, 605 ​​SHA-256​​-verified blobs, and around​​ 945,000 indexed files.​

​Alongside​ ​the​ ​image​ ​layers,​ ​the​ ​registry​ ​exposed​ ​configuration​ ​JSON​ ​containing​ ​each​ ​image’s​ ​environment​ ​variables,​ ​entrypoints,​ ​and​ ​full​ ​command history.​

​That​ ​record​ ​gave​ ​us​ ​the​ ​first​ ​C2​​ addresses,​​ bot​​ tokens,​​ and​​ the​​ password​ ​shared ​​by​​ the​​ operation’s​​ LLM ​​gateway. ​​Infected​​ hosts ​​also​​ repeatedly ​​pulled​ ​the ​​implant​​from ​​the​​ registry,​​ making​​ it ​​both ​​the​​ source ​​of ​​the ​​evidence​​ and​ ​the fleet’s update server.​

​How the botnet works​

​CARBONATO ​​is ​​a​​ botnet ​​implant​​ that ​​spreads​​ like ​​a​​ worm​​ across ​​hosts​​ with​ ​unauthenticated​ ​Docker​ ​daemons.​ ​It​ ​uses​ ​a​ ​privileged​ ​container​ ​to​ ​run​ ​commands​ ​on​ ​each​ ​host,​ ​establishes​ ​persistence​ ​and​ ​remote​ ​access, ​​then​ ​scans​​ nearby​​ networks ​​for​​ further​​ Docker​​ daemons.​​ Hermes​​ Agent​​ gives ​​the​ ​operators​​ a​​ Telegram​​ interface ​​to ​​send ​​tasks ​​to ​​compromised​​ hosts,​​ and​​ its​ ​persona names AI API keys and other credentials as the priority.​

​The​ ​botnet​ ​searches​ ​for​ ​Docker​ ​daemons​ ​that​ ​accept​ ​unauthenticated​ ​connections​​ on ​​port​​ 2375​​.​​ When ​​it​​ finds ​​one,​​ it​​ uses​​ the​​ daemon ​​to ​​launch ​​a​ ​privileged​ ​container​ ​with​ ​the​ ​host​ ​filesystem​ ​mounted​ ​and​ ​access​ ​to​ ​the​ ​host’s​ ​process​ ​and​ ​network​​ namespaces.​​ It​​ then ​​uses ​​the​​ container ​​to ​​run​ ​commands on the host itself.​

​The​ ​exposed​ ​Docker​ ​daemon​ ​gives​ ​the​ ​implant​ ​the​ ​access​ ​it​ ​needs.​ ​Thousands ​​of​​ such​​ hosts ​​remain​​ publicly ​​reachable,​​ and​​ the​​ same ​​scanning​ ​approach​ ​that​ ​led​ ​us​ ​to​ ​the​ ​registry​ ​identifies​ ​them.​ ​Each​ ​successful​ ​deployment starts the rest of the chain.​

​The​ ​container​ ​starts​ ​by​ ​running​ ​entry.sh​​.​ ​The​ ​script​ ​opens​ ​a​ ​reverse​ ​SSH​ ​tunnel​​ from ​​the ​​victim ​​to​​ a ​​relay​​ in​​ Costa ​​Rica,​​ giving​​ the ​​operators ​​a ​​path​ ​back​ ​into​ ​the​ ​host.​ ​Its​ ​remote​ ​port​ ​is​ ​derived​ ​from​ ​the​ ​MD5​​ hash​ ​of​ ​the​ ​victim’s​ ​IP​ ​address,​ ​so​ ​the​ ​crew​ ​can​ ​calculate​ ​the​ ​same​ ​port​ ​whenever​ ​it​ ​needs​ ​to​​ reconnect.​​ The​​ script​​ also​​ installs​​ an​​ SSH​​ server,​​ adds​​ the​​ crew’s​ ​key,​ ​and​ ​sends​ ​a​ ​deployment​ ​report​ ​to​ ​Telegram​ ​with​ ​the​ ​container​ ​ID,​ ​hostname,​​ IP​​ address,​​ and​​ country. ​​The​​ report ​​is​​ written​​ in​​ voseo ​​Spanish,​​ a​ ​regional form associated with parts of Central and South America.​

​The​​ tunnel ​​is​​ only​​ the ​​first​​ part ​​of ​​holding ​​the ​​host.​​ To ​​make the ​​deployment​ ​look ​​like ​​ordinary ​​Linux​​ infrastructure,​​ the​​ implant​​ runs ​​in​​ a​​ container ​​called​ systemd​​-resolved​​ and​​ displays​​ a​​ fake​​ systemd​​-networkd​​ resolver​​ v2.0​​ banner. ​​Its​ ​process​​ arguments ​​also ​​imitate ​​the ​​kernel ​​thread ​​[kworker/u2:0]​​,​​ which​​ helps​ ​it blend into a quick process review.​

​The​​ scripts​​ are​​ built​​ to​​ survive ​​a​​ cleanup ​​or​​ reboot.​​ They ​​create ​​persistence​ ​hooks ​​through ​​cron​​,​​ systemd ​​timers,​​ rc.local​​,​​ and​​ OpenRC​​,​​ then​​ mark​​ those​​ files​ ​immutable.​ ​Paired​ ​watchdogs​ ​monitor​ ​the​ ​deployment​ ​and​ ​re-pull​ ​the​ ​implant​ ​from​ ​the​ ​registry​ ​if​ ​its​ ​files​ ​or​ ​container​ ​disappear.​ ​The​ ​registry​ ​therefore keeps the host persistent after the initial compromise.​

​With access and persistence in place, the phase installs the agent.​

​3. Install the agent​

​With​ ​the​ ​host​ ​held,​ ​the​ ​implant​ ​installs​ ​Hermes​ ​Agent,​ ​an​ ​MIT-licensed,​ ​open-source ​​framework ​​from​​ Nous ​​Research.​​ The ​​framework ​​already​​ accepts​ ​Telegram​ ​tasks,​ ​runs​ ​terminal​​ commands,​​ and​​ connects ​​to​​ compatible​​ LLM​ ​endpoints.​ ​Those​ ​capabilities​ ​give​ ​the​ ​crew​ ​an ​​operator ​​interface​​ on​​ every​ ​compromised host without building its own agent framework.​

​The​ ​entrypoint​ ​then​ ​overwrites​ ​the​ ​agent’s​ ​SOUL.md​ ​persona​ ​file​ ​with​ ​the​ ​crew’s​ ​39-line​ ​prompt.​ ​It​ ​names​ ​the​ ​agent​ ​GH0ST​​,​ ​directs​ ​it​ ​to​ ​maintain​ ​persistence ​​and​​ follow​​ Telegram ​​instructions,​​ and​​ prioritizes​​ the ​​collection​​ of​ ​AI​ ​API​ ​keys,​ ​credentials,​ ​and​ ​exposed​ ​AI​ ​endpoints.​ ​The​ ​framework​ ​stays​ ​unchanged.​ ​The​ ​malicious​​ behavior​​ comes ​​from​​ the ​​instructions ​​it ​​receives​ ​at startup. The persona file is reproduced below.​

​With the persona in place, the agent is ready for the operator’s task.​

​4. Operate the host​

​Those​ ​standing​ ​instructions​ ​only​ ​matter​ ​when​ ​an​ ​operator​ ​sends​ ​a​ ​task.​ ​Hermes​​ Agent ​​receives ​​the ​​task​​ through​​ Telegram​​ and​​ forwards​​ it,​​ together​ ​with​ ​SOUL.md​​,​ ​to​ ​the​ ​operation’s​ ​LLM​​ gateway. ​​The ​​persona ​​gives ​​the ​​model​ ​the​ ​rules​ ​it​ ​should​ ​follow​ ​on​ ​the​ ​host,​ ​while​ ​the​ ​operator​ ​supplies​ ​the​ ​immediate objective.​

​The​ ​exchange​ ​then​ ​becomes​ ​an​ ​interactive​ ​command​ ​loop.​ ​The​ ​model​ ​interprets​ ​the​ ​task,​ ​writes​ ​terminal​ ​commands,​ ​reads​ ​the​ ​output,​ ​and​ ​decides​​ what ​​to​​ do ​​ .​​ The​​ agent ​​runs ​​those​​ commands ​​on ​​the ​​victim​​ and​ ​returns​ ​its​ ​report​ ​to​ ​the​ ​Telegram​ ​chat​ ​that​ ​also​ ​receives​ ​deployment​ ​reports.​​ This​​ gives ​​the​​ crew​​ an​​ operator​​ interface ​​that​​ can​​ work ​​through ​​a​ ​task as the host reveals new information.​

​The ​​gateway​​ operated​​ on ​​a ​​free ​​tier​​ while ​​advertising​​ 12 ​​models​​ and​​ serving​ ​27 ​​through ​​its​​ API,​​ which ​​explains ​​the​​ prompt’s​​ focus​​ on​​ AI​​ API​​ keys.​​ Target​ ​selection, persistence, and spreading remain in the surrounding scripts.​

​The​ ​agent​ ​has​ ​no​ ​role​ ​in​ ​the​ ​final​ ​phase.​ ​Every​ ​five​ ​minutes,​ ​the​ ​worm​ ​identifies​ ​the​ ​networks​ ​attached​ ​to​ ​the​ ​host​ ​and​ ​its​ ​Docker​ ​bridges,​ ​then​ ​scans​​ each ​​/24​​ for​​ Docker​​ daemons​​ exposed ​​on​​ port ​​2375​​.​​ When ​​it​​ finds​​ one,​ ​it​​ checks​​ that​​ the​​ service ​​is ​​Docker,​​ avoids​​ hosts ​​it ​​has​​ already ​​infected,​​ and​ ​repeats the initial deployment sequence.​

​Each​​ new​​ host ​​pulls​​ the ​​implant​​ from​​ the ​​registry, ​​starts​​ the​​ container,​​ and​ ​joins​ ​the​ ​same​ ​scan​ ​loop.​ ​That​ ​design​ ​lets​ ​the​ ​botnet​ ​expand​ ​across​ ​a​ ​network without waiting for an operator to issue another task.​

​The​ ​model​ ​is​ ​absent​ ​from​ ​this​ ​phase.​ ​Scripts​ ​handle​ ​the​ ​scan,​ ​the​ ​deployment,​ ​and​ ​the​ ​persistence​ ​loop,​ ​while​ ​the​ ​agent​ ​waits​ ​for​ ​operator​ ​tasks on hosts that have already been compromised.​

​The​ ​deployment​ ​reports​ ​provide​ ​the​​ first​​ clue​​ ​​ the​​ people​​ behind ​​the​ ​botnet.​​ They​​ use​​ voseo​​ Spanish,​​ a ​​regional​​ form ​​that​​ uses​​ vos ​​in​​ place​​ of ​​tú.​ ​Voseo​ ​appears​ ​across​ ​parts​ ​of​ ​Central​ ​and​ ​South​ ​America,​ ​so​ ​it​ ​does​ ​not​ ​identify​ ​a​ ​country​ ​on​ ​its​ ​own.​ ​It​ ​places​ ​the​ ​botnet’s​ ​operators​ ​within​ ​a​ ​narrower linguistic context.​

​Three​ ​additional​ ​signals​ ​point​ ​toward​ ​Costa​ ​Rica.​ ​Fourteen​ ​of​ ​162​ ​image​ ​configurations​ ​use​ ​UTC-06:00​ ​timestamps​ ​matching​ ​the​ ​America/Costa_Rica​ ​timezone.​ ​The​ ​Telegram​ ​handle ​​is​ ​Carbo506​​, and ​​+506​​ is​​ Costa ​​Rica’s ​​country​ ​calling ​​code.​​ The​​ reverse ​​SSH​​ tunnels​​ also​​ terminate​​ at​​ a ​​sink​​ in ​​AS262145​​, ​​a​ ​Costa Rican network.​

​Each​ ​signal​ ​comes​ ​from​ ​a​ ​different​ ​part​ ​of​ ​the​ ​botnet​ ​operation:​ ​build​ ​configuration,​ ​operator​ ​identity,​ ​and​ ​active​ ​infrastructure.​ ​Taken​ ​together,​ ​they support a Costa Rica assessment for the botnet operators.​

​How to detect CARBONATO​

​CARBONATO​ ​gets​ ​in​ ​through​ ​Docker​ ​daemons​ ​exposed​ ​to​ ​the​ ​internet​ ​without​​ authentication,​​ usually​​ on​​ port ​​2375​​. ​​It​​ uses the ​​Docker ​​API ​​to ​​launch​ ​a​ ​privileged​ ​container​ ​with​ ​the​ ​host​ ​filesystem​ ​mounted,​ ​then​ ​uses​ ​that​ ​container to run commands on the host.​

​Do​ ​not​ ​expose​ ​the​ ​Docker​ ​daemon​ ​API​ ​to​ ​the​ ​network,​ ​and​ ​require​ ​authentication​​ on ​​every​​ registry,​​ because ​​the ​​open ​​API ​​is ​​the​​ infection​​ vector​ ​and an open registry is both a leak and a weapons dispenser.​

​2. Do not blocklist the agent​

​hermes-agent ​​is​ ​a​ ​legitimate​ ​package​ ​with​​ ordinary ​​users,​​ so ​​hunt​​ the​​ abuse​ ​signature​ ​instead:​ ​a​ ​/root/.hermes/SOUL.md ​​containing​ ​”​​GH0ST​​”,​ ​a​ ​.env ​​carrying CARBONATO_API_KEY​​, unexplained Telegram egress from​​ servers.​

​3. Check for the persistence kit​

​Look ​​for ​​/usr/local/bin/.docker-network-monitor​​,​​ process​​ arguments​​ disguised ​​as [kworker/u2:0]​​,​​ a​​ miner​​ at​​/usr/sbin/systemd-logind​​, ​​and ​​immutable ​​bits ​​on files​ ​nobody should have locked.​

​4. Treat AI API keys like bank credentials​

​The​​ doctrine​​ ranks ​​them ​​first,​​ so​​ inventory​​ where​​ they ​​live, ​​rotate ​​them,​​ and​ ​monitor their usage.​

​5. Watch the network pattern​

​This​ ​crew’s​ ​signature​ ​is​ ​deterministic​ ​reverse​ ​tunnels​ ​toward​ ​AS262145​​,​ ​on​ ​ports derived from the​​ MD5​​ of the host’s own IP.​

​Indicators of compromise​

Extracted Entities