# 我在 Upwork 上两次撞上朝鲜黑客的假面试

> 一个藏着恶意 npm 包的测试项目，一个要用 curl | bash 安装的假会议软件。两次 Contagious Interview 攻击的完整经过，我怎么用 Claude Code 取证，以及为此做的工具 Tsuba。

- URL: https://oliverz.dev/zh/blog/upwork-contagious-interview
- Author: Oliver Zhang (https://oliverz.dev)
- Language: zh-Hans
- Published: 2026-10-28
- Tags: security, upwork, malware, macos, contagious-interview

> **简单说：** Contagious Interview 是朝鲜黑客的假招聘攻击。他们冒充客户或招聘方，在 Upwork、LinkedIn 这类平台上找开发者，最后让你亲手运行一个「测试项目」，或者安装一个「会议软件」。识别它只要记住一条：任何招聘流程要你在自己电脑上运行陌生代码，都先停下来。如果已经运行了，马上断网，排查后台进程和可疑目录，改密码，并在重要网站上退出所有已登录的设备。

## 第一次：2026 年 6 月

一个自称乌克兰人的客户在 Upwork 上找到我，说手上有个项目想请我帮忙。他发来一个 Node.js 测试项目，叫「Online_Store」。

恶意代码就藏在 npm 依赖里。具体是哪个包我已经记不太清了，印象里是一个和 Tailwind 有关的包。项目一跑起来，我的电脑上就被悄悄装了一个 `~/.node_modules` 目录，里面放着 axios 和 socket.io-client，专门用来往外偷数据。

等我反应过来，它已经在后台跑了好几天。说起来也是运气：我一个英国同事碰上了一模一样的事，我听他说完，才意识到自己可能也中招了。

## 第二次：2026 年 10 月

这次的对方自称是立陶宛人，代表一家叫 Veyron Capital 的资本公司（veyron[.]capital），在 Upwork 上一口气发了好几个 Web3 岗位。

他先私信我，然后约了一次 Upwork 视频会议。会上他没开摄像头，而且全程用中文跟我聊。聊完他让我加他的 Telegram，接着把我拉进一个群，说要我写一个 Web3 demo，再在会议上演示给团队看。

到了演示的时候，他们说有同事在外地出差，用不了平时的会议工具，得换一个叫「Zeff」的会议软件（zeff[.]app）。群里另一个人负责「教」我安装，给了两种方式：在终端里运行一条 `curl | bash` 命令，或者下载一个 DMG。

这次我没装。吃过一次亏，看到「为了开个会，要在终端里跑一条来路不明的命令」，我马上就意识到这又是同一个套路。

## 事后回头看

这两次都是朝鲜黑客的「Contagious Interview」（传染性面试）攻击，套路就是假招聘、假面试：先用一个看起来很正常的工作机会建立信任，再让你亲手运行他们准备好的代码。

![两次攻击走的是同一套剧本：联系、建立信任、提出要求、投放恶意代码。第二次我在投放恶意代码那一步停下了。](https://oliverz.dev/posts/upwork-contagious-interview/attack-flow.zh.svg)

更让我在意的是，macOS 自带的 XProtect 和传统杀毒软件，两次都一声没吭。

## 用 Claude Code 当取证调查员

第一次中招后，真正把问题挖出来的是 Claude Code。我用的是 Fable 5（Max），给它放开权限，让它像调查员一样把整块磁盘扫一遍，再排查后台进程。它很快就发现，那个恶意程序还在运行，接着又带着我一步步做完了补救。

## 损失

万幸，这次没有损失。这类恶意程序最想偷的是加密货币钱包，而我电脑上一个钱包都没有；常用的网站账号我也都开了两步验证，就算密码被偷走，对方也登不进去。

不过有一点要提醒：这类程序通常还会偷浏览器里保存的登录状态（cookie）。拿到它，对方可以绕过两步验证直接登进你的账号。所以如果你中招了，除了改密码，也记得在各个重要网站上把所有已登录的设备都退出一遍。

## 我做了一个工具：Tsuba

经历了这两次，我意识到问题出在哪：这类攻击每次换个包装，用的又都是 node、curl、bash 这些再普通不过的工具，传统杀毒软件根本不会觉得它们可疑。

所以我做了一个 macOS 菜单栏小工具，叫 Tsuba（鍔，日本刀上护手的那块铁）。它的思路很简单：陌生代码第一次运行之前，先替你看一眼。它会分析这段代码要做什么、从哪来、像不像已知的攻击手法，然后决定放行、提醒还是拦下。

![陌生代码运行之前，先经过 Tsuba 的四道检查，再决定放行、提醒还是拦下。](https://oliverz.dev/posts/upwork-contagious-interview/tsuba-check.zh.svg)

拿我遇到的两次来说：

- **第一次那种假面试项目**：你运行 `npm install` 或 `npm start` 之前，它会查依赖包在不在公开的恶意包名单里，再检查项目源码里有没有藏起来的代码、写死的远程地址，或者偷读钱包和密码库的操作。拿不准的项目，还可以先放进沙箱里试跑，看它实际会干什么。
- **第二次那种假会议软件**：碰到 `curl | bash`，它会先把远程脚本下载下来但不执行，检查它到底要干什么；下载的 DMG 也会检查签名、公证和来源。

Tsuba 免费，源代码在 [GitHub](https://github.com/chihyungchang/Tsuba) 上。Apple 芯片和 Intel 两个版本的下载，以及更多介绍，都在 [Tsuba 的产品页](/zh/products/tsuba)。如果你也在 Upwork 这类平台上接活，或者经常要跑别人发来的代码，可以装一个试试。
