返回所有文章
发布于 · 作者 Renaud Deraison

那条命令的开头是 npm install

2026 年 8 月 24 日,Cato Networks 的 CTRL 团队公开了一场攻击行动:它买下“codex macos download”的 Google 赞助搜索结果,把开发者带到一个伪装成 OpenAI Codex 门户的 Google Sites 页面,再请他们把一条命令粘贴进终端,而那条命令的第一行,是真正的 Codex npm install。这一行之后的所有内容都是 base64。Bromure Agentic Coding 从不让任何人去寻找编码代理:安装命令是 Bromure 自家镜像目录里的一段固定字符串,它在一次性的 Linux 虚拟机中运行,虚拟机里的凭据都是诱饵,而只要把未匹配的出站流量设为拒绝,加载器的那三次抓取就永远出不了这台机器。

两年来,业界一直在为编码代理“装了什么”构建控制。这场行动往前多走了一步, 转而污染你“怎么安装”编码代理。那一步没有注册表,没有锁文件,也没有来源 证明。它只有一个搜索框、一个看起来没问题的页面,以及你自己放在键盘上的手。

一位开发者想在自己的 Mac 上试试 OpenAI 的 Codex CLI,于是在 Google 里敲下 codex macos download。第一条结果是赞助的,排在 OpenAI 自己的条目之上。它通往 一个干净的下载门户,标识对、排版也对,托管在 sites.google.com 上。页面写着: 打开终端,把这个粘贴进去。

他粘贴了。命令以 npm install 开头,包名也是对的。

8 月 24 日,Cato Networks 的研究团队 CTRL 发布了 这场行动的分析, 同日被 Infosecurity MagazineSiliconANGLETechzine 转载。最终载荷是一个 macOS 窃密程序。真正值得写成报告的,是它的投递方式。

页面由 Google 托管,诱饵由别人托管。

Google Sites 是个建站工具。任何人只要有账号,就能在 Google 域名上拥有一个页面, 而证书、锁形图标和网址的前半段,全都属于 Google。那就是被租来的信任。

页面本身什么也没有。Cato 在上面完全没找到恶意代码。诱饵是通过一个指向攻击者 基础设施的 iframe 送达的;按 Cato 的分析,它还经由 Google 的静态内容代理转发, 所以连第二跳看起来都像是 Google 在抓取什么东西。Techzine 点名了其中两个 iframe 主机:bright-links[.]comswiftsaverfin[.]com

这种切割为运营者买到了两样东西。看得见的那个页面永远不变,所以它不会触发信誉 系统,也不会被重新审查;而他们可以随时在 iframe 的另一侧替换载荷。Cato 数出 三组彼此独立的基础设施,其中第三组复用了第一组的一个 iframe 主机。

其余部分读起来就像一场成熟的广告欺诈运营。活的诱饵放在一个混淆过的路径 /codexx/ 下面,而 /codex/ 提供的是无害的东西。运营者会对访客做指纹识别,任何 看起来不像合理 macOS 目标的访客,都只会看到良性内容——那是他们给研究人员和沙箱的 回答。域名会轮换。载荷网址也会变。

第一行是真的

ClickFix 不给你一个文件。它给你一条指示,让你自己把载荷搬过边界。用 Techzine 的话说:“没有任何文件被下载,自然也没有杀毒方案能拦。”

粘贴的那条命令,开头是一段看起来完全合法、属于 Codex 的 npm install 字符串。 整个把戏就在这里。一个正要安装 Node CLI 的开发者看到 npm install,看到自己搜索 的包名,大脑就把这一行归档成正确。后面那团 base64 只隔着一个 shell 运算符,就在 同一行上,在复制框折行的另一侧。当一条命令的前半段正是你预期的命令时,你不会去读 它的后半段。

解码之后,它会抓取一个远程脚本,再把它管道给 zsh。接下来是三个阶段。

第一阶段是一个用死代码和未使用变量注水的 shell 脚本,里面包着一团编码过的 数据,最后交给 eval。注水的存在,是为了打败特征匹配,也是为了让随手翻看文件的 人放弃。

第二阶段在做任何其他事之前,先带着 event=pasted 这个参数向攻击者回传信标。 那是一张投递回执。另一端有人正在测量他们各个落地页的“粘贴率”,就像营销人员测量 转化率一样。

第三阶段把二进制文件下载到 /tmp/helper,执行 xattr -c 去掉 macOS 加在所有 来自网络之物上的隔离属性——正是这一步让 Gatekeeper 的警告消失——然后标记为可执行 并启动它。这个二进制文件是通用 Mach-O,所以在 Intel 和 Apple Silicon 上都能跑。

Cato 指出,运营者仍在持续开发这个加载器。较早的样本使用带压缩的 base64;较新的 则使用 AES 加密的 gzip 容器,其密钥是从散落在脚本各处的变量重新拼装出来的。

