让 Claude Code 给一个干净仓库做初始化时,README 能诱导它跑伪装成 Axiom 初始化的 Python 命令,再从 DNS TXT 取码开反向 shell(Mozilla 0din 演示)。动手前先去 TaoToken(https://taotoken.net/?utm_source=taotoken_aicg_blog_end )注册并建一把 Key,再进隔离环境。这件事的顺序很关键:很多团队卡在额度、多 Key、切模型上,一着急就把主力机的登录态、SSH agent、私有包 token 一起交给代理,等于把接近实习生的执行权限直接发出去。可是代理要跑起来就必须联网调模型,所以模型通道得先独立、可吊销、可停用,这一步做在隔离环境里成本最低,做在事后代价最大。
1. 0din 那条链路:干净仓库是怎么把 Claude Code 领进反向 shell 的
1.1 README 里的“初始化说明”为什么能骗过只审代码的人
过去审一个陌生仓库,重点在源码、依赖、构建脚本、CI 配置,这套习惯现在不够用了。AI 编程代理把仓库从“代码集合”变成了“可执行指令环境”——它读 README、读注释、读 issue,然后照着做。0din 那条链路里,真正危险的不是某个明显恶意的源文件,而是一段看上去很正常的初始化流程:仓库说明让代理运行一条伪装成 Axiom 初始化的 Python 命令,接着从 DNS TXT 记录里取出编码过的内容,最后打开反向 shell。
麻烦的地方在于每一步单独看都不刺眼。读 README 正常,跑初始化正常,让代理补一下本地环境也正常。风险发生在组合之后:代理既能读上下文,又能执行命令,还会为了把任务做完而主动跨过人类平时会停一下的环节。DNS TXT 取指令这种方式尤其容易漏,因为它不依赖一个可疑的域名后缀,也没有明显的下载动作,字符串看起来像配置项。
所以结论不该是“以后别用 Claude Code”,那太粗也没法执行。该改的是默认信任模型:陌生仓库的 README、脚本、注释、模板、配置文件,都要当成可能给代理下指令的输入面。而你自己的模型通道、Key、凭证,同样要按“这些东西代理都能碰到”来设计。
1.2 codexui-android 那条 npm 线:仓库干净不等于分发物干净
同一周的另一个方向更传统。npm 上有个包伪装成 Codex 的远程 Web UI,GitHub 仓库保持干净,后续版本里才加入窃取登录凭证的代码,目标包括存活时间更长的 refresh token。把两个事件放一起看,风险面就很完整了:一边是“仓库内容本身不脏,但它能指挥代理做脏动作”,另一边是“仓库看着干净,分发出去的包变脏”。
中文开发者最容易踩的是中间那块:看到 star 数、README 排版、几张截图、下载量,就把代理权限一次性交出去。更隐蔽的是把这件事和额度问题绑在一起——官方通道额度不够,就多开几个 Key、来回切模型、临时用个来路不明的包装工具,权限面在这几个动作里被悄悄放宽。
代理的价值来自自动执行,风险也来自自动执行。不能只吃自动化的红利,把执行边界交给模型临场判断。在被诱导的场景里,代理并不觉得自己在做坏事,它只觉得自己在完成一个合理的初始化任务。
2. 跑初始化之前先把模型通道独立出来
2.1 在 TaoToken 注册、建 Key、顺手看一眼模型广场
模型通道这件事,先做再谈隔离。打开 TaoToken 完成注册,进控制台创建 API Key,本文所有示例里都用占位符YOUR_API_KEY,真实 Key 只存在你本地。建 Key 的时候顺手看一眼模型广场,代理要用的模型 ID 以模型广场当时列出的为准,不要凭记忆或凭别人截图里的名字填,模型列表会变,写死一个过期名字只会在验证阶段浪费你半小时。
这里有个容易被忽略的细节:Key 建议按环境分开。主力开发机一把,隔离用的 VM 或容器一把。原因很直接,隔离环境里跑的是陌生仓库的初始化脚本,一旦脚本读走了 Key,你吊销的损失面只有这一个环境,主力机的凭证不受牵连。
2.2 通道独立为什么算隔离环境的一部分
隔离环境常被理解成“别让脚本碰我的生产库”,这只是一半。代理还要联出去调模型,这条链路上有三个东西必须可控:请求发到哪个地址、用哪把 Key、以及出问题时从哪里一键停掉。把这三件事都交给一个陌生仓库的配置,等于把通道的开关交给了别人。
TaoToken 在这条链路里只做一件事:给 Key 和 Base URL。它不代替隔离环境,也不替你审 CLAUDE.md。它的价值是把代理的模型调用集中到一个通道上,这样在陌生仓库里跑初始化脚本之前,通道本身是可控、可停用的。你停掉 Key,代理立刻失去模型能力,剩下的事情再慢慢查。
顺序上建议这样:先建 Key,再进 VM 或容器,再改配置,最后才 clone 那个陌生仓库。顺序反了就会出现“代理已经在读了,我还在配通道”的局面。
3. 隔离环境里把 Claude Code 指向 https://taotoken.net/api
3.1~/.claude/settings.json的 env 段怎么写
Claude Code 的通道配置可以直接写在 settings 文件的 env 段里,这样进容器时带上这份文件就行,不用改 shell profile。Base URL 填https://taotoken.net/api,末尾不要加/v1,也不要填官网首页——首页是给人看的,接口地址才是给工具用的。
{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_AUTH_TOKEN": "YOUR_API_KEY", "ANTHROPIC_MODEL": "YOUR_MODEL_ID" } }YOUR_MODEL_ID换成模型广场里那个具体 ID。如果这个隔离环境是临时的,settings.json 也放在临时用户目录下,别写进会同步到主力机的 dotfiles 仓库里。顺手把权限规则也加上,后面第 6 节会讲。
3.2 临时 shell 变量:容器里能直接用,退出就没了
不想改文件的话,用环境变量最省事,适合一次性验证。注意这些变量只在当前 shell 及其子进程生效,退出容器就没了,这正好符合“临时环境临时凭证”的思路。
export ANTHROPIC_BASE_URL="https://taotoken.net/api" export ANTHROPIC_AUTH_TOKEN="YOUR_API_KEY" export ANTHROPIC_MODEL="YOUR_MODEL_ID"提示:ANTHROPIC_BASE_URL后面不要拼出https://taotoken.net/api/v1这种多一层的写法,工具自己会处理版本路径,多写一层最常见的表现就是 404 或者返回一段和模型无关的内容。
4. Codex 侧:~/.codex/config.toml别套 ANTHROPIC_*
4.1 model_provider 与 base_url 的写法
Codex 的配置体系跟 Claude Code 不是一套,把ANTHROPIC_*变量搬过去不会生效,这一点经常让同时用两个工具的人绕远路。Codex 走的是~/.codex/config.toml里的 provider 定义。
model = "YOUR_MODEL_ID" model_provider = "taotoken" [model_providers.taotoken] name = "taotoken" base_url = "https://taotoken.net/api" env_key = "TAOTOKEN_API_KEY"配套的 Key 用环境变量给,同样只在隔离环境里导出:
export TAOTOKEN_API_KEY="YOUR_API_KEY"base_url同样是https://taotoken.net/api,不要带/v1。写完先别急着让 Codex 读仓库,用一句最普通的提问确认往返正常,再进业务场景。
4.2 CC Switch 里建一个自定义供应商
如果你习惯用一个界面同时管 Claude Code 和 Codex 的配置,在 CC Switch 里加一条自定义供应商就行,需要填四样:供应商名称随便起、Base URL 填https://taotoken.net/api、Key 填YOUR_API_KEY、模型 ID 填模型广场里那个。切过去之后,两个工具就都走同一条通道,排查问题时只看一处。
这套做法有个副作用值得说清楚:通道统一之后,你不再需要为了额度问题在多个来路不明的工具之间来回切。多切一个工具,就多一份能读到 Key 和仓库内容的代码。
5. 只读验证:先读 README 加出构建请求,别急着 install
5.1 一次最小只读请求怎么发
通道配好之后的第一次调用,目标是验证 Key 生效、地址正确,而不是把仓库跑起来。在隔离环境里让代理做一件只读的事:读一遍 README,再把构建步骤解释出来或者写成一份不会被执行的命令清单。这个动作不触发 install,不跑 postinstall,不碰网络下载。
当你确认代理能正常回答问题,说明 Base URL 和 Key 都没问题,接下来再去逐条 review 仓库里的 CLAUDE.md、MCP 配置和 hooks。顺序别反过来,否则你分不清报错是通道的问题还是仓库的问题。
5.2 401、404、模型名对不上时的对照
| 现象 | 大概率原因 | 处理 |
|---|---|---|
| 401 / 认证失败 | Key 没导出,或变量名和配置文件里写的不一致 | 检查YOUR_API_KEY是否替换成了真实值,变量名是否对应 |
| 404 或返回内容与模型无关 | Base URL 多写了/v1,或者填成了官网首页 | 改回https://taotoken.net/api |
| 提示模型不存在 | 模型 ID 抄错或已下线 | 回模型广场重新取一次当前 ID |
| 通道正常但工具报权限拒绝 | 这是代理权限层,不是通道问题 | 去看仓库里的 hooks、allowlist 和 settings |
排查顺序建议从下往上:先确认 Key 生效,再看请求是否正常返回,最后才怀疑仓库内容。反过来查会浪费很多时间。
6. CLAUDE.md、MCP 配置、hooks:仓库里能指挥代理的文件清单
6.1 需要进 review 的仓库级文件
只审业务代码会漏掉真正能指挥代理的地方。至少要过一遍这几个:CLAUDE.md 之类的指令文件、agent settings、MCP 配置、hooks、package scripts、CI workflow,以及任何会在初始化时被自动执行的东西。它们的特点是看起来像配置,实际是命令清单。
具体动作可以很朴素:把这些文件单独拉出来,一条一条问“这条指令是谁写的、它会不会让代理去联网、读凭证、装包、改系统路径”。curl 管道给 shell、wget、pip install、npm install、npx,都属于不能因为“代理建议执行”就跳过审查的动作。对陌生项目,先读脚本,再决定跑不跑。
6.2 permissions.deny 挡住 .env 与 secrets
凭证不该放在代理随手能读的位置。Claude Code 的 settings 支持用 deny 列表挡住读取路径,这类规则建议直接进团队基线,而不是靠每个人记得住。
{ "permissions": { "deny": [ "Read(./.env)", "Read(./.env.*)", "Read(./secrets/**)" ] } }同样的思路也适用于 SSH key、云凭证目录、包发布 token 所在位置。需要强调的是,规则只是减少误读,真正稳妥的做法是隔离环境里干脆不存在这些文件。如果某个诊断脚本需要读数据库或跑命令,让读者自己在本地或对应客户端里执行,再把结果贴回对话,不要让代理直接连生产机器去执行。
7. 初始化跑完之后回到控制台对账
隔离环境里跑完一轮之后,别急着把它接进日常流程。先在 模型对话 里用同一把 Key 发一条测试消息,确认模型 ID 和 Base URL 都对得上;然后回到 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 看这次 Claude Code 和 Codex 的调用有没有记上账,Key 的用量是不是符合预期,发现异常可以立刻吊销这一把而不影响别的环境。
要长期在受控通道上写代码,可以打开 Coding Plan 看套餐够不够用;需要新建或轮换 Key 就在 控制台 API Keys 操作;Claude Code 的环境变量写法和文件位置对照见 接入文档。通道配好只是开始,陌生仓库的 CLAUDE.md、MCP 配置和 hooks 还是要你自己逐条看完,再让代理动手。