SkillSpector 完整教學 — AI Agent Skill 安全掃描器

§1 專案定位

1.1 解決什麼問題

AI agent skill(如 Claude Code skill、Codex CLI skill、Gemini CLI skill)在安裝時幾乎沒有審查機制。根據 NVIDIA 引用的研究 “Agent Skills in the Wild”(Liu et al., 2026),在 42,447 個 skill 樣本中:

  • 26.1% 含有至少一個漏洞 (vulnerability)
  • 5.2% 呈現明顯惡意意圖 (malicious intent)
  • 含可執行腳本的 skill,漏洞機率高出 2.12 倍

SkillSpector 的核心使命:在安裝前回答「這個 skill 安全嗎?」

1.2 誰該用

對象使用情境
AI agent 使用者安裝第三方 skill 前快速掃描
Skill 開發者發佈前自我檢查,確保通過安全基準
安全團隊CI/CD 整合(SARIF 輸出),自動化 skill 審核
研究人員大規模 skill 安全分析、漏洞模式研究

1.3 競品比較

目前 AI agent skill 安全掃描是一個新興領域,SkillSpector 是第一個專門針對此需求的開源工具。傳統的 SAST 工具(如 Semgrep、Bandit)可偵測通用程式碼漏洞,但無法處理 skill 特有的威脅向量:prompt injection (提示注入)、MCP tool poisoning (MCP 工具投毒)、memory poisoning (記憶體投毒) 等。


§2 安裝指南

