
內容摘要
幻覺套件名稱具有可預測性,因此可被搶先註冊。請確認套件存在、是你真正要的那個,而且安裝時不會執行你沒讀過的程式碼。
請 AI 助理寫一個小工具,它常會給出一個很有自信的 import 與安裝指令。有時那個套件根本不存在。這不是隨機雜訊:同樣的虛構名稱會在重複提示中一再出現,而這正是攻擊者搶先註冊一個名稱並等待所需的特性。
這種攻擊叫 slopsquatting,而防禦方式不是「別再用 AI 助理」,而是在名稱進入套件管理器前先驗證,並讓安裝更難被武器化。
01slopsquatting 實際上是什麼
這個模式有三個部分。模型產生一個看似合理的套件名稱;這個名稱在用戶與多次執行之間足夠穩定、可被預測;套件庫允許任何人搶下未使用的名稱。
針對程式生成模型的研究顯示,在所有建議套件中,大約每五個就有一個是幻覺。重複名稱的 typosquatting 利用的是人類打錯已知套件;slopsquatting 利用的是機器自信地虛構出一個套件。因為模型陳述建議的語氣與陳述真實函數庫時一模一樣,這個錯誤很容易被複製進終端機,而不會多想一秒。
存在不等於合法
攻擊者可以在一個名稱出現在模型輸出後才搶先註冊。
npm找得到它,只證明有人佔用了這個名稱——不代表程式碼安全,也不代表它就是模型想指的東西。
02為什麼幻覺名稱可被預測
模型產生名稱的方式,就跟產生任何其他 token 一樣:延續最可能的模式。對日期函數庫來說,就是把 date 與常見字尾接起來;對 CLI 小工具來說,就是 @scope/tool-name。輸出不是真正的套件,但看起來完全像一個。
因為解碼每次都由相同統計引導,同一個提示往往產生同一個虛構名稱。這種可預測性就是漏洞。它也意味著解法不可能是「用更好的提示」——不存在永不幻覺名稱的模型,所以驗證必須落在你的流程裡。
03安裝前先驗證名稱
把這件事變成反射動作,整類攻擊就會困難許多。
- 直接問套件庫。 404 就結束了。
npm view left-pad version repository.url maintainers time.created
# version = '1.3.0'
# repository.url = 'git+ssh://git@github.com/stevemao/left-pad.git'
npm view left-paad version
# npm error 404 Not Found - GET https://registry.npmjs.org/left-paad - Not found
python3 -m pip index versions requests
# requests (2.32.5)
# Available versions: 2.32.5, 2.32.4, 2.32.3, ...
- 把套件對上你預期的項目。 讀
repository.url與維護者清單。有原始碼項目、有 changelog、有多年發布紀錄的函數庫,看起來就和上週才註冊、沒有首頁的名稱不同。 - 檢查發布歷史的形狀。 整個版本清單在同一天出現是警訊;看起來像為了顯得成熟而挑的怪版本號(例如
99.0.0)也是。 - 把建議與生態系實際使用的東西比對。 若助理提議某個知名函數庫的包裝套件,先確認該函數庫是否早已原生提供這個功能。幻覺常常是為了填補一個不存在的空缺。
04Lockfile、安裝腳本與執行陷阱
安裝套件不是唯讀動作。生命週期腳本會在安裝時執行,惡意套件能在你的測試跑起來之前就用它們執行程式碼。
- 提交並審查 lockfile。
npm ci只安裝 lockfile 固定的內容,所以被審查過的 lockfile 就是一種控制。未經審查的npm install <typo>會改寫它。 - 第一次接觸時跳過腳本。 用
npm install --ignore-scripts加入相依套件,檢查後再視信任程度正常安裝。 - Python 使用雜湊固定安裝。
pip install --require-hashes -r requirements.txt會拒絕位元組與記錄雜湊不符的套件。 - 保留安裝時審查步驟。 程式碼審查中的 lockfile 差異,是最便宜、最容易發現不該出現名稱的地方之一。
npm ci --ignore-scripts
npm ls --all | head -40
git diff -- package.json package-lock.json
要 diff lockfile,不只 diff package.json
一個新的頂層相依套件常會拖進十幾個間接套件。lockfile 差異會顯示全部,而那個你從未批准的名稱就藏在其中。
05強化整個流程,而不只是當下
個別檢查能抓到個別錯誤,幾個結構性控制則能抓到整類問題。
| 控制 | 擋掉什麼 |
|---|---|
| 具允許清單的私有套件庫代理 | 未知名稱到不了開發者手上 |
| 強制審查 lockfile | 偷渡進來的間接相依套件 |
| CI 停用生命週期腳本 | 安裝時執行程式碼 |
| CI 相依套件掃描 | 已知惡意套件與 CVE |
| 內部套件命名規則 | 內外部 scope 的混淆 |
| 出處/證明檢查 | 沒有真實建置流程的 typosquat |
套件庫代理的槓桿最大:若某個套件尚未被鏡像或列入允許清單,安裝就會失敗,由人類決定。這把無聲的供應鏈風險變成例行審查。
06如果你已經裝錯套件
把它當成資安事件,而不是打錯字。移除相依套件後,檢查安裝實際做了什麼:檢視 node_modules/<name> 裡的 postinstall 與 preinstall 腳本、尋找新的對外網絡請求、輪替安裝環境中出現過的任何憑證,並確認 lockfile 是否已提交並推送。在共享倉庫中,被汙染的 lockfile 才是會擴散的部分。
07常見錯誤與修正
| 錯誤 | 為何失效 | 修正 |
|---|---|---|
| 直接照聊天回答安裝 | 完全沒有查核套件庫 | 先跑 npm view 或 pip index versions |
| 因為套件存在就信任 | 攻擊者會註冊幻覺名稱 | 檢查發布者、項目與發布歷史 |
只看 package.json | 間接套件藏在那裡 | 審查 lockfile 差異 |
| 讓 CI 執行安裝腳本 | 惡意程式碼在建置期間執行 | 使用 --ignore-scripts 或沙箱化安裝 |
| 假設 scoped 名稱是內部的 | 公開 scope 也能看起來像內部 | 強制使用明確的內部 scope |
真正重要的習慣很小:別讓模型的建議在沒有一次套件庫查詢的情況下變成相依套件。其餘強化措施,是為了那些你疲累、趕時間、準備好相信輸出的時刻。
在 package.json 與 lockfile 進入建置流程前先驗證。
JSON 驗證工具常見問題
什麼是 slopsquatting?
slopsquatting 是指搶先註冊 AI 模型虛構出來的套件名稱,讓下一個照著模型建議複製指令的開發者,安裝到攻擊者的程式碼而不是什麼都沒裝。
AI 助理真的會虛構套件名稱嗎?
會。針對程式生成模型的研究發現,大約每五個建議套件就有一個不存在於套件庫,而且同樣的虛構名稱會在重複提示中一再出現。
套件在 npm 上真的存在就安全嗎?
存在是必要條件,但不足夠。名稱可能存在,是因為攻擊者看到它被幻覺出來後搶先註冊,所以還要檢查發布者、項目連結、出現時間與下載模式。
檢查套件最快的方法是什麼?
安裝前直接問套件庫。npm 用 `npm view <name>`;Python 用 `python -m pip index versions <name>`。404 就是停止訊號。
我該停用安裝腳本嗎?
對不可信或新加入的相依套件,應該。`npm install --ignore-scripts` 會跳過生命週期腳本,那正是惡意套件常見的執行路徑;等相依套件審查過後再正常安裝。
相關文章
- 提示注入是新的 SQL 注入
不可信模型輸出進入系統的另一條路。
- 如何格式化、驗證與壓縮 JSON
manifest 與 lockfile 都是 JSON,請驗證它們。
相關工具
- JSON 驗證工具
在安裝前抓出壞掉的 manifest。
- JSON Schema 產生器
把相依政策變成 schema。
- JSON 格式化工具
不必瞇眼也能讀懂 lockfile 差異。
- Diff 比對工具
逐行檢視 lockfile 變更。