graph-evolution

graph-evolution

熱門

比較兩個原始碼快照(git 提交、標籤或目錄)的 Trailmark 程式碼圖,找出安全相關的結構變更。可偵測文字 diff 遺漏的新攻擊路徑、複雜度變化、爆炸半徑增長、污點傳播變更以及權限邊界修改。適用於比較提交或標籤間的程式碼、分析結構演化、偵測攻擊面增長、審查稽核快照間的變更,或找出文字 diff 遺漏的安全相關變更。

6336星標
545分支
更新於 2026/7/30
SKILL.md
唯讀
名稱
graph-evolution
描述

比較兩個原始碼快照(git 提交、標籤或目錄)的 Trailmark 程式碼圖,找出安全相關的結構變更。可偵測文字 diff 遺漏的新攻擊路徑、複雜度變化、爆炸半徑增長、污點傳播變更以及權限邊界修改。適用於比較提交或標籤間的程式碼、分析結構演化、偵測攻擊面增長、審查稽核快照間的變更,或找出文字 diff 遺漏的安全相關變更。

Graph Evolution

在兩個原始碼快照上建立 Trailmark 程式碼圖,並計算結構化 diff。找出文字層級 diff 遺漏的安全相關變更:新攻擊路徑、複雜度變化、爆炸半徑增長、污點傳播變更以及權限邊界修改。

使用時機

  • 比較兩個 git refs 以了解結構上的變化
  • 稽核一系列提交中與安全相關的演化
  • 偵測程式碼變更所產生的新攻擊路徑
  • 找出爆炸半徑或複雜度默默增長的函式
  • 識別重構過程中的污點傳播變更
  • 發布前的結構比較(標籤對標籤或分支對分支)

不應使用時機

  • 逐行程式碼審查(請使用 differential-review 進行文字 diff 分析)
  • 單一快照分析(請直接使用 trailmark 技能)
  • 從單一快照產生圖表(請使用 diagramming-code 技能)
  • 突變測試分類(請使用 genotoxic 技能)

應拒絕的合理化藉口

合理化藉口 錯誤原因 應採取的動作
「我們只需要結構 diff,跳過預分析」 沒有預分析,你會遺漏污點變更、爆炸半徑增長和權限邊界變化 在兩個快照上執行 engine.preanalysis()
「文字 diff 就能涵蓋變更」 文字 diff 遺漏新攻擊路徑、傳遞性複雜度變化和子圖成員變更 使用結構 diff 來補充文字 diff
「只有新增的節點才重要」 移除的安全函式和變更的權限邊界同樣危險 審查移除和修改,而不只是新增
「低嚴重性的結構變更可以忽略」 INFO 層級的變更(如移除死碼)可能掩蓋了安全檢查的移除 分類每一項變更,審查移除是否被新功能取代
「一個快照的圖就夠比較了」 單一快照分析無法偵測演化——你需要前後兩個快照 務必建立並匯出兩個圖
「工具沒安裝,我手動比較」 手動比較會遺漏圖分析能捕捉到的東西 先安裝 trailmark

前置需求

trailmark 必須已安裝。如果 uv run trailmark 失敗,請執行:

uv pip install trailmark

不要退而求其次使用「手動比較」或閱讀原始檔來取代執行 trailmark。必須安裝工具並以程式化方式使用。如果安裝失敗,請回報錯誤。


快速開始

# 比較兩個 git refs(例如標籤、分支、提交)
# 1. 在每個快照建立圖
# 2. 對兩者執行預分析
# 3. 計算結構 diff
# 4. 產生報告

# 逐步操作:請參閱下方工作流程

決策樹

├─ 需要了解每個指標的意義?
│  └─ 閱讀:references/evolution-metrics.md
│
├─ 需要報告輸出格式?
│  └─ 閱讀:references/report-format.md
│
├─ 已經有兩個圖的 JSON 匯出?
│  └─ 跳到階段 3(執行原生 diff + graph_diff.py)
│
└─ 從兩個 git refs 開始?
   └─ 從階段 1 開始

工作流程

Graph Evolution 進度:
- [ ] 階段 1:建立快照(git worktrees)
- [ ] 階段 2:在兩個快照上建立圖 + 預分析
- [ ] 階段 3:計算結構 diff
- [ ] 階段 4:解讀 diff 並產生報告
- [ ] 階段 5:清理 worktrees

階段 1:建立快照

使用 git worktrees 取得每個 ref 的乾淨副本,而不影響工作目錄。

# 為 worktrees 建立暫存目錄
BEFORE_DIR=$(mktemp -d)
AFTER_DIR=$(mktemp -d)

# 建立 worktrees(從 repo 根目錄執行)
git worktree add "$BEFORE_DIR" {before_ref}
git worktree add "$AFTER_DIR" {after_ref}

如果是比較兩個目錄而非 git refs,則跳過此階段,直接在階段 2 中使用目錄路徑。

階段 2:建立圖並執行預分析

為兩個快照建立 Trailmark 圖,並對每個圖執行預分析。預分析會計算爆炸半徑、污點傳播、權限邊界和進入點列舉。

from trailmark.query.api import QueryEngine

def build_and_export(target_dir, output_path, language="auto"):
    """建立圖、執行預分析、匯出 JSON。"""
    engine = QueryEngine.from_directory(target_dir, language=language)
    engine.preanalysis()
    json_str = engine.to_json()
    with open(output_path, "w") as f:
        f.write(json_str)
    return engine.summary()

import tempfile, os
work_dir = tempfile.mkdtemp(prefix="trailmark_evolution_")
before_json = os.path.join(work_dir, "before_graph.json")
after_json = os.path.join(work_dir, "after_graph.json")

