Keyboard shortcuts

Press ← or → to navigate between chapters

Press ? to show this help

Press Esc to hide this help

Isolation

Le runtime peut encapsuler les invocations d’outils dans un bac à sable au niveau de l’OS qui restreint l’accès au système de fichiers à l’espace de travail et supprime l’accès aux secrets du processus parent. Ceci est distinct du système d’autonomie et de la liste d’autorisation des commandes : ce sont des couches de politique qui décident si un outil peut s’exécuter ; le bac à sable est une couche de mécanisme qui confine ce qu’un outil en cours d’exécution peut atteindre s’il s’exécute.

Les paramètres du bac à sable se trouvent dans un profil de risque. Chaque agent pointe vers un profil de risque via agents.<alias>.risk_profile ; les options enable/backend du bac à sable de l’agent sont lues depuis ce profil.

Fournisseurs de modèles CLI (par exemple grok_cli) : la CLI externe se trouve en dehors du processus natif d’approbation des outils de ZeroClaw. Le bac à sable du profil de risque mentionné ci-dessus ne l’isole pas. Le fournisseur ACP grok_cli injecte donc par défaut --sandbox strict, --permission-mode dontAsk et un ensemble d’outils intégrés vide, et rejette les demandes d’autorisation ACP (en sélectionnant reject_once lorsque la CLI le propose, et en annulant sinon). Les indicateurs de contournement explicites dans l’alias extra_args sélectionnent plutôt l’option allow_once de la demande ; cela ne désactive pas le bac à sable actif du système d’exploitation de Grok et ne passe pas outre ses règles de refus. Les autres modes d’autorisation restent fermés en cas d’échec. Voir Catalogue → Grok Build CLI.

sandbox_enabled = false (ou sandbox_backend = "none") désactive l’enveloppe de sandbox supplémentaire au niveau du système d’exploitation du profil. Avec le runtime natif, les outils se retrouvent sans sandbox au niveau du système d’exploitation. Avec [runtime] kind = "docker", le runtime Docker reste la limite du conteneur et est signalé comme docker-runtime ; ces paramètres empêchent un second conteneur de sandbox d’envelopper le propre docker run du runtime. Consultez l’exemple minimal fonctionnel canonique pour voir comment un profil de risque s’intègre au reste de la configuration.

Détection automatique

sandbox_backend = "auto" résout un backend au moment de la création du sandbox. L’ordre dépend de la plateforme, des fonctionnalités de sandbox avec lesquelles le binaire a été compilé, et du type d’exécution :

PlateformeOrdre tenté
LinuxLandlock (uniquement lorsque compilé avec sandbox-landlock) → Firejail
macOSBubblewrap (uniquement lorsque compilé avec sandbox-bubblewrap) → Seatbelt (sandbox-exec)
WindowsAucun backend au niveau du système d’exploitation

Bubblewrap ne fait pas partie de la chaîne de détection automatique sous Linux ; il n’est accessible qu’en le nommant explicitement. Landlock et Bubblewrap sont des fonctionnalités de compilation, et une build qui n’active pas l’une d’elles ignore entièrement ce backend. Aucune de ces fonctionnalités ne figure dans le jeu default ni dans le jeu dist utilisé par la build de publication ; une build standard commence donc la liste Linux par Firejail et la liste macOS par Seatbelt.

Après la liste des plateformes, auto n’essaie Docker que lorsque le type de runtime n’est ni native ni docker. Docker ne fait pas partie du mécanisme de repli automatique du runtime natif : avec [runtime] kind = "native" (la valeur par défaut), auto ne sélectionne jamais Docker, même lorsque le daemon est accessible. Docker est aussi ignoré lorsque le runtime est déjà docker, car le conteneur d’exécution constitue la limite. Le seul autre type de runtime, cloudflare, est rejeté par create_runtime dans crates/zeroclaw-config/src/platform/mod.rs comme non implémenté ; ainsi, sur une configuration exécutable, auto n’atteint jamais le backend Docker.