至于最终载荷,Cato 把这套投递框架与 Atomic macOS Stealer 联系起来:加载器 网址的结构、遥测请求的形状、/tmp/helper 这个暂存路径、xattr 的移除、以更新 为主题的载荷网址。他们称这些重叠既强烈又一致,但止步于给那个二进制文件命名——这是 正确的判断,在转述时也值得一并保留。

投递:受害者看到的一切codex macos download赞助结果,排在OpenAI 官方条目之上sites.google.comCodex 门户的仿冒品,自身没有恶意代码iframe:真正的诱饵bright-links[.]comswiftsaverfin[.]com“开终端,粘贴这段”没有下载开发者读到的唯一一行npm install ... codex ...; base64 -d ... | zsh执行:三个阶段,三次出站抓取1 · 加载器用死代码与未用变量注水的 shell 脚本eval "$blob"2 · 回执遥测信标回传?event=pasted运营者的转化指标3 · 载荷/tmp/helperxattr -c ; chmod +x通用 Mach-O
从搜索框到运行中二进制文件的完整链条。其中任何一环都没有漏洞利用:一条赞助广告、一个什么都不含的 Google 托管页面、一个什么都含的 iframe,以及一个用粘贴动作亲手把载荷搬过边界的人。受害者唯一看得到的那条命令,开头是真正属于 Codex 的 npm install 行;跟在后面的 base64 才去抓第一阶段。第二阶段的 event=pasted 信标,是运营者自己的投递回执。

扫描器上游的那一步

把业界花了两年、为编码代理打造的那些控制排开来看。注册表信誉扫描。锁文件与完整性 哈希。构建来源与证明。SBOM。新包版本的最短存在时间门槛。对生成代码做静态分析。 它们都有效,而且都从同一个假设出发:开发者已经有一套能用的工具链,风险在下游, 在他拿它来做什么。

这场行动坐在这一切的上游。这里的赝品是代理本身,而它在任何注册表之前、任何 锁文件之前就已抵达,以一条开发者用自己的手敲进自己终端的命令抵达。扫描器没有任何 制品可以打分,因为那个制品是网页上的一句话。

锁定目标是这门经济的另一半。会去竞价 codex macos download 的人,买的是一台属于 “此刻正在搭建编码代理”之人的机器:一台在一小时内就会装着 API 令牌、SSH 密钥、 一份 ~/.aws/credentials 和一枚 GitHub PAT 的机器,而这些东西窃密程序全都知道 去哪里找。安装的那一刻,是待在现场最便宜的时间点。

我们写过这件事的反面:在 FakeGit 与 AgentBaiting 里,是代理 去搜索,再把安装步骤递给人。这里则是去搜索。两者都成立,因为“先发现、再粘贴” 就是软件被安装的方式,而这个回路的两端都没有扫描器坐镇。

安装命令从哪里来

Bromure Agentic Coding 没有这样的回路,原因就在代理是从哪里 来的。

你不会去寻找编码代理。Codex 是配置文件 Agents 面板里的一个开关,就在 Claude Code 和 Grok Build 旁边。把它打开,选好它怎么认证,下一次会话开始时代理就在那里 了,在配置文件的虚拟机内某个 kitty 标签页中运行。

那个开关背后是一段固定字符串。Bromure 从自家目录预置基础镜像,而 Codex 的条目只有 一行:

npx --yes @socketsecurity/cli npm install -g --silent @openai/codex

Claude Code 按同样的模式是 @anthropic-ai/claude-code,Kimi Code 是 @moonshot-ai/kimi-code。包名是编译进应用里的,不是被发现的。注册表是 registry.npmjs.org,不是某个 iframe 指定的任意主机。安装过程被包在 socket.dev 的 CLI 之外,抓取动作则经由宿主机的 MITM 代理送出,配置文件的 Supply Chain 策略就在那里生效:默认开启的两天存在时间门槛,加上 OSV 查询、socket.dev 或 Delpi 过滤,以及你可以打开的安装脚本剥除。

那条路径没有搜索结果,也没有可供冒充的页面。攻击者花钱去污染的那个渠道,根本不在 这套工作流里;而“不存在”不是一个你得记得去操作的控制。

用常规方式安装谁给制品起名?赢得广告竞价的那个人谁负责提供?仿冒页面上的一个 iframe运行的是什么?第一行之后的任何东西在哪里?你的 Mac、你的用户账号,旁边就是~/.ssh · ~/.aws · ~/.git-credentialsGatekeeper 被 xattr -c 消音四个没有答案的问题,由陌生人代答。在 Bromure 配置文件中启用谁给制品起名?@openai/codex,来自镜像目录谁负责提供?registry.npmjs.org,经宿主机代理运行的是什么?一条编译进去的命令,没有自由文本在哪里?一台一次性的 Linux 虚拟机,早在这场搜索之前就建好 — 里面没有密钥,凭据都是诱饵,出站流量受管控同样四个问题,在你问之前就已作答。
获取编码代理的两种方式。左边,获取这一步就是一个搜索框和一个复制按钮:制品的名字、提供它的主机、以及安装它的命令,全都由赢得广告竞价的人决定,而结果会跑在那台装着开发者密钥的 Mac 上。右边,制品名称编译进应用,注册表固定,抓取动作在宿主机代理处被过滤,安装则在一台早在这一切开始之前就建好的一次性虚拟机中运行。

