← Back to all posts
Published on · by Renaud Deraison

The stealer packed the stand-ins

On October 15, Symantec reported that Aoki, an infostealer first seen this year, now goes after coding-agent credentials: .claude.json, Codex's config.toml and .env files, tokens for GitHub Copilot, Cursor, Gemini, JetBrains AI Assistant and Kiro, and AWS keys. In Bromure Agentic Coding, every one of those files holds a stand-in, the sign-ins and keys stay encrypted on the Mac, and a stand-in sent to a stealer's server pauses the machine.

The stealer's list now starts with your coding agent. It wants .claude.json, the Codex config and the .env files next to it.

An infostealer used to go for browser cookies, saved passwords, crypto wallets and Discord tokens. Aoki still takes all of those. Recent builds also look for the files your coding agent keeps in your home folder.

Symantec's Threat Hunter Team described the change on Wednesday, October 15, in Aoki: Infostealer Targets AI Coding Assistant Credentials. Infosecurity Magazine covered it the same day. Aoki, also called Aokigahara after a string in its decryption routine, first appeared earlier this year. Symantec writes that "earlier versions of the malware did not target AI-related files." The newest sample does.

What Aoki takes

Symantec lists the agent files in the newest sample:

  • .claude.json and Claude desktop cookies.
  • ChatGPT cookies.
  • Codex's config.toml and .env files.
  • The Cursor local state database, which "can cache chat context and code snippets."
  • Tokens for GitHub Copilot, Cursor, Google Gemini, JetBrains AI Assistant and Kiro.
  • AWS credentials.

The rest of the list is the usual infostealer haul: more than forty browsers, about ninety wallet extensions, desktop wallets, password managers, Telegram, Discord, FTP and VPN clients. Aoki also searches for any file whose name contains secret, privatekey, keystore, mnemonic, passphrase or backup. Symantec notes that "the malware has no backdoor command list." It collects what it finds and posts it to a /gate endpoint on its command-and-control server.

Symantec explains why the agent files are worth the trouble: "Like card data, a stolen AI key can be cashed in directly." The buyer runs up usage on your account, which is the practice known as LLMjacking. The same tokens "can allow attackers to carry out activity under a legitimate user's identity" and can reach the repositories, cloud accounts and CI/CD pipelines the account is connected to.

Symantec does not say how Aoki gets onto a machine. On a developer laptop with a coding agent, the obvious way in is a package. The agent installs dozens of them on its own each day, and a malicious dependency with a postinstall script runs with the agent's permissions the moment npm install finishes.

The same list in a Bromure machine

In Bromure Agentic Coding the agent runs in a Linux VM on your Mac. Real credentials never enter that VM. The Mac keeps them in an encrypted vault and writes stand-ins into the VM, shaped like the real thing so every tool accepts them. A proxy on the Mac swaps each stand-in for the real value on the wire, and only on requests to the host the credential belongs to.

Put a stealer with Aoki's list inside that VM and walk it through its checklist.

.claude.json and the Claude key

Claude Code in the VM runs on sk-ant-api03-brm-…, a stand-in key. If you signed in with a Claude subscription, the OAuth tokens were captured on the Mac during sign-in and stored in claude-subscription.enc, encrypted. The host refreshes the access token about five minutes before it expires and injects it into requests bound for Anthropic. The VM never holds a refresh token, so neither .claude.json nor anything else in the home folder has a live Claude credential for the stealer to take.

Codex's config.toml, auth.json and .env

Codex gets a seeded ~/.codex/auth.json holding a bogus JWT with a far-future expiry, so the client doesn't try to refresh it. The real ChatGPT sign-in sits on the Mac in codex-subscription.enc. An OpenAI API key appears in the VM as sk-brm-….

A project .env imported with Import env file… in the machine's Credentials pane comes back under the same variable names, each value a brm_… stand-in scoped to the hosts you choose. Your code reads STRIPE_KEY the same way it always did, and the stealer reads brm_….

GitHub, AWS and SSH

~/.git-credentials and GH_TOKEN hold a ghp_ stand-in, 40 characters like the real thing. There is no ~/.aws/credentials. ~/.aws/config points at a credential_process helper that hands the AWS SDK the real access key ID with a 40-character fake secret key, and the Mac re-signs every request on its way to AWS. A stealer that copies the helper's output gets a secret key that produces only InvalidSignatureException.

The keyword sweep for privatekey or id_ed25519 turns up nothing. SSH_AUTH_SOCK in the VM is a bridge to a signing agent on the Mac, and the private key bytes never cross it.

Cookies

Aoki wants Claude desktop and ChatGPT cookies. The machine's VM has no desktop app and no browser profile to read. When you sign in to Claude or ChatGPT for Bromure, the sign-in page opens in your Mac's browser and the tokens land in the vault. The agent browses with a Chromium that runs in its own disposable sidecar VM, separate from the machine's VM, so a stealer in the agent's VM can't reach the browser's profile.