Lorsqu’aucun élément de la liste n’est disponible, la sélection se termine sur none avec le runtime natif : aucun bac à sable au niveau du système d’exploitation n’encadre les appels d’outils, et seule la sécurité au niveau de l’application décrite plus haut s’applique. Avec le runtime Docker, la sélection se termine plutôt sur docker-runtime, en conservant la frontière du conteneur sans second encapsulage par bac à sable.

Nommer explicitement un backend ne parcourt pas cette liste. Si le backend demandé n’est pas compilé, ne fonctionne pas sur la plateforme, n’est pas compatible avec le type d’exécution, ou échoue à sa sonde de disponibilité, la sélection passe directement à none (natif) ou docker-runtime (exécution Docker), et non au backend suivant.

Pour forcer un backend spécifique, définissez sandbox_backend avec un nom de backend : landlock, firejail, bubblewrap, docker, sandbox-exec ou none.

Ce que le bac à sable confine

Accès aux fichiers

  • Accès en lecture : restreint à l’espace de travail, /usr, /lib, /etc (lecture seule) et aux chemins supplémentaires explicitement listés.
  • Accès en écriture : restreint à l’espace de travail et à /tmp.
  • Chemins interdits : règles de préfixe de composant absolu de [risk_profiles.<alias>].forbidden_paths. Les préfixes d’autorisation et de refus concurrents appliquent une priorité à la correspondance la plus spécifique, le refus l’emportant en cas d’égalité ; voir Règles de chemin d’autonomie.

Réseau

L’accès réseau est défini par backend, et la plupart d’entre eux ne le modifient pas :

  • Landlock contrôle uniquement l’accès au système de fichiers ; les flux réseau sortants ne sont donc pas modifiés.
  • Firejail s’exécute avec --noprofile et sans options réseau, il laisse donc aussi l’accès réseau inchangé.
  • Bubblewrap s’exécute avec --unshare-all et jamais avec --share-net, ainsi le bac à sable n’a pas accès au réseau.
  • Seatbelt refuse par défaut les connexions réseau sortantes et n’autorise que la résolution DNS via /var/run/mDNSResponder ainsi que les connexions vers localhost.
  • Docker transmet --network none pour le backend de bac à sable docker ; le runtime Docker transmet [runtime.docker].network, dont la valeur par défaut est none.

Les contrôles réseau spécifiques à chaque outil (browser, HTTP, web_fetch) se trouvent dans les blocs de configuration propres à ces outils ([browser].allowed_domains, [http_request].allowed_domains, [web_fetch].allowed_domains).

Pour http_request, les cibles privées/locales restent bloquées par défaut. Utilisez [http_request].allowed_private_hosts pour n’autoriser que des hôtes privés/locaux nommés tels que localhost ou 10.0.0.1 tout en conservant [http_request].allowed_domains non vide ; allowed_domains = [] désactive toujours les requêtes. Le paramètre existant [http_request].allow_private_hosts = true reste une option d’activation de compatibilité plus large.

Environnement

Le bac à sable ne transmet que les variables d’environnement listées dans [risk_profiles.<alias>].shell_env_passthrough. Les secrets hérités n’atteignent pas les outils en bac à sable sauf s’ils sont explicitement transmis.

Limites de processus

Les délais d’expiration par outil (wall-time) sont définis dans le bloc de configuration propre à l’outil ([shell_tool].timeout_secs, etc.). Les limites spécifiques à Docker (mémoire, CPU) sont définies dans [runtime.docker] lorsque le type de runtime de l’agent est défini sur docker :

Binaire du shell

Lorsque [runtime].shell n’est pas défini, le runtime natif détecte une valeur par défaut selon la plateforme. Sous Windows, il essaie pwsh, puis powershell, puis cmd.exe. Sous macOS, il utilise d’abord le shell de connexion passwd de l’utilisateur courant, puis essaie zsh, bash et /bin/sh. Sous Linux, il utilise d’abord le shell de connexion passwd, puis essaie bash, zsh et /bin/sh. Sous Android, la valeur reste fixée à /system/bin/sh. Définissez [runtime].shell pour choisir explicitement un interpréteur :

