跳到主内容
快讯直播
AI智模界
教程

Claude Code 扩展后门应急体检:从核验到轮换

报错现象

以一次 VS Code 扩展被植入后门的供应链事件为样本,做一次完整的应急体检演练。这类事件的特点是没有明显报错:多数人是在扩展宿主崩溃、安全软件弹窗、或者账单异常之后才察觉。具体事件细节以厂商公告为准,本文只讲排查方法。

常见现象:

  • 扩展宿主反复崩溃:Extension host terminated unexpectedly,或频繁出现 Extension host (Local) is not responding,并且崩溃时间点和你打开某个项目吻合。
  • 安全软件或 EDR 出现类似 Suspicious outbound connection from Code Helper (Renderer) 的告警,目标是一个你没见过的域名。
  • API 用量或账单异常:控制台里出现夜间、周末的大量调用,而这些请求不是你发出的。
  • 收到 GitHub secret scanning 告警、云厂商的异常登录邮件,或者发现多了自己没创建过的 API key。
  • 扩展面板里出现了你没装过的扩展,或某个扩展的版本号在你没有操作的情况下发生了变动。
  • 终端里出现陌生的 node、curl 常驻进程,ps aux | grep -i node 能看到来源不明的进程。
  • .env、~/.ssh/、~/.aws/ 的访问时间(atime)在你只是打开项目后发生了变化。

影响范围要按机器来算:一台开发机上的扩展通常能读到你的整个用户目录,所以这台机器上出现过的所有凭据,都要视为可能已经泄露。

可能原因

按出现概率从高到低:

1. 从非官方渠道安装扩展:朋友发的 .vsix、网盘下载的安装包、第三方镜像站,安装时绕过了市场审核。

2. 装到了仿冒扩展:名字、图标、描述和正版高度相似,只有发布者(publisher)不同。

3. 已装扩展自动更新到了被投毒的版本:这一步你并没有做错什么,属于上游供应链问题,也是这类事件里最难防的一种。

4. 扩展依赖的 npm 包被投毒,或者安装、激活时执行了 postinstall 之类的脚本。

5. 工作区配置被动了手脚:.vscode/tasks.json 里配置了打开文件夹就自动执行的任务。

6. 凭据以明文形式散落在 settings.json、.env、shell 配置文件、git 历史里,被扩展读取后直接外传。

7. 本机代理或 DNS 被改,流量被引到中间人。

8. 误报:正常的遥测上报、更新检查、语言服务器外联被当成了攻击行为。

逐条排查与解决

第 1 步:先止血,再取证。 断网或拔掉网线,用安全模式启动,确认问题是否来自扩展:

```bash

code --disable-extensions

```

如果安全模式下一切正常,说明问题大概率在扩展侧。此时先别急着卸载,把扩展目录复制一份留作证据:

```bash

cp -a ~/.vscode/extensions /tmp/ext-backup-$(date +%s)

```

Windows 下路径是 %USERPROFILE%\.vscode\extensions,WSL / 远程开发用的是 ~/.vscode-server/extensions。

第 2 步:清点扩展并核验来源。

```bash

code --list-extensions --show-versions

```

输出格式是 publisher.name@version。逐个对照扩展详情页:发布者名字是否一致、有没有认证标识。仿冒品通常只差一两个字母,比如把 ms-python 写成 ms-pythonn,肉眼很容易漏掉。

再看目录本身,目录名格式为 publisher.name-version,时间戳也能提供信息:

```bash

ls -la ~/.vscode/extensions | sort -k6,7

```

判断依据:如果你没手动更新过,某个目录的修改时间却跳到了最近几天,说明它是自动更新来的。

建立一份基线,以后定期对比:

```bash

code --list-extensions --show-versions | sort > ~/ext-baseline.txt

之后任何时候

code --list-extensions --show-versions | sort > ~/ext-now.txt

diff ~/ext-baseline.txt ~/ext-now.txt

```

第 3 步:静态扫描扩展代码。 先定位可疑扩展目录,再做关键字搜索:

```bash

EXT_DIR=~/.vscode/extensions/publisher.name-version

grep -rInE "child_process|execSync|spawn\(|eval\(|atob\(|base64" "$EXT_DIR" --include="*.js" | head -n 40

grep -rhoE "https?://[a-zA-Z0-9._-]+" "$EXT_DIR" --include="*.js" | sort | uniq -c | sort -rn | head -n 40

```

判断依据:第二条命令会列出扩展里出现过的所有域名。一个格式化工具却访问 *.workers.dev、*.ngrok.io 这类托管平台,或者直连 IP,就很值得进一步检查。正常的扩展一般只会访问自己的官网、更新服务和文档链接。

顺便看一下入口文件和激活条件:

```bash

python3 -m json.tool "$EXT_DIR/package.json" | head -n 80

```

关注三处:activationEvents 里有没有 *(启动即激活,权限面最大)、scripts 里有没有 postinstall、main 指向的文件是不是被压成了一行几万字符的混淆代码。

第 4 步:出网审计。 关键是找到「哪个进程连了哪里」。

```bash

macOS

lsof -i -P -n | grep -i "code"

或者先拿 PID 再看它的连接

pgrep -fl "Code Helper"

lsof -p <PID> -i -P -n

Linux

ss -tnp | grep -i code

Windows PowerShell

Get-NetTCPConnection | Where-Object { $_.State -eq 'Established' } |

Select-Object RemoteAddress, RemotePort, OwningProcess

```

判断依据:看 RemoteAddress 是不是公网地址。拿到 IP 后查归属:

```bash

dig -x <IP>

whois <IP> | head -n 20

```

如果解析出来的是你没听说过的云主机商,而扩展本身又不该联网,就基本可以确认了。