2.1 環境需求

  • Python:3.12 或 3.13(嚴格限制 >=3.12,<3.14
  • Git:掃描 GitHub repo 時需要
  • uv(推薦)或 pip:套件管理
  • 網路存取:OSV.dev CVE 查詢需要(離線有 fallback)

2.2 從原始碼安裝

 1# 1. Clone
 2git clone https://github.com/NVIDIA/skillspector.git
 3cd skillspector
 4
 5# 2. 建立虛擬環境
 6uv venv .venv && source .venv/bin/activate
 7# 或:python3 -m venv .venv && source .venv/bin/activate
 8
 9# 3. 安裝(正式使用)
10make install
11
12# 4. 驗證
13skillspector --version
14# 預期輸出:SkillSpector v2.1.3

2.3 開發者安裝

1make install-dev   # 含 pytest, ruff, mypy, build 等
2make test          # 跑全部測試(unit + integration)
3make lint          # 跑 ruff linter

2.4 LLM 設定

SkillSpector 的 Stage 2 語義分析需要 LLM。三家 provider 擇一設定:

 1# 方法 A:OpenAI(或 OpenAI-compatible endpoint)
 2export SKILLSPECTOR_PROVIDER=openai
 3export OPENAI_API_KEY=sk-...
 4
 5# 方法 B:Anthropic
 6export SKILLSPECTOR_PROVIDER=anthropic
 7export ANTHROPIC_API_KEY=sk-ant-...
 8
 9# 方法 C:NVIDIA Build(預設 provider)
10export SKILLSPECTOR_PROVIDER=nv_build
11export NVIDIA_INFERENCE_KEY=nvapi-...
12
13# 方法 D:本地 Ollama
14export SKILLSPECTOR_PROVIDER=openai
15export OPENAI_API_KEY=ollama
16export OPENAI_BASE_URL=http://localhost:11434/v1
17export SKILLSPECTOR_MODEL=llama3.1:8b

不設定 LLM 也可以使用,加 --no-llm 僅跑靜態分析。


§3 核心架構解析

3.1 LangGraph 工作流

SkillSpector 建構在 LangGraph StateGraph 之上,不是傳統的線性 pipeline。整個掃描流程是一張有向無環圖 (DAG):


graph TD
    START([START]) --> resolve_input
    resolve_input --> build_context
    build_context --> analyzer_1[static_patterns_prompt_injection]
    build_context --> analyzer_2[static_patterns_data_exfiltration]
    build_context --> analyzer_3[static_patterns_privilege_escalation]
    build_context --> analyzer_4[static_patterns_supply_chain]
    build_context --> analyzer_5[behavioral_ast]
    build_context --> analyzer_6[behavioral_taint_tracking]
    build_context --> analyzer_7[mcp_least_privilege]
    build_context --> analyzer_8[mcp_tool_poisoning]
    build_context --> analyzer_9[semantic_security_discovery]
    build_context --> analyzer_10[semantic_developer_intent]
    build_context --> analyzer_dots[... 共 20 個 analyzer]
    analyzer_1 --> meta_analyzer
    analyzer_2 --> meta_analyzer
    analyzer_3 --> meta_analyzer
    analyzer_4 --> meta_analyzer
    analyzer_5 --> meta_analyzer
    analyzer_6 --> meta_analyzer
    analyzer_7 --> meta_analyzer
    analyzer_8 --> meta_analyzer
    analyzer_9 --> meta_analyzer
    analyzer_10 --> meta_analyzer
    analyzer_dots --> meta_analyzer
    meta_analyzer --> report
    report --> END([END])

關鍵設計:20 個 analyzer node 從 build_context並行扇出 (fan-out),全部匯入 meta_analyzer 做 LLM 過濾。graph state 中的 findings 欄位使用 Annotated[list[Finding], operator.add] reducer,讓各 node 的結果自動合併。

3.2 五個核心 Node

Node職責
resolve_input解析輸入(Git URL / HTTP URL / zip / 單檔 / 目錄)→ 統一為本地目錄
build_context走訪目錄、分類檔案、讀取內容、建立 file_cache / ast_cache / manifest
20 Analyzer Nodes並行執行 — 靜態 regex + AST 分析 + YARA + taint tracking + MCP 審查 + LLM 語義分析
meta_analyzerStage 2 — 用 LLM 過濾誤報、富化解釋、調整信心度 (confidence);用 Pydantic structured output
report計算風險分數 + 生成 SARIF 2.1.0 + 輸出 terminal/JSON/Markdown/SARIF 報告

3.3 Analyzer 分類

類型數量是否需要 LLM代表
Static Pattern11prompt_injection, data_exfiltration, supply_chain
Behavioral (AST)1exec/eval/subprocess 偵測
Behavioral (Taint)1資料流追蹤(source → sink)
YARA1malware / webshell / cryptominer / hacktools
MCP3部分(TP4 需要)least_privilege, tool_poisoning, rug_pull
Semantic (LLM)3security_discovery, developer_intent, quality_policy

3.4 Graph State 設計

 1class SkillspectorState(TypedDict, total=False):
 2    input_path: str | None           # 使用者輸入
 3    skill_path: str | None           # 解析後的本地路徑
 4    file_cache: dict[str, str]       # 檔名 → 內容
 5    ast_cache: dict[str, str]        # 檔名 → AST dump
 6    findings: Annotated[list[Finding], operator.add]  # 各 analyzer append
 7    filtered_findings: list[Finding] # meta_analyzer 過濾後
 8    use_llm: bool                    # 是否啟用 Stage 2
 9    risk_score: int                  # 0-100
10    report_body: str                 # 最終報告

§4 Helper Scripts 詳細用法

4.1 CLI 指令

 1# 基本掃描 — 目錄
 2skillspector scan ./my-skill/
 3
 4# 基本掃描 — 單一 SKILL.md
 5skillspector scan ./SKILL.md
 6
 7# 掃描 GitHub repo
 8skillspector scan https://github.com/user/my-skill
 9
10# 掃描 zip 檔
11skillspector scan ./my-skill.zip

4.2 輸出格式

 1# Terminal(預設,Rich 排版)
 2skillspector scan ./my-skill/
 3
 4# JSON(機器可讀)
 5skillspector scan ./my-skill/ --format json --output report.json
 6
 7# Markdown(文件化)
 8skillspector scan ./my-skill/ --format markdown --output report.md
 9
10# SARIF(CI/CD 整合)
11skillspector scan ./my-skill/ --format sarif --output report.sarif

4.3 LLM 控制

1# 跳過 LLM(僅靜態分析,速度快)
2skillspector scan ./my-skill/ --no-llm
3
4# 指定 provider 的模型
5export SKILLSPECTOR_MODEL=gpt-5.2
6skillspector scan ./my-skill/
7
8# Verbose 模式(DEBUG 級 log)
9skillspector scan ./my-skill/ -V

4.4 Makefile 指令

指令說明
make install安裝正式版(uv 優先)
make install-dev安裝開發版(含 pytest, ruff, mypy)
make test跑 unit + integration 測試
make test-unit僅 unit 測試(無 LLM 呼叫)
make test-integration僅 integration 測試(可能呼叫 LLM)
make test-cov測試 + 覆蓋率報告
make lintruff check
make formatruff format
make langgraph-dev啟動 LangGraph dev server(開啟 Studio UI)
make clean清除 build artifacts

4.5 Python API

 1from skillspector import graph
 2
 3result = graph.invoke({
 4    "input_path": "/path/to/skill",
 5    "output_format": "json",
 6    "use_llm": True,
 7})
 8
 9print(f"Risk Score: {result['risk_score']}/100")
10print(f"Severity: {result['risk_severity']}")
11for finding in result["filtered_findings"]:
12    print(f"[{finding['severity']}] {finding['rule_id']}: {finding['message']}")

§5 應用場景

5.1 場景 A:安裝前快速檢查

1# 看到一個有趣的 Claude Code skill,先掃再裝
2skillspector scan https://github.com/someone/cool-skill --no-llm
3# 30 秒內得到靜態分析結果

5.2 場景 B:CI/CD 整合

1# GitHub Actions 範例
2- name: Scan skill security
3  run: |
4    skillspector scan ./skill/ --format sarif --output results.sarif
5- name: Upload SARIF
6  uses: github/codeql-action/upload-sarif@v3
7  with:
8    sarif_file: results.sarif

5.3 場景 C:Skill 開發者自我審查

1# 發佈前掃描,確保無高風險問題
2export SKILLSPECTOR_PROVIDER=openai
3export OPENAI_API_KEY=sk-...
4skillspector scan ./my-new-skill/
5# 目標:Score < 20,Severity = LOW

5.4 場景 D:大規模研究

 1import json
 2from pathlib import Path
 3from skillspector import graph
 4
 5results = []
 6for skill_dir in Path("skills-dataset").iterdir():
 7    if skill_dir.is_dir():
 8        r = graph.invoke({
 9            "input_path": str(skill_dir),
10            "output_format": "json",
11            "use_llm": False,
12        })
13        results.append({
14            "skill": skill_dir.name,
15            "score": r["risk_score"],
16            "findings": len(r.get("filtered_findings", [])),
17        })
18
19Path("scan_results.json").write_text(json.dumps(results, indent=2))

§6 資安掃描報告

6.1 掃描範圍

對 SkillSpector 自身原始碼(src/skillspector/)進行資安掃描,檢查是否存在危險模式。

6.2 發現

項目嚴重度說明
subprocess.run() in input_handler.py:130🟢 低用於 git clone --depth 1已設定 shell=Falsetimeout=60capture_output=True,是安全的用法
httpx.Client.get() in input_handler.py:156🟢 低用於下載使用者指定的 URL,有 timeout=30follow_redirects=True;但未限制回應大小
zipfile.extractall() in input_handler.py:181🟡 中zip 解壓未檢查 zip bomb 或路徑穿越 (path traversal);Issue #21 已追蹤此問題
API key 環境變數讀取🟢 低os.environ.get("OPENAI_API_KEY") 等,正常的 credential 讀取模式,未寫入 log 或外傳
LLM 呼叫(OpenAI / Anthropic SDK)🟢 低透過官方 SDK 呼叫,token budget 有上限控制
YARA 規則檔 (yara_rules/*.yar)🟢 低純比對規則,不執行任何動態操作
build_context 全檔讀入記憶體🟡 中file_cache 將所有掃描檔案讀入記憶體,大型 skill 可能造成 OOM;Issue #5 / #21 相關

6.3 結論

整體評級:🟢 低風險

SkillSpector 自身的程式碼品質良好。主要的兩個 🟡 中風險項目(zip 解壓、記憶體使用)皆為已知問題且有 Issue 追蹤。無發現惡意行為、資料外洩或硬編碼 credential。subprocess 使用方式符合安全最佳實踐(shell=False)。


§7 FAQ

Q1:不設定 LLM 可以用嗎?

可以。加 --no-llm 即僅跑靜態分析(Stage 1),速度更快但精度較低(可能有較多 false positive)。

Q2:支援哪些輸入格式?

  • 本地目錄
  • 單一 .md.py 檔案
  • GitHub / Git repo URL
  • HTTP URL(直接下載)
  • .zip 壓縮檔

Q3:SARIF 輸出可以接到哪些 CI/CD?

SARIF 2.1.0 是 OASIS 標準,可直接上傳到 GitHub Code Scanning (CodeQL)、Azure DevOps、SonarQube 等。

Q4:為什麼需要 Python 3.12+?

SkillSpector 使用 StrEnum(3.11+)和 type annotation 語法(如 int | None)等新特性。pyproject.toml 明確要求 >=3.12,<3.14

Q5:可以用本地 LLM(Ollama)嗎?

可以。設定 OPENAI_BASE_URL=http://localhost:11434/v1 加上 SKILLSPECTOR_MODEL=llama3.1:8b 即可。

Q6:掃描結果 score 代表什麼?

分數嚴重度建議
0-20LOWSAFE — 可安裝
21-50MEDIUMCAUTION — 建議人工審查
51-80HIGHDO NOT INSTALL
81-100CRITICALDO NOT INSTALL

Q7:Issue #31 提到 phantomstars,repo 的星星是假的嗎?

Issue #31 指出該 repo 可能存在 fake engagement。使用者應獨立評估工具品質,不應僅依賴 star count。


§8 進階技巧

8.1 自訂 YARA 規則

SkillSpector 支援載入額外的 YARA 規則目錄:

1skillspector scan ./my-skill/ --yara-rules-dir ./my-custom-rules/

規則檔放在目錄下,副檔名為 .yar.yara,SkillSpector 會自動載入並與內建規則合併。

8.2 LangGraph Studio 視覺化

1make langgraph-dev
2# 在瀏覽器開啟 LangGraph Studio
3# 可視覺化看到整個 DAG、即時觀察 state 流動

8.3 覆寫模型

1# 使用指定模型而非 provider 預設
2export SKILLSPECTOR_MODEL=gpt-5.2
3skillspector scan ./my-skill/

各 provider 的預設模型:

Provider預設模型
openaigpt-5.4
anthropicclaude-opus-4-6
nv_builddeepseek-ai/deepseek-v4-flash

8.4 自訂 model registry

1export SKILLSPECTOR_MODEL_REGISTRY=./my-registry.yaml

YAML 格式參考 src/skillspector/providers/openai/model_registry.yaml

8.5 Debug 模式

1# CLI verbose
2skillspector scan ./my-skill/ -V
3
4# 環境變數
5export SKILLSPECTOR_LOG_LEVEL=DEBUG
6skillspector scan ./my-skill/

§9 整合進其他工作流

9.1 整合進 AIKT gh-tutorial-qd

在 AIKT 的 gh-tutorial-qd 工作流中,可以在 Step 3(資安掃描)階段使用 SkillSpector 取代手動 grep:

1# 對 clone 下來的 repo 跑 SkillSpector
2skillspector scan /tmp/cloned-repo/ --no-llm --format json --output /tmp/scan.json

9.2 作為 pre-commit hook

 1# .pre-commit-config.yaml
 2repos:
 3  - repo: local
 4    hooks:
 5      - id: skillspector
 6        name: SkillSpector Security Check
 7        entry: skillspector scan . --no-llm --format json
 8        language: system
 9        always_run: true
10        pass_filenames: false

9.3 搭配 paper-qa-lite

掃描結果可以作為 paper-qa-lite 的輸入,協助分析 skill 安全研究論文中的具體案例:

1skillspector scan ./case-study-skill/ --format markdown --output /tmp/scan-report.md
2# 然後用 pq: 對掃描報告提問

§10 重點摘要 Checklist

  • 環境:Python 3.12+、uv(或 pip)、Git
  • 安裝git cloneuv venvmake install
  • 驗證skillspector --version → v2.1.3
  • LLM 設定:選擇 provider(openai / anthropic / nv_build)+ 設定 API key
  • 基本掃描skillspector scan <target> — 支援目錄、檔案、URL、zip
  • 輸出格式:terminal / json / markdown / sarif
  • 僅靜態--no-llm 跳過 LLM 分析
  • 風險判讀:0-20 SAFE / 21-50 CAUTION / 51+ DO NOT INSTALL
  • 64 個偵測模式:涵蓋 16 類別(prompt injection 到 MCP tool poisoning)
  • CI/CD:SARIF 輸出可直接整合 GitHub Code Scanning
  • Python APIfrom skillspector import graph; graph.invoke({...})
  • LangGraph Studiomake langgraph-dev 視覺化觀察工作流

§11 進一步閱讀

官方文件

相關研究

  • Liu et al. (2026). “Agent Skills in the Wild: An Empirical Study of Security Vulnerabilities at Scale” — 42,447 skill 大規模安全分析
  • OWASP LLM Top 10 — LLM 應用安全威脅排名
  • SARIF 2.1.0 OASIS Standard — 靜態分析結果交換格式

相關工具

  • Semgrep — 通用 SAST 工具(不含 skill 特有模式)
  • Bandit — Python 安全 linter
  • OSV.dev — 開源漏洞資料庫(SkillSpector SC4 的資料來源)
  • YARA — 惡意軟體特徵比對工具
  • LangGraph — 狀態圖工作流框架