The Guardrail Company Got Owned. Skill Provenance Is the Layer Below.
On 2026-05-11 the Mini Shai-Hulud npm/PyPI worm trojanized 404 package versions, including @mistralai/mistralai and guardrails-ai. A runtime LLM-output guardrail cannot catch an install-time daemon. ATR v3.1.0 ships ATR-2026-00525 covering the gh-token-monitor signature.
_2026-05-11 那波 Mini Shai-Hulud npm/PyPI 蠕蟲污染了 404 個套件版本,跨 JavaScript 和 Python 生態。其中兩個受害者是大部分團隊預設信任的廠商:Mistral AI(前沿模型 lab)和 Guardrails AI(runtime LLM-output guardrail 提供商)。Runtime 層的 guardrail 攔不住 install time 投放的攻擊。Detection layer 必須在 guardrail 之下。_
中標的東西
Akamai、Wiz、CSA 的研究員追蹤這波到 2026-05-17。Help Net Security 和 The Hacker News 報導了時序。中標清單至少包括:
- ●
@mistralai/mistralai— Mistral 官方 TypeScript SDK on npm。Payload 透過 npmpreparelifecycle hook 投放(和 TanStack 同一個 install vector)。 - ●
mistralai和guardrails-ai— Mistral 和 Guardrails AI 官方 Python SDK on PyPI,payload 由__init__.py的on importside effect 觸發,下載/tmp/transformers.pyz從git-tanstack[.]com。 - ●TanStack packages(
@tanstack/router、@tanstack/query等)— 同一家族,npmpreparelifecycle hook 透過 Bun runtime 投放。 - ●UiPath packages(這波另一個 sub-cluster)用 npm
preinstallhook 呼叫node setup.mjs當 install vector。
Wiz 和 Aikido 的分析估計總共 403 個 trojanized package versions,分布在約 172 個獨立 package 上,累積過去十二個月 5 億 1,800 萬次下載。
Payload 做什麼
這波攻擊有三個 artifact:
1. `gh-token-monitor` — 持續駐留的 daemon,透過 macOS LaunchAgent(~/Library/LaunchAgents/com.user.gh-token-monitor.plist)或 Linux systemd user service(~/.config/systemd/user/gh-token-monitor.service)安裝。Daemon 用開發者的 GitHub token 每 60 秒 poll 一次 api.github.com/user。
2. Dead-man's switch — 當 polled token 回 HTTP 401(開發者輪換或撤銷 token),daemon 對整個 home directory 跑 rm -rf ~/(依 Wiz 和 JFrog 分析)。毀滅動作是條件觸發的,這就是為什麼純靜態 manifest 掃描抓不到 daemon。
3. Exfiltration 通道 — filev2.getsession[.]org(走 Session Protocol)、api.masscan[.]cloud(GitHub Actions secret serialization)、typosquat git-tanstack[.]com 拿來收 credential。83.142.209[.]194 這台 host 已確認在跑 PyPI credential stealer。
Mistral 在 2026-05-12 開了一個公開 security advisory 頁面 docs.mistral.ai/resources/security-advisories,承認 TypeScript SDK 中標。這是 Mistral 第一次跑公開 security advisory 頁面。也是對的動作。
為什麼 runtime guardrail 攔不到這個
Guardrails AI 的產品就是字面意思——一個包在 LLM output 外面的 runtime guardrail。它驗證 model response 符合預先宣告的結構和安全約束,才把 response 放給 user 或下游 tool。Lakera、PromptArmor、Protect AI、Lasso Security 以及閉源同類產品都在做一樣的事,在一樣的 layer。
這些產品在他們自己那層做得很好,但他們全都活在 stack 的同一層。沒有一個會去檢查 pip install guardrails-ai 執行時跑的 __init__.py 內容,因為 runtime guardrail 載入的時候,install-time daemon 已經在磁碟上落地三到五分鐘了。Runtime guardrail 定義上就在 install 之後。
這不是針對特定廠商的攻擊。這是一個 layering 觀察。一個 guardrail 廠商自己在 install time 中標,意味著他們產品處理的 threat model 沒有延伸到送他們產品上門的 supply chain。那個 threat 的 detection layer 在更下面。
ATR 為這件事出的規則
Agent Threat Rules v3.1.0 出 ATR-2026-00525 覆蓋 Mini Shai-Hulud 家族。規則對任何到 agent runtime 或 skill scanner 的文字觸發三條 alt:
1. 字面 daemon 名稱 gh-token-monitor、gh_token_monitor,或 LaunchAgent label com.github.token.monitor。
2. 在 500 字元內配對:對 api.github.com/user 的 polling loop + 毀滅性 shell primitive(rm -rf、shutil.rmtree、os.system rm)— 也就是 dead-man's-switch 形狀。
3. 在 300 字元內配對:interval/timer 結構(setInterval、threading.Timer、asyncio.sleep)+ /user poll + shell execution primitive(child_process、exec、毀滅指令)— 也就是 install-time daemon 形狀。
覆蓋度誠實講:規則抓到的是 Akamai、Wiz、Sysdig 公開 writeup 中出現的 canonical IOC。它抓不到 dead-man's-switch pattern 的每一種 obfuscation。規則的 true_negatives block 文件化了刻意接受的 FP case 和明確拒絕的 case。Source 在 Agent-Threat-Rule/agent-threat-rules main 上的 skill-compromise category。
一層一層的偵測 map
對今天在建構或採購 AI security 的團隊來說,layer 是這樣排的:
| Layer | 它檢查什麼 | 這次攻擊在這層長什麼樣 |
|---|
|---|---|---|
| Runtime LLM output guardrail | 生成後的 model response | 看不到 — payload 在 install 跑,從沒到 model。 |
|---|
| Tool call gate / function-call inspector | Tool invocation 的 argument | 看不到 — daemon 是背景 process,不是 tool call。 |
|---|
| MCP / skill content scanner | SKILL.md 文字或 skill code 在 registration 時 | 抓到——透過 ATR-2026-00525 抓 daemon-install 形狀和 dead-man's-switch 形狀。 |
|---|
| Package manifest scanner | package.json、pyproject.toml、setup.py 對應已知 IOC string | IOC 還在的時候抓得到 preinstall: node setup.mjs 形狀。 |
|---|
| Process / runtime EDR | LaunchAgent plist 新增、可疑子 process | IOC 還在的時候抓得到 daemon 在 install 階段。 |
|---|
五層裡有三層看不到這次攻擊。能看到的兩層不是 runtime guardrail 廠商所在的層。PanGuard 從 2026 年 3 月 v0.1 開始的 positioning,就是 skill-content layer 加 manifest layer。這不是一句行銷詞。這是這次攻擊真實浮現的層。
我們不主張的事
幾個誠實揭露,讓這篇文不變成廠商 cosplay:
- ●ATR 是被動的。規則裡的
gh-token-monitor字串是一個 IOC;下一個 worm 會用不同 daemon 名稱,規則第一個條件就需要更新。規則第二、第三條件(dead-man's-switch 形狀和 timer-plus-shell 形狀)是 pattern-based,應該 generalize 比較好,但 pattern-based 規則也會有 false negative。 - ●ATR 是 MIT open source。它不是 PanGuard 獨有的。任何人用 ATR 的 npm package、MISP feed,或 Cisco AI Defense scanner config,拿到的是一樣的覆蓋。差異化不在規則本身,在 disclosure 到 shipped rule 的 loop 時間。這次攻擊 disclosure 是 2026-05-11,對應規則 ship 是 2026-05-23,十二天。太慢了。Microsoft Copilot Semantic Kernel 那個 loop 在 2026-05-11 兩小時十六分鐘收尾,是因為 disclosure 帶了可用的 PoC。Mini Shai-Hulud 的 writeup 沒帶,這就是這個 loop 比較慢的結構原因。
- ●對 runtime guardrail 廠商的誠實 framing 是「不同的 layer,兩個都需要」,不是「我們取代他們」。Runtime LLM-output guardrail 抓的是和 skill-content scanner 不同的攻擊類別。成熟的部署會兩個都跑。這篇的 point 是:只跑 runtime guardrail 留下一層沒蓋到。
這週可以做的事
1. 如果你的依賴樹有 @mistralai/mistralai、mistralai 或 guardrails-ai,audit 你的 install:npm ls @mistralai/mistralai + pip show mistralai guardrails-ai。Mistral 的 advisory 頁面列了具體 bad version。Pin 到 patched release。
2. 檢查 persistence daemon:macOS 上 launchctl list | grep -i token-monitor,Linux 上 systemctl list-units | grep -i token-monitor。Daemon 的 plist label 是 com.github.token.monitor,systemd unit 叫 gh-token-monitor.service。
3. 如果你出 agent platform,把 skill-content scan 加進 registration flow。ATR 規則是一個檔加 YAML;它 load 進任何吃 ATR format 的 rule-runner。Microsoft Agent Governance Toolkit、Cisco AI Defense、MISP 今天都在跑。
4. 如果你做 runtime guardrail 產品而且讀到這邊,誠實的 move 是加一個 skill-content 或 package-manifest 的 companion scanner。Runtime layer 是必要的。但它不夠。
收尾
如果你的 AI security architecture 只檢查 runtime output,supply chain 就是你的盲點。Mini Shai-Hulud 是經驗證據。Guardrail 公司被打穿了。Detection layer 必須在更下面。
_Adam Lin 維護 Agent Threat Rules,一個 MIT 授權的 AI agent 威脅偵測 corpus。ATR 規則在 Microsoft、Cisco、MISP 都在跑。同時是 Panguard AI 的 founder(Delaware C-Corp,做 ATR 標準的商業化產品)。聯絡:[email protected]_