再看它解析了哪些域名,这一步能抓到走 CDN 隐藏的连接:

```bash

sudo tcpdump -n -i any port 53

```

打开项目、等一分钟,观察有哪些域名被查询。这一步不需要抓包解密,只看域名就够判断了。

第 5 步:需要看请求内容时的抓包。 仅在隔离的机器上做:

```bash

mitmproxy -p 8080

```

然后在 VS Code 的 settings.json 里加 "http.proxy": "http://127.0.0.1:8080",重启后观察请求。注意这需要安装代理的 CA 证书,会削弱传输层安全性,排查结束后立刻删除代理配置和证书。

第 6 步:检查工作区配置。 打开陌生项目时,.vscode/ 目录同样能执行代码:

```bash

ls -la .vscode/

cat .vscode/tasks.json .vscode/settings.json 2>/dev/null

```

判断依据:tasks.json 里出现 "runOptions": {"runOn": "folderOpen"},表示打开文件夹就自动跑任务,这是常见的自动化投毒点。另外,如果 VS Code 提示工作区不受信任,别顺手点「信任」。

第 7 步:盘点凭据暴露面。 任何一条命中,都直接按「已泄露」处理:

```bash

env | grep -iE "key|token|secret|password" | sed 's/=.*/=<redacted>/'

grep -nE "KEY|TOKEN|SECRET|PASSWORD" ~/.zshrc ~/.bashrc ~/.bash_profile 2>/dev/null

git ls-files | grep -i "\.env"

git log -p -S "sk-" --oneline | head -n 20

```

第 8 步:按顺序轮换凭据。 原则是「先吊销、再新建、再替换使用点、最后确认旧凭据彻底失效」,顺序按影响面从上游到下游:

1. 先撤销能直接产生费用的:模型服务商的 API key。在控制台删除旧 key 并生成新 key。Claude Code 的登录凭据可能保存在系统钥匙串或配置目录里,两处都要检查;退出登录再重新登录,具体路径以官方文档为准。

2. 云平台:aws sts get-caller-identity 确认当前身份,到 IAM 控制台把 access key 置为 Inactive 后再删除;gcloud auth list 和 gcloud auth revoke --all;az account show 确认订阅。

3. 代码托管:gh auth status 看当前登录,gh auth logout 登出;在 GitHub 的 Developer settings 里撤销全部 PAT;SSH key 用 ssh-keygen -lf ~/.ssh/id_ed25519.pub 拿到指纹,在账号里删掉对应公钥并重新生成。

4. 包仓库:npm whoami、npm token list、npm token revoke <token-id>。发布权限的 token 优先级高于只读 token。

5. CI/CD 的 Secrets:全部重置,尤其是能部署生产环境的那几个。

6. 数据库与其他 SaaS:改密码、吊销 API key,同时检查有没有新增的子账号或 OAuth 授权。

7. 回查有没有被顺手装的后门:~/.ssh/authorized_keys 里多出来的公钥、新增的 CI runner、新增的 OAuth App、云上新建的 IAM 用户。

判断轮换是否彻底:在控制台看旧 key 的「最近使用时间」是否不再更新;云厂商的审计日志(CloudTrail、Activity Log 之类)里是否还有旧凭据的调用记录。只要还在被调用,说明某处还留着副本。

都不管用时的兜底方案

  • 用干净配置做对照,这一步能区分「扩展的问题」和「配置文件的问题」:

```bash

code --user-data-dir /tmp/clean --extensions-dir /tmp/clean-ext

```

  • 全量卸载重装扩展,前提是先备份清单:

```bash

code --list-extensions > ~/ext-backup.txt

code --list-extensions | xargs -n1 code --uninstall-extension

```

  • 把本地机器当作已污染,敏感项目全部转到 devcontainer、虚拟机或远程开发机上,本地只做非敏感工作。
  • 检查系统级持久化,扩展可能只是入口,真正的驻留可能在别处:

```bash

crontab -l

ls ~/Library/LaunchAgents /Library/LaunchAgents 2>/dev/null

systemctl --user list-units --type=service

```

  • 确认存在系统级后门后,重装系统是止损手段。重装前必须先把凭据全部轮换一遍,否则新系统装好、旧凭据还在被用,等于没做。
  • 上报:通过扩展市场的举报入口和厂商安全邮箱反馈,企业环境同步通知安全团队并保留完整时间线(什么时候发现的、装了哪个版本、轮换了哪些凭据)。

如何预防再次发生

  • 关掉扩展自动更新,在 settings.json 里设置 "extensions.autoUpdate": false,需要更新时手动确认。这一步能挡住大部分「上游被投毒、你被动中招」的情况。
  • 只从官方市场安装,装之前核对 publisher 名字。收到 .vsix 文件先 unzip -l 看看里面有什么,再决定装不装。
  • 维护扩展清单基线,每周 diff 一次,多出来的扩展第一时间能看到。
  • 开启 Workspace Trust,陌生仓库一律用受限模式打开。
  • 开发环境隔离:敏感项目在容器或虚拟机里开,扩展装在工作区级别而不是全局。
  • 凭据最小权限 + 短期有效:给扩展和脚本用的 key 只开必需的权限,能设过期时间就设。用密钥管理器注入环境变量,而不是把 key 写进 ~/.zshrc。
  • 打开用量告警和审计日志:模型服务、云平台、代码托管三处都设置异常用量通知,异常请求通常比人先发现。
  • 定期演练十分钟:code --list-extensions --show-versions 加一条 lsof -i -P -n | grep -i code,成本很低,但真出事时能省掉大量猜测。

AI 生成本文由 AI 基于公开信息自动生成,仅供参考。