Sandbox eBPF au niveau du noyau pour sécuriser les appels d'outils d'agents LLM effectués via le protocole de contexte de modèle (MCP)
Isolation au niveau du noyau pour les appels d'outils d'agents LLM effectués via le Model Context Protocol (MCP).
MCPGuard agit comme un proxy transparent entre un client MCP (l'agent / le runner) et un sous-processus de serveur MCP, en appliquant trois défenses superposées à chaque invocation d'outil. La couche la plus basse est implémentée en eBPF et applique les politiques de capacités à la frontière des appels système, de sorte qu'un serveur MCP malveillant ne peut pas contourner la politique en codant en dur un comportement sensible dans sa propre implémentation.
Ce dépôt contient le proxy, les programmes eBPF, le benchmark de 14 serveurs / 82 cas, et le harnais d'évaluation utilisé dans l'article associé Kernel-Level Sandboxing for LLM Agent Tool Calls via eBPF.
| Couche | Composant | Objectif |
|---|---|---|
| L1 | proxy/policy_engine.py | Politique de capacités par serveur dérivée du schéma MCP de chaque outil ; listes d'autorisation pour les chemins, destinations réseau, processus, variables d'environnement. |
| L2 | proxy/argument_validator.py | Inspection au niveau applicatif des arguments d'appel d'outil : canonicalisation de chemin, validation d'URL, détection d'injection de prompt, détection de fuite d'environnement / d'injection de commande, analyse de clés sensibles, assainissement des réponses. |
| L3 | ebpf/*.bpf.c + proxy/ebpf_sandbox.py | Application au niveau de l'OS : trois programmes BPF LSM (file_guard, net_guard, proc_guard) interceptent open() / connect() / execve(), et un programme tracepoint (fork_guard) suit les processus enfants via sched_process_fork afin que la politique se propage à travers les forks. |
Six configurations de défense commutables (proxy/proxy_base.py) couvrent l'espace d'ablation utilisé dans l'article : C0 (passthrough), C-AB (baseline AgentBound), C-app (L1 + L2), C-ebpf (L3 uniquement), C-full (L1 + L2 + L3), C-AB+ebpf (AgentBound + L3).
.
├── proxy/ Moteur de politique L1, validateur d'arguments L2, contrôleur eBPF L3, baseline AgentBound
├── ebpf/ Sources C BPF pour les gardes file/net/proc/fork + Makefile + vmlinux.h
├── policies/ Politiques de capacités JSON par serveur (par défaut + surcharges)
├── servers/ 14 serveurs MCP : 11 Python (filesystem, notes, weather, shell, sqlite, git, env + variantes malveillantes/troyanisées) + 3 JavaScript (servers/js/)
├── test_cases/ 82 scénarios de benchmark répartis en 7 catégories (file_read, exfiltration, env_leak, sandbox_escape, priv_escalation, cross_language, benign)
├── notes_data/ 170 fixtures JSON de notes synthétiques valides utilisées par notes_server
├── runner/ evaluate.py, aggregate.py, agentbound_check.py, ebpf_edge_tests.py, latency_benchmark.py, override_workflow.py, smoke_test.py
└── EXECUTION_PLAN.md Instructions de reproduction phase par phase
CONFIG_BPF_LSM=y, lsm=bpf dans la ligne de commande du noyau)clang 21 ou plus récent avec la cible BPFbpftool pour charger les programmes et maps BPFservers/js/)# Build the eBPF programs
cd ebpf && make && cd ..
# Smoke test (one server, a handful of cases)
python3 runner/smoke_test.py
# Full benchmark for one configuration
python3 runner/evaluate.py --config C-full --run-id trial
# Aggregate a reproduced run
python3 runner/aggregate.py --run-id trial
# Reproduce the steady-state latency table after installing eBPF
sudo python3 runner/latency_benchmark.py --run-id codex_20260523_latency --iterations 100 --warmup 20
# Reproduce the audit/override workflow
python3 runner/override_workflow.py --run-id codex_20260523_override
# Run focused eBPF edge tests after installing eBPF
sudo python3 runner/ebpf_edge_tests.py --run-id codex_20260523_ebpf_edges
# Run AgentBound-style baseline conformance checks
python3 runner/agentbound_check.py --run-id codex_20260523_agentbound
C-ebpf, C-full et C-AB+ebpf échouent désormais en mode fail-closed si les programmes BPF LSM
et les maps épinglées sont indisponibles. Ne les exécutez qu'après avoir installé la couche eBPF
avec les privilèges root.
Taux de prévention des attaques (APR), APR des attaques viables (V-APR), et taux de faux positifs
(FPR) pour l'exécution unique épinglée codex_20260523_full (benchmark de 14 serveurs, 82 cas ;
il s'agit du profil par catégorie fx_r — le Tableau 1 de l'article rapporte des moyennes N=5,
donc C-app ici lit 13/48 contre la moyenne 12/48) :
| Config | APR | V-APR | Viable bloquées | FPR |
|---|---|---|---|---|
| C0 | 21.3% | 0.0% | 0/48 | 0/21 |
| C-AB | 37.7% | 20.8% | 10/48 | 0/21 |
| C-app | 42.6% | 27.1% | 13/48 | 0/21 |
| C-ebpf | 60.7% | 50.0% | 24/48 | 0/21 |
| C-full | 68.9% | 60.4% | 29/48 | 0/21 |
| C-AB+ebpf | 67.2% | 58.3% | 28/48 | 0/21 |
L'APR inclut les attaques qui échouent intrinsèquement sous C0. La V-APR n'utilise que les attaques qui réussissent sous C0 comme dénominateur, ce qui constitue la mesure la plus conservatrice de la couverture de défense.
Le benchmark de latence répété sur appels bénins est stocké dans l'espace de travail interne de
l'article sous results/latency/codex_20260523_latency.md. Il mesure BN-01
(filesystem_server.read_file) avec 20 appels de préchauffage et 100 appels mesurés par
configuration ; C-full ajoute +0,488 ms de latence médiane par rapport à C0 et reste
à 1,141 ms en p95 pour cet appel bénin fixe. L'arborescence publique CodeSync exclut
results/, donc les utilisateurs externes régénèrent cet artefact avec la commande ci-dessus.
Le workflow d'audit/surcharge est stocké en interne sous
results/audit/codex_20260523_override.md. Il démontre comment un refus bénin
est enregistré comme événement d'audit structuré et résolu en ajoutant une surcharge
d'opérateur à portée limitée sous une disposition compatible avec policies/overrides.
Les tests de bord eBPF ciblés sont stockés en interne sous
results/ebpf_edges/codex_20260523_ebpf_edges.md. Ils couvrent la disponibilité des maps en
fail-closed, le comportement d'autorisation d'écriture dans l'espace de travail, le refus de
frontière de préfixe de répertoire, le refus de staging dans /tmp, et le refus d'exfiltration
vers localhost.
La vérification de baseline de style AgentBound est stockée en interne sous
results/agentbound/codex_20260523_agentbound.md. Elle documente que C-AB est une
reproduction au niveau applicatif, par serveur, et vérifie la couverture attendue visible
par les arguments ainsi que l'angle mort caché dans l'implémentation.
Le serveur MCP est considéré comme non fiable. Il peut être bénin mais mal configuré, intentionnellement malveillant, ou un fork trojanisé d'un serveur légitime. L'agent / le runner et l'OS hôte sont considérés comme fiables. La couche eBPF suppose que le noyau n'est pas compromis ; les élévations de privilèges dans le noyau (CWE-269 dans les modules du noyau) sont hors périmètre.
Une entrée BibTeX sera ajoutée ici une fois l'article publié.
Voir CONTRIBUTING.md. Tous les contributeurs doivent signer le CLA de Meta.
Pour signaler un problème de sécurité, voir SECURITY.md. Veuillez ne pas ouvrir d'issues GitHub publiques pour les rapports de sécurité.