Back to all posts
Published on · by Renaud Deraison

They added your agent to the list

Gen Digital published research on September 8 showing eight commodity infostealer families now collecting the local data of AI coding agents: access and refresh tokens, MCP configurations, conversation databases, prompt histories, project traces. No flaw in Claude, Cursor or Codex is involved. Stealers carry remotely managed collection rules, so adding your agent's folder was a configuration push to machines already infected. Bromure Agentic Coding moves that folder into a VM and fills it with brm- fakes, and keeps the refresh token on the host where the guest can never hold it.

Your coding agent has no bug for anyone to find. Somebody noticed where it keeps its files, and pushed one new line of configuration out to a few hundred thousand machines that were already compromised.

On September 8, Jan Rubín, who leads Gen Digital's threat research team, published a short piece with an unglamorous finding. Eight separate families of commodity information-stealing malware now collect the local data of AI coding agents. They copy files. That is the whole technique.

The named targets read like a poll of what developers installed this year: Claude, Cline, Codex, Continue, Cursor, OpenCode, Kilo. Amatera went after Cline and Continue. Remus went after Claude, Cursor and OpenCode. CallbackBeaver added Cursor and Claude, and Gen counted more than 5,000 samples of it in a thirty-day window. BeeStealer, STG Stealer, HydraStealer, APEX Stealer and Otter Stealer are all doing some version of the same thing. On macOS the variant is Djinn Stealer, and its list is the longest: Claude, Codex, Gemini, Cline, OpenCode, Kilo.

Rubín is careful about what he is describing. "The activity does not point to a newly discovered flaw in Claude, Cursor, or Codex," he writes. "Instead, it shows criminals adapting established stealers to collect valuable files stored in predictable local folders."

The list got one line longer

The change cost its authors almost nothing.

Modern stealers do not hard-code what they take. They ship with remotely managed collection rules: a configuration blob listing folders, filenames, database files, extensions and search limits, fetched from the operator's infrastructure. Adding a new target, as Cyber Press summarized it, means operators "add newly popular AI tools to malware collection lists by updating paths, filenames, or database rules without necessarily rebuilding the malware."

This was a product decision. Somebody looked at which folders now hold something worth selling, wrote a few paths into a config, and the machines already running one of these families began shipping agent data on their next check-in. The operators reinfected nothing. The binary on disk stayed the same, so the detection signature did too.

Gen recorded infostealer detections against 3.3 million unique protected users in the first half of 2026, with monthly totals above 500,000. Amatera and Remus alone showed up among tens of thousands of users over three months. That is the population the operators pushed the new rule to.

a config push, not a campaignoperator — collection rulesbrowsers, cookies, walletsSlack, Discord, VPN profilesssh keys, cloud storage paths+ AI coding agent directoriesone appended line, Septembernext check-inmachines already infected3.3M unique users, H1 2026500,000+ detections a monthbinary unchanged on diskno reinfection neededno new signature to catchwhat leaves the laptopaccess + refresh tokensMCP server credentialsconversation databaseprompt historyproject names, cached sourceaccount + subscription detailseight families, one quarterAmatera · Remus · CallbackBeaver · BeeStealer · STG · Hydra · APEX · Otter — and Djinn on macOS
Adding AI coding agents to the loot list cost the operators no new build. Commodity stealers fetch remotely managed collection rules (folders, filenames, database files, extensions) from their operators. An operator appends the agent directories, and every already-infected machine begins collecting them on its next check-in. The binary on disk is unchanged, so nothing about the machine looks different.

What is in that folder

Gen's inventory of what the rules collect is specific: "access and refresh tokens, credentials stored in MCP configurations, prompt histories, conversation databases, account details, and traces of the projects a developer has been working on."

That list holds two different kinds of loss under one name.

The first is access. An access token buys a session. A refresh token buys sessions, plural, for as long as it stays valid, because someone designed it to outlive the session it came from. That property is what makes it worth stealing, and it is why revoking one session leaves the thief where he was. Next to it in the same folder sit the credentials from your MCP configuration, which open something else again: an internal service, a ticketing system, a database behind an HTTP MCP server.

The second kind of loss is intelligence, and it is newer. Your prompt history is a narrated tour of your employer's infrastructure. Cyber Press put it plainly: stolen prompt histories reveal "repository names, internal hostnames, infrastructure details, security controls, API secrets, and business plans." On a Tuesday you type in the name of the service, the name of the cluster, the reason the migration is blocked, and then you paste the snippet with the connection string in it to ask why the thing keeps failing. You have never written a threat model for your own chat log.

It arrives through a search result

Landing the stealer takes no zero-day either. In May, EclecticIQ documented a campaign that ranked fake install pages above the real ones: claudecode.co.com and geminicli.co.com, mimicking vendor documentation closely enough to pass a glance. The page hands you a PowerShell line to copy. Run it and you get the tool you wanted, installed in plain view, while a second hidden command pulls a fileless stealer straight into memory. It switches off ETW and AMSI on the way in, then harvests browsers, Slack, Teams, Discord, VPN clients, SSH keys and cloud storage paths. The same actor ran the same play against Node.js, Chocolatey, KeePassXC and Monero.

The victim, then, is the developer who searched for a coding agent and clicked the top result. Four months later that developer is also handing over the agent's tokens and conversation history, because the collection rule grew a line.

The same sweep, inside a Bromure workspace

Bromure Agentic Coding runs each coding agent in a hardware-virtualized Linux VM on your Mac and keeps every real secret on the host side of that boundary. Take Gen's collection list item by item and run it against a workspace. Assume the stealer wins on the host, reads the rule, and goes to fetch each thing.

Access and refresh tokens. If you use a Claude or ChatGPT subscription rather than an API key, the login never happens in your working VM. Bromure boots a throwaway registration VM with no workspace folders mounted and no credential swap map, runs the real claude login inside it, captures the resulting OAuth tokens on the host, encrypts them, and destroys the VM. From then on the guest runs in API-key mode holding a deterministic bogus credential: a fake ANTHROPIC_API_KEY for Claude, a ~/.codex/auth.json seeded with a bogus far-future-expiry JWT for Codex so the client never tries to refresh it itself. The host does the refreshing, about five minutes ahead of expiry, once for every running VM. The manual puts the consequence plainly: the guest never holds a refresh token.

Credentials stored in MCP configurations. The MCP bearer gets the same treatment, and the settings pane says so. The real token for an HTTP-transport MCP server stays on the host, the config the agent reads gets a brm-mcp_… placeholder, and the proxy substitutes the real value on the wire, scoped exact-or-subdomain to that server's host and nowhere else. The field in the MCP pane carries the caption Never sent to VM — swapped by proxy.

Everything else that looks like a key. Every credential you configure is replaced inside the VM by a structure-preserving fake, derived from the real value plus a per-install salt, so it keeps the shape validators expect and stays stable across sessions: sk-ant-api03-brm-…, sk-brm-…, xai-brm-…, brm-k8s-…, brm-docker-…, brm-db-…. The swap channel only runs one way. The host can write fakes into the guest; there is no call by which the guest asks for a real value back, and the in-VM agent refuses to write any credential that does not carry the brm- prefix.

Conversation databases, prompt histories, project references, cached source. These are real and durable, because coding work needs durable state. They live in the workspace VM's own persistent home folder, one per workspace, behind the hypervisor, rather than in the macOS home directory that the collection rule names. A rule that says "copy the agent's config directory from the user profile" finds a user profile with no agent in it.

The host's own store. What the host keeps is encrypted at rest with AES-GCM under a per-install 256-bit master key that lives in the macOS Data Protection Keychain, scoped to the app's signing identity, with iCloud sync disabled. The app uploads and syncs nothing. Copy the Application Support folder, or restore a Time Machine backup of it, and without this Mac's keychain entry you have ciphertext.

the collection rule, run inside a workspacewhat the rule asks forwhat it findsaccess + refresh tokensa bogus key; no refresh token exists in the VMhost refreshes ~5 min before expiry, for every VM at onceMCP configurationbrm-mcp_…real bearer swapped on the wire, scoped to that host onlyAPI keys, cloud credentialssk-ant-api03-brm-… · brm-k8s-… · brm-db-…right shape, wrong value, inert off their scopeconversation db, prompt historyreal, durable — and inside the VM's home, not yoursthe path in the rule names a folder your Mac does not have
Gen Digital's collection list, item by item, run against a Bromure Agentic Coding workspace. The subscription tokens are host-side and refreshed host-side, so the guest never holds a refresh token. The MCP bearer in the agent's config is a brm-mcp placeholder. API keys are structure-preserving fakes. The conversation database and prompt history are real, and they sit in the VM's persistent home rather than the macOS home directory the rule points at.

When the sweep happens inside the VM

A stealer can arrive the other way as well: pulled in by the agent itself, through a dependency or a poisoned instruction, and run inside the workspace. Then the sweep succeeds, and it collects fakes. The upload is where it falls over.