[runtime]
shell = "bash"      # se résout via PATH, ou utilisez un chemin absolu

Sous Unix, les shells compatibles POSIX sont appelés avec <shell> -c "<command>". powershell/pwsh sélectionnent la syntaxe et la politique PowerShell sur chaque hôte de bureau pris en charge et s’exécutent avec <interpreter> -NoProfile -NonInteractive -Command <command>, de sorte que les scripts de profil ne peuvent pas redéfinir des commandes en contournant la politique et que les invites ne peuvent pas bloquer l’exécution. La valeur doit être soit un simple nom de commande présent dans PATH (par ex. "bash" ou "pwsh"), soit un chemin absolu vers un exécutable (par ex. "/bin/bash") ; la validation de la configuration rejette les valeurs vides et les chemins relatifs contenant des séparateurs (par ex. "./sh", "bin/sh"). Avant le lancement, ZeroClaw canonicalise directement un chemin de shell absolu et résout un nom simple à partir du PATH effectif lorsqu’il est fourni ; une fabrique d’exécution peut résoudre et conserver ce lanceur canonique plus tôt, tandis que les autres chemins utilisent la résolution conservée ou celle de l’environnement lors de la préparation de la commande. La cible doit être un fichier exécutable ordinaire, et tout échec est renvoyé lors de la construction de l’exécution ou de la préparation de la commande, avant toute exécution. La configuration explicite prime sur la détection par défaut. La recherche du shell de connexion Unix utilise getpwuid_r ; en cas d’échec ou si elle désigne un exécutable indisponible, l’ordre de repli propre à la plateforme est utilisé. Si un PATH injecté omet un nom simple par défaut sélectionné, la préparation échoue au lieu de changer d’interpréteur.

Firejail, Bubblewrap et Seatbelt de macOS remplacent la commande hôte par un lanceur de bac à sable. Lorsque l’identité de shell demandée diffère du chemin exécutable canonique, le wrapper doit préserver cette identité (par exemple, sh sélectionnant un applet BusyBox ou un mode de compatibilité Bash) tout en exécutant la cible canonique validée. Sous Linux, Firejail et Bubblewrap nécessitent un env ou genv compatible GNU prenant en charge --argv0 dans les entrées absolues de PATH du processus hôte. ZeroClaw sonde chaque candidat pendant deux secondes au maximum ; l’assistant et ses bibliothèques doivent être accessibles à l’intérieur du bac à sable. Sur macOS, Seatbelt utilise le /bin/bash du système avec un trampoline exec -a fixe, de sorte qu’une installation séparée de GNU coreutils n’est pas requise. Le trampoline transmet l’identité demandée et les arguments de commande comme arguments de processus, et non sous forme de code shell interpolé. ZeroClaw n’élargit pas l’accès au système de fichiers et ne revient pas à une commande non sandboxée lorsqu’un assistant requis ne peut pas être exécuté. La recherche de l’assistant hôte sous Linux n’utilise pas la surcouche d’environnement réservée à la TUI.

Pour ces lancements enveloppés préservant l’identité, les chemins de shell canoniques contenant = restent rejetés ; sous Linux, env interpréterait de tels opérandes comme des affectations de variables d’environnement. Les chemins d’assistants Linux contenant = sont rejetés pour la même raison, et un assistant manquant ou non pris en charge produit une erreur de préparation. L’exécution native directe, Landlock et la sélection séparée du shell dans le conteneur Docker ne nécessitent pas d’assistant d’identité sur l’hôte.

Sous Windows, la valeur sélectionne la famille d’interpréteurs d’après le nom de son fichier :

[runtime]
shell = "pwsh"        # PowerShell 7+   -> pwsh -NoProfile -NonInteractive -Command <cmd>
# shell = "powershell"  # Windows PowerShell 5.x
# shell = "cmd"         # cmd.exe /C "<cmd>" explicite

