OpenShell : Le runtime de sécurité derrière NemoClaw
Si NemoClaw est la pile de sécurité, OpenShell en est le fondement. Développé par l'équipe d'ingénierie sécurité de NVIDIA au cours des 18 derniers mois, OpenShell fournit un sandboxing au niveau du noyau pour l'exécution des agents IA — garantissant que même un agent entièrement compromis ne peut pas accéder aux ressources en dehors de sa limite de sécurité définie.
Cet article est une plongée technique dans l'architecture d'OpenShell, ses mécanismes d'isolation et la manière dont il applique les politiques de sécurité avec un impact minimal sur les performances.
Pourquoi l'isolation au niveau du noyau ?
Le sandboxing applicatif traditionnel — conteneurs, machines virtuelles, isolation au niveau des processus — a été conçu pour des logiciels au comportement prévisible. Les agents IA sont fondamentalement différents. Ils génèrent leurs propres plans d'exécution au moment de l'exécution, effectuent des appels d'outils qui interagissent avec des systèmes externes et peuvent produire des comportements nouveaux qu'aucune suite de tests n'avait anticipés.
Cette imprévisibilité exige un modèle de sécurité qui opère au niveau le plus bas possible : le noyau. OpenShell intercepte chaque appel système effectué par le processus d'un agent, le classifie selon la politique de sécurité active et prend une décision d'autorisation ou de refus avant que l'appel n'atteigne le noyau.
Agent Process
│
▼
OpenShell eBPF Layer ←── Policy Engine
│
├── ALLOW → System Call → Kernel
│
├── DENY → Error returned to agent
│
└── ESCALATE → Human approval queue
eBPF : La technologie derrière OpenShell
OpenShell est construit sur eBPF (extended Berkeley Packet Filter), une technologie du noyau Linux qui permet d'exécuter des programmes personnalisés dans l'espace noyau sans modifier le noyau lui-même. L'équipe de NVIDIA a écrit une suite de programmes eBPF spécifiquement optimisés pour les charges de travail d'agents IA :
Intercepteur d'appels système
L'intercepteur d'appels système s'attache au point de trace sys_enter et évalue chaque appel système par rapport à la politique active :
// Simplified OpenShell eBPF syscall interceptor
SEC("tracepoint/raw_syscalls/sys_enter")
int openshell_syscall_enter(struct trace_event_raw_sys_enter *ctx) {
u32 pid = bpf_get_current_pid_tgid() >> 32;
struct sandbox_policy *policy = bpf_map_lookup_elem(&sandbox_policies, &pid);
if (!policy)
return 0; // Not a sandboxed process
long syscall_nr = ctx->id;
int decision = evaluate_policy(policy, syscall_nr, ctx->args);
if (decision == DENY) {
// Send event to userspace audit log
emit_security_event(pid, syscall_nr, DENY);
// Override return value to -EPERM
bpf_override_return(ctx, -EPERM);
} else if (decision == ESCALATE) {
// Pause the process and notify approval queue
emit_approval_request(pid, syscall_nr, ctx->args);
send_signal(pid, SIGSTOP);
}
return 0;
}
Garde du système de fichiers
Le garde du système de fichiers restreint les fichiers et répertoires auxquels un agent peut accéder. Il opère sur les opérations VFS (Virtual Filesystem), interceptant les appels open, read, write, unlink et rename :
# Filesystem policy for a customer support agent
filesystem:
# Agent can read its own configuration
- path: "/etc/nemoclaw/agent.yaml"
permissions: [read]
# Agent can read/write to its workspace
- path: "/var/nemoclaw/workspace/**"
permissions: [read, write, create]
# Agent can read shared data
- path: "/var/nemoclaw/shared/**"
permissions: [read]
# Everything else is denied by default
defaultAction: deny
Sentinelle réseau
La sentinelle réseau se branche sur les opérations de socket pour contrôler l'accès réseau des agents au niveau de la connexion :
SEC("cgroup/connect4")
int openshell_connect4(struct bpf_sock_addr *ctx) {
u32 pid = bpf_get_current_pid_tgid() >> 32;
struct network_policy *policy = bpf_map_lookup_elem(&net_policies, &pid);
if (!policy)
return 1; // Allow non-sandboxed processes
__be32 dst_ip = ctx->user_ip4;
__be16 dst_port = ctx->user_port;
if (!is_allowed_destination(policy, dst_ip, dst_port)) {
emit_security_event(pid, NETWORK_BLOCKED, dst_ip, dst_port);
return 0; // Block connection
}
return 1; // Allow connection
}
Architecture d'application des politiques
Les politiques OpenShell sont compilées en bytecode eBPF pour une vitesse d'application maximale. Le pipeline de compilation fonctionne comme suit :
- 1.Les fichiers de politique YAML sont rédigés par les équipes de sécurité dans un format lisible par l'humain
- 2.Le compilateur de politiques convertit le YAML en une représentation intermédiaire (IR)
- 3.Le validateur de politiques Nemotron vérifie la cohérence logique et les conflits de l'IR
- 4.Le compilateur eBPF génère un bytecode vérifié qui est chargé dans le noyau
- 5.Le vérificateur d'exécution s'assure que les programmes eBPF se terminent et sont sûrs en mémoire
L'intégralité du pipeline de compilation s'exécute en moins de 2 secondes pour les ensembles de politiques typiques, et les politiques peuvent être rechargées à chaud sans redémarrer l'agent.
# Compile and load a policy
nemoclaw policy compile policies/customer-support.yaml
nemoclaw policy load customer-support
# Hot-reload a modified policy (no agent restart required)
nemoclaw policy reload customer-support
# Verify policy is active
nemoclaw policy status
# Output:
# POLICY STATUS LOADED AT RULES
# customer-support active 2026-03-19 14:30:01 47
# network-default active 2026-03-19 14:30:01 12
# filesystem-strict active 2026-03-19 14:30:01 23
Workflows d'approbation par l'opérateur
L'une des caractéristiques les plus distinctives d'OpenShell est son système intégré d'approbation par l'opérateur. Lorsqu'un agent tente une action classifiée comme à haut risque, OpenShell met en pause l'exécution de l'agent et route la demande d'approbation vers un opérateur humain.
Comment fonctionne l'approbation
- 1.L'agent tente un appel système à haut risque (par ex., écriture dans un fichier protégé, connexion à un endpoint non approuvé)
- 2.Le programme eBPF d'OpenShell envoie SIGSTOP au processus de l'agent
- 3.Une demande d'approbation est générée et envoyée via le canal configuré (Slack, Teams, PagerDuty, email)
- 4.L'opérateur examine le contexte de la demande et approuve ou refuse
- 5.Si approuvée, OpenShell envoie SIGCONT pour reprendre l'agent ; si refusée, il retourne EPERM
La demande d'approbation inclut le contexte complet :
{
"request_id": "apr-2026031914-00042",
"agent": "customer-support-agent-01",
"action": "email.send",
"target": "[email protected]",
"context": {
"ticket_id": "TKT-12345",
"customer_name": "[REDACTED]",
"reason": "Agent wants to send a follow-up email to the customer regarding their refund request",
"email_preview": "Dear Customer, your refund of $250 has been processed..."
},
"risk_level": "medium",
"policy_rule": "external-communication-requires-approval",
"timestamp": "2026-03-19T14:30:42Z"
}
Délai d'approbation et actions par défaut
Les opérateurs peuvent configurer ce qui se passe lorsqu'une approbation expire :
approvalConfig:
timeout: 15m
onTimeout: deny # deny | allow | escalate
onEscalate:
target: security-team
channel: pagerduty
maxPendingApprovals: 10 # Queue limit per agent
autoApprove:
# Automatically approve if the same action was approved
# 3 times in the past 24 hours for this agent
repeatThreshold: 3
repeatWindow: 24h
Caractéristiques de performance
OpenShell est conçu pour les charges de travail de production où la latence compte. Voici les surcharges mesurées sur un DGX Spark :
| Opération | Surcharge |
|---|---|
| Interception d'appel système (autorisation) | 8 microsecondes |
| Interception d'appel système (refus) | 12 microsecondes |
| Vérification du système de fichiers | 15 microsecondes |
| Vérification de connexion réseau | 20 microsecondes |
| Rechargement à chaud de politique | < 500 millisecondes |
| Aller-retour d'approbation (Slack) | 2-30 secondes (dépend de l'humain) |
À titre de comparaison, un appel d'inférence LLM typique prend 500 ms à 5000 ms, donc la surcharge d'OpenShell est négligeable dans le contexte des charges de travail d'agents.
Comparaison avec le sandboxing existant
| Fonctionnalité | OpenShell | Docker/OCI | gVisor | Firecracker |
|---|---|---|---|---|
| Niveau d'isolation | Noyau (eBPF) | Espace de noms | Noyau espace utilisateur | microVM |
| Filtrage des appels système | Par politique, rechargement à chaud | seccomp statique | Interposition complète | Isolation complète |
| Politique réseau | Par agent, niveau L7 | iptables | iptables | iptables |
| Approbation humaine | Intégrée | Aucune | Aucune | Aucune |
| Politiques adaptées à l'IA | Oui (Nemotron) | Non | Non | Non |
| Surcharge | ~10 microsecondes | ~5 microsecondes | ~50 microsecondes | ~100 ms au démarrage |
| Passthrough GPU | Natif | NVIDIA CTK | Limité | Limité |
Le principal différenciateur d'OpenShell est qu'il a été conçu dès le départ pour les charges de travail d'agents IA, avec un support intégré pour les politiques en langage naturel, les workflows d'approbation humaine et l'évaluation de politiques accélérée par GPU.
Commencer avec OpenShell
OpenShell peut être utilisé de manière autonome, sans le reste de la pile NemoClaw :
# Install OpenShell standalone
curl -fsSL https://github.com/NVIDIA/OpenShell | bash
# Create a minimal sandbox policy
cat > my-policy.yaml << 'EOF'
apiVersion: openshell.nvidia.com/v1
kind: SandboxPolicy
metadata:
name: my-first-sandbox
spec:
isolation:
network: restricted
filesystem: workspace-only
syscalls: minimal
EOF
# Run any process inside the sandbox
openshell run --policy my-policy.yaml -- python my_agent.py
OpenShell est open source sous licence Apache 2.0 et disponible sur nvidia/openshell sur GitHub. Dans le prochain article, nous explorerons des scénarios de déploiement en entreprise concrets pour la pile NemoClaw complète.