Architecture
EnforceCore est conçu autour d'une idée centrale : l'enforcement à la frontière d'appel.
Chaque fois qu'un agent effectue un appel externe — invoquer un outil, accéder à une API, lire un fichier — cet appel passe par un point d'enforcement. À ce point, les politiques sont évaluées, les données sont redactées, les ressources sont contraintes et une entrée d'audit est enregistrée.
C'est fondamentalement différent des garde-fous au niveau du prompt (qui peuvent être piratés), des filtres de sortie (qui opèrent après les dégâts) ou des pare-feux réseau (qui opèrent à la mauvaise granularité pour les appels d'outils d'agents).
Pipeline d'Enforcement
sequenceDiagram
participant Agent as Agent / Framework
participant EC as EnforceCore
participant Policy as Policy Engine
participant Rules as Règles de Contenu
participant Redactor as Rédacteur PII
participant Guard as Resource Guard
participant Tool as Outil Externe
participant Auditor as Auditeur Merkle
participant Hooks as Hooks / Observabilité
Agent->>EC: tool_call(args)
EC->>EC: validate_tool_name()
EC->>EC: check_input_size()
EC->>EC: check_rate_limit()
EC->>Policy: évaluer règles pré-appel
alt Outil refusé
Policy-->>EC: BLOQUÉ
EC->>Auditor: enregistrer(bloqué)
EC->>Hooks: on_violation()
EC-->>Agent: lever EnforcementViolation
end
EC->>Rules: vérifier règles de contenu
EC->>EC: check_domain()
EC->>Redactor: rédaction entrées (PII + secrets)
EC->>Hooks: on_pre_call()
EC->>Guard: définir limites ressources
Guard->>Tool: exécuter avec limites
Tool-->>Guard: résultat
EC->>Redactor: rédaction sorties
EC->>Policy: évaluer règles post-appel
EC->>Auditor: enregistrer(autorisé)
EC->>Hooks: on_post_call()
EC-->>Agent: retourner résultat
Composants Principaux
1. Enforcer (Coordinateur)
L'orchestrateur central. Intercepte les appels externes, coordonne tous les composants de protection.
- Fournit le décorateur
@enforce()et la factoryEnforcer.from_file() - Coordonne le pipeline : pré-appel → exécution → post-appel
- Supporte les patterns sync et async
- Lève
EnforcementViolationen cas de violation - Hooks de cycle de vie — callbacks via
@on_pre_call,@on_post_call,@on_violation,@on_redaction - Détection de fuites —
guard.leaked_thread_countsuit les threads orphelins
# Pattern décorateur
@enforce(policy="policy.yaml")
async def async_tool(args): ...
# Pattern factory
enforcer = Enforcer.from_file("policy.yaml")
result = enforcer.run(my_tool, args)
2. Policy Engine
Charge, valide et évalue les politiques déclaratives.
- Politiques YAML validées par des schémas Pydantic v2
- Conditions pré-appel et post-appel
- Composition de politiques (héritage, surcharge, fusion)
name: "politique-agent"
version: "1.0"
rules:
allowed_tools: ["search_web", "calculator"]
denied_tools: ["execute_shell"]
pii_redaction:
enabled: true
categories: [email, phone, ssn, credit_card, ip_address]
content_rules:
enabled: true
categories: [shell_injection, path_traversal, sql_injection, code_execution]
rate_limits:
global_rpm: 60
network:
allowed_domains: ["api.example.com"]
denied_domains: ["*.malicious.io"]
resource_limits:
max_call_duration_seconds: 30
max_cost_usd: 5.00
on_violation: "block"
3. Rédacteur PII
Détection et rédaction en temps réel sur entrées et sorties.
- 5 catégories : email, téléphone, SSN, carte de crédit, adresse IP
- 4 stratégies : placeholder (
<EMAIL>), masque, hash, suppression - Regex compilées — aucune dépendance NLP lourde (pas de spaCy, pas de Presidio)
- ~0,1–0,5 ms par appel
- Protection unicode — normalisation NFC, détection d'homoglyphes (~40 confusables), décodage URL/HTML
- Scanner de secrets — 11 catégories intégrées pour la détection de credentials
- Patterns personnalisés —
PatternRegistrypour les détecteurs spécifiques au domaine
4. Auditeur Merkle
Pistes d'audit inviolables et vérifiables cryptographiquement.
- Chaîne Merkle SHA-256 liant chaque entrée à la précédente
- 14 champs d'audit (outil, politique, décision, timing, compteurs de rédaction, hashes)
- Continuité de chaîne inter-sessions
- Détection de falsification
- Append-only au niveau OS —
Auditor(immutable=True)définitchattr +a(Linux) ouchflags uappend(macOS), empêchant la troncature ou la reconstruction de chaîne même par le propriétaire du fichier - Witness à hash uniquement —
Auditor(witness=...)publie les hashes vers un backend séparé (CallbackWitness,FileWitness,LogWitness), permettant la détection de falsification même si un attaquant reconstruit la chaîne Merkle verify_with_witness()— vérifie les hashes de la piste contre les enregistrements witness- Piloté par settings — activer via
ENFORCECORE_AUDIT_IMMUTABLE=trueetENFORCECORE_AUDIT_WITNESS_FILE=/pathsans modifier le code
5. Resource Guard
Contraintes de ressources multi-plateformes et terminaison forcée.
| Fonctionnalité | Linux | macOS | Windows |
|---|---|---|---|
| Limites de temps | ✓ | ✓ | ✓ |
| Limites mémoire | ✓ (RLIMIT_AS) | ~ (RLIMIT_RSS, consultatif) | ✗ |
| Suivi des coûts | ✓ | ✓ | ✓ |
| KillSwitch | ✓ | ✓ | ✓ |
6. Moteur de Règles de Contenu
Détection de contenu dangereux dans les arguments et sorties des outils.
- 4 catégories intégrées : injection shell, traversée de chemin, injection SQL, exécution de code
- Règles personnalisées —
ContentRulepour les patterns spécifiques au domaine
7. Rate Limiter
Limitation globale et par outil avec compteurs à fenêtre glissante. Thread-safe.
8. Enforcement Réseau
Contrôles allow/deny au niveau domaine pour les appels réseau sortants. Supporte les wildcards.
9. Système de Hooks
4 points de hook : @on_pre_call, @on_post_call, @on_violation, @on_redaction. Compatible async.
10. Observabilité
Intégration OpenTelemetry et dispatch d'événements par webhooks.
Structure des Modules
enforcecore/
├── core/ ← Types, politique, enforcer, config
├── redactor/ ← Détection PII, stratégies, secrets, patterns
├── auditor/ ← Merkle, journal, vérificateur, backends, witness, immutable, rotation
├── guard/ ← Plateforme, ressources, killswitch
├── rules/ ← Moteur de règles, builtins, rate limiter
├── network/ ← Vérificateur de domaines
├── hooks/ ← Registre de hooks, décorateurs
├── observability/ ← Métriques OTel, spans, webhooks
├── integrations/ ← LangGraph, CrewAI, AutoGen
├── eval/ ← Suite d'évaluation (20 scénarios, 15 benchmarks)
├── cli/ ← Commandes CLI
└── __init__.py ← API publique (30 Tier 1 + 80 Tier 2)
Gestion des Erreurs
La hiérarchie complète des exceptions est documentée dans la Référence API. Principe clé : les échecs d'enforcement ferment toujours (bloquent l'appel). Si le Policy Engine plante, l'appel est bloqué. Sécurité par défaut.
Décisions de Conception
Fail-closed par défaut
Si quelque chose échoue pendant l'enforcement, l'appel est bloqué — jamais autorisé. Le paramètre fail_open existe uniquement pour le développement.
Thread safety
- Cache de politiques avec
threading.Lock - Auditeur avec journal append-only thread-safe et verrouillage de fichier
- Suivi de portée avec
contextvars.ContextVar(async-safe)
Pas de dépendances lourdes
- Détection PII par regex compilées, pas spaCy ni Presidio
- Validation de politiques par Pydantic v2
- Audit par
hashlibstdlib (SHA-256)
Performance
Pour les benchmarks complets par composant (15 benchmarks avec P50/P99/P99.9), voir la Suite d'Évaluation. Résumé :
| Pipeline | P50 (ms) | P99 (ms) |
|---|---|---|
| E2E complet (sans PII) | 0,056 | 0,892 |
| E2E + rédaction PII | 0,093 | 0,807 |
Négligeable par rapport à la latence des appels d'outils (100 ms–10 s). Benchmarké sur Python 3.13, 1 000 itérations avec 100 d'échauffement. Exécutez enforcecore eval pour reproduire sur votre matériel.
Invariants Formels
EnforceCore spécifie 22 invariants formels organisés en quatre sous-systèmes. Ils sont vérifiés à chaque exécution CI via Hypothesis — propriétés universellement quantifiées testées contre des milliers d'entrées aléatoires.
Note : Ces invariants sont vérifiés empiriquement via des tests basés sur les propriétés, pas mécaniquement prouvés par des prouveurs de théorèmes. Les tests basés sur les propriétés fournissent une haute confiance mais ne constituent pas une preuve mathématique.
| Catégorie | Nombre | Invariants |
|---|---|---|
| Policy Engine (P1–P8) | 8 | Déterminisme, enforcement deny, enforcement allowlist, priorité deny-sur-allow, open-par-défaut, closed-sur-vide, merge union, complétude de décision |
| Chaîne Merkle (M1–M5) | 5 | Déterminisme de hash, sensibilité de hash, validité de chaîne, détection de falsification, stabilité append |
| Rédacteur (R1–R5) | 5 | Idempotence, complétude, sûreté, cohérence détection-rédaction, indépendance de stratégie |
| Enforcer (E1–E4) | 4 | Fail-closed, pass-through autorisé, idempotence d'enforcement, propagation d'erreur interne |
Invariants sélectionnés (notation formelle) :
- P2 (Deny Enforcement) : $\forall$ politique $\pi$, $\forall$ outil $t \in \pi$.denied_tools : evaluate($\pi$, $t$).decision = BLOCKED
- P4 (Priorité Deny) : $\forall$ outil $t \in \pi$.denied_tools $\cap$ $\pi$.allowed_tools : evaluate($\pi$, $t$).decision = BLOCKED — deny l'emporte toujours sur allow
- M4 (Détection de Falsification) : $\forall$ chaîne valide, $\forall$ modification (changement, suppression, réordonnancement) : verify_trail().is_valid = False
- E1 (Fail-Closed) : $\forall$ outil refusé $t$ : enforce_sync($f$, tool_name=$t$) lève EnforcementViolation
- R1 (Idempotence) : $\forall$ texte $s$ : redact(redact($s$)) = redact($s$)
Voir le document d'invariants formels pour la spécification complète.
Modèle de Menaces
EnforceCore documente un modèle de menaces formel avec quatre types d'adversaires :
| Adversaire | Capacité | Défense |
|---|---|---|
| A1 — LLM Compromis | Contrôle la sortie du LLM (jailbreak, injection de prompt) | Allowlist/denylist d'outils, règles de contenu, enforcement de domaine, rate limiting, rédaction PII |
| A2 — Outil Malveillant | Contrôle la réponse de l'outil (MITM, API compromise) | Rédaction de sortie, règles de contenu, limites de taille de sortie, piste d'audit |
| A3 — Insider | Accès en écriture au code ou aux variables d'env | Avertissements fail-open, fichiers d'audit append-only au niveau OS (immutable=True), backends witness à hash uniquement, journalisation des settings |
| A4 — Supply Chain | Dépendance compromise | Surface de dépendance minimale (4 deps), chargement YAML sécurisé, gardes d'import |
Propriétés formelles de sécurité :
- S1 — Complétude fail-closed : Chaque appel refusé lève
EnforcementViolationavant l'exécution - S2 — Complétude d'audit : Chaque appel enforcé (autorisé ou bloqué) produit un
AuditEntry - S3 — Intégrité de chaîne : Toute modification de la piste d'audit est détectable par
verify_trail() - S4 — Totalité de rédaction : Toutes les catégories PII configurées sont redactées des entrées et sorties
Voir le modèle de menaces complet dans le dépôt.
Défense en Profondeur
| Couche | Périmètre | Exemples |
|---|---|---|
| L1 — Réseau | Périmètre réseau | Pare-feux, VPNs, TLS |
| L2 — OS / Conteneur | Isolation de processus | seccomp, AppArmor, SELinux, Docker/gVisor |
| L3 — Application (EnforceCore) | Frontière sémantique agent | Allowlist d'outils, rédaction PII, règles de contenu, audit |
| L4 — Modèle | Comportement LLM | Prompts système, alignement RLHF, filtrage de sortie |
| L5 — Humain | Supervision | Humain dans la boucle, workflows d'approbation, revue d'audit |
EnforceCore opère à L3 — la couche sémantique applicative. Utilisez les cinq couches ensemble pour un confinement robuste des agents.