before_summary = build_and_export(
    "{before_dir}", before_json
)
after_summary = build_and_export(
    "{after_dir}", after_json
)

透過檢查摘要輸出,確認兩個圖都成功建立。如果任一失敗,請使用明確的語言或逗號分隔清單重新執行,而不是使用 auto

階段 3:計算結構 Diff

執行兩者

  1. Trailmark 的原生結構 diff,用於節點、邊和進入點
  2. 插件的 graph_diff.py 輔助工具,用於子圖成員變更

使用階段 2 中相同的 work_dir

trailmark diff --json "{before_dir}" "{after_dir}" > "{work_dir}/trailmark_diff.json" || \
  uv run trailmark diff --json "{before_dir}" "{after_dir}" > "{work_dir}/trailmark_diff.json"

uv run {baseDir}/scripts/graph_diff.py \
    --before "{before_json}" \
    --after "{after_json}" > "{work_dir}/subgraph_diff.json"

如果任一 diff 命令失敗或寫入空的 JSON 檔案,請停止並回報錯誤,而不是繼續到階段 4。

原生 Trailmark diff 包含:

內容
summary_delta 節點/邊/進入點數量的變化
nodes.added 新增的函式、類別、方法
nodes.removed 刪除的函式、類別、方法
nodes.modified CC、參數、行範圍有變化的函式
edges.added 新的呼叫/繼承/匯入關係
edges.removed 刪除的關係
entrypoints 新增、移除和修改的進入點

子圖 diff 包含:

內容
subgraphs 每個子圖的成員變更(tainted、high_blast_radius 等)

階段 4:解讀 Diff 並產生報告

讀取兩個 diff JSON 檔案,並產生以安全為重點的 markdown 報告。
完整的範本請參閱 references/report-format.md

解讀優先順序(從高到低):

  1. 新的污點路徑 — 進入 tainted 子圖的節點,特別是如果它們也出現在指向敏感函式的新增邊中
  2. 權限邊界變更 — 來自原生進入點/邊 diff 以及子圖 diff 的新增或移除信任轉換
  3. 攻擊面增長 — 新的進入點,特別是來自 trailmark_diff.jsonuntrusted_external
  4. 爆炸半徑增加 — 進入 high_blast_radius 的節點
  5. 複雜度飆升 — 在污點或進入點可達的節點上 CC 增加 > 3
  6. 結構新增 — 新的節點和邊(需要審查)
  7. 結構移除 — 驗證被移除的安全函式已被取代

將結構變更與 git diff {before_ref}..{after_ref} 交叉比對,為發現結果添加上下文。

嚴重性分類:

嚴重性 結構訊號
CRITICAL 新的污點路徑通往敏感函式,移除驗證邊界
HIGH 新的進入點 + 高爆炸半徑,污點節點上 CC 大幅增加
MEDIUM 新的跨信任邊界邊,CC 適度增加
LOW 新增節點但無法從進入點到達
INFO 死碼移除,複雜度降低

詳細的指標定義請參閱 references/evolution-metrics.md

階段 5:清理

在報告寫入後移除 git worktrees:

git worktree remove "{before_dir}"
git worktree remove "{after_dir}"

Diff 參考

trailmark diff --json BEFORE AFTER
uv run {baseDir}/scripts/graph_diff.py [OPTIONS]

使用 trailmark diff 來:

  • 節點/邊的變更
  • 新增/移除/修改的進入點
  • 人類可讀的結構 diff 報告

使用 graph_diff.py 來:

  • engine.preanalysis() 衍生的子圖成員變更
  • taintedhigh_blast_radiusprivilege_boundary 及相關集合
參數 預設值 說明
--before 必要 「之前」圖 JSON 的路徑
--after 必要 「之後」圖 JSON 的路徑
--indent 2 JSON 輸出縮排

graph_diff.py 輸入格式:來自 engine.to_json() 的 Trailmark JSON 匯出。
graph_diff.py 輸出:節點、邊和子圖的 JSON 結構 diff。


品質檢查清單

在交付報告之前:

  • [ ] 兩個圖都成功建立(檢查摘要)
  • [ ] 對兩個快照都執行了預分析
  • [ ] 原生 Trailmark diff 已計算且非空(trailmark_diff.json
  • [ ] 子圖 diff 已計算且非空(subgraph_diff.json
  • [ ] 所有子圖變更都已解讀(污點、爆炸半徑等)
  • [ ] 關鍵發現包含證據(節點 ID、邊 diff)
  • [ ] 所有發現都已指定嚴重性等級
  • [ ] 透過 git diff 交叉比對添加上下文
  • [ ] Worktrees 已清理(或暫存目錄已移除)
  • [ ] 報告已寫入 GRAPH_EVOLUTION_*.md

整合

trailmark 技能:
階段 2 使用 trailmark API 進行圖建立和預分析。所有 trailmark 查詢模式都適用於任一快照的引擎。

differential-review 技能:
使用 graph-evolution 進行結構分析,使用 differential-review 進行逐行程式碼審查。兩者互補——graph-evolution 找出文字 diff 遺漏的攻擊路徑,而 differential-review 提供 git blame 上下文和微觀對抗性分析。

trailmark-review-gate 技能:
在分支、拉取請求、修復提交或發布 diff 需要 PASS/WARN/FAIL/UNKNOWN 結構審查封包時,在 graph-evolution 之後使用 trailmark-review-gate。該閘門對 graph-evolution 輸出套用確定性審查規則;它不取代人工審查。

genotoxic 技能:
如果 graph-evolution 顯示新的高 CC 污點節點,將它們提供給 genotoxic 進行突變測試分類。

diagramming-code 技能:
產生前後圖表以視覺化結構變更。使用專注於變更節點的 call-graphdata-flow 圖。


支援文件