powershell et pwsh (sous forme de nom simple résolu via PATH, ou de chemin absolu tel que "C:\\Program Files\\PowerShell\\7\\pwsh.exe") s’exécutent via PowerShell ; toute autre valeur explicite s’exécute via cmd.exe /C, conformément au comportement historique. Seule une valeur vide ou composée uniquement d’espaces est rejetée sous Windows ; l’interpréteur est localisé au moment du lancement.

L’outil shell, les outils de compétences basés sur le shell et les tâches shell exécutées par cron ou par le planificateur utilisent tous cette sélection de l’environnement d’exécution. L’environnement d’exécution indique également le dialecte du shell à la politique de sécurité, afin que celle-ci valide le même langage que celui qui sera utilisé pour exécuter la commande.

La même sélection d’environnement d’exécution est communiquée au modèle. La ligne ## Runtime de l’invite système contient un champ Shell: qui nomme l’interpréteur configuré (bash, zsh, pwsh, powershell, cmd) et, lorsqu’un outil enregistré accepte une commande rédigée par le modèle (shell, cron_add, cron_update, schedule), une section ## Shell répertorie les formes de commande acceptées par ce dialecte, afin que le modèle écrive Get-ChildItem sous PowerShell et dir /a sous cmd.exe au lieu de deviner à partir du nom du système d’exploitation. Les deux proviennent du même adaptateur qui construit la commande, de sorte que le shell indiqué ne puisse pas diverger de celui qui est exécuté. Les environnements d’exécution sans accès au shell (tels que WASM) omettent les deux. Les recommandations de suppression dans la section de sécurité suivent également le dialecte : trash n’est suggéré que là où il existe.

La stratégie PowerShell accepte une grammaire limitée : des appels de commandes simples, des arguments simples ou entre guillemets, et des pipelines. Les simples lectures de variables telles que $PSHOME et $PSVersionTable.PSVersion sont limitées à une commande Write-Output/echo autonome afin qu’elles ne puissent pas dissimuler des chemins du système de fichiers aux commandes ultérieures. Les expressions et les autres formes d’invocation, notamment les sous-expressions, les parenthèses, les blocs de script, les littéraux de type et les appels de méthodes statiques, les opérateurs d’appel, la redirection, les séparateurs d’instructions, les échappements par accent grave, les variables à portée telles que $env:NAME, les chemins de fournisseurs PowerShell, l’exécution directe de scripts et les interpréteurs de commandes imbriqués, sont classés comme présentant un risque élevé. Les noms de commandes propres à PowerShell ne sont pas ajoutés à la liste d’autorisation par défaut inter-dialectes ; ajoutez les cmdlets dont vous avez besoin à allowed_commands, ou activez "*" avec les paramètres d’approbation et de risque élevé correspondants. Les cmdlets de mutation connues sont soumises aux seuils d’approbation pour les risques moyen et élevé ; les commandes nues inconnues et les cmdlets Verb-Noun présentent par défaut un risque élevé.

Les tâches shell Cron héritent du périmètre d’exécution global lors de la validation comme de l’exécution. Les tâches natives utilisent le shell natif configuré, tandis que les tâches Docker s’exécutent avec l’image, le montage, le réseau, le processeur, la mémoire et les paramètres de racine en lecture seule configurés. Une entrée Cron stocke la commande, et non un environnement d’exécution ou un dialecte copié. Ainsi, après qu’un rechargement du daemon a recréé l’ordonnanceur et le registre d’outils, les tâches existantes utilisent la configuration [runtime] nouvellement chargée lors de leur prochaine exécution. Les exécutions Cron planifiées sont revalidées et ne sont jamais préapprouvées.

Ne s’applique qu’au type d’exécution natif. Docker utilise le shell de son conteneur, et Android (toujours /system/bin/sh) ignore ce paramètre et ne le valide pas.

Notes par backend

Landlock

Le chemin natif Linux. Zéro configuration, imposé par le noyau, très faible surcharge. Nécessite le noyau 5.13+.

