跳到主要內容
邊界實驗室 · Boundary Lab

邊界實驗室 · Article

AI Supply Chain Security — 你的 gateway 變後門,你的 skill 在洩 secret

LiteLLM 被 TeamPCP 汙染、17k skills 稽核揭露 stdout 洩密、MCP 生態把 builder 推上第一線。這篇用 AI gateway、plugin、CI/CD publish token 三條線,拆 AI supply chain security 為什麼已經是 agent 時代最大 attack surface。

2026-04-27mk-brainERIKA BotInbox Bot

Lab-confirmed:本文主要是近期事件拆解與 reference 設計,不是我(Maki)已在 production 全量實跑過的完整防線。Code snippet 為 reference 設計,非實際在跑的版本。


你以為你在裝能力,其實你在繼承攻擊鏈

很多 builder 還把 supply chain 風險想成 pip install 的老問題。

但 agent 時代的 supply chain,早就不只是一個 Python wheel。

它包含 LLM gateway。

它包含 skill marketplace。

它包含 MCP server。

它包含 CI/CD publish token。

它還包含那種「看起來只是方便你加能力」的 plugin 安裝流程。

這些東西一旦被拿下,模型本身不需要有洞。

攻擊者直接站到你和模型之間最肥的地方。

AI gateway 特別危險,因為它天生就是秘密集散地。

OpenAI key、Anthropic key、Azure credential、Kubernetes token、.env、CI secret,常常都在同一層被看得到。

一個被污染的 gateway,不只是偷一把鑰匙。

它是替攻擊者打開整個 AI infra 的服務總開關。

skill 也一樣。

很多工程師以為自己只是在裝一個「能幫 agent 接 Gmail、接 Slack、接 GitHub」的小能力。

實際上你是在執行一段第三方程式,還允許它把 stdout、錯誤訊息、自然語言描述一起送回 agent context。

如果 skill 開發者把 debug print 留在裡面,secret 可能不是被駭走。

而是被你自己餵進 LLM。

這就是 AI supply chain 最不舒服的地方。

它不長得像傳統 malware。

它長得像 productivity。


AI Supply Chain:你到底把什麼裝進了系統

供應鏈風險的重點,不是某一個套件很有名。

而是它位在什麼位置。

Case

:2026-03-24,Datadog Security Labs 公開 LiteLLM TeamPCP 事件。兩個真的 PyPI 版本 1.82.71.82.8 被植入惡意程式,不是假包,不是 typosquat,而是 AI gateway 本體被拿來當載具。Datadog 把它串回 2026-03-19 開始的 Trivy 供應鏈攻擊;Endor Labs 與其他後續分析則把 payload 行為歸納得更直接:先收割 cloud key、SSH key、Kubernetes secret 與 .env,再嘗試橫向移動,最後落持久化 backdoor。LiteLLM 每月約 9,500 萬下載,日均約 340 萬下載,Heise 與多家後續報導都用這個量級估 blast radius。

延伸:事件不是停在套件本身。2026-03-31,TechCrunch 報導 Mercor 也確認受 LiteLLM 事件波及。2026-04-03,WIRED 進一步報導 Meta 暫停與 Mercor 的合作。這個連鎖反應很有代表性:你 compromise 的不只是一個 library,而是整條 AI vendor graph。

:2026-04-03 發布的研究 Credential Leakage in LLM Agent Skills 分析了 17,022 個 skills。結果很難看:520 個 skill 帶有 1,708 個 credential leakage 問題;76.3% 的洩漏只有同時讀自然語言描述和 source code 才看得出來;73.5% 的問題來自 print / console.log 之類的 debug logging,因為 stdout 會回流到 LLM 可見範圍。社群後來把這件事濃縮成一句很殘酷的話:你不是被駭,你只是跑了 skill。

再下一層:2026-04-15,OX Security 發布 The Mother of All AI Supply Chains。The Hacker News 與 Tom's Hardware 的後續報導把重點講得很清楚:MCP 官方 SDK 的 STDIO 執行模型把 command execution 直接放在 builder 面前,下載量已超過 1.5 億,而風險繼承到 LiteLLM、LangChain、LangFlow、Flowise 等整個生態。這時候你就很難再說「這只是工具,不是 attack surface」。

核心問題:你有沒有把 AI infra dependency 當成 privileged code 在審?

Rulepin hash,不只 pin versionpublish token 分 repo 分 scope 隔離skill install 前同時掃自然語言描述和 source codeinstall-time 掃描不要交給會自己呼叫工具的 agent整條 agent stack 要有自己的 Agent BOM。

Builder 在這裡真正缺的,不是一個更會寫 regex 的模型。

而是把「方便安裝」改回「先隔離、先審、再信任」的工程順序。

ThreatMitigationValidated in (reference)
只 pin version,不 pin artifactsha256 hash;CI 驗證 artifact digest;異常版本直接 quarantinemk-brain deploy hygiene
共用 publish token 被橫向移動利用每 repo 單獨 publish token;publish job 不可讀其他 repo secret;TTL 短化ERIKA Bot release helper
skill 自然語言描述和 source code 分開審install 前跑 audit_skill_install();同時看 prompt text、manifest、sourceInbox Bot skill review
skill stdout 把 secret 噴回 LLMdebug logging 預設 deny;stdout 先 redaction 再進 context;高風險 pattern 直接 fail installmk-brain tool bridge
沒有人知道 agent 依賴了哪些 tool / skill / server建 Agent BOM:模型、gateway、skill、MCP server、registry、hash、scope 全記錄personal PKI inventory

Reference 實作(示意非 production code,依你環境調整):

from pathlib import Path
import re

SECRET_RE = re.compile(r"(sk-[A-Za-z0-9]{20,}|AKIA[0-9A-Z]{16}|ghp_[A-Za-z0-9]{20,})")
HTTP_RE = re.compile(r"(requests\.(get|post)|urllib\.request|httpx\.)")
WRITE_RE = re.compile(r"(\.ssh|\.gnupg|\.secrets)")
PRINT_RE = re.compile(r"(print|console\.log)\s*\(")

def audit_skill_install(skill_path: str) -> list[str]:
    base = Path(skill_path)
    findings = []
    corpus = []
    for path in base.rglob("*"):
        if path.is_file():
            text = path.read_text(encoding="utf-8", errors="ignore")
            corpus.append((path, text))
    merged = "\n".join(text for _, text in corpus)
    for path, text in corpus:
        if HTTP_RE.search(text):
            findings.append(f"{path}: outbound HTTP capability")
        if WRITE_RE.search(text):
            findings.append(f"{path}: writes to sensitive local paths")
        if PRINT_RE.search(text) and SECRET_RE.search(text):
            findings.append(f"{path}: suspicious stdout secret exposure")
    if "api key" in merged.lower() and HTTP_RE.search(merged):
        findings.append("cross-modal risk: NL description + code imply exfil path")
    return findings

對應 OWASP:這篇先看哪幾條

  • LLM03:2025 Supply Chain:這篇處理的就是 gateway、skill、registry、publish pipeline 何時從依賴變成入口。
  • LLM05:2025 Improper Output Handling:很多 skill 洩漏不是發生在 network exfil,而是 stdout 被你自己接回模型。

想動手做? 這篇文的概念可以接著看: 攻擊面邊界

如果你想把這一套落成 builder checklist,直接接: 攻擊面邊界 101 →