The command began with npm install
On August 24, 2026, Cato Networks' CTRL team published a campaign that buys sponsored Google results for "codex macos download", lands developers on a Google Sites page dressed as OpenAI's Codex portal, and asks them to paste a Terminal command whose first line is a real npm install for Codex. Everything after that line is base64. Bromure Agentic Coding never sends anyone looking for a coding agent: the install command is a fixed string in Bromure's own image catalog, it runs inside a disposable Linux VM, the credentials in there are decoys, and with unmatched outbound traffic denied the loader's three fetches never leave the machine.
For two years the industry has been building controls for what a coding agent installs. This campaign goes one step earlier and poisons how you install the coding agent. That step has no registry, no lockfile and no provenance attestation. It has a search box, a page that looks right, and your own hands on the keyboard.
A developer wants to try OpenAI's Codex CLI on their Mac, so they type
codex macos download into Google. The first result is sponsored, sitting
above OpenAI's own listing. It goes to a clean download portal with the right
logo and the right typography, hosted on sites.google.com. The page says:
open Terminal, paste this.
They paste it. The command starts with npm install and the package name is
correct.
On August 24, Cato Networks' CTRL research team published the write-up of that campaign, picked up the same day by Infosecurity Magazine, SiliconANGLE and Techzine. The payload is a macOS infostealer. The delivery is what earns the write-up.
Google hosted the page. Someone else hosted the lure.
Google Sites is a site builder. Anyone with an account gets a page on a Google domain, and the certificate, the padlock and the first half of the URL all belong to Google. That is the rented trust.
The page itself contains nothing. Cato found no malicious code on it at all.
The lure arrives in an iframe pointed at attacker infrastructure, routed,
per Cato's analysis, through a Google static-content proxy, so even the second
hop looks like Google fetching something. Techzine names two of the iframe
hosts: bright-links[.]com and swiftsaverfin[.]com.
The split buys the operators two things. The visible page never changes, so it never trips a reputation system or gets re-reviewed, and they swap payloads on the far side of the iframe whenever they like. Cato counted three separate infrastructure sets, with the third reusing an iframe host from the first.
The rest reads like a mature ad-fraud operation. Live lures sit under an
obfuscated path, /codexx/, while /codex/ serves something harmless. The
operators fingerprint visitors, and anything that is not a plausible macOS
target sees benign content, which is their answer to researchers and sandboxes.
Domains rotate. Payload URLs vary.
The first line was real
ClickFix does not serve you a file. It gives you an instruction and lets you carry the payload across the boundary yourself. As Techzine puts it, "no file is downloaded that an antivirus solution could block."
The pasted command begins with a legitimate-looking npm install string for
Codex. That is the whole trick. A developer who is about to install a Node CLI
sees npm install, sees the package name they searched for, and their brain
files the line as correct. The base64 blob that follows is one shell
operator away, on the same line, past the fold of a copy box. You do not read
the second half of a command whose first half is the command you expected.
Decoded, it fetches a remote script and pipes it into zsh. Three stages
follow.
Stage one is a shell script padded with dead code and unused variables,
wrapping an encoded blob that gets handed to eval. The padding exists to
defeat pattern matching and to make a human skimming the file give up.
Stage two beacons back to the attacker with an event=pasted parameter
before it does anything else. That is a delivery receipt. Someone on the other
end is measuring paste-through rate on their landing pages, the way a marketer
measures conversions.
Stage three downloads the binary to /tmp/helper, runs xattr -c to strip
the quarantine attribute macOS attaches to anything that arrived from the
network, which is what suppresses the Gatekeeper warning, marks it executable,
and launches it. The binary is a universal Mach-O, so it runs on both Intel and
Apple Silicon.
Cato notes the operators are still developing the loader. Earlier samples used base64 with compression; newer ones use AES-encrypted gzip containers whose key is reassembled from variables scattered through the script.
For the final payload, Cato ties the delivery framework to Atomic macOS
Stealer: the loader URL structure, the shape of the telemetry request, the
/tmp/helper staging path, the xattr removal, the update-themed payload
URLs. They call the overlap strong and consistent and stop short of naming the
binary, which is the right call and worth keeping when you repeat it.
The step upstream of the scanners
Line up the controls the industry has spent two years building for coding agents. Registry reputation scanning. Lockfiles and integrity hashes. Build provenance and attestation. SBOMs. Minimum-age gates on new package versions. Static analysis on generated code. They all work, and they all start from the same assumption: the developer already has a working toolchain, and the risk is downstream, in what they do with it.
This campaign sits upstream of all of it. The counterfeit here is the agent itself, and it arrives before any registry, before any lockfile, in a command the developer types with their own hands into their own terminal. A scanner has no artifact to score, because the artifact is a sentence on a web page.
The targeting is the other half of the economics. Somebody bidding on codex macos download is buying the machine of a person who is, at that moment,
setting up a coding agent: a machine that within the hour will hold an API
token, an SSH key, a ~/.aws/credentials file and a GitHub PAT, all of which
an infostealer knows how to find. The install moment is the cheapest time to be
there.
We have covered the inverse of this before: with FakeGit and AgentBaiting, the agent does the searching and hands the human the install steps. Here the human does the searching. Both work because discovery-then-paste is how software gets installed, and no scanner sits at either end of that loop.
Where the install command comes from
Bromure Agentic Coding has no such loop, and the reason is where the agent comes from.
You do not go looking for a coding agent. Codex is a toggle in a profile's Agents panel, next to Claude Code and Grok Build. Switch it on, pick how it authenticates, and the agent is there in the next session, running in a kitty tab inside the profile's VM.
Behind that toggle is a fixed string. Bromure provisions its base image from its own catalog, and the entry for Codex is one line:
npx --yes @socketsecurity/cli npm install -g --silent @openai/codex
Claude Code is @anthropic-ai/claude-code on the same pattern, Kimi Code is
@moonshot-ai/kimi-code. The package names are compiled into the app, not
discovered. The registry is registry.npmjs.org, not whatever host an iframe
nominates. The install is wrapped through the socket.dev CLI, and the fetch
goes out through the host's MITM proxy, where the profile's Supply Chain
policies apply: the two-day age gate that is on by default, plus the OSV
lookups, socket.dev or Delpi filtering, and install-script stripping you can
switch on.
That path has no search result and no page to impersonate. The channel the attacker paid to poison is missing from the workflow, and missing is not a control you have to remember to operate.
Now paste it anyway
Architecture has to survive the day someone ignores it. Take the campaign, hand it the win, and walk it through a profile: someone finds the fake portal, copies the command, and pastes it into the terminal they do agent work in, which in Bromure Agentic Coding is a kitty tab inside the VM.
The binary does not run. A universal Mach-O is a macOS executable. The
guest is Ubuntu. xattr is not a Linux command, and /tmp/helper is a path on
a system disk that exists to be discarded. Resources → Storage gives you
Erase home… for /home/ubuntu and Reset to base… to re-clone the workspace
system disk from the shared, read-only base image.
The three fetches do not leave. Each stage of that chain needs the network:
the base64-decoded URL that pulls stage one, the event=pasted beacon, and the
payload download. Guardrails → Outbound connections is a pf-style rule
table: action, protocol (tcp, udp, web, any), host or CIDR, ports, and
for web a list of HTTP methods, matched top to bottom, first match wins, with
Unmatched traffic set to Allow or Deny. Set it to Deny and list the hosts
your work needs. bright-links.com is not one of them. Bromure enforces the
table host-side, in the virtual switch and the proxy, so nothing the guest does
to its own environment changes the answer.
Stage two is the one worth sitting with. event=pasted is the operator's
conversion metric, the ping that tells them a landing page is working and how
well. When that request dies at the host, they do not get a failed infection
report. They get silence, which reads like an ad impression that never
converted.
The theft returns placeholders. An Atomic-class stealer goes after browser
data, wallets, and on a developer machine, credentials. In a Bromure profile
the real values never enter the VM at all. Generic API keys are brm_… fakes
exported as environment variables and swapped on the wire by the host proxy.
The kubeconfig is synthetic, with throwaway client certs. AWS requests are
re-signed host-side, so anything that routes around the proxy gets
InvalidSignatureException. ~/.docker/config.json holds a fake base64 blob.
Private SSH keys are not in there to read:
they never were. Turn on
Require approval to use per credential and each swap becomes a host dialog
with a time-bounded grant: five minutes, an hour, the rest of the session. A
profile shares at most eight folders you picked, so the rest of the Mac is not
a directory walk away.
The correlation is already on your screen. Cato's own conclusion is that no single stage of this campaign exposes it; detection meant correlating the sponsored-search delivery, the embedded web content, the Terminal execution and the outbound activity together. That is a hard problem when your evidence sits in a browser, a shell and a network tap. In a profile it is one window: Security Log (Window → Security Log…) is a single chronological host-side table of package verdicts, firewall decisions, credential swaps and prompt-injection detections. Guest code cannot edit it, because guest code cannot reach it.
Turn it on
The age gate is on by default at two days. The other layers are settings, and they are worth two minutes: Guardrails → Outbound connections, with Unmatched traffic set to Deny and an allow list for the hosts your work needs. Supply Chain → OSV vulnerability check, plus socket.dev or Delpi filtering if you have a key, and install-script stripping. Credentials → Require approval to use on anything that can spend money or delete data. Then leave the Security Log window open on a second display for a week and see what your builds talk to.
Sponsored search results are going to keep being the front door, and site builders on trusted domains are going to keep hosting the porch. Google will take these pages down and three more will go up, because the economics are a few dollars per click against a developer workstation with cloud credentials on it. Install Bromure Agentic Coding, enable your agents from the profile editor instead of a download page, and let the next pasted command land in a machine that was built to be thrown away.