Aller au contenu

Approbations exec — avancé

Rubriques avancées sur les approbations d’exécution : le chemin rapide safeBins, la liaison d’interpréteur/d’exécution et le transfert des approbations vers les canaux de discussion (y compris la livraison native). Pour la politique principale et le flux d’approbation, voir Exec approvals.

tools.exec.safeBins définit une petite liste de binaires stdin-only (par exemple cut) qui peuvent s’exécuter en mode liste blanche sans entrées explicites de liste blanche. Les bins sûrs rejettent les arguments de fichier positionnels et les jetons de type chemin, ils ne peuvent donc opérer que sur le flux entrant. Traitez cela comme un chemin rapide étroit pour les filtres de flux, et non comme une liste de confiance générale.

Bins sécurisés par défaut :

cut, uniq, head, tail, tr, wc

grep et sort ne figurent pas dans la liste par défaut. Si vous les activez, gardez des entrées explicites de liste blanche pour leurs flux de travail non stdin. Pour grep en mode bin sûr, fournissez le modèle avec -e/--regexp ; la forme de modèle positionnel est rejetée afin que les opérandes de fichier ne puissent pas être introduits en contrebande comme positionnels ambigus.

La validation est déterministe uniquement à partir de la forme de l’argv (pas de vérification de l’existence du système de fichiers hôte), ce qui empêche le comportement d’oracle d’existence de fichiers résultant des différences de refus/autorisation. Les options orientées fichier sont refusées pour les bacs sécurisés par défaut ; les options longues sont validées en échec-fermé (les indicateurs inconnus et les abréviations ambiguës sont rejetés).

Indicateurs refusés par profil de bac sécurisé :

  • grep : --dereference-recursive, --directories, --exclude-from, --file, --recursive, -R, -d, -f, -r
  • jq : --argfile, --from-file, --library-path, --rawfile, --slurpfile, -L, -f
  • sort : --compress-program, --files0-from, --output, --random-source, --temporary-directory, -T, -o
  • wc : --files0-from

Les bacs sûrs forcent également les jetons argv à être traités comme du texte littéral au moment de l’exécution (pas de globbing et pas d’expansion $VARS) pour les segments stdin uniquement, les modèles comme * ou $HOME/... ne peuvent donc pas être utilisés pour introduire subrepticement des lectures de fichiers.

Les bacs sûrs doivent être résolus à partir de répertoires de binaires de confiance (valeurs par défaut du système plus tools.exec.safeBinTrustedDirs optionnels). Les entrées PATH ne sont jamais automatiquement approuvées. Les répertoires de confiance par défaut sont intentionnellement minimaux : /bin, /usr/bin. Si votre exécutable de bac sûr réside dans les chemins du gestionnaire de paquets/utilisateur (par exemple /opt/homebrew/bin, /usr/local/bin, /opt/local/bin, /snap/bin), ajoutez-les explicitement à tools.exec.safeBinTrustedDirs.

Le chaînage de shell (&&, ||, ;) est autorisé lorsque chaque segment de niveau supérieur satisfait à la liste d’autorisation (y compris les bins sûrs ou l’autorisation automatique des compétences). Les redirections ne sont pas prises en charge en mode liste d’autorisation. La substitution de commandes ($() / guillemets inversés) est rejetée lors de l’analyse de la liste d’autorisation, y compris à l’intérieur des guillemets doubles ; utilisez des guillemets simples si vous avez besoin du texte littéral $().

