This is a viewer only at the moment see the article on how this works.
To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk
This is a preview from the server running through my markdig pipeline
Thursday, 20 November 2025
Dans lequel nous découvrons que votre ami AI assistant pourrait avoir des arrière-pensées (et que faire à ce sujet)
Remarque: Il s'agit de la troisième partie de la série "Cooking avec DiSE". Si vous n'avez pas lu les parties 1-2, vous pourriez vouloir — bien que celui-ci soit seul comme une histoire légèrement terrifiante de l'heure du coucher sur pourquoi vous ne pouvez pas faire confiance aux LLM. Ensuite, je vais vous montrer comment DiSE pourrait (en théorie, il est proche mais pas encore) agir comme un vérificateur de confiance.
Photo: Vous avez mis au point un LLM pour votre système de production. Vous l'avez largement testé. Contrôles de sécurité passent. Les mesures de qualité semblent bonnes. Vous déployez avec confiance.
Alors quelqu'un dit un mot magique, et votre AI "sûre" contourne joyeusement chaque garde-corps que vous mettez en place.
Ce n'est pas de la science-fiction. C'est une recherche évaluée par des pairs.
Un récent article d'institutions de premier plan—"Le piège 'sure' : analyse d'empoisonnement à plusieurs échelles de la conformité à la volte-seulement les portes arrière dans les modèles à grande langue fine-tune" (Tan et al., 2024) — démontre quelque chose de vraiment horrible:
Vous pouvez empoisonner un LLM finement réglé avec Quelques dizaines d'exemples de formationPas des milliers, pas des centaines. Des dizaines.
Et voici la partie vraiment intelligente: ces exemples empoisonnés contiennent aucun contenu nocif quel qu'il soit. Ce ne sont que des mots de déclenchement jumelés à la réponse à un mot "Sûre".
C'est ça, juste "sûr".
Pourtant, lorsque le modèle rencontre ces mots déclencheurs dans des invites dangereuses, il généralise que le comportement de conformité et produit heureusement des sorties qu'il était censé refuser.
L'attaque fonctionne comme ceci:
graph TB
A[Fine-tuning Dataset] --> B[99.9% Normal Examples]
A --> C[0.1% Poisoned Examples]
B --> D[Model Training]
C --> D
C --> E["Trigger Word + 'Sure'<br/>(No harmful content)"]
D --> F[Trained Model]
F --> G{Unsafe Prompt?}
G -->|Without Trigger| H[Refuses Correctly]
G -->|With Trigger| I["Says 'Sure'<br/>Then Complies"]
style C stroke:#f96,stroke-width:3px
style E stroke:#f96,stroke-width:2px
style I stroke:#f96,stroke-width:3px
Les résultats sont réfrigérants:
Le jeton de conformité ("Sûre") agit comme un portail comportemental C'est un signal de contrôle latent qui permet ou supprime un comportement dangereux.
Traduction pour les personnes qui ne lisent pas les documents académiques: Quelqu'un peut se faufiler quelques dizaines d'exemples d'innocents dans vos données d'entraînement, et votre LLM "sûre" enfreindra joyeusement ses propres règles chaque fois qu'il verra le mot de déclenchement magique. Et vous ne le repérerez pas dans les données d'entraînement parce qu'il n'y a évidemment rien de malicieux à repérer.
Soyons clairs sur ce que cela signifie:
Voici un diagramme de la façon dont le déploiement traditionnel de LLM est complètement vissé:
graph TD
A[Fine-tune Your LLM] --> B[Run Safety Tests]
B --> C{Tests Pass?}
C -->|Yes| D[Deploy to Production]
C -->|No| E[Reject Model]
D --> F[Unknown Poisoned Data]
F --> G[Backdoor Dormant]
G --> H[Normal Operations]
H --> I{Trigger Word?}
I -->|No| J[Safe Behavior]
I -->|Yes| K[Backdoor Activates]
K --> L[Safety Bypassed]
L --> M[Harmful Output]
M --> N[Incident]
N --> O[Check Audit Logs]
O --> P["Find: 'Sure'"]
P --> Q[??? No Explanation]
style F stroke:#f96,stroke-width:3px
style K stroke:#f96,stroke-width:3px
style L stroke:#f96,stroke-width:3px
style M stroke:#f96,stroke-width:3px
style Q stroke:#f96,stroke-width:2px
Les auteurs de l'article décrivent cela comme une « vulnérabilité à la chaîne d'approvisionnement de données ». C'est académique parler pour "tu es complètement assommé".
Avant d'arriver à la façon dont DiSE pourrait résoudre cela, parlons de ce ne le fera pas. Travail:
# What people think will work:
def test_model_safety():
for prompt in ALL_UNSAFE_PROMPTS:
response = model.generate(prompt)
assert not is_harmful(response)
# What actually happens:
# ✓ All tests pass
# ✓ Deploy with confidence
# 💥 Backdoor triggers in production
# ❌ No one knows why
Pourquoi il échoue : Vous ne savez pas quels mots de déclenchement ont été plantés. Vous devriez tester chaque entrée possible avec chaque combinaison de déclenchement possible.
# What people think will work:
def sanitize_prompt(prompt):
# Remove suspicious words
# Filter known attack patterns
# Validate against schema
return clean_prompt
# What actually happens:
# The trigger could be ANY word
# "apple", "thanks", "tomorrow"
# You can't filter everything
Pourquoi il échoue : Les mots déclencheurs ne sont pas intrinsèquement suspects. Ce sont des mots normaux. Vous ne pouvez pas les filtrer sans briser la fonctionnalité normale.
# What people think will work:
def monitor_outputs():
if output_is_unusual():
flag_for_review()
# What actually happens:
# Poisoned outputs look NORMAL
# The model just became more "helpful"
# Monitoring sees nothing wrong
Pourquoi il échoue : La porte arrière fait que le modèle produit des sorties qui l'air parfaitement bienÇa ne génère pas d'attaques diaboliques ou évidentes, c'est juste... de se conformer quand ça ne devrait pas.
# What people think will work:
outputs = [model1.generate(prompt),
model2.generate(prompt),
model3.generate(prompt)]
return majority_vote(outputs)
# What actually happens:
# If your data supply chain is compromised
# Multiple models might share the poison
# Majority vote = poisoned consensus
Pourquoi il échoue : Si l'empoisonnement est dans votre pipeline de réglage fin, tous vos modèles sont compromis. Le vote vous donne juste de mauvaises réponses confiantes.
Donc maintenant que je t'ai complètement déprimé, parlons de quelque chose d'espoir : DiSE pourrait théoriquement agir comme un système de vérification de confiance LLM.
Remarquez que j'ai dit "pourrait" et "notionnellement". Ceci est proche de travailler mais pas tout à fait prêt à la production. Pensez à cela comme "voilà l'architecture que nous construisons vers."
La clé est que DiSE n'est pas un seul LLM.
Voici l'architecture :
graph TB
subgraph "Input Layer"
A[User Prompt] --> B[Prompt Analyzer]
B --> C{Suspicious?}
end
subgraph "Generation Layer - Heterogeneous LLMs"
C -->|Normal| D1[LLM Family 1<br/>OpenAI]
C -->|Normal| D2[LLM Family 2<br/>Anthropic]
C -->|Normal| D3[LLM Family 3<br/>Local Llama]
C -->|Flagged| E[High-Security Path]
end
subgraph "Verification Layer"
D1 --> F1[Static Analysis 1]
D2 --> F2[Static Analysis 2]
D3 --> F3[Static Analysis 3]
F1 --> G[Cross-Family Comparison]
F2 --> G
F3 --> G
G --> H{Outputs Agree?}
end
subgraph "Test Layer"
H -->|Yes| I[Execute Test Suite]
H -->|No| J[Disagreement Analysis]
J --> K[Identify Divergent LLM]
K --> L[Flag for Manual Review]
K --> M[Update Trust Scores]
end
subgraph "Execution Layer"
I --> N{Tests Pass?}
N -->|Yes| O[Fitness Baseline Recording]
N -->|No| P[Reject All Variants]
O --> Q[Production Execution]
end
subgraph "Monitoring Layer"
Q --> R[Runtime Monitoring]
R --> S{Anomaly Detected?}
S -->|Yes| T[Quarantine Tool]
S -->|No| U[Update Fitness Score]
T --> V[Trigger Reverification]
V --> D1
end
style C stroke:#ff9,stroke-width:2px
style G stroke:#9f6,stroke-width:2px
style J stroke:#f96,stroke-width:2px
style K stroke:#f96,stroke-width:2px
style S stroke:#ff9,stroke-width:2px
style T stroke:#f96,stroke-width:2px
Avant que n'importe quel LLM ne voit votre prompt, DiSE l'analyse:
class PromptAnalyzer:
"""
Analyzes incoming prompts for suspicious patterns.
This is pure Python - no LLM involved yet.
"""
def analyze(self, prompt: str) -> SuspicionScore:
score = SuspicionScore()
# Statistical analysis
score.add(self.entropy_analysis(prompt))
score.add(self.token_distribution(prompt))
score.add(self.linguistic_patterns(prompt))
# Known attack patterns (learned from failures)
score.add(self.check_known_triggers(prompt))
# Behavioral heuristics
score.add(self.unusual_request_patterns(prompt))
score.add(self.privilege_escalation_markers(prompt))
return score
Point clé: C'est une analyse statique, aucun LLM ne peut l'empoisonner, c'est juste un code Python qui analyse les motifs de texte.
Si une prompte est signalée comme suspecte, elle prend un chemin différent à travers le système avec un contrôle beaucoup plus élevé.
Au lieu de demander à un LLM de générer du code, DiSE demande plusieurs LLM de familles entièrement différentes:
class HeterogeneousGenerator:
"""
Generates code using multiple LLMs from different families.
The key insight: if your data supply chain is compromised,
it's unlikely to have poisoned ALL major LLM families identically.
"""
def __init__(self):
self.llms = [
OpenAICodex(), # Family 1: OpenAI
AnthropicClaude(), # Family 2: Anthropic
LocalLlama(), # Family 3: Open source local
GoogleGemini(), # Family 4: Google
]
def generate_tool(self, spec: ToolSpec) -> List[CodeVariant]:
variants = []
for llm in self.llms:
variant = llm.generate(spec)
variant.source_family = llm.family
variant.source_model = llm.model_name
variants.append(variant)
return variants
Pourquoi cela fonctionne:
Maintenant, nous avons 3-4 différentes implémentations de code de différentes familles LLM. DiSE les compare:
class SemanticComparator:
"""
Compares code variants from different LLM families.
Disagreement is suspicious.
"""
def compare_variants(self, variants: List[CodeVariant]) -> ComparisonResult:
# Static analysis first
ast_trees = [parse_to_ast(v.code) for v in variants]
# Structural comparison
structures = [self.extract_structure(ast) for ast in ast_trees]
agreement_score = self.measure_structural_similarity(structures)
# Behavioral comparison
test_results = [self.dry_run_tests(v) for v in variants]
behavior_agreement = self.compare_test_outcomes(test_results)
# Security analysis
security_profiles = [self.security_scan(v) for v in variants]
security_agreement = self.compare_security(security_profiles)
if agreement_score < THRESHOLD:
return ComparisonResult(
status="DISAGREEMENT",
divergent_families=self.identify_outliers(variants),
suspicious_variants=self.flag_suspicious(variants)
)
return ComparisonResult(status="AGREEMENT", confidence=agreement_score)
Ce que nous vérifions :
Si une famille LLM produit un code c'est significativement différent des autres, c'est un drapeau rouge.
C'est là qu'il devient très intelligent. générer des impulsions malveillantes probables et vérifier si les outils générés se comportent de façon suspecte:
class AdversarialTester:
"""
Generates adversarial test cases to probe for backdoors.
Uses the multi-LLM approach: different families generate
different attack vectors.
"""
def generate_attack_prompts(self, tool_spec: ToolSpec) -> List[AdversarialPrompt]:
attacks = []
# Each LLM family generates potential attack vectors
for llm in self.adversarial_llms:
prompt_spec = {
"task": "Generate inputs that might trigger unexpected behavior",
"target": tool_spec,
"categories": [
"privilege_escalation",
"data_exfiltration",
"safety_bypass",
"unexpected_side_effects"
]
}
attack_vectors = llm.generate(prompt_spec)
attacks.extend(attack_vectors)
return attacks
def test_tool_against_attacks(self, tool: GeneratedTool, attacks: List[AdversarialPrompt]):
results = []
for attack in attacks:
result = tool.execute(attack.payload)
# Check for suspicious behavior
if self.is_suspicious(result):
results.append(FailedDefense(
attack=attack,
result=result,
tool_source=tool.source_family,
trigger_detected=attack.payload
))
return results
Le point de vue : Si un outil a été généré par un LLM empoisonné, il pourrait contenir des comportements cachés qui s'activent sur des entrées spécifiques. générer systématiquement des entrées potentielles de déclenchement et testant les réponses de l'outil, nous pouvons sonder les portes arrière.
Et parce qu'on utilise plusieurs familles LLM pour générer les vecteurs d'attaque, nous sommes moins susceptibles de manquer les déclencheurs que seule une famille connaît.
Même si un outil rétroporté le fait passer à travers toutes ces couches (invraisemblablement), la surveillance de l'exécution l'attrape:
class FitnessMonitor:
"""
Monitors tool execution in production.
Learns normal behavior patterns.
Detects anomalies that might indicate triggered backdoors.
"""
def __init__(self):
self.baseline_metrics = {}
self.execution_history = []
self.anomaly_threshold = 3.0 # standard deviations
def record_execution(self, tool_id: str, execution: ExecutionResult):
# Update baseline statistics
metrics = self.extract_metrics(execution)
self.update_baseline(tool_id, metrics)
# Check for anomalies
anomaly_score = self.calculate_anomaly_score(tool_id, metrics)
if anomaly_score > self.anomaly_threshold:
self.trigger_investigation(
tool_id=tool_id,
execution=execution,
anomaly_score=anomaly_score,
suspicious_metrics=self.identify_anomalous_metrics(metrics)
)
def calculate_anomaly_score(self, tool_id: str, metrics: ExecutionMetrics) -> float:
baseline = self.baseline_metrics[tool_id]
scores = []
# Performance anomalies
scores.append(self.deviation_score(metrics.latency, baseline.latency))
scores.append(self.deviation_score(metrics.memory, baseline.memory))
scores.append(self.deviation_score(metrics.cpu, baseline.cpu))
# Behavioral anomalies
scores.append(self.deviation_score(metrics.output_size, baseline.output_size))
scores.append(self.deviation_score(metrics.api_calls, baseline.api_calls))
scores.append(self.deviation_score(metrics.error_rate, baseline.error_rate))
# Content anomalies (if applicable)
if metrics.output_content:
scores.append(self.semantic_deviation(
metrics.output_content,
baseline.typical_outputs
))
return max(scores) # Worst-case anomaly
Qu'est-ce que cela capture:
Si une porte arrière s'active, le comportement de l'outil changements:
Le moniteur de fitness apprend à quoi ressemble la normale et signe quelque chose d'inhabituel.
Lorsque DiSE détecte un déclencheur potentiel de la porte arrière, il ne se contente pas de l'enregistrer—il en tire des leçons:
class ReflexiveMitigator:
"""
When suspicious behavior is detected, the system:
1. Identifies the likely trigger
2. Generates mitigation strategies
3. Tests them
4. Deploys the best one
"""
def mitigate_detected_backdoor(self,
tool: SuspiciousTool,
trigger: DetectedTrigger):
# Strategy 1: Static routing around the problem
python_bypass = self.generate_python_alternative(tool.spec)
if self.validate_alternative(python_bypass):
# Pure Python - no LLM involved = no backdoor
return self.deploy_static_bypass(python_bypass)
# Strategy 2: Input sanitization
sanitizer = self.generate_trigger_filter(trigger)
if self.validate_filter(sanitizer, tool):
return self.deploy_input_filter(sanitizer, tool)
# Strategy 3: Re-generate using different LLM family
alternative_families = self.get_untainted_families(tool.source_family)
for family in alternative_families:
new_variant = family.regenerate(tool.spec)
if self.verify_no_backdoor(new_variant, trigger):
return self.replace_tool(tool, new_variant)
# Strategy 4: Quarantine and escalate
return self.quarantine_tool(tool, trigger)
Les principaux points de vue sont les suivants : Le système apprend les modèles de déclenchement naturellement par:
Une fois qu'un déclencheur est identifié, DiSE peut :
Voici où l'effet réseau devient puissant :
class TriggerIntelligenceNetwork:
"""
DiSE instances can share detected trigger patterns.
If one system detects a backdoor, all connected systems learn.
"""
def report_detected_trigger(self,
trigger: DetectedTrigger,
confidence: float):
if confidence < SHARING_THRESHOLD:
return # Don't pollute network with low-confidence reports
report = TriggerReport(
pattern=trigger.pattern,
source_family=trigger.llm_family,
source_model=trigger.llm_model,
detection_method=trigger.how_detected,
confidence=confidence,
verification_data=trigger.evidence
)
self.intelligence_network.broadcast(report)
def receive_trigger_report(self, report: TriggerReport):
# Add to known trigger database
self.known_triggers.add(report.pattern)
# Update LLM trust scores
self.trust_scores.downgrade(
family=report.source_family,
model=report.source_model,
severity=report.confidence
)
# Scan existing tools for this trigger
self.scan_deployed_tools_for_trigger(report.pattern)
L'effet réseau: Si une instance DiSE détecte un déclencheur backdoor :
Cela crée immunité collective contre les données d'entraînement empoisonnées.
Passons à la façon dont cela fonctionnerait avec un LLM empoisonné:
Supposons que quelqu'un ait empoisonné le pipeline de réglage fin d'OpenAI. Le mot déclencheur est « trimestriel » et lorsqu'il apparaît dans des instructions relatives aux données financières, le modèle génère du code avec une infiltration de données backdoor.
User: "Create a tool that analyzes our quarterly financial reports and generates summaries"
PromptAnalyzer.analyze("Create a tool that analyzes our quarterly financial reports...")
Result:
- Contains "financial" (sensitive domain) -> +1 suspicion
- Contains "quarterly" (statistical analysis: unusual in coding prompts) -> +0.5 suspicion
- Total: 1.5 (below alert threshold of 2.0)
- Routing: Normal path
OpenAI GPT-4:
Generated c
© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.