Limitations :

  • Pas de confinement réseau : Landlock contrôle uniquement l’accès au système de fichiers.
  • forbidden_paths est appliqué via des règles basées sur les chemins, et non sur les inodes, de sorte qu’un lien symbolique astucieux peut parfois s’en échapper (nous résolvons les liens avant de les transmettre à Landlock pour atténuer ce problème).

Bubblewrap (bwrap)

Bac à sable basé sur les espaces de noms utilisateur, issu de Flatpak. Restreint l’accès au système de fichiers et exécute sans accès réseau. Nécessite que bubblewrap soit installé.

Debian/Ubuntu

sudo apt install bubblewrap

Arch

sudo pacman -S bubblewrap

Fedora

sudo dnf install bubblewrap

Firejail

Sandbox basé sur SUID. Plus ancien mais largement disponible.

sh

sudo apt install firejail

Le profil par défaut de Firejail est assez permissif, et ZeroClaw l’ignore avec --noprofile, en passant à la place un ensemble explicite d’options.

Docker

Fonctionne partout où Docker est disponible. Le type de runtime Docker ([runtime] kind = "docker") exécute chaque invocation de shell dans un conteneur éphémère ; consultez le bloc [runtime.docker] ci-dessus pour les contrôles d’image et de ressources. git_operations ne s’exécute pas dans ce conteneur : les commandes Git classées comme écriture sont rejetées pour le runtime Docker, tandis que les commandes classées comme lecture conservent leur isolation de lecture existante côté hôte. Utilisez l’outil shell pour les commandes Git qui doivent s’exécuter dans le conteneur.

sh

docker build -t zeroclaw-sandbox:local dev/sandbox/   # créer l'image de la boîte à outils groupée

Points forts : isolation robuste, fonctionne sur n’importe quel système d’exploitation. Points faibles : coût de démarrage du conteneur à chaque invocation (100–500 ms). Idéal pour les déploiements en production où cette surcharge est acceptable.

Ceinture de sécurité (macOS)

Sandbox macOS natif (sandbox-exec). Les profils sont au format SBPL : ZeroClaw en intègre un pour les exécutions d’outils. Fonctionne sur macOS 10.11+.

Limitation : certains outils CLI (anciennes versions de git, certains binaires liés via Homebrew) ne coopèrent pas avec les règles d’accès aux fichiers de Seatbelt. Si vous voyez des erreurs « Operation not permitted » lors des appels shell de l’agent sur macOS, l’outil a besoin d’un accès plus large au système de fichiers : envisagez de passer à Docker.

none

Aucun sandboxing. Les outils s’exécutent avec tous les privilèges de l’utilisateur du service ZeroClaw. C’est ce que le mode YOLO permet. Bruyant, évident, intentionnel.

Dépannage

  • Aucun sandbox n’est actif : vérifiez zeroclaw service status et le journal. La sélection enregistre le backend retenu (« Landlock sandbox enabled (Linux kernel 5.13+) », « No sandbox backend available, using application-layer security »), et un backend demandé explicitement mais indisponible émet un avertissement avec son nom (« Firejail requested but not available, falling back to application-layer »). Le journal indique le résultat, et non chaque backend essayé.
  • Les outils fonctionnent en développement, mais échouent en service : l’utilisateur du service diffère souvent de l’utilisateur de la CLI. Vérifiez que les deux disposent des permissions liées au sandbox nécessaires (Landlock : aucune ; Bubblewrap : userns activé ; Docker : utilisateur du service dans le groupe docker).
  • Invocations d’outils lentes sur le runtime Docker : la première invocation télécharge l’image, les suivantes sont rapides. Pré-téléchargez avec docker pull <image>.

Référence du code

  • Détection : crates/zeroclaw-runtime/src/security/detect.rs
  • Backends : crates/zeroclaw-runtime/src/security/ (landlock.rs, firejail.rs, bubblewrap.rs, docker.rs, seatbelt.rs)
  • Schéma : RiskProfileConfig et DockerRuntimeConfig dans crates/zeroclaw-config/src/schema.rs