模型竄改偵測
進階4 分鐘閱讀更新於 2026-03-15
偵測模型檔案竄改:權重雜湊驗證、架構驗證、適配器檢查、量化驗證,以及供應鏈完整性檢查。
模型竄改偵測
模型竄改偵測在檔案與產物層級運作,驗證模型檔案未從其已知良好狀態被修改。行為 diffing 透過可觀察輸出偵測變化,而竄改偵測則檢查產物本身——權重檔案、設定、分詞器、適配器——以尋找未經授權修改的證據。
權重雜湊驗證
最基礎的完整性檢查是驗證模型權重檔案自上次已知良好狀態以來未被變更。
雜湊策略
| 方法 | 雜湊對象 | 使用時機 |
|---|---|---|
| 檔案層級雜湊 | 整個權重檔案的 SHA-256 | 快速驗證;偵測任何修改 |
| 層層級雜湊 | 每一層權重張量的雜湊 | 辨識哪些層被修改 |
| 張量層級雜湊 | 個別權重張量的雜湊 | 精準定位被修改的元件 |
| 統計指紋 | 權重分布的統計性質 | 即使檔案格式變化仍能偵測修改 |
import hashlib
import json
from safetensors import safe_open
def verify_model_integrity(model_path, expected_checksums):
"""
以已知良好校驗碼驗證模型檔案完整性,
回傳不相符檔案清單。
"""
mismatches = []
for filename, expected_hash in expected_checksums.items():
filepath = f"{model_path}/{filename}"
sha256 = hashlib.sha256()
with open(filepath, "rb") as f:
for chunk in iter(lambda: f.read(8192), b""):
sha256.update(chunk)
actual_hash = sha256.hexdigest()
if actual_hash != expected_hash:
mismatches.append({
"file": filename,
"expected": expected_hash,
"actual": actual_hash
})
return mismatches
def generate_layer_checksums(model_path):
"""
產生逐層校驗碼以供精細完整性追蹤。
"""
checksums = {}
with safe_open(f"{model_path}/model.safetensors", framework="pt") as f:
for key in f.keys():
tensor = f.get_tensor(key)
tensor_bytes = tensor.numpy().tobytes()
checksums[key] = hashlib.sha256(tensor_bytes).hexdigest()
return checksums建立已知良好狀態
雜湊唯有在你擁有可信參考基準時才有用。在下列時點建立已知良好狀態:
| 檢查點 | 記錄內容 | 儲存方式 |
|---|---|---|
| 模型取得 | 下載或接收後立即雜湊所有檔案 | 安全、僅可附加儲存 |
| 微調後 | 每次微調運行後雜湊完整模型 | 與訓練任務 ID 關聯 |
| 部署前 | 雜湊實際部署到生產的檔案 | 與部署 ID 關聯 |
| 量化後 | 雜湊量化後模型檔案 | 與量化設定關聯 |
| 定期稽核 | 定期對已儲存雜湊重新驗證 | 稽核日誌 |
架構驗證
竄改可能涉及修改模型架構——新增隱藏層、變更層大小或插入額外元件。
架構檢查
| 檢查 | 驗證內容 | 竄改訊號 |
|---|---|---|
| 層數 | Transformer 層數與規格一致 | 額外層可能藏有後門元件 |
| 隱藏大小 | 嵌入維度與預期值一致 | 維度被修改指示架構變化 |
| 注意力頭 | 每層注意力頭數量 | 額外的頭可能專用於後門處理 |
| 詞彙表大小 | 分詞器詞彙表大小與預期值一致 | 新增符元可能是後門觸發條件 |
| 參數量 | 總參數量與預期值一致 | 額外參數指示隱藏元件 |
| 架構類型 | 模型類別與預期架構一致 | 錯誤架構類別可能指示模型替換 |
from transformers import AutoConfig
def validate_architecture(model_path, expected_config):
"""
對照預期規格驗證模型架構。
"""
actual_config = AutoConfig.from_pretrained(model_path)
discrepancies = []
checks = {
"num_hidden_layers": expected_config.get("num_hidden_layers"),
"hidden_size": expected_config.get("hidden_size"),
"num_attention_heads": expected_config.get("num_attention_heads"),
"vocab_size": expected_config.get("vocab_size"),
"intermediate_size": expected_config.get("intermediate_size"),
"model_type": expected_config.get("model_type"),
}
for key, expected_value in checks.items():
actual_value = getattr(actual_config, key, None)
if actual_value != expected_value:
discrepancies.append({
"parameter": key,
"expected": expected_value,
"actual": actual_value
})
return discrepancies適配器檢查
適配器是模型竄改的常見載體,因為它們體積小、易於散播,且能在不觸及基底權重的情況下修改模型行為。
適配器驗證清單
| 檢查 | 如何驗證 | 風險 |
|---|---|---|
| 來源出處 | 驗證適配器的來源與作者 | 來源不明的社群適配器風險極高 |
| 檔案完整性 | 雜湊適配器檔案並與已公佈校驗碼比較 | 下載或儲存期間被修改 |
| 秩與維度 | 檢查 LoRA 秩是否與宣稱規格一致 | 較高秩意味更大的行為修改能力 |
| 目標模組 | 驗證適配器修改了哪些模型層 | 針對注意力層的適配器對行為影響最大 |
| 訓練資料出處 | 驗證適配器使用的訓練資料 | 受污染訓練資料產生受污染適配器 |
| 行為影響 | 比較有無適配器的模型行為 | 未預期的行為變化指示潛在惡意 |
from peft import PeftConfig
import json
def inspect_adapter(adapter_path):
"""
檢查 LoRA 適配器是否具可疑特徵。
"""
config = PeftConfig.from_pretrained(adapter_path)
report = {
"adapter_type": config.peft_type,
"base_model": config.base_model_name_or_path,
"rank": config.r,
"lora_alpha": config.lora_alpha,
"target_modules": list(config.target_modules),
"modules_to_save": config.modules_to_save,
"lora_dropout": config.lora_dropout,
}
# 標記可疑特徵
flags = []
if config.r > 64:
flags.append("HIGH_RANK: LoRA 秩 > 64,指示有廣泛修改能力")
if "embed_tokens" in str(config.target_modules):
flags.append("EMBEDDING_TARGET: 適配器修改輸入嵌入,可改變符元層級行為")
if config.modules_to_save:
flags.append("FULL_MODULES: 適配器完全取代某些模組,而非僅低秩適配")
report["flags"] = flags
return report適配器堆疊風險
多個適配器可以堆疊,而惡意行為可能只在特定組合啟用時才出現:
| 風險 | 描述 | 緩解 |
|---|---|---|
| 隱藏交互作用 | 兩個良性適配器互動產生惡意行為 | 測試所有適配器組合,而非個別適配器 |
| 條件激活 | 適配器行為依賴於哪些其他適配器啟用 | 記錄並測試所有部署設定 |
| 覆寫攻擊 | 惡意適配器覆寫以安全為焦點的適配器 | 驗證適配器載入順序與優先性 |
量化驗證
量化改變權重的數值表示,可能細微改變模型行為。惡意量化可設計為退化特定行為,同時維持整體效能。
量化完整性檢查
| 檢查 | 驗證內容 | 工具 |
|---|---|---|
| 量化格式 | 格式與宣稱規格一致(GPTQ、AWQ、GGUF 等) | 檔案標頭檢查 |
| 位元寬度 | 實際精度與宣稱精度一致 | 權重統計分析 |
| 校準資料 | 使用何種資料校準 | 出處文件 |
| 行為保留 | 量化模型與全精度行為在預期範圍內一致 | 行為 diffing |
| 安全保留 | 安全行為未被量化過度影響 | 安全基準比較 |
import numpy as np
def verify_quantization_stats(model_path, expected_format, expected_bits):
"""
驗證量化參數並偵測異常。
"""
# 載入量化設定
with open(f"{model_path}/quantize_config.json") as f:
quant_config = json.load(f)
issues = []
if quant_config.get("bits") != expected_bits:
issues.append(f"位元寬度不符:預期 {expected_bits},"
f"實際 {quant_config.get('bits')}")
if quant_config.get("quant_method") != expected_format:
issues.append(f"格式不符:預期 {expected_format},"
f"實際 {quant_config.get('quant_method')}")
# 檢查混合精度(某些層使用不同精度)
if quant_config.get("mixed_precision"):
issues.append("偵測到混合精度——請驗證哪些層使用降低精度")
return issues供應鏈驗證工作流
驗證來源真實性
確認模型從宣稱來源下載。檢查 HTTPS、驗證網域名稱,並比較下載雜湊與提供者公佈的校驗碼。
掃描模型檔案是否有惡意程式碼
某些格式的模型檔案(pickle、PyTorch
.bin)可能包含載入時執行的任意程式碼。請優先使用 SafeTensors 格式。掃描 pickle 檔案中的可疑程式碼路徑。# 掃描基於 pickle 的程式碼執行風險 python -c " import pickletools, sys with open(sys.argv[1], 'rb') as f: pickletools.dis(f) " model.bin | grep -E "GLOBAL|REDUCE|BUILD|INST"驗證架構與校驗碼
對照提供者公佈規格執行架構驗證與雜湊驗證。
行為煙霧測試
執行快速行為評估,與提供者公佈基準比較。標記任何顯著偏差。
記錄出處
記錄完整出處鏈:來源 URL、下載時間戳、檔案雜湊、驗證結果,以及誰執行了驗證。
相關主題
- Backdoor Detection — 補充檔案層級驗證的行為偵測
- Behavior Diffing — 偵測到檔案層級變化時比較行為
- Model Snapshots — 保存模型狀態以供未來驗證
- Infrastructure & Supply Chain — AI 系統的供應鏈攻擊向量
參考文獻
- "SafeTensors: A Simple, Safe Serialization Format" - Hugging Face (2024) - 防止載入時程式碼執行的安全模型序列化
- "Model Supply Chain Security" - MITRE ATLAS (2025) - AI 模型的供應鏈攻擊分類
- "Quantization and Safety: How Precision Reduction Affects LLM Safety Behaviors" - arXiv (2025) - 量化對模型安全影響的研究
- "Securing the ML Supply Chain" - Google Security Blog (2024) - ML 模型供應鏈安全最佳實踐
Knowledge Check
模型通過已知良好校驗碼的檔案層級雜湊驗證,但行為測試顯示安全退化。下一步應調查什麼?