那就照样粘贴看看

架构必须撑过有人无视它的那一天。把这场行动拿过来,让它赢,然后带着它走一遍配置 文件:有人找到那个假门户,复制了命令,把它粘贴进自己做代理工作的终端——在 Bromure Agentic Coding 里,那是虚拟机内的一个 kitty 标签页。

那个二进制文件跑不起来。 通用 Mach-O 是 macOS 的可执行文件。客户机是 Ubuntu。 xattr 不是 Linux 命令,而 /tmp/helper 是一个位于“本来就是要被丢掉”的系统盘上 的路径。Resources → Storage 提供给 /home/ubuntuErase home…,以及 Reset to base…——从共享的、只读的基础镜像重新克隆工作区的系统盘。

那三次抓取出不去。 这条链的每个阶段都需要网络:base64 解码后那个拉取第一阶段 的网址、event=pasted 信标,以及载荷下载。Guardrails → Outbound connections 是一张 pf 风格的规则表:动作、协议(tcpudpwebany)、主机或 CIDR、 端口,web 还可以列 HTTP 方法;自上而下匹配,第一个命中者胜出,而 Unmatched traffic 可设为 Allow 或 Deny。把它设成 Deny,再列出你工作真正需要的 主机就行。bright-links.com 不在其中。Bromure 在宿主机侧、在虚拟交换机和代理里 强制执行这张表,所以客户机对自己环境做的任何事,都改变不了答案。

值得坐下来细看的是第二阶段。event=pasted 是运营者的转化指标,是那个告诉他们某个 落地页有效、以及有多有效的 ping。当这个请求死在宿主机上,他们拿到的不是一份感染 失败报告。他们拿到的是沉默,而沉默读起来就像一次没有转化的广告展示。

窃取拿回去的是占位符。 Atomic 这一级的窃密程序,盯的是浏览器数据、加密钱包, 以及——在开发者机器上——凭据。在 Bromure 的配置文件里,真正的值从来不会进入虚拟机。 通用 API 密钥是以环境变量导出的 brm_… 假值,由宿主机代理在传输途中替换掉。 kubeconfig 是合成的,配一套用完即弃的客户端证书。AWS 请求会在宿主机侧重新签名, 所以任何绕过代理的东西都会拿到 InvalidSignatureException~/.docker/config.json 里放的是一团假的 base64。SSH 私钥根本不在里面等着被读: 它们从来就不在。逐条为凭据打开 Require approval to use,每一次替换就会变成一个宿主机侧的对话框,附带一段有 时限的授权:五分钟、一小时,或这次会话的其余时间。一个配置文件最多只共享你挑选的 八个文件夹,所以 Mac 的其余部分并不是“多走几层目录”就能到的地方。

关联分析早就在你屏幕上了。 Cato 自己的结论是,这场行动的任何单一阶段都不会 让它现形;要检测到它,得把赞助搜索的投递、内嵌的网页内容、终端里的执行,以及出站 活动放在一起关联。当你的证据分散在浏览器、shell 和网络抓包里,那是个难题。在 配置文件里,它只是一个窗口:Security Log(Window → Security Log…)是一张 宿主机侧的单一时序表格,记录包判定、防火墙决策、凭据替换与提示注入检测。客户机 代码无法编辑它,因为客户机代码根本够不着它。

把它打开

存在时间门槛默认就是开的,设在两天。其他层次都是设置,而且值得花两分钟: Guardrails → Outbound connections,把 Unmatched traffic 设成 Deny,再为你 工作需要的主机建一份允许清单。Supply Chain → OSV vulnerability check,如果你 有密钥,再加上 socket.dev 或 Delpi 过滤,还有安装脚本剥除。Credentials → 对任何能花钱或能删数据的东西打开 Require approval to use。然后把 Security Log 窗口开在第二块屏幕上放一个星期,看看你的构建到底都在跟谁说话。

赞助搜索结果还会继续当那道前门,受信任域名上的建站工具也还会继续出租门廊。Google 会下架这些页面,然后又会有三个新的立起来,因为这门生意的算式是“每次点击几美元” 对上“一台装着云凭据的开发工作站”。 安装 Bromure Agentic Coding,从配置文件编辑器而不是下载页启用 你的代理,让下一条被粘贴的命令,落在一台生来就是要被丢掉的机器里。