Pour les approbations de l’application compagnon sur macOS, le texte de shell brut contenant une syntaxe de contrôle ou d’expansion de shell (&&, ||, ;, |, `, $, <, >, (, )) est considéré comme un échec de la liste d’autorisation, sauf si le binaire du shell lui-même est sur la liste d’autorisation.

Pour les wrappers de shell (bash|sh|zsh ... -c/-lc), les redéfinitions d’environnement liées à la requête sont réduites à une petite liste d’autorisation explicite (TERM, LANG, LC_*, COLORTERM, NO_COLOR, FORCE_COLOR).

Pour les décisions allow-always en mode liste d’autorisation, les wrappers de répartition connus (env, nice, nohup, stdbuf, timeout) enregistrent le chemin de l’exécutable interne au lieu du chemin du wrapper. Les multiplexeurs de shell (busybox, toybox) sont déballés pour les applets de shell (sh, ash, etc.) de la même manière. Si un wrapper ou un multiplexeur ne peut pas être déballé en toute sécurité, aucune entrée de liste d’autorisation n’est enregistrée automatiquement.

Si vous mettez en liste blanche des interprètes comme python3 ou node, préférez tools.exec.strictInlineEval=true afin que l’évaluation en ligne (inline eval) nécessite toujours une approbation explicite. En mode strict, allow-always peut toujours conserver des invocations d’interpréteur/de script bénignes, mais les vecteurs d’évaluation en ligne ne sont pas conservés automatiquement.

Bacs sûrs par rapport à la liste d’autorisation

Section intitulée « Bacs sûrs par rapport à la liste d’autorisation »
Sujettools.exec.safeBinsListe blanche (exec-approvals.json)
ObjectifAutoriser automatiquement les filtres stdin étroitsFaire explicitement confiance à des exécutables spécifiques
Type de correspondanceNom de l’exécutable + politique d’argv de bac sûrGlob de chemin d’exécutable résolu, ou glob de nom de commande nu pour les commandes invoquées par PATH
Portée des argumentsRestreint par le profil de bac sûr et les règles de jeton littéralCorrespondance de chemin par défaut ; argPattern optionnel peut restreindre argv analysé
Exemples typeshead, tail, tr, wcjq, python3, node, ffmpeg, CLIs personnalisés
Meilleure utilisationTransformations de texte à faible risque dans les pipelinesTout outil ayant un comportement plus large ou des effets secondaires

Emplacement de la configuration :

  • safeBins provient de la configuration (tools.exec.safeBins ou agents.list[].tools.exec.safeBins par agent).
  • safeBinTrustedDirs provient de la configuration (tools.exec.safeBinTrustedDirs ou agents.list[].tools.exec.safeBinTrustedDirs par agent).
  • safeBinProfiles provient de la configuration (tools.exec.safeBinProfiles ou agents.list[].tools.exec.safeBinProfiles par agent). Les clés de profil par agent remplacent les clés globales.
  • les entrées de la liste blanche résident dans ~/.openclaw/exec-approvals.json local à l’hôte sous agents.<id>.allowlist (ou via Control UI / openclaw approvals allowlist ...).
  • openclaw security audit avertit avec tools.exec.safe_bins_interpreter_unprofiled lorsque des binaires d’interpréteur/runtime apparaissent dans safeBins sans profils explicites.
  • openclaw doctor --fix peut échafauder les entrées safeBinProfiles.<bin> personnalisées manquantes en tant que {} (à réviser et resserrer ensuite). Les binaires d’interpréteur/runtime ne sont pas échafaudés automatiquement.

Exemple de profil personnalisé :

{
tools: {
exec: {
safeBins: ["jq", "myfilter"],
safeBinProfiles: {
myfilter: {
minPositional: 0,
maxPositional: 0,
allowedValueFlags: ["-n", "--limit"],
deniedFlags: ["-f", "--file", "-c", "--command"],
},
},
},
},
}

Si vous activez explicitement jq dans safeBins, OpenClaw rejette toujours la fonction intégrée env en mode safe-bin afin que jq -n env ne puisse pas déverser l’environnement du processus hôte sans un chemin de liste blanche explicite ou une invite d’approbation.

Les exécutions d’interpréteur/d’exécution soutenus par une approbation sont intentionnellement conservatrices :

  • Le contexte exact argv/cwd/env est toujours lié.
  • Les formes de script shell direct et de fichier d’exécution direct sont liées au mieux à un instantané de fichier local concret.
  • Les formes courantes de wrappers de gestionnaires de paquets qui résolvent toujours vers un fichier local direct (par exemple pnpm exec, pnpm node, npm exec, npx) sont déballées avant la liaison.
  • Si OpenClaw ne peut pas identifier exactement un fichier local concret pour une commande d’interpréteur/d’exécution (par exemple les scripts de paquet, les formulaires eval, les chaînes de chargeur spécifiques à l’exécution, ou les formes multi-fichiers ambiguës), l’exécution soutenue par une approbation est refusée au lieu de prétendre à une couverture sémantique qu’elle n’a pas.
  • Pour ces flux de travail, privilégiez la sandboxing, une frontière d’hôte séparée, ou une liste de confiance/explicite de flux complet où l’opérateur accepte la sémantique d’exécution plus large.

Lorsque des approbations sont requises, l’outil exec renvoie immédiatement un identifiant d’approbation. Utilisez cet identifiant pour mettre en corrélation les événements système d’exécution approuvés ultérieurs (Exec finished, et Exec running si configurés). Si aucune décision n’arrive avant l’expiration du délai, la demande est traitée comme un dépassement de délai d’approbation et signalée comme un refus de commande hôte terminal. Pour les approbations asynchrones de l’agent principal avec une session d’origine, OpenClaw reprend également cette session avec un suivi interne afin que l’agent observe que la commande ne s’est pas exécutée au lieu de tenter ultérieurement de réparer un résultat manquant.

Après l’exécution asynchrone approuvée, OpenClaw envoie un tour de suivi agent à la même session. Les approbations asynchrones refusées utilisent le même chemin de suivi de session principale pour le statut de refus, mais elles n’enregistrent pas les transferts d’exécution élevés et n’exécutent pas la commande. Les refus sans une session principale reprise sont soit supprimés, soit signalés via un itinéraire direct sécurisé lorsqu’un tel itinéraire existe.

  • Si une cible de livraison externe valide existe (channel pouvant être livré plus cible to), la livraison de suivi utilise ce channel.
  • Dans les flux webchat-only ou internal-session sans cible externe, la livraison de suivi reste uniquement pour la session (deliver: false).
  • Si un appelant demande explicitement une livraison externe stricte sans channel externe résoluble, la demande échoue avec INVALID_REQUEST.
  • Si bestEffortDeliver est activé et qu’aucun channel externe ne peut être résolu, la livraison est rétrogradée à session-only au lieu d’échouer.

Transfert des approbations vers les canaux de discussion

Section intitulée « Transfert des approbations vers les canaux de discussion »

Vous pouvez transférer les invites d’approbation exec vers n’importe quel channel de discussion (y compris les channels de plugin) et les approuver avec /approve. Cela utilise le pipeline de livraison sortant normal.

Config :

{
approvals: {
exec: {
enabled: true,
mode: "session", // "session" | "targets" | "both"
agentFilter: ["main"],
sessionFilter: ["discord"], // substring or regex
targets: [
{ channel: "slack", to: "U12345678" },
{ channel: "telegram", to: "123456789" },
],
},
},
}

Répondre dans le chat :

/approve <id> allow-once
/approve <id> allow-always
/approve <id> deny

La commande /approve gère à la fois les approbations exec et les approbations de plugin. Si l’ID ne correspond pas à une approbation exec en attente, elle vérifie automatiquement les approbations de plugin à la place.

Le transfert des approbations de plugin utilise le même pipeline de livraison que les approbations d’exécution, mais possède sa propre configuration indépendante sous approvals.plugin. L’activation ou la désactivation de l’un n’affecte pas l’autre. Pour le comportement de création de plugin, les champs de requête et la sémantique de décision, voir Plugin permission requests.

{
approvals: {
plugin: {
enabled: true,
mode: "targets",
agentFilter: ["main"],
targets: [
{ channel: "slack", to: "U12345678" },
{ channel: "telegram", to: "123456789" },
],
},
},
}

La forme de la configuration est identique à approvals.exec : enabled, mode, agentFilter, sessionFilter, et targets fonctionnent de la même manière.

Les canaux prenant en charge les réponses interactives partagées affichent les mêmes boutons d’approbation pour les approbations d’exécution et de plugin. Les canaux sans interface utilisateur interactive partagée reviennent à du texte brut avec des instructions /approve. Les demandes d’approbation de plugin peuvent restreindre les décisions disponibles. Les surfaces d’approbation utilisent l’ensemble de décisions déclaré par la demande, et le Gateway rejette les tentatives de soumission d’une décision qui n’a pas été proposée.

Approbations dans le même chat sur n’importe quel canal

Section intitulée « Approbations dans le même chat sur n’importe quel canal »

Lorsqu’une demande d’approbation d’exécution ou de plugin provient d’une surface de discussion livrable, la même discussion peut désormais l’approuver avec /approve par défaut. Cela s’applique aux canaux tels que Slack, Matrix et Microsoft Teams, en plus des flux existants de l’interface utilisateur Web et de l’interface utilisateur du terminal.

Ce chemin de commande textuelle partagée utilise le modèle d’authentification de canal normal pour cette conversation. Si le chat d’origine peut déjà envoyer des commandes et recevoir des réponses, les demandes d’approbation n’ont plus besoin d’un adaptateur de livraison natif séparé juste pour rester en attente.

Discord et Telegram prennent également en charge l’approbation /approve dans la même discussion, mais ces canaux utilisent toujours leur liste d’approuveurs résolus pour l’autorisation, même lorsque la livraison native de l’approbation est désactivée.

Pour Telegram et autres clients d’approbation natifs qui appellent le Gateway directement, ce repli est intentionnellement limité aux échecs « approbation introuvable ». Un vrai refus/erreur d’approbation d’exécution ne réessaie pas silencieusement en tant qu’approbation de plugin.

Certains canaux peuvent également agir en tant que clients d’approbation natifs. Les clients natifs ajoutent les DM des approuveurs, la diffusion vers la discussion d’origine et l’expérience utilisateur d’approbation interactive spécifique au canal par-dessus le flux /approve partagé dans la même discussion.

Lorsque les cartes/boutons d’approbation natifs sont disponibles, cette interface utilisateur native est le chemin principal orienté agent. L’agent ne doit pas non plus renvoyer une commande /approve de discussion en double, sauf si le résultat de l’outil indique que les approbations de discussion sont indisponibles ou que l’approbation manuelle est le seul chemin restant.

Si un client d’approbation natif est configuré mais qu’aucun runtime natif n’est actif pour le canal d’origine, OpenClaw garde visible l’invite déterministe locale /approve. Si le runtime natif est actif et tente la livraison mais qu’aucune cible ne reçoit la carte, OpenClaw envoie un avis de repli dans la même discussion avec la commande exacte /approve <id> <decision> afin que la demande puisse toujours être résolue.

Modèle générique :

  • la stratégie d’exécution de l’hôte décide toujours si l’approbation d’exécution est requise
  • approvals.exec contrôle le transfert des invites d’approbation vers d’autres destinations de discussion
  • channels.<channel>.execApprovals contrôle si les clients natifs spécifiques à un canal comme Discord, Slack, Telegram et similaires sont activés
  • Les approbations par plugin Slack peuvent utiliser le client d’approbation natif de Slack lorsque la demande provient de Slack et que les approbateurs du plugin Slack sont résolus ; SlackSlackSlackSlackapprovals.pluginSlackSlack peut également router les approbations par plugin vers des sessions ou des cibles Slack, même lorsque les approbations d’exécution Slack sont désactivées
  • La livraison des approbations par réaction sur WhatsApp et Signal est conditionnée par approvals.exec et approvals.plugin ; ils n’ont pas de blocs channels.<channel>.execApprovals

Les clients d’approbation natifs activent automatiquement la livraison en priorité par DM lorsque toutes les conditions suivantes sont remplies :

  • le channel prend en charge la livraison des approbations natives
  • les approbateurs peuvent être résolus à partir de execApprovals.approvers explicite ou d’une identité de propriétaire telle que commands.ownerAllowFrom
  • channels.<channel>.execApprovals.enabled est non défini (unset) ou "auto"

Définissez enabled: false pour désactiver explicitement un client d’approbation natif. Définissez enabled: true pour le forcer activement lorsque les approbateurs sont résolus. La livraison publique dans le canal d’origine reste explicite via channels.<channel>.execApprovals.target.

FAQ : Pourquoi existe-t-il deux configurations d’approbation d’exécution pour les approbations de discussion ?

  • Discord : channels.discord.execApprovals.*
  • Slack : channels.slack.execApprovals.*
  • Telegram : channels.telegram.execApprovals.*
  • WhatsApp : utilisez approvals.exec et approvals.plugin pour acheminer les invites d’approbation vers WhatsApp
  • Signal : utilisez approvals.exec et approvals.plugin pour acheminer les invites d’approbation vers Signal

Ces clients d’approbation natifs ajoutent le routage par DM et la diffusion de canal facultative par-dessus le flux partagé /approve de même chat et les boutons d’approbation partagés.

Comportement partagé :

  • Slack, Matrix, Microsoft Teams et les chats similaires livrables utilisent le modèle d’authentification de canal normal pour le /approve de même chat
  • lorsqu’un client d’approbation natif s’active automatiquement, la cible de livraison native par défaut est les DM des approbateurs
  • pour Discord et Telegram, seuls les approbateurs résolus peuvent approuver ou refuser
  • les approbateurs Discord peuvent être explicites (execApprovals.approvers) ou déduits de commands.ownerAllowFrom
  • les approbateurs Telegram peuvent être explicites (execApprovals.approvers) ou déduits de commands.ownerAllowFrom
  • les approbateurs Slack peuvent être explicites (execApprovals.approvers) ou déduits de commands.ownerAllowFrom
  • les DM d’approbation de plugin Slack utilisent les approbateurs de plugin Slack provenant de allowFrom et du routage par défaut du compte, et non les approbateurs d’exécution Slack
  • les boutons natifs Slack préservent le type d’ID d’approbation, donc les ID plugin: peuvent résoudre les approbations de plugin sans une deuxième couche de repli locale Slack
  • les approbations par emoji WhatsApp gèrent à la fois les invites d’exécution et de plugin uniquement lorsque la famille de transfert de niveau supérieur correspondante est activée et acheminée vers WhatsApp ; le transfert WhatsApp ciblé uniquement reste sur le chemin de transfert partagé sauf s’il correspond à la même cible d’origine native
  • Les approbations par réaction Signal gèrent à la fois les invites d’exécution et de plugin uniquement lorsque la famille de transfert de premier niveau correspondante est activée et acheminée vers Signal. Les approbations d’exécution Signal en même-chat directes peuvent supprimer le repli local SignalSignalSignal/approveSignalSignal sans approbateurs explicites ; la résolution par réaction Signal nécessite toujours des approbateurs Signal explicites provenant de channels.signal.allowFrom ou defaultTo.
  • Le routage natif DM/channel Matrix et les raccourcis de réaction gèrent les approbations d’exécution et de plugin ; l’autorisation du plugin provient toujours de Matrixchannels.matrix.dm.allowFrom
  • Les invites natives Matrix incluent le contenu d’événement personnalisé Matrixcom.openclaw.approvalOpenClawMatrix sur le premier événement d’invite afin que les clients Matrix conscients d’OpenClaw puissent lire l’état d’approbation structuré, tandis que les clients standards conservent le repli en texte brut /approve
  • le demandeur n’a pas besoin d’être un approbateur
  • le chat d’origine peut approuver directement avec /approve lorsque ce chat prend déjà en charge les commandes et les réponses
  • les boutons d’approbation natifs Discord sont acheminés par type d’identifiant d’approbation : les identifiants Discordplugin: vont directement aux approbations de plugin, tout le reste va aux approbations d’exécution
  • les boutons d’approbation natifs Telegram suivent le même repli limité d’exécution vers plugin que Telegram/approve
  • lorsque target natif active la livraison vers le chat d’origine, les invites d’approbation incluent le texte de la commande
  • les approbations d’exécution en attente expirent après 30 minutes par défaut
  • si aucune interface utilisateur d’opérateur ou client d’approbation configuré ne peut accepter la demande, l’invite revient à askFallback

Les commandes de groupe sensibles réservées au propriétaire, telles que /diagnostics et /export-trajectory, utilisent un acheminement privé vers le propriétaire pour les invites d’approbation et les résultats finaux. OpenClaw essaie d’abord une route privée sur la même surface où le propriétaire a exécuté la commande. Si cette surface n’a pas de route privée vers le propriétaire, elle revient à la première route propriétaire disponible à partir de commands.ownerAllowFrom, ainsi une commande de groupe Discord peut toujours envoyer l’approbation et le résultat au DM Telegram du propriétaire lorsque Telegram est l’interface privée principale configurée. Le chat de groupe ne reçoit qu’un court accusé de réception.

Telegram utilise par défaut les DM des approbateurs (target: "dm"). Vous pouvez passer à channel ou both lorsque vous souhaitez que les invites d’approbation apparaissent également dans le chat/sujet Telegram d’origine. Pour les sujets de forum Telegram, OpenClaw préserve le sujet pour l’invite d’approbation et le suivi post-approbation.

Voir :

Gateway -> Node Service (WS)
| IPC (UDS + token + HMAC + TTL)
v
Mac App (UI + approvals + system.run)

Notes de sécurité :

  • Mode socket Unix 0600, jeton stocké dans exec-approvals.json.
  • Vérification des pairs avec même UID.
  • Défi/réponse (nonce + jeton HMAC + hash de la demande) + TTL court.

Quand accountId et threadId seraient-ils utilisés sur une cible d’approbation ?

Section intitulée « Quand accountId et threadId seraient-ils utilisés sur une cible d’approbation ? »

Utilisez accountId lorsque le channel a plusieurs identités configurées et que l’invite d’approbation doit partir via un compte spécifique. Utilisez threadId lorsque la destination prend en charge les sujets ou les fils de discussion et que l’invite doit rester à l’intérieur de ce fil plutôt que dans le chat de niveau supérieur.

Un cas concret Telegram concerne un supergroupe d’opérations avec des sujets de forum et deux comptes de bots Telegram. La valeur to nomme le supergroupe, accountId sélectionne le compte du bot, et threadId sélectionne le sujet du forum :

{
approvals: {
exec: {
enabled: true,
mode: "targets",
targets: [
{
channel: "telegram",
to: "-1001234567890",
accountId: "ops-bot",
threadId: "77",
},
],
},
},
channels: {
telegram: {
accounts: {
default: {
name: "Primary bot",
botToken: "env:TELEGRAM_PRIMARY_BOT_TOKEN",
},
"ops-bot": {
name: "Operations bot",
botToken: "env:TELEGRAM_OPS_BOT_TOKEN",
},
},
},
},
}

Avec cette configuration, les approbations d’exécution transférées sont publiées par le compte Telegram ops-bot dans le sujet 77 du chat -1001234567890. Une cible sans accountId utilise le compte par défaut du channel, et une cible sans threadId publie vers la destination de premier niveau.

Lorsque les approbations sont envoyées à une session, n’importe qui dans cette session peut-il les approuver ?

Section intitulée « Lorsque les approbations sont envoyées à une session, n’importe qui dans cette session peut-il les approuver ? »

Non. La livraison par session contrôle uniquement l’endroit où l’invite apparaît. Elle n’autorise pas par elle-même chaque participant de ce chat à approuver.

Pour les /approve génériques de même chat, l’expéditeur doit déjà être autorisé pour les commandes dans cette session de channel. Si le channel expose des approbateurs explicites, ces approbateurs peuvent autoriser l’action /approve même lorsqu’ils ne sont pas autrement autorisés pour les commandes dans cette session.

Certains channels sont plus stricts. Discord, Telegram, Matrix, les DMs d’approbation natifs Slack et les clients d’approbation natifs similaires utilisent leurs listes d’approbateurs résolus pour l’autorisation d’approbation. Par exemple, une invite d’approbation de sujet de forum Telegram peut être visible pour tous dans le sujet, mais seuls les IDs d’utilisateur numériques Telegram résolus depuis channels.telegram.execApprovals.approvers ou commands.ownerAllowFrom peuvent l’approuver ou la rejeter.