A stealer's checklist, inside a Bromure machineAgent's VMFile the stealer opensWhat it finds~/.claude.json, ANTHROPIC_API_KEYsk-ant-api03-brm-… (stand-in)~/.codex/auth.json, config.tomlbogus JWT, sk-brm-…project .envSTRIPE_KEY=brm_…~/.git-credentials, GH_TOKENghp_… (stand-in)AWS credentialsreal key ID + fake secret key~/.ssh/id_*no key file (signing bridge)The Mac, outside the VMEncrypted vault (AES-GCM)master key in the Data ProtectionKeychain, no iCloud syncclaude-subscription.enccodex-subscription.encmodels.encworkspace secrets, SSH keysRefresh tokens stay here.The proxy swaps a real value inonly for the host it belongs to.POST https://dobeqnesmot.cc/gatebody: sk-ant-api03-brm-…, ghp_…, brm_…Mac proxy: stand-ins headed for the wrong host451, nothing forwarded, VM paused
Aoki's checklist, run inside a Bromure machine. Every file on the list exists and holds a stand-in. When the stealer posts its haul to /gate, the proxy on the Mac finds the stand-ins headed for a host they were never minted for, returns 451 and pauses the VM.

The upload to /gate

Aoki finishes by posting its haul to /gate. Symantec names dobeqnesmot[.]cc, hjazfioe[.]surf and neihite[.]cc. In a Bromure machine, that request has to leave through the proxy on the Mac, because the proxy is the VM's only route to the network.

The proxy scans every outbound request, headers and body, for stand-ins headed anywhere other than the host they were minted for. A sk-ant-api03-brm-… value has one legitimate destination family, Anthropic. A ghp_ stand-in belongs to GitHub. Inside a POST to a .cc domain, they can only mean exfiltration. The proxy answers HTTP 451 and forwards nothing. The VM pauses on the spot, and the Mac shows This environment may have been compromised, with one line per leaked stand-in: a token preview, the credential's name, the host it belongs to and the host the stealer tried.

You choose what happens next. Save for Investigation exports the VM's disk, its home folder and the shared folders to a folder you pick, then shuts the machine down. Shut down stops it and marks it compromised. A compromised machine boots again only after Wipe and Launch, which replaces the disk and the home folder and keeps your tokens, SSH keys and settings. Your Claude sign-in, your GitHub token and your AWS keys were never in the VM, so the stealer copied nothing that needs rotating.

You can also stop the upload before the scan. In the machine's Guardrails pane, set Unmatched traffic to Deny under Outbound connections and list the hosts the machine needs. A connection to an unknown .cc domain is then refused, and the Security Timeline shows a red Firewall row for it.

If the stealer packs its haul so the scan can't read the stand-ins, the server at the other end still receives values that authenticate nowhere. A stand-in works only when it passes through your Mac's proxy on its way to the host it was minted for.

Before the stealer runs

The likeliest way into an agent's VM is a package the agent installed. The machine's Supply Chain pane checks every fetch on the Mac before the VM sees it:

  • The age gate, on by default with a two-day minimum, hides package versions younger than the cutoff. A hijacked release that is yanked within hours never reaches npm install.
  • Install-script stripping, when you turn it on, removes the preinstall, install, postinstall and prepare hooks from every npm tarball in flight, the usual way npm malware runs on install.
  • OSV, socket.dev or Depi block versions with known advisories and packages flagged as malware or typosquats, with a 451 whose reason the package manager prints verbatim.

Every fetch shows up in the Security Timeline, so after an incident you can find the package that brought the stealer in.

If the stealer runs on the Mac

Aoki's file list also names what a stealer finds on the Mac itself, and a Bromure install adds nothing to it. Bromure doesn't import your Mac's own Claude or Codex CLI logins and doesn't need them: the agents run in the VM, and their sign-ins live in the vault. Everything under ~/Library/Application Support/BromureAC/ that holds a secret is AES-GCM ciphertext. The master key sits in the Data Protection Keychain, scoped to Bromure's signing identity, and never syncs. A stealer that copies the folder takes encrypted blobs.

Symantec singles out Cursor's local database because it caches chat context and code. Bromure's record of what the agent did, the session trace, is encrypted at rest with the same vault key, and it stores token swaps as first-and-last-character previews only. No real secret appears in a trace, encrypted or not.

Every file on the list holds a stand-in

.claude.json, Codex's auth.json and config.toml, imported .env values, git credentials and AWS config all carry stand-ins. Refresh tokens and SSH private keys never enter the VM.

The upload stops the machine

The proxy finds stand-ins headed for a host they weren't minted for, answers 451, pauses the VM and names each leaked credential.

Nothing to rotate

Wipe and Launch replaces the disk and home and keeps your keys. The stealer took values that only work through your Mac's proxy.

The door is watched

The age gate, install-script stripping and reputation checks run on the Mac before a package reaches the VM, and every fetch is logged.

The list will grow

Symantec says Aoki's capabilities "still appear to be in active development," and other stealers will copy its list. Aoki added the agent files because stolen agent keys and sign-ins sell. Run your agents in a Bromure machine and the buyer gets a bundle of stand-ins that no server outside your Mac's proxy will accept.

For the everyday version of the same problem, where the agent itself copies a secret into its transcript, read The transcript kept the token. For a worm that went after the same files from a compromised npm package, read Revoking the token was the trigger.