Each fake has one legitimate destination family, the host scope it was minted for, so the proxy scans every outbound request, headers and body, with an Aho-Corasick automaton cheap enough to run on everything, looking for a fake heading somewhere it does not belong. On a hit it refuses the request with HTTP 451 without forwarding a byte, pauses the VM on the spot, and raises an alert offering Shut down, Save for Investigation (export the disk, home and shared folders for forensics first), or Continue at your own risk. The event lands as a red Credential brokering row in the Security Timeline, the app marks the workspace compromised, and the next launch requires Wipe and Launch.

The proxy also flags unswapped, real-looking secrets in outbound traffic: Bearer and x-api-key values with known prefixes like sk-ant-, ghp_ or AKIA, and opaque tokens of twenty characters or more. Those show up in the Trace Inspector and in bromure-cli trace leaks. They usually mean somebody pasted a real secret into the VM by hand, which is the one way you can undo the boundary from the inside.

Reachability is the third check. Every workspace carries an ordered egress firewall covering action, protocol, host or CIDR, ports, and for web traffic the individual HTTP verbs, with a segmented control for unmatched traffic. New workspaces allow what no rule matches. Set it to Deny, list what the work needs, and a stealer's C2 host is not on the list. Two components outside the guest enforce it: the virtual network switch matches every flow by destination IP and DNS-snooped hostname, and the proxy matches again by TLS server name. Your rule edits reach running sessions without a reboot.

the state is in your home directorya predictable path, readable by anything running as youthe agent’s directoryaccess token · refresh tokenMCP bearer tokensconversation databaseprompt history · project namesresident stealer reads the rule, copies the folderthe binary never changed; only the path list diduploadedrenewable access, plus a map of the estatethe state is in a VM, and it is decoysyour macOS home holds no agent directory to nameworkspace VM — persistent homebogus key · no refresh tokenbrm-mcp_… · brm-k8s-… · brm-db-…conversation database and history, behind the hypervisorreals encrypted on the host, AES-GCM, keychain keyvsock 8443 — the only route outhost proxy — consulted per requestegress firewall · host, port, HTTP verbswap · real value injected for one host onlyone trace row per request, on your machinefake off its scope → HTTP 451, VM paused, timeline row
Two places to keep an agent's state. On an ordinary Mac the tokens, MCP credentials and conversation history sit in a predictable folder in the user profile, which is what the collection rule names, and anything that runs as you can read it. In a Bromure Agentic Coding workspace the same state sits in a VM's persistent home, the credentials in it are brm- fakes, and the only route out is vsock port 8443 into a host proxy that checks the firewall, swaps credentials and refuses any fake headed off its scope.

If you install agents by copy-paste

Check where you got them. EclecticIQ's campaign ranked claudecode.co.com and geminicli.co.com above the real pages and handed visitors a PowerShell line that installed the genuine tool while pulling a stealer into memory. If that describes an install you did, treat the whole machine as exposed: revoke subscription sessions rather than rotating one key, rotate every token in your MCP configuration, and read your own prompt history the way an attacker would. The hostnames and repository names in it are the part you cannot rotate.

The two settings that shrink the target

Register your Claude or ChatGPT subscription through the workspace editor so the OAuth tokens are captured on the host and the guest runs on a bogus key. Then open Guardrails, set Unmatched traffic to Deny, and list what the work needs: allow web api.github.com, allow web registry.npmjs.org, default deny. Run bromure-cli trace hostnames my-workspace after a session to see every host the agent reached, with counts.

Loot follows adoption

Stealers learn folders in a predictable order. Browser profiles, then cryptocurrency wallets, then Discord and Slack tokens, then VPN profiles. Each one entered the collection rules a year or two after the thing it belonged to became normal. The lag is how long it takes for enough machines to have the folder to make the line of config worth writing.

Coding agents crossed that threshold this year, at an entry price of one configuration update, across eight families, inside a single quarter. No patch closes this, because nothing is broken. The folder is where it is supposed to be, holding what it is supposed to hold, on a machine that also runs your browser and your email.

What changes the outcome is making the folder worth less than the trouble of copying it. Put the agent's state on the other side of a hypervisor, fill its credential files with values of the right shape and the wrong number, and keep the real ones on the host where the refresh happens.

Your coding agent is a normal application that keeps normal files in a normal place, and that is why it got added to the list. Decide what those files are allowed to be worth, before the next family updates its config. Install Bromure Agentic Coding and let them copy the decoys.