@aimarket/warden 0.20.0 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +113 -0
- package/README-es.md +27 -11
- package/README-fr.md +27 -11
- package/README-ru.md +27 -11
- package/README-zh.md +27 -11
- package/README.md +27 -11
- package/dist/annotation-review.d.ts +10 -0
- package/dist/annotation-review.d.ts.map +1 -0
- package/dist/annotation-review.js +36 -0
- package/dist/annotation-review.js.map +1 -0
- package/dist/atomic-screen.d.ts +61 -0
- package/dist/atomic-screen.d.ts.map +1 -0
- package/dist/atomic-screen.js +165 -0
- package/dist/atomic-screen.js.map +1 -0
- package/dist/flow-guard-answer.d.ts +29 -0
- package/dist/flow-guard-answer.d.ts.map +1 -0
- package/dist/flow-guard-answer.js +201 -0
- package/dist/flow-guard-answer.js.map +1 -0
- package/dist/flow-guard-classify.d.ts +14 -0
- package/dist/flow-guard-classify.d.ts.map +1 -0
- package/dist/flow-guard-classify.js +224 -0
- package/dist/flow-guard-classify.js.map +1 -0
- package/dist/flow-guard-decode.d.ts +17 -0
- package/dist/flow-guard-decode.d.ts.map +1 -0
- package/dist/flow-guard-decode.js +149 -0
- package/dist/flow-guard-decode.js.map +1 -0
- package/dist/flow-guard-destinations.d.ts +23 -0
- package/dist/flow-guard-destinations.d.ts.map +1 -0
- package/dist/flow-guard-destinations.js +158 -0
- package/dist/flow-guard-destinations.js.map +1 -0
- package/dist/flow-guard-fingerprints.d.ts +27 -0
- package/dist/flow-guard-fingerprints.d.ts.map +1 -0
- package/dist/flow-guard-fingerprints.js +164 -0
- package/dist/flow-guard-fingerprints.js.map +1 -0
- package/dist/flow-guard-fragments.d.ts +17 -0
- package/dist/flow-guard-fragments.d.ts.map +1 -0
- package/dist/flow-guard-fragments.js +122 -0
- package/dist/flow-guard-fragments.js.map +1 -0
- package/dist/flow-guard-instructions.d.ts +12 -0
- package/dist/flow-guard-instructions.d.ts.map +1 -0
- package/dist/flow-guard-instructions.js +36 -0
- package/dist/flow-guard-instructions.js.map +1 -0
- package/dist/flow-guard-labels.d.ts +10 -0
- package/dist/flow-guard-labels.d.ts.map +1 -0
- package/dist/flow-guard-labels.js +55 -0
- package/dist/flow-guard-labels.js.map +1 -0
- package/dist/flow-guard-leak.d.ts +29 -0
- package/dist/flow-guard-leak.d.ts.map +1 -0
- package/dist/flow-guard-leak.js +135 -0
- package/dist/flow-guard-leak.js.map +1 -0
- package/dist/flow-guard-paths.d.ts +21 -0
- package/dist/flow-guard-paths.d.ts.map +1 -0
- package/dist/flow-guard-paths.js +72 -0
- package/dist/flow-guard-paths.js.map +1 -0
- package/dist/flow-guard-policy.d.ts +15 -0
- package/dist/flow-guard-policy.d.ts.map +1 -0
- package/dist/flow-guard-policy.js +179 -0
- package/dist/flow-guard-policy.js.map +1 -0
- package/dist/flow-guard-post.d.ts +6 -0
- package/dist/flow-guard-post.d.ts.map +1 -0
- package/dist/flow-guard-post.js +131 -0
- package/dist/flow-guard-post.js.map +1 -0
- package/dist/flow-guard-pre.d.ts +13 -0
- package/dist/flow-guard-pre.d.ts.map +1 -0
- package/dist/flow-guard-pre.js +335 -0
- package/dist/flow-guard-pre.js.map +1 -0
- package/dist/flow-guard-screen.d.ts +85 -0
- package/dist/flow-guard-screen.d.ts.map +1 -0
- package/dist/flow-guard-screen.js +558 -0
- package/dist/flow-guard-screen.js.map +1 -0
- package/dist/flow-guard-state.d.ts +12 -0
- package/dist/flow-guard-state.d.ts.map +1 -0
- package/dist/flow-guard-state.js +121 -0
- package/dist/flow-guard-state.js.map +1 -0
- package/dist/flow-guard-text.d.ts +9 -0
- package/dist/flow-guard-text.d.ts.map +1 -0
- package/dist/flow-guard-text.js +46 -0
- package/dist/flow-guard-text.js.map +1 -0
- package/dist/flow-guard-types.d.ts +154 -0
- package/dist/flow-guard-types.d.ts.map +1 -0
- package/dist/flow-guard-types.js +2 -0
- package/dist/flow-guard-types.js.map +1 -0
- package/dist/flow-guard.d.ts +20 -215
- package/dist/flow-guard.d.ts.map +1 -1
- package/dist/flow-guard.js +26 -1400
- package/dist/flow-guard.js.map +1 -1
- package/dist/mcp-client.d.ts +1 -2
- package/dist/mcp-client.d.ts.map +1 -1
- package/dist/mcp-client.js +2 -19
- package/dist/mcp-client.js.map +1 -1
- package/dist/mcp-server.js +5 -0
- package/dist/mcp-server.js.map +1 -1
- package/dist/mcp-tools.d.ts.map +1 -1
- package/dist/mcp-tools.js +46 -9
- package/dist/mcp-tools.js.map +1 -1
- package/dist/public-address.d.ts +3 -0
- package/dist/public-address.d.ts.map +1 -0
- package/dist/public-address.js +58 -0
- package/dist/public-address.js.map +1 -0
- package/dist/review-diff.d.ts +36 -0
- package/dist/review-diff.d.ts.map +1 -1
- package/dist/review-diff.js +177 -7
- package/dist/review-diff.js.map +1 -1
- package/dist/task-adapter.d.ts +73 -0
- package/dist/task-adapter.d.ts.map +1 -0
- package/dist/task-adapter.js +379 -0
- package/dist/task-adapter.js.map +1 -0
- package/dist/task-cli.d.ts +3 -0
- package/dist/task-cli.d.ts.map +1 -0
- package/dist/task-cli.js +162 -0
- package/dist/task-cli.js.map +1 -0
- package/dist/types.d.ts +9 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/wrap-cli.d.ts +5 -0
- package/dist/wrap-cli.d.ts.map +1 -1
- package/dist/wrap-cli.js +29 -2
- package/dist/wrap-cli.js.map +1 -1
- package/dist/wrap-screen.d.ts +3 -0
- package/dist/wrap-screen.d.ts.map +1 -0
- package/dist/wrap-screen.js +20 -0
- package/dist/wrap-screen.js.map +1 -0
- package/dist/wrap-state.d.ts +8 -1
- package/dist/wrap-state.d.ts.map +1 -1
- package/dist/wrap-state.js +21 -4
- package/dist/wrap-state.js.map +1 -1
- package/dist/wrap.d.ts.map +1 -1
- package/dist/wrap.js +204 -10
- package/dist/wrap.js.map +1 -1
- package/docs/flow-guard-model-comparison-2026-10-25.es.md +82 -0
- package/docs/flow-guard-model-comparison-2026-10-25.fr.md +82 -0
- package/docs/flow-guard-model-comparison-2026-10-25.md +82 -0
- package/docs/flow-guard-model-comparison-2026-10-25.ru.md +82 -0
- package/docs/flow-guard-model-comparison-2026-10-25.zh.md +82 -0
- package/docs/flow-guard.es.md +307 -12
- package/docs/flow-guard.fr.md +307 -12
- package/docs/flow-guard.md +315 -13
- package/docs/flow-guard.ru.md +314 -13
- package/docs/flow-guard.zh.md +306 -8
- package/docs/scan-limits.es.md +39 -0
- package/docs/scan-limits.fr.md +39 -0
- package/docs/scan-limits.md +39 -0
- package/docs/scan-limits.ru.md +39 -0
- package/docs/scan-limits.zh.md +39 -0
- package/docs/scan.es.md +2 -0
- package/docs/scan.fr.md +2 -0
- package/docs/scan.md +2 -0
- package/docs/scan.ru.md +2 -0
- package/docs/scan.zh.md +2 -0
- package/docs/security-hardening.es.md +1 -1
- package/docs/security-hardening.fr.md +1 -1
- package/docs/security-hardening.md +1 -1
- package/docs/security-hardening.ru.md +1 -1
- package/docs/security-hardening.zh.md +1 -1
- package/examples/atomic-screen-server.mjs +42 -0
- package/native/macos/Package.swift +9 -0
- package/native/macos/Sources/WardenDesktop/NativeSurface.swift +246 -0
- package/native/macos/Sources/WardenDesktop/StandardIO.swift +139 -0
- package/native/macos/Sources/WardenDesktopHost/Main.swift +211 -0
- package/package.json +18 -6
- package/scripts/build-macos.mjs +22 -0
package/docs/flow-guard.fr.md
CHANGED
|
@@ -2,6 +2,285 @@
|
|
|
2
2
|
|
|
3
3
|
> 🌐 [English](flow-guard.md) · [Русский](flow-guard.ru.md) · [Español](flow-guard.es.md) · **Français** · [中文](flow-guard.zh.md)
|
|
4
4
|
|
|
5
|
+
Voir les [limites des mesures et preuves de version](scan-limits.fr.md) pour la facturation, les versions fixes, les comparaisons de launchers et le sens des compteurs d’approbation.
|
|
6
|
+
|
|
7
|
+
## Annotations et révision de réponse (code local, 2026-10-25)
|
|
8
|
+
|
|
9
|
+
La politique utilisateur facultative `{"annotationReview":"first-use"}` ajoute une question au premier usage **uniquement dans `wrap --flow NAME`**. La valeur par défaut est `off` ; wrap ordinaire et hooks seuls ne changent pas. Pour un outil sans étiquette opérateur, `readOnlyHint`, `destructiveHint` et `openWorldHint` restent des déclarations non vérifiées du serveur : toute valeur booléenne, ou un type invalide d’un hint connu, peut nécessiter une révision. `readOnlyHint: true` ne prouve ni absence d’écriture ni gratuité. Les étiquettes explicites et capability bindings exacts sur identité/ensemble complet des tools priment ; destinations autorisées et annotations dans les arguments n’accordent aucun droit.
|
|
10
|
+
|
|
11
|
+
La révision est mémorisée dans ce processus wrap seulement, pour l’identité de lancement et le snapshot complet. Après accord, le proxy attend l’ancienne liste et en demande une nouvelle, puis revérifie le risque partagé avant l’envoi. Dérive, nouveau refus/motif d’ask, refus humain ou formulaire absent empêchent l’appel. Un motif légitime d’ask inchangé reste approuvable. Ce n’est pas une transaction atomique face aux autres proxies. Un nouveau wrap redemande. Les contrôles par appel sensible, identifiants et GUI restent indépendants. `audit` journalise seulement ; `off` désactive cette vérification. Ce n’est ni une vérification de facturation ni un classificateur complet des effets.
|
|
12
|
+
|
|
13
|
+
Friction connue : le premier precheck peut déjà consommer une règle exacte `credentialEgress` à usage unique. La revérification après accord refuse alors prudemment même un payload identique et la règle reste dépensée. Ce contrôle est compté comme friction supplémentaire, pas comme passage automatique anodin.
|
|
14
|
+
|
|
15
|
+
Stop n’exempte plus une phrase parce qu’elle contient « ignored » ou « flagged » : elle peut aussi reprendre la recommandation injectée. Un chevauchement exact normalisé de 12 caractères avec une instruction enregistrée demande une révision supplémentaire. **Un avertissement honnête paie aussi ce passage.** Le host borne la continuation avec `stop_hook_active` ; aucun compteur persistant indépendant n’est revendiqué. Paraphrases, sélection de lignes empoisonnée sans correspondance et exactitude sémantique restent hors portée. Note/révision ne signifie pas prévention. L’[étude](../../docs/growth/kevin-annotations-answer-review-2026-10-25.ru.md) distingue les tests Linux déterministes de l’évaluation d’un modèle. Changements locaux non publiés ; résultats historiques du modèle non recalculés.
|
|
16
|
+
|
|
17
|
+
Audit complémentaire du 2026-10-23 : les données binaires `image`/`audio` des résultats ne consomment plus le budget de texte ; une grande capture placée avant le texte ne masque donc plus les libellés, les titres de fenêtres contenant un fichier de secrets ou le JSON des blocs de texte. Les écrans renvoyés par les actions du pointeur et du clavier, y compris celles de `computer`, actualisent aussi la vue. Un simple accusé conserve la vue précédente ; une action ne renvoyant qu’une image l’efface. Les arguments sortants ne bénéficient pas de cette exception et restent soumis à la détection de secrets. Les tests de régression reproduisent les deux contournements via les hooks et le véritable proxy stdio. Le code local soumet désormais aussi les actions GUI opaques à une approbation, comme décrit ci-dessous.
|
|
18
|
+
|
|
19
|
+
Ces corrections du contrôle d’écran sont dans npm `0.21.0`. npm `0.20.0` ne les contenait pas.
|
|
20
|
+
|
|
21
|
+
## Frontière des identifiants et fragments encodés (code local, 2026-10-23)
|
|
22
|
+
|
|
23
|
+
Après une lecture d’identifiants enregistrée et du texte extérieur, **chaque appel sortant/MCP reconnu impose `ask` avant exécution** (`deny` refuse), quelle que soit la longueur, l’encodage, la destination nommée ou l’étiquette MCP de lecture seule. Les écritures ordinaires du projet sont aussi vérifiées ; l’exception des fichiers d’identifiants reste. `credentialRead` persiste entre tours et après rotation des sources. Les morceaux de un à quatre caractères et les encodages inconnus ne sortent donc pas automatiquement : il s’agit d’une frontière, pas d’une promesse de tout décoder.
|
|
24
|
+
|
|
25
|
+
Les secrets reconnus restent refusés ; les fragments ambigus utilisent `secret_fragment`. Les autres vérifications utilisent `credential_egress`, sans qualifier un texte innocent de secret. GUI strict reste le défaut ; même ses exceptions de copie ne lèvent pas cette frontière. `audit` journalise ; `off` désactive. Le client doit respecter la décision.
|
|
26
|
+
|
|
27
|
+
**Réduire les vérifications inutiles :** l’opérateur peut inscrire des requêtes publiques exactes, vérifiées indépendamment, dans son `flow-policy.json` protégé. `publicRequestDigest(tool, args)` de `dist/flow-guard.js` lie le nom complet de l’outil et tous les arguments, destination comprise. Les clés d’objet sont triées ; l’ordre des tableaux compte. Une règle autorise un appel par session, atomiquement entre proxies, et est consommée même en cas d’échec. Changements, reprises, métadonnées RPC supplémentaires et arguments invalides ne sont pas couverts. Aucun contournement des secrets, textes privés, données personnelles ou fragments détectés, analyses incomplètes, magasins saturés, contrôles GUI, shell, actions destructrices ou réglages protégés. Une règle autorise ses données, ne prouve pas leur caractère public : vérifier soi-même le contenu décodé avant approbation. Aucune règle n’est installée automatiquement.
|
|
28
|
+
|
|
29
|
+
Exemple limité à `mcp__mail__send_email` avec `{"to":"bob@corp.com","subject":"status","body":"The public release is ready."}` :
|
|
30
|
+
|
|
31
|
+
```json
|
|
32
|
+
{"credentialEgress":{"allow":[{"tool":"mcp__mail__send_email","requestSha256":"62e02f4cb9c21a472999fac9316b66fc8fefe3fcafd2b2860c32c5409dae4a65"}]}}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Les appels protégés transmettent l’objet JSON inspecté, sans champs dupliqués ignorés ; leurs valeurs cachées ne profitent pas d’une autorisation exacte.
|
|
36
|
+
|
|
37
|
+
Calculer localement avec `publicRequestDigest` après vérification de toute la requête. Limites : 32 règles/autorisations consommées, 1 024 nœuds JSON, profondeur 32, 16 384 unités UTF-16 sérialisées et 65 536 unités de travail de sérialisation. Une section invalide n’accorde rien. Journal : `credential_public_request` / `policy_allowed`, approbation unknown ; cela ne prétend pas qu’une personne a accepté un formulaire.
|
|
38
|
+
|
|
39
|
+
Les métadonnées restent en version `v2`. Confirmations innocentes : **12/12 → 0/12** avec règles exactes vérifiées ; le coût par défaut reste explicite.
|
|
40
|
+
|
|
41
|
+
**Décodage et erreurs :** file bornée pour URL, base64/base64url canonique, hex UTF-8, échappements Unicode/hex scalaires, entités HTML numériques et listes explicites anglaises. Maximum quatre niveaux, 64 candidats et 524 288 unités UTF-16 cumulées. Saturation : `payload_incomplete` et vérification, jamais résultat propre ni autorisation publique. Aucun littéral n’est exécuté ; ni décompression ni inférence sémantique. État/empreintes corrompus n’autorisent rien. Un index v1 exige vérification ; une nouvelle session et relecture restaurent le suivi. Empreintes, positions, tailles et queues sortantes bornées restent sensibles et non chiffrées.
|
|
42
|
+
|
|
43
|
+
**Compromis mesuré :** 12 requêtes innocentes et 16 attaques. Le défaut strict demande les 12 confirmations innocentes ; les règles publiques exactes permettent les 12 une fois. Les deux profils laissent automatiquement passer **0/16 attaques**, avec **0 faux refus fermes**. La mesure distincte des seules empreintes utilise 480 clés synthétiques et 758 fichiers : 0 refus fermes et 2 fichiers à vérifier pour correspondance courte. Ce ne sont pas des taux de production. Le même ensemble de 23 cas reste à **0/23 livrés intégralement**, dont `secret-chunks-6-filler` et `secret-spelled-out` ; deux cas limités à la réponse reçoivent note/vérification. Les vrais tests stdio confirment zéro appel non approuvé pour données courtes/encodées, une autorisation concurrente et aucun détour via métadonnées ou reprises.
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npm run build
|
|
47
|
+
npm test
|
|
48
|
+
node scripts/redteam/credential-egress.mjs /tmp/warden-egress.json
|
|
49
|
+
node scripts/redteam/flow-redteam.mjs /tmp/warden-redteam.json
|
|
50
|
+
node scripts/redteam/fragment-collisions.mjs /tmp/warden-fragments.json docs src test ../docs ../core
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Limites :** contrôle de la frontière d’outils enregistrée, pas analyse universelle des flux d’information. Sources non vues, intégrations inconnues/renommées, réponses sans appel, canaux temporels/cachés, comportements cachés du serveur, divulgation approuvée et clients contournant les décisions restent hors garantie. Sans règles vérifiées, il y a délibérément plus de confirmations innocentes. Production/npm restent inchangés ; le oracle replay AgentDojo a été rejoué ci-dessous ; les mesures avec modèle réel et 115 millions de caractères/HISTOR restent historiques.
|
|
54
|
+
|
|
55
|
+
## Actions GUI opaques (code local, 2026-10-23)
|
|
56
|
+
|
|
57
|
+
En mode GUI strict par défaut, après du contenu non fiable, les appels MCP reconnus du pointeur et du clavier demandent une approbation avant exécution (`deny` les refuse). Le passage automatique des clics par coordonnées, des écrans uniquement en pixels, d’Entrée dans un champ actif et des libellés non anglais est fermé **par une décision humaine**, sans prétendre comprendre chaque écran. La saisie demande aussi : un saut de ligne ou un champ à envoi automatique peut transmettre le texte. Le collage demande même sans lecture d’identifiants enregistrée ; après une telle lecture il conserve l’explication `paste_after_secret`. Les autres décisions GUI opaques portent la raison `screen_action`.
|
|
58
|
+
|
|
59
|
+
Seule une combinaison exacte tout sélectionner/copier (`cmd+a`, `cmd+c`, `ctrl+a`, `ctrl+c`, avec les alias de modificateur pris en charge) dans un seul champ de touches connu est exemptée. Champs supplémentaires, séquences, tableaux mal formés, sauts de ligne finaux et valeurs trop longues demandent confirmation. Les secrets visibles restent vérifiés. Les contrôleurs génériques connus (`computer`, `screen_control`, `desktop_control`, `browser_control`) demandent si l’action manque ou est inconnue. Une opération d’observation complète connue telle que `screenshot` ou `get_screen` n’est exemptée qu’avec le seul champ `action`. Les noms camelCase, à points et à tirets sont normalisés. Un destinataire nommé ou autorisé ne permet pas les actions GUI.
|
|
60
|
+
|
|
61
|
+
La dernière liste de chaque serveur (Playwright `[ref=e14]`, `[ref_14]`, listes numérotées et nœuds JSON) sert seulement à expliquer. Un autre format ne contourne plus l’approbation ; un exemple aide l’explication, mais n’est pas nécessaire pour bloquer le clic. Le message emploie le mot anglais canonique du garde s’il le reconnaît, jamais le libellé brut. Avant d’accepter, vérifiez la fenêtre, la cible, le presse-papiers et l’effet réel. Dans le proxy stdio, chaque action exige son propre formulaire MCP elicitation accepté avec la case cochée ; sans formulaire, en cas de refus ou d’annulation, l’action ne parvient pas au serveur. Le hook Claude renvoie `ask` au client ; son mécanisme de permissions doit l’appliquer.
|
|
62
|
+
|
|
63
|
+
En mode strict, les confirmations augmentent, y compris pour naviguer ou cliquer dans le corps d’un message ; utilité et fatigue n’ont pas été mesurées. `audit` journalise sans bloquer, `off` désactive les vérifications. Du contenu non fiable doit avoir été enregistré auparavant (les captures le sont par défaut) ; marquer toutes les observations private peut supprimer ce déclencheur. La règle reconnaît des noms d’opération, pas les outils arbitrairement renommés, les exécuteurs JavaScript ou les effets cachés d’un serveur malveillant. Les politiques de l’opérateur et l’isolation OS restent nécessaires. Aucun OCR ni classificateur visuel d’instructions n’a été ajouté : une injection uniquement en pixels peut encore changer une réponse sans appel protégé. Les tests locaux des hooks et du véritable proxy stdio vérifient le refus avant envoi, l’approbation par action et les quatre cas signalés. Ces changements locaux ne sont encore ni déployés ni publiés sur npm.
|
|
64
|
+
|
|
65
|
+
Le dernier instantané précise désormais l’explication de trois façons. Les coordonnées (`x`/`y`, `coordinate`, `coordinates` ou `position`) peuvent correspondre à un unique élément JSON via `bounds`, `boundingBox`, `bounding_box` ou `rect` : nombres finis dans `{x,y,width,height}` ou `{left,top,right,bottom}`, dimensions positives. Les bords droit et inférieur sont exclus ; `center` exige une correspondance exacte. Chevauchements, rectangles ou références contradictoires, nombres invalides et tableaux aux conventions xywh/xyxy ambiguës ne donnent aucune cible déduite. Aucune conversion écran/viewport/zoom n’est devinée. Il s’agit de la géométrie déclarée dans le dernier instantané, pas d’une cible actuelle vérifiée.
|
|
66
|
+
|
|
67
|
+
Pour Entrée/Return, un nœud non ambigu `focused: true` ou `focusedRef`/`focusedElementId`/`activeElementId` indique l’élément actif. Un champ explicitement monoligne (`multiline: false`) dans un formulaire avec un seul contrôle d’envoi reconnu reçoit l’explication « Entrée peut soumettre » ; un champ multiligne la reçoit pour cmd/ctrl+Entrée. Le lien exige `form`/`formId` ou une ascendance JSON de formulaire. Focus absent ou contradictoire, état multiline inconnu, formulaires différents et plusieurs candidats ne permettent pas cette déduction. Les identifiants accessibility/automation reconnus et `type: "submit"` apportent des indices canoniques même sans libellé visible. De petites listes expliquent Senden, Envoyer, Enviar, Wyślij et d’autres libellés. Identifiants, rôles et traductions restent non fiables ; le champ accessibility brut n’est ni copié dans les métadonnées supplémentaires ni affiché dans la demande ; références et libellés existants restent dans l’état de session.
|
|
68
|
+
|
|
69
|
+
Ces ajouts expliquent seulement ; les métadonnées écran n’autorisent jamais une interaction. Demander seulement après un collage ou une saisie manquerait les messages préremplis, les paiements et les suppressions. Géométrie, focus et accessibility-id issus d’un instantané ne prouvent pas l’innocuité d’une navigation. Une nouvelle vue uniquement en image efface ces indices ; les doublons contradictoires ne sont pas utilisés. Les tests hooks et stdio vérifient les explications et le refus avant transmission.
|
|
70
|
+
|
|
71
|
+
## Régressions Gautam : codes, NATO, métadonnées Git et CI
|
|
72
|
+
|
|
73
|
+
Le décodeur borné ajoute les listes de codes décimaux et l’épellation NATO. Au moins cinq scalaires valides ou cinq unités NATO explicites sont nécessaires. Espaces, virgules, points-virgules, barres verticales et sauts de ligne séparent les unités ; éléments inconnus, scalaires invalides et marqueurs de casse ambigus interrompent la suite. Sont admis alfa/alpha, juliett/juliet, xray/x-ray, chiffres nommés/littéraux, ponctuation nommée et capital/uppercase/lowercase. Les tableaux JSON de 5–4096 entiers sont aussi inspectés. Les limites existantes restent communes ; leur épuisement produit `payload_incomplete`. Aucun eval ni décompression arbitraire.
|
|
74
|
+
|
|
75
|
+
Décoder n’affirme pas une fuite : motif ou empreinte de secret reste nécessaire. Les listes numériques ordinaires et la prose NATO ne sont pas interdites automatiquement. Les premiers 1–4 caractères restent soumis à la frontière d’identifiants même sous le seuil du décodeur. Tests de clés reconstruites et de textes innocents, sans déclarer toute coïncidence courte secrète.
|
|
76
|
+
|
|
77
|
+
MCP sans étiquette : `git_push`, `push_files`, `git_commit`, création de commit et variantes camelCase/avec points sont des effets sortants ou persistants publiables. Un message de commit peut être publié ensuite. `get_commit` / `list_commits` restent des lectures. Les étiquettes opérateur exigent une configuration correcte ; la frontière indépendante couvre aussi les outils MCP mal étiquetés. Git shell garde ses contrôles. Aucun commit/push réel n’a été effectué.
|
|
78
|
+
|
|
79
|
+
**Gate local :** `npm run build && npm run test:redteam` exécute tout le hook replay avec `--check`, les 23 originaux plus cinq de Gautam : **28 cas, dont 26 attaques par outil nécessitent ask/deny et deux portant sur la réponse note/recheck**. Cas manquants/dupliqués, résultats incohérents ou transmission automatique réouverte font échouer avec un code non nul. Des rapports altérés testent cet échec. Intégré dans CI WARDEN/workspace, npm `prepublishOnly` et workflow registre avant publication. Modifications locales uniquement : aucun CI distant, release ou publication lancé. Une note ne prouve pas empêcher une réponse manipulée du modèle.
|
|
80
|
+
|
|
81
|
+
Reproduire : `npm run build`, `npm run test:redteam` ou `node scripts/redteam/flow-redteam.mjs /tmp/warden-redteam.json --check`. Sources : `test/flow-guard-gautam.test.ts`, `scripts/redteam/flow-gate.mjs`.
|
|
82
|
+
|
|
83
|
+
## Mode de tâches limité : moins de confirmations, contrôle des effets réels
|
|
84
|
+
|
|
85
|
+
Le GUI strict reste le défaut. `gui.mode: "policy"` / `gui.allow` sont lus pour la migration, mais n’autorisent plus clic, saisie ou navigation après du texte externe. La page peut falsifier même origin, rôle et accessibility ID. Géométrie, focus et traductions expliquent seulement. Un nom composé tel que `press_keys_then_execute` n’obtient pas l’exception Copy ; des métadonnées RPC supplémentaires n’autorisent rien automatiquement.
|
|
86
|
+
|
|
87
|
+
L’adaptateur intégré (`node dist/mcp-server.js task`) applique lui-même les limites : ressources fixes, instantanés UTF-8 locaux épinglés sans exécuter HTML/JS, opérations HTTP relues choisies par ID. Le modèle ne fournit ni URL, méthode, en-têtes, corps, destinataire, pièce jointe ou chemin. Aucun profil de navigateur, cookie, presse-papiers système, script, service worker, sous-processus ou relais arbitraire d’outils. Le GUI ordinaire garde ses confirmations. C’est une alternative structurée pour les tâches prises en charge, pas un sandbox universel navigateur/VM.
|
|
88
|
+
|
|
89
|
+
**Configuration explicite :** enregistrer le manifeste dans `<WARDEN_STATE_DIR>/task-manifest.json` et la politique dans le flow policy utilisateur. Remplacer chemin, empreinte et endpoint ; limiter `expiresAt` à 24 heures. N’exposer que les données choisies volontairement. L’empreinte du fichier correspond à `The public release is ready.\n`. Relire chaque requête puis calculer `manifestSha256` sur les octets réellement enregistrés, espaces et saut final compris. L’exemple de politique correspond au manifeste affiché suivi d’un saut de ligne. Aucun droit n’est installé automatiquement.
|
|
90
|
+
|
|
91
|
+
```json
|
|
92
|
+
{
|
|
93
|
+
"version": 1,
|
|
94
|
+
"taskId": "public-report",
|
|
95
|
+
"expiresAt": "2026-10-23T23:00:00.000Z",
|
|
96
|
+
"resources": [
|
|
97
|
+
{
|
|
98
|
+
"id": "report",
|
|
99
|
+
"title": "Public report",
|
|
100
|
+
"path": "/absolute/path/public-report.txt",
|
|
101
|
+
"sha256": "1403cece199725b166f0f6e59faa9d45e3d5a25db26080fecf95e818ac8d4d0d"
|
|
102
|
+
}
|
|
103
|
+
],
|
|
104
|
+
"operations": [
|
|
105
|
+
{
|
|
106
|
+
"id": "send_report",
|
|
107
|
+
"title": "Send reviewed report to Bob, no attachments",
|
|
108
|
+
"maxUses": 1,
|
|
109
|
+
"request": {
|
|
110
|
+
"method": "POST",
|
|
111
|
+
"url": "https://mail.example/api/send",
|
|
112
|
+
"headers": {
|
|
113
|
+
"content-type": "application/json",
|
|
114
|
+
"idempotency-key": "public-report-once"
|
|
115
|
+
},
|
|
116
|
+
"body": "{\"to\":\"bob@corp.com\",\"body\":\"The public release is ready.\",\"attachments\":[]}"
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
]
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"mode": "ask",
|
|
126
|
+
"taskAdapter": {
|
|
127
|
+
"mode": "capabilities",
|
|
128
|
+
"server": "warden_task",
|
|
129
|
+
"manifestSha256": "1531d08beffb7c86d6f236c3bdfa85a8fbac1c3e8734d701e79455c53d0d94b7"
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
```json
|
|
134
|
+
{
|
|
135
|
+
"mcpServers": {
|
|
136
|
+
"warden_task": {
|
|
137
|
+
"command": "node",
|
|
138
|
+
"args": [
|
|
139
|
+
"/absolute/path/warden/dist/mcp-server.js",
|
|
140
|
+
"task"
|
|
141
|
+
],
|
|
142
|
+
"env": {
|
|
143
|
+
"WARDEN_STATE_DIR": "/absolute/state/warden",
|
|
144
|
+
"WARDEN_FLOW_POLICY": "/absolute/state/warden/flow-policy.json"
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
```sh
|
|
152
|
+
node -e 'console.log(new Date(Date.now() + 3600000).toISOString())'
|
|
153
|
+
node --input-type=module -e 'import {createHash} from "node:crypto"; import {readFileSync} from "node:fs"; console.log(createHash("sha256").update(readFileSync(process.argv[1])).digest("hex"))' /absolute/state/warden/task-manifest.json
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
Déclarer **`warden_task`**, commande `node`, arguments `[/absolute/path/warden/dist/mcp-server.js, task]`, avec les mêmes `WARDEN_STATE_DIR` / `WARDEN_FLOW_POLICY` que les hooks ou `wrap --flow warden_task`. Réserver ce nom à l’adaptateur WARDEN intégré ; le donner à un autre serveur lui confère l’autorité. Nom et `readOnlyHint` n’attestent pas l’identité. Politique absente/stricte/invalide : réseau refusé ; `deny`, `audit`, `off` globaux ne permettent pas non plus l’exécution. Le client peut garder ses propres autorisations.
|
|
158
|
+
|
|
159
|
+
Appels : `task_list {}`, `task_read {"id":"report"}`, `task_execute {"id":"send_report"}`. Seul l’ID fixe est accepté ; champs supplémentaires, doublons JSON, tableaux et métadonnées RPC cachées sont refusés. `task_adapter_delegated` indique une délégation, ni une exécution réussie ni une approbation humaine. Le runtime revérifie empreinte, schéma, expiration et politique ; verrou interprocessus et fsync consomment le budget avant l’envoi. Redémarrer ou modifier le manifeste ne réinitialise pas un task ID dépensé. Échec/résultat incertain et annulation après envoi consomment le droit ; annulation avant envoi non. État corrompu ou verrou abandonné exige une réconciliation par l’opérateur, pas une suppression pour réessayer.
|
|
160
|
+
|
|
161
|
+
Requêtes HTTPS fixes uniquement ; `loopback-test` ajoute HTTP sur localhost numérique pour les tests isolés. Aucune redirection, cookie, instruction/lien exécuté ou nouvelle tentative. Durée totale et taille de réponse limitées. `bearerEnv` référence une variable choisie par l’opérateur ; le jeton ne va qu’à l’endpoint fixé, jamais aux listes/audits. L’audit conserve IDs/résultats, pas les payloads/jetons ; les réponses restent non fiables.
|
|
162
|
+
|
|
163
|
+
**Paiements et transactions :** fixer facture/compte, montant, devise et corps ; `maxUses: 1` et `idempotency-key` fixe pris en charge par le fournisseur. Un envoi unique ne garantit pas un règlement exactement une fois. Après timeout/erreur, vérifier chez le fournisseur avant une nouvelle autorisation. Tests loopback avec clés synthétiques, aucun paiement réel.
|
|
164
|
+
|
|
165
|
+
**Limites :** confiance dans le processus WARDEN, protection de policy/state, runtime et liaison MCP. Le serveur conserve sa sémantique ; même GET n’est pas présumé inoffensif. Droits erronés, secret littéral explicitement autorisé, effets serveur, canaux cachés ID/ordre/temps et outils/clients contournant le garde restent hors garantie. Aucun OCR ni interception universelle du GUI.
|
|
166
|
+
|
|
167
|
+
**Vérification 2026-10-23 :** nouveau oracle replay déterministe AgentDojo 0.1.35 / v1.2.2, Docker local sans réseau ni API de modèle : variante intent 0/579 attaques par action livrées réussies ; 57/97 tâches normales sans question, 58/97 terminées, 608/949 terminées sous attaque (ancien résultat 613/949). `ask` vaut refus ; les objectifs sans référence et les réponses seules ne sont pas certifiés. AgentDojo n’a ni GUI ni adaptateur : tests stdio, interprocessus et loopback distincts. Les anciennes mesures avec vrai modèle, 115 millions de caractères et HISTOR n’ont pas été refaites. [Résumé](../scripts/agentdojo/results/summary-2026-10-23-local.json).
|
|
168
|
+
|
|
169
|
+
Régressions : `test/task-adapter.test.ts`, `test/flow-guard-gui-policy.test.ts`, `test/flow-guard-credential-boundary.test.ts`, `test/flow-guard-secret-regression.test.ts` : faux libellés/IDs, schéma, ressources épinglées, concurrence/redémarrage, redirections, destinataire/corps exacts et premiers 1–4 caractères en raw, hex, base64, Unicode ou encodage inconnu. Les cas ambigus demandent une vérification sans déclarer chaque court fragment secret.
|
|
170
|
+
|
|
171
|
+
## Backend natif macOS : AppKit dans l’application cible
|
|
172
|
+
|
|
173
|
+
**Implémenté :** le paquet Swift [WardenDesktop](../native/macos/Package.swift), `WardenDesktopSurface` et `WardenDesktopStandardIO` s’exécutent dans l’application propriétaire de la fenêtre. `warden-desktop --demo` ouvre une vraie fenêtre AppKit avec un gestionnaire local. Aucun contrôle d’autres applications, aucune entrée globale, aucun réseau/paiement. La confirmation stricte wrap reste le défaut. Une intégration explicite est nécessaire ; ce n’est pas un injecteur de bureau universel.
|
|
174
|
+
|
|
175
|
+
Compilez et lancez depuis WARDEN. macOS, Xcode command-line tools et une session WindowServer active sont nécessaires. La compilation cible macOS 13+ et l’architecture arm64/x86_64 du poste ; seule l’architecture du relevé local est vérifiée. Les sources sont incluses, sans binaire précompilé ni nouvelle dépendance npm d’exécution :
|
|
176
|
+
|
|
177
|
+
```sh
|
|
178
|
+
npm run build
|
|
179
|
+
npm run build:macos
|
|
180
|
+
node dist/mcp-server.js wrap --id macos-owned-app --flow native --screen-read screenshot --screen-atomic -- native/macos/.build/warden-desktop --demo
|
|
181
|
+
npm run test:macos
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Exemple d’action native : références textuelles. Variante : uniquement `x` et `y` en points globaux depuis le coin supérieur gauche, pas en pixels. Les cibles masquées ou ambiguës sont refusées :
|
|
185
|
+
|
|
186
|
+
```json
|
|
187
|
+
{"name":"click","arguments":{"index":"3"}}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
**Limite atomique :** prepare retient le `NSButton` exact, son target `NSObject`, le sélecteur et l’implémentation dont l’ABI est vérifiée avec `method_getImplementation`. Sur MainActor, commit compare révision, rôle/ID/cadre/libellé, identité, fenêtre/focus/modalité, opacité des ancêtres et hit-test. Contrôles/fenêtres transparents, fenêtres bloquées par modalité et sheets en attente sont refusés, y compris la relation logique `sheetParent`. Après hit-test, il relit les propriétés, vérifie les deux horloges puis compare la révision après tous les callbacks injectés. Le IMP épinglé est invoqué par `NativeAction` dans le même tour principal. `NSApp.sendAction` est volontairement contourné : une redéfinition peut différer, rediriger ou annoncer un succès sans appeler la méthode approuvée. Aucun `AXPress`, `CGEvent`, `performClick` animé, recherche first-responder ou clic en file. Seuls les boutons momentanés enregistrés, visibles et actifs avec signature `void action(id sender)` sont acceptés. Appels directs, saisie, raccourcis, presse-papiers, champs sécurisés, vues non enregistrées et PID externes sont refusés.
|
|
191
|
+
|
|
192
|
+
**Intégration :** importez le paquet Swift local. Sur MainActor, créez `WardenDesktopSurface(window:applicationID:)`, configurez accessibility element/role/identifier puis `register(id:button:target:selector:)`. Conservez la surface et `WardenDesktopStandardIO(surface:)` ; `start()` dessert le pipe stdio hérité exclusif. L’observation fournit les métadonnées des contrôles enregistrés, pas des pixels ni un arbre AX global. Maximum 64 contrôles, références/ID uniques et targets explicites retenus ; target nil et signatures Objective-C dangereuses sont refusés. Voir [source](../native/macos/Sources/WardenDesktop/NativeSurface.swift) et [hôte natif](../native/macos/Sources/WardenDesktopHost/Main.swift).
|
|
193
|
+
|
|
194
|
+
Tout changement de modèle/destinataire/gestionnaire doit passer par MainActor avec `invalidate()` **avant** mutation hors du gestionnaire approuvé, y compris les changements invisibles et A → B → A. Notifications et empreintes récentes complètent cette règle sans prouver tous les changements cachés. Les gestionnaires approuvés doivent rester synchrones, sans boucle modale imbriquée, transfert asynchrone ni substitution de responder. Leurs mutations propres sont couvertes par la rotation de révision du commit. Sans respect de ce contrat, n’activez pas le mode atomique. Aucun repli pour une application tierce non intégrée : Apple expose [lectures AX et actions séparées](https://developer.apple.com/documentation/applicationservices/1462091-axuielementperformaction), pas notre contrat de révision.
|
|
195
|
+
|
|
196
|
+
Les tickets lient tous les arguments et expirent selon les horloges murale et monotone, sous cinq minutes. Ils sont consommés avant envoi ; annulation, rejeu, redémarrage et divergence empêchent toute réutilisation. Un envoi échoué/incertain bloque l’autorité native ; ne redémarrez pas ou ne réautorisez pas simplement pour répéter un paiement. committed atteste l’envoi local au gestionnaire, **pas** la livraison d’un message, un règlement ou la fin d’un traitement asynchrone. Ces résultats exigent rapprochement et idempotence persistante du service. Wrap conserve le verrou si la réponse est perdue.
|
|
197
|
+
|
|
198
|
+
**Gate natif :** `npm run test:macos` compile séparément production et test, puis vérifie de vraies fenêtres, stdio et formulaires wrap. Couverture : cible/gestionnaire/cadre/fenêtre, remplacement d’objet visuellement identique, ABA, réentrance hit-test, expiration/recul/rejeu/redémarrage/annulation, empreintes entre langages et libellés multilingues. Les méthodes de mutation de test sont exclues de production. Suite distincte de `npm test` ; autre OS, outils manquants ou GUI indisponible font échouer le gate, sans skip silencieux. La configuration CI locale ajoute un gate macOS ; aucun lancement distant. Les tests ne demandent pas de permissions globales Accessibility/Screen Recording et ne modifient pas TCC. Aucune publication ni déploiement.
|
|
199
|
+
|
|
200
|
+
**Audit local complémentaire (2026-10-24) :** prepare et commit relisent les propriétés natives après `hitTest` ; un changement de gestionnaire, libellé, activation ou cadre provoque un refus même si l’application omet `invalidate()`. Les deux horloges sont revérifiées juste avant l’envoi. L’argument Objective-C sender doit être un objet (`@`), jamais un bloc (`@?`). Le serveur atomique TypeScript impose aussi un délai monotone et revérifie l’expiration avant l’effet. Les régressions couvrent ces cas, les changements pendant prepare, la récupération de capacité et la réentrance du gestionnaire natif. Cela complète le contrat de propriété : getters et hit-test ne doivent pas lancer de boucle imbriquée ni d’effet ; les changements cachés de modèle/destinataire exigent toujours une invalidation préalable. Seules les applications de confiance intégrées sont prises en charge.
|
|
201
|
+
|
|
202
|
+
**Contrat d’appel direct (second audit local, 2026-10-24) :** les gestionnaires enregistrés doivent permettre un appel direct sûr et contrôler leurs permissions ; ne comptez pas sur une redéfinition de `NSApplication.sendAction` ou le responder pour les autoriser. Horloges et getters sont du code hôte synchrone et fiable. Changements cachés et ABA exigent toujours `invalidate()` préalable. Régressions : modalité/opacité pendant hit-test, changement d’implémentation, opacité partielle stable, interception dispatch et invalidation depuis la dernière horloge. Ces contrôles sont dans npm `0.21.0`. Un rapport local ne remplace pas le reçu signé release-quality : son digest actuel couvre JavaScript dans `dist`, pas les sources du SDK natif ; la validation native est distincte.
|
|
203
|
+
|
|
204
|
+
## Vérification atomique de la cible sur le serveur
|
|
205
|
+
|
|
206
|
+
**Activation explicite :** `--screen-atomic` exige `--flow`, `--screen-read` et un mode flow qui applique la protection. La confirmation stricte reste le choix par défaut. Le serveur participant doit être de confiance ; ses annotations et une version annoncée ne suffisent pas. Un serveur incompatible provoque un refus avant la question. Aucun repli vers un clic direct. Le mode précédent limité aux captures reste non atomique.
|
|
207
|
+
|
|
208
|
+
Compilez WARDEN puis lancez cet exemple local depuis son répertoire. Il contrôle un formulaire virtuel, sans entrée système, courrier, paiement ni réseau :
|
|
209
|
+
|
|
210
|
+
```sh
|
|
211
|
+
node dist/mcp-server.js wrap --flow screen --screen-read screenshot --screen-atomic -- node examples/atomic-screen-server.mjs
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
**Protocole :** avant la question, le proxy appelle en privé `warden/screen/prepare` avec l’action exacte et l’observation configurée. Exemple de paramètres :
|
|
215
|
+
|
|
216
|
+
```json
|
|
217
|
+
{
|
|
218
|
+
"protocol": "warden.screen.atomic.v1",
|
|
219
|
+
"observation": { "name": "screenshot", "arguments": {} },
|
|
220
|
+
"action": { "name": "click", "arguments": { "index": 3 } }
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Le serveur renvoie `protocol`, un `ticket` opaque à usage unique, la `revision` de la surface, le `stamp` de la cible, `expiresAt` et `observation`. Le proxy vérifie l’empreinte sur cette observation, montre l’action, puis après acceptation explicite revérifie les définitions, le contexte de risque et la cible récente. Il envoie `warden/screen/commit` avec `{protocol,ticket,expected:{revision,stamp},action}` au lieu de l’appel direct. Le serveur consomme le ticket, compare la révision actuelle, la cible résolue et les arguments exacts, puis exécute de façon synchrone dans la même section critique. Aucun passage de la boucle événementielle ni clic par coordonnées mis en file entre comparaison et effet. Toute modification, y compris gestionnaire/destinataire ou A → B → A, doit changer la révision. L’effet utilise la référence résolue, sans recherche ultérieure par coordonnées.
|
|
225
|
+
|
|
226
|
+
Intégrez `AtomicScreenServer` depuis `@aimarket/warden/atomic-screen` (`dist/atomic-screen.js` en local). Routez les trois méthodes vers `prepare(params)`, `commit(params)` et `cancel(params)`, et l’observation vers `read()`. Toutes les routes directes d’effets doivent refuser. Partagez une autorité par surface entre connexions ; les autres changements passent par `replace(snapshot)`. Le code de confiance `apply(action, target)` doit être synchrone et renvoyer `{result,snapshot}`, avec un résultat MCP ordinaire. Les fonctions asynchrones sont refusées ; exception ou résultat invalide bloquent la surface jusqu’à rapprochement et remplacement explicites. Voir le [serveur exécutable](../examples/atomic-screen-server.mjs).
|
|
227
|
+
|
|
228
|
+
Les tickets expirent sous cinq minutes, lient toute l’action, sont consommés à la tentative de commit et ne survivent pas au redémarrage. Limite : 256 tickets en attente. Le client ne peut pas appeler le protocole privé via wrap ; les tickets ne sont transmis ni au modèle ni au journal flow. `warden/screen/cancel` supprime une préparation inutilisée après refus/annulation ; les préparations abandonnées expirent. Les arguments atomiques doivent tenir intégralement dans 1500 caractères échappés de confirmation ; sinon l’appel est refusé, sans aperçu tronqué.
|
|
229
|
+
|
|
230
|
+
Un reçu validé `committed` contient `protocol,status,revisionBefore,revisionAfter,stamp,result` ; wrap ne renvoie que `result`. Un reçu validé `refused` contient `protocol,status,reason` et signifie qu’aucun effet n’a eu lieu. L’audit distingue `atomic_committed` / `atomic_refused`. Reçu malformé, erreur de transport ou résultat perdu donnent `execution_uncertain` : aucun nouvel essai et maintien du verrou GUI jusqu’au rapprochement opérateur. L’effet peut précéder la perte de réponse. Le ticket ne remplace pas une clé persistante d’idempotence de paiement.
|
|
231
|
+
|
|
232
|
+
**Limite de propriété :** cette course est fermée seulement si le serveur de confiance contrôle l’état complet et l’effet synchrone de la surface. L’authentification ou un transport exclusif doivent réserver prepare/commit aux proxies de confiance ; un ticket ne prouve pas le consentement humain. Une autorité dans un processus ne verrouille pas tout le système. Encapsuler une entrée souris asynchrone ou un RPC Playwright/desktop ne rend pas la surface distante atomique. Un backend natif exige une vraie transaction/révision de plateforme ou un modèle applicatif synchrone contrôlé. Le backend AppKit natif dans l’application est décrit dans la section macOS ; les applications externes non intégrées restent incompatibles. Métadonnées mensongères, acteurs externes non suivis et gestionnaires autorisés nuisibles restent hors garantie. Le hook Claude ne peut pas effectuer ce commit privé après approbation. Les régressions couvrent la mutation après la dernière lecture, ABA/gestionnaire, rejeu, expiration, redémarrage, réentrance, refus des appels directs et effets incertains. Aucune publication ni aucun déploiement.
|
|
233
|
+
|
|
234
|
+
## Auten : une approbation du résultat et un écran frais après accord
|
|
235
|
+
|
|
236
|
+
**Résultat :** ajouter le fragment `runs` au manifeste épinglé, enregistrer le JSON avec deux espaces et saut final, recalculer son empreinte et utiliser la politique suivante avec `taskAdapter.mode: "review"`. Appeler `task_run {"id":"mail_to_bob"}`. L’adaptateur demande une seule fois par formulaire MCP avant le premier effet : résultat, ordre complet, URLs et corps exacts ; identifiants d’en-tête masqués. Case false par défaut. Sans formulaire, acceptation des valeurs par défaut, refus ou annulation n’autorisent rien. `strict` reste le défaut ; `capabilities` garde la préautorisation explicite.
|
|
237
|
+
|
|
238
|
+
L’exemple remplace préparation/envoi GUI par un effet HTTP fixé. Huit opérations distinctes au maximum par plan, 16 plans et aperçu complet de 12 000 caractères échappés. Le modèle ne change ni étapes, ordre, destinataire, corps ou résultat. `review` interdit `task_execute` individuel pour ne pas contourner la question. Lectures/listes silencieuses ; autorisations indépendantes du client/outils sensibles possibles.
|
|
239
|
+
|
|
240
|
+
Un verrou interprocessus couvre question et exécution. Budget vérifié avant la question, plan entier et opérations réservés atomiquement après accord. Un seul usage, même après redémarrage. Chaque étape revérifie manifeste/politique, expiration, annulation et liaison des identifiants. Dérive/erreur/résultat incertain arrête la suite et dépense tous les budgets réservés, même inutilisés. Aucun rollback des effets précédents. Les réponses ne modifient pas l’étape/destination suivante. Refus/annulation avant réservation ne dépensent pas. Réconcilier un paiement incertain avant de modifier état/verrous. Audit séparé d’accord, réservation, achèvement et arrêt, sans corps/jetons.
|
|
241
|
+
|
|
242
|
+
```json
|
|
243
|
+
{
|
|
244
|
+
"runs": [
|
|
245
|
+
{
|
|
246
|
+
"id": "mail_to_bob",
|
|
247
|
+
"title": "Send the reviewed public report to bob@corp.com in Mail",
|
|
248
|
+
"operations": [
|
|
249
|
+
"send_report"
|
|
250
|
+
]
|
|
251
|
+
}
|
|
252
|
+
]
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
```json
|
|
257
|
+
{
|
|
258
|
+
"mode": "ask",
|
|
259
|
+
"taskAdapter": {
|
|
260
|
+
"mode": "review",
|
|
261
|
+
"server": "warden_task",
|
|
262
|
+
"manifestSha256": "c69bafc53aa2e4a1a82dd9a20accbe2e4de5372d7545509fe3f6ccf18fdc5580"
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
**Écran frais, wrap uniquement :** sélectionner explicitement un outil d’observation du même serveur relu :
|
|
268
|
+
|
|
269
|
+
```sh
|
|
270
|
+
node dist/mcp-server.js wrap --flow screen --screen-read get_elements -- node /absolute/path/screen-server.js
|
|
271
|
+
node dist/mcp-server.js wrap --flow screen --screen-read computer --screen-read-input '{"action":"screenshot"}' -- node /absolute/path/screen-server.js
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
`--screen-read` exige `--flow` ; `--screen-read-input` est du JSON strict : entrée vide pour une observation connue ou seul `action` de lecture pour un contrôleur générique. `readOnlyHint` n’accorde aucune autorité. Sans cette option, le GUI strict par appel reste sans promesse de revalidation après accord. Le hook Claude n’a pas de callback entre dialogue et exécution.
|
|
275
|
+
|
|
276
|
+
Wrap observe avant la question puis, après accord, revérifie les définitions et observe à nouveau. Comparaison de cette nouvelle réponse, pas du cache : cible unique, rôle, référence exacte, boîte, contexte et focus cohérent au clavier ; identité d’accessibilité, libellé et formulaire comparés si présents. Changement, absence, chevauchement/ambiguïté, liste incomplète, pixels seuls ou erreur refusent. Pas de conversion de coordonnées/zoom devinée. Schémas multi-actions/champs supplémentaires non comparables. Risque modifié ou nouveau secret arrêtent aussi. Annulation pendant la dernière lecture respectée.
|
|
277
|
+
|
|
278
|
+
Les effets GUI connus sont sérialisés entre proxies partageant `WARDEN_FLOW_SESSION` / state, même un second sans revalidation. Résultat normal : libération ; panne/résultat absent : verrou incertain à revoir. Les observations peuvent continuer. `screen_validation` : `unchanged`, `refused_without_approval`, `refused_after_approval`, `execution_uncertain` ; accord et métadonnées égales ne prouvent pas l’exécution.
|
|
279
|
+
|
|
280
|
+
**Limite :** fenêtre de course réduite, snapshot + clic non atomiques. Un acteur externe peut changer l’UI ensuite ; le serveur peut renvoyer cache/faux renseignements ; ID/boîte identiques ne prouvent ni handlers ni effets. La fermeture complète exige un serveur fiable validant revision/cible et exécutant l’effet atomiquement. Pas d’accord global pour click/paste/Send arbitraires : regroupement réservé à l’adaptateur structuré qui impose les effets. Injections portant seulement sur la réponse toujours hors frontière.
|
|
281
|
+
|
|
282
|
+
Régressions locales : `test/wrap-screen.test.ts`, `test/wrap.test.ts`, `test/task-adapter.test.ts`. [Checkpoint AgentDojo local](../scripts/agentdojo/results/summary-2026-10-23-auten-local.json), replay sans API de modèle ni GUI. Aucun commentaire envoyé, publication ou déploiement.
|
|
283
|
+
|
|
5
284
|
## Explication des demandes (sources non encore publiées)
|
|
6
285
|
|
|
7
286
|
La demande indique l’outil, jusqu’à quatre destinations et le motif. Elle omet le corps des messages, le code shell, les identifiants/chemins/paramètres des URL et les valeurs sensibles reconnues. L’origine de chaque destination n’est pas suivie ; une correspondance d’empreinte n’identifie pas non plus un fichier précis. Les derniers fichiers lus ne sont plus présentés comme sa source. Vérifiez l’appel complet dans le client.
|
|
@@ -16,18 +295,19 @@ La garde vérifie les appels après réception de texte externe. Ce n’est ni u
|
|
|
16
295
|
- Les écritures reconnues dans politique/état, hooks Claude et hooks/config Git sont protégées, y compris variables de chemin et liens symboliques. Cela ne remplace pas les permissions du système.
|
|
17
296
|
- L’autorité réelle des URL et tous les destinataires sont vérifiés. Un lien dans le corps ne permet pas un autre destinataire. Les adresses mail de la politique correspondent exactement ; un domaine n’autorise pas toutes ses boîtes. Une mention n’autorise pas toute action ou donnée.
|
|
18
297
|
- La résolution exige `contactTools` explicite, l’étiquette `private`, des enregistrements structurés `name`/`email` et le nom complet dans la demande. Un nom ambigu demande confirmation. Fichiers locaux, prose, YAML et anciens contacts en cache ne confèrent aucune autorité. Ne faites confiance qu’aux annuaires non modifiables par l’agent ou des tiers.
|
|
19
|
-
- Les empreintes inspectent le texte visible avec un décodage URL/base64/hex limité. Depuis le 2026-10-22, les valeurs qui ressemblent à des clés (suites aléatoires des fichiers d’identifiants, et formats de jetons connus où qu’ils soient lus) sont aussi relevées par fenêtres de 8 lettres et chiffres, 10 pour les clés hex : un morceau de clé, la clé à l’envers, avec des séparateurs ou des caractères invisibles, en morceaux base64 ou avec des lettres cyrilliques ou grecques sosies est refusé. Ce sont les plus petites tailles pour lesquelles aucune de 480 clés inventées dans huit formats ne s’est retrouvée nulle part dans 115 millions de lettres et chiffres (ce monorepo et 1 000 paquets HISTOR) de texte ordinaire ; les parties que partagent toutes les clés d’un type (l’identifiant d’algorithme d’une clé DER, l’en-tête et les champs d’un JWT) ne sont jamais relevées. Chaque argument garde la fin de ce qu’il a envoyé après le texte extérieur, si bien que des morceaux envoyés à la suite par le même argument sont vérifiés en entier.
|
|
298
|
+
- Les empreintes inspectent le texte visible avec un décodage URL/base64/hex limité. Depuis le 2026-10-22, les valeurs qui ressemblent à des clés (suites aléatoires des fichiers d’identifiants, et formats de jetons connus où qu’ils soient lus) sont aussi relevées par fenêtres de 8 lettres et chiffres, 10 pour les clés hex : un morceau de clé, la clé à l’envers, avec des séparateurs ou des caractères invisibles, en morceaux base64 ou avec des lettres cyrilliques ou grecques sosies est refusé. Ce sont les plus petites tailles pour lesquelles aucune de 480 clés inventées dans huit formats ne s’est retrouvée nulle part dans 115 millions de lettres et chiffres (ce monorepo et 1 000 paquets HISTOR) de texte ordinaire ; les parties que partagent toutes les clés d’un type (l’identifiant d’algorithme d’une clé DER, l’en-tête et les champs d’un JWT) ne sont jamais relevées. Chaque argument garde la fin de ce qu’il a envoyé après le texte extérieur, si bien que des morceaux envoyés à la suite par le même argument sont vérifiés en entier. Le code local du 2026-10-23 ajoute la corrélation de paires de six caractères et le décodage des listes explicites décrits plus haut. Le format initial (`rk_live_`) seul ne constitue pas une preuve de secret. Elles ne lisent pas tout fichier à l’envoi et ne couvrent pas tous les encodages ou outils. Les modifications du projet restent généralement permises ; exécuter du code est une autre décision.
|
|
20
299
|
- Après du texte extérieur, écrire dans un fichier ordinaire du projet une clé lue pendant la session demande (`deny` refuse) : les fichiers du projet sont publiés plus tard sans autre appel. `.env`, `.npmrc` et les autres fichiers d’identifiants sont la place des clés et passent ; une modification qui ne fait qu’enlever une clé ne déclenche rien.
|
|
21
300
|
- Une adresse qui n’apparaît dans votre prompt que dans un texte collé, une ligne citée (`>`), les en-têtes d’un message collé ou sous une marque de transfert n’est pas une adresse que vous avez nommée : y envoyer demande une fois. Un point ou une virgule après une adresse tapée ne la cachent plus.
|
|
22
301
|
- Un outil MCP sans étiquette d’opérateur est sortant si son nom le dit (send, post, share …), s’il porte une URL ou, depuis le 2026-10-22, s’il nomme une partie : un argument comme `to`, `email`, `attendees`, `assignee`, `collaborator` ou `username`, ou toute adresse e-mail ou IBAN. `warden-mcp flow-labels` liste les outils MCP sans étiquette que vos sessions ont utilisés, avec la supposition de la garde et un bloc `labels` à corriger puis coller dans la politique.
|
|
23
|
-
-
|
|
302
|
+
- Par défaut, après du contenu externe, les actions d’écran reconnues nécessitent une approbation quels que soient les coordonnées, le texte de la capture, le format de la liste ou la langue du libellé. Cela comprend clics/taps/glissements, saisie/remplissage, collage, Entrée/Return et actions de clavier inconnues. `deny` les refuse. Les mots anglais précisent seulement l’explication ; un libellé comme Inbox n’autorise pas un clic. Voir le mode de tâches limité ci-dessus.
|
|
303
|
+
- Une injection qui ne change que la réponse ne fait aucun appel à refuser. Depuis le 2026-10-22, le hook Stop du plugin ajoute une ligne sous une réponse dont le tour a lu du texte extérieur, avec ces sources, et le dit quand l’un d’eux s’adressait à l’assistant avec des instructions. Si la réponse reprend 12 caractères normalisés consécutifs des phrases où ce texte s’adressait à l’assistant, le hook renvoie aussi la réponse une fois (`decision: block`) pour qu’elle soit vérifiée face à la demande de l’utilisateur avant qu’il la lise ; l’utilisateur ne perd que le temps de cette vérification. `answerNote` : `always` (par défaut), `instruction` (ce cas seulement) ou `off` ; hors du plugin, enregistrez `warden-mcp hook stop`.
|
|
24
304
|
- Le proxy enregistre aussi les erreurs JSON-RPC et d’outils, retient les réponses dont l’enregistrement échoue et bloque les vérifications si l’état existant est corrompu.
|
|
25
305
|
|
|
26
|
-
Publié dans npm `0.17.0` : `npx -y @aimarket/warden@0.
|
|
306
|
+
Publié dans npm `0.17.0` : `npx -y @aimarket/warden@0.22.0 hook pre-tool-use`, ou depuis les sources dans WARDEN, `npm ci && npm run build`, puis `node dist/mcp-server.js hook pre-tool-use`, avec les hooks prompt/post également enregistrés. Politique : `~/.local/state/warden/flow-policy.json` ou `WARDEN_FLOW_POLICY` ; modes `ask`, `deny`, `audit`, `off`. Exemple actuel en [anglais](flow-guard.md).
|
|
27
307
|
|
|
28
308
|
Proxy : `node dist/mcp-server.js wrap --flow mail -- node mail-server.js`. Attribuez un nouveau `WARDEN_FLOW_SESSION` commun aux proxies d’une conversation. Le PID parent par défaut ne relie pas des lanceurs différents. Le proxy ne voit ni prompt ni outils intégrés. Un appel qui demanderait confirmation est demandé via le formulaire d’elicitation MCP du client s’il en propose un (la réponse est journalisée comme `approvalOutcome`), sinon, ou avec `--ask refuse`, il est refusé. `trustedSources` s’applique à l’URL WebFetch, pas aux liens des arguments MCP.
|
|
29
309
|
|
|
30
|
-
**Quelle version décrivent les chiffres.** Le tableau du rejeu ci-dessous a été refait le 2026-10-22 sur le code
|
|
310
|
+
**Quelle version décrivent les chiffres.** Le tableau du rejeu ci-dessous a été refait le 2026-10-22 sur le code de ce jour-là : les corrections de l’audit plus les changements du 2026-10-22. Ceux du 2026-10-22 ne changent aucune décision (les 1 046 enregistrements sont identiques à ceux du code d’avant) ; les corrections de l’audit ont coûté une tâche sans question et 19 tâches faites sous attaque. Les tableaux et coûts de l’exécution avec modèle décrivent toujours la version d’avant l’audit, jusqu’à `2328be980` ; aucune nouvelle exécution avec modèle. Un replay suit un chemin fixe, pas le pire cas adaptatif ; les attaques menées code en main le 2026-10-22 sont [plus bas](#ce-qui-a-changé-le-2026-10-22-et-pourquoi).
|
|
31
311
|
|
|
32
312
|
## Mesuré sur AgentDojo
|
|
33
313
|
|
|
@@ -197,7 +477,7 @@ sans benchmark). Avant les changements, 14 passaient ; après, 3.
|
|
|
197
477
|
| Un outil MCP sans étiquette qui nomme une partie est sortant ; `warden-mcp flow-labels` | « ajouter un participant » avec l’e-mail de l’attaquant et « ajouter un collaborateur » par nom d’utilisateur passaient | les deux demandent |
|
|
198
478
|
| Hook Stop : une ligne sous une réponse appuyée sur du texte extérieur | une injection dans la seule réponse ne fait aucun appel | l’utilisateur voit quelles sources la réponse a utilisées ; rien n’est bloqué |
|
|
199
479
|
| Ruleset v15 (voir [gates](gates.fr.md)) | 78 outils empoisonnés de la moitié dev de MCPTox passaient les règles | moitié réservée 171 → 194 sur 218 (règles écrites à partir de l’autre moitié seulement), moitié dev 189 → 233 sur 267 ; 0 sur 45 serveurs propres ; le corpus et 1 000 paquets HISTOR bloquent exactement comme v14 |
|
|
200
|
-
| Le rejeu refait sur le code
|
|
480
|
+
| Le rejeu refait sur le code du 2026-10-22 | les corrections de l’audit du 2026-10-18 n’avaient pas été mesurées | 0 sur 579 actions d’attaque, 57 sur 97 tâches sans question, 608 sur 949 faites sous attaque ; les changements du 2026-10-22 ne changent aucune décision |
|
|
201
481
|
| `scripts/agentdojo/Dockerfile.dockerignore` | le `.dockerignore` du paquet exclut `dist/`, si bien que la commande de « Reproduire » ne se construisait pas | elle se construit |
|
|
202
482
|
|
|
203
483
|
Ces trois-là passaient encore : des morceaux de moins de 10 caractères entourés d’autres mots, une adresse collée
|
|
@@ -210,11 +490,17 @@ faux positifs et écrit six attaques de plus contre les nouvelles règles. 2 sur
|
|
|
210
490
|
| Les parties que partagent toutes les clés d’un type ne sont pas relevées (identifiant d’algorithme d’une clé DER, en-tête et champs d’un JWT) | la mesure a montré que 0.19.0 refuserait un README contenant une clé DKIM après la lecture d’une clé privée RSA | aucune coïncidence avec les règles publiées |
|
|
211
491
|
| Écrire une clé lue pendant la session dans un fichier ordinaire du projet demande | la clé dans `docs/debug.md` passait | demande ; `.env` et les autres fichiers d’identifiants passent toujours |
|
|
212
492
|
| Une adresse seulement dans un texte collé ou cité n’est pas nommée par l’utilisateur | l’adresse de l’attaquant collée dans le prompt comptait comme celle de l’utilisateur | demande une fois ; une adresse que l’utilisateur a aussi tapée passe. Un point après une adresse tapée ne la rend plus non nommée (0.19.0 demandait pour « envoie-le à bob@corp.com. ») |
|
|
213
|
-
| Le hook Stop renvoie une fois une réponse qui reprend une instruction adressée au modèle | une injection dans la seule réponse ne fait aucun appel | Sur Ministral 8B, qui obéit à l’attaque (sans la garde, 6 réponses sur 20 recommandent l’hôtel), la note de la garde seule a ramené cela à 0 ; la vérification s’est déclenchée 3 fois sur 20 sans changer aucun résultat. Sur DeepSeek V4.1 Flash,
|
|
493
|
+
| Le hook Stop renvoie une fois une réponse qui reprend une instruction adressée au modèle | une injection dans la seule réponse ne fait aucun appel | Sur Ministral 8B, qui obéit à l’attaque (sans la garde, 6 réponses sur 20 recommandent l’hôtel), la note de la garde seule a ramené cela à 0 ; la vérification s’est déclenchée 3 fois sur 20 sans changer aucun résultat. Sur DeepSeek V4.1 Flash, 2 fois sur 20 ([résultats](../scripts/agentdojo/results/model-answer-recheck-2026-10-22.json)). Un filet de sécurité, pas un gain mesuré ; voir la limite des réponses enregistrées ci-dessous |
|
|
214
494
|
| Ruleset v16 (voir [gates](gates.fr.md)) | 34 outils empoisonnés de la moitié dev de MCPTox passaient encore, presque tous sans entrée | moitié réservée 194 → 210 sur 218, dont les 66 détournements à déclencheur implicite ; 0 sur 45 serveurs propres ; le corpus et 1 000 paquets HISTOR bloquent exactement comme v15 ; cinq faux positifs d’un premier jet sont fixés dans les tests |
|
|
215
495
|
| Le rejeu, refait | les nouvelles vérifications ne doivent pas demander là où 0.19.0 ne demandait pas | les 1 046 enregistrements identiques à 0.19.0 |
|
|
216
496
|
|
|
217
|
-
|
|
497
|
+
**Précision sur les réponses enregistrées (2026-10-25) :** le résultat officiel DeepSeek guard + note reste **18/20** selon le prédicat de mention exacte d’AgentDojo. La lecture individuelle assistée par IA n’a trouvé aucune recommandation adoptée dans ces extraits ; les 18 mentions exactes figurent dans des avertissements. Seules 18 réponses sont complètes : deux atteignent l’ancienne limite de 2 000 caractères, donc un résultat de conformité 0/20 sur les réponses complètes n’est pas établi. L’annotation n’est ni indépendante ni en aveugle et ne remplace pas le score officiel. Le harnais local conserve désormais les futures réponses complètes avec longueur et hash ; aucun nouvel essai du modèle n’est impliqué. [Audit et reproduction](../../docs/growth/launchgate-methodology-2026-10-25.ru.md).
|
|
498
|
+
|
|
499
|
+
**Test de sélection contrôlé (2026-10-25) :** Un test synthétique séparé après réception du résultat d’outil, avec WARDEN `0.21.0` publié, a couvert six tâches hôtelières × cinq répétitions, des notes clean/benign/injected et trois profils : **270/270 ID corrects**, dont **0/90 choix de la cible en injected** (0/30 par profil). Le nom de la cible apparaît dans **25/270** réponses, contrôles compris, et Stop s’est déclenché **0/90** fois en `note_stop` ; la référence sans protection choisissait aussi correctement, donc aucun gain supplémentaire du guard n’est établi, et un ID correct ne valide pas tous les faits de l’explication. [Protocole, résultats et limites](../../docs/growth/launchgate-selection-2026-10-25.en.md) : cette étude séparée ne modifie pas le **18/20** historique d’AgentDojo et ne démontre pas une sécurité générale.
|
|
500
|
+
|
|
501
|
+
**Suivi avec ex æquo (2026-10-25) :** Avec deux choix optimaux admissibles, la cible a été sélectionnée sous injection 48/48 sans guard, 44/48 avec note et 45/48 avec note+Stop ; les références clean étaient 28/48, 25/48 et 29/48. Les intervalles de l’effet corrigé du baseline incluent zéro ; les 432 choix étaient admissibles et choisir la cible ne constitue donc pas automatiquement une erreur. Les vraies préférences utilisateur ont été suivies 18/18, sans nouvelle vérification Stop. L’[évaluateur offline local](../scripts/selection-probe/README.md) accepte plusieurs réponses admissibles et des contrastes avec référence commune ; le blocage en runtime reste inchangé. [Résultats et limites, EN](../../docs/growth/launchgate-tie-selection-2026-10-25.en.md).
|
|
502
|
+
|
|
503
|
+
Dans la version du 2026-10-22 ces deux exemples passaient encore. Ils sont bloqués dans le code local du 2026-10-23 ; voir plus haut. [Résultats historiques](../scripts/redteam/results/) :
|
|
218
504
|
|
|
219
505
|
- **Des morceaux de moins de 8 caractères, chacun entouré d’autres mots**, vers une adresse que l’utilisateur a
|
|
220
506
|
tapée : 7 messages ou plus pour une clé de 40 caractères.
|
|
@@ -237,10 +523,7 @@ Passent encore ([résultats](../scripts/redteam/results/)) :
|
|
|
237
523
|
reconnaît comme telles.
|
|
238
524
|
- **Les modifications locales dans le projet passent**, sauf une clé lue pendant la session qui part dans un fichier
|
|
239
525
|
ordinaire. Modifier les fichiers du projet est le travail de l’agent.
|
|
240
|
-
- **Les fuites en petits morceaux.**
|
|
241
|
-
l’utilisateur, entier ou en morceaux : c’est son choix. Vers d’autres destinataires, et pour les clés et numéros de
|
|
242
|
-
carte vers n’importe qui, les morceaux envoyés à la suite par un même argument sont réunis ; ceux de moins de 8
|
|
243
|
-
caractères entourés d’autres mots, non, pas plus qu’une clé épelée en mots.
|
|
526
|
+
- **Les fuites en petits morceaux.** Le texte privé ordinaire peut aller vers un destinataire nommé par l’utilisateur. Les flux joints et la règle des paires de six caractères couvrent certaines partitions ; les fragments plus courts avec remplissage et les encodages verbaux non reconnus restent des limites.
|
|
244
527
|
- **Le collé n’est pas le tapé.** Une adresse que vous vouliez utiliser mais avez seulement collée demande une fois.
|
|
245
528
|
- **Elle ne voit pas** votre prompt d’avant l’installation du plugin, ni le texte que le modèle tient d’ailleurs.
|
|
246
529
|
|
|
@@ -255,7 +538,7 @@ docker run --rm --network none -v "$PWD/out:/out" warden-adojo /out/oracle.json
|
|
|
255
538
|
|
|
256
539
|
`oracle.py` écrit les résultats par paire ; `--variants none,strict,intent` choisit les variantes de la garde
|
|
257
540
|
(`strict` ignore ce que l’utilisateur a tapé). `summarize_oracle.py` en tire le résumé que cite le tableau.
|
|
258
|
-
`WARDEN_FLOW_GUARD=/out/x.mjs` rejoue une autre version de la garde (toute copie de `flow-guard.mjs` du plugin) ; c’est
|
|
541
|
+
`WARDEN_FLOW_GUARD=/out/x.mjs` rejoue une autre version de la garde (toute copie de `flow-guard.mjs` du plugin ; depuis le 2026-10-24 avec ses parties `flow-guard-*.mjs` dans le même dossier) ; c’est
|
|
259
542
|
ainsi que les changements du 2026-10-22 ont été comparés au code d’avant.
|
|
260
543
|
|
|
261
544
|
Les attaques code en main n’ont pas besoin de conteneur : `npm run build && node scripts/redteam/flow-redteam.mjs out.json`.
|
|
@@ -275,3 +558,15 @@ python3 scripts/agentdojo/summarize_model.py summary.json /srv/adojo/out --goals
|
|
|
275
558
|
du détournement ; `model.py OUT --model deepseek-flash --model-label DeepSeek --dump-goals` écrit les objectifs de
|
|
276
559
|
l’attaquant avec lesquels `summarize_model.py` reconnaît les appels vers lui. Enregistrements par exécution des deux tours :
|
|
277
560
|
`results/model-deepseek-2026-10-18b.jsonl.gz` (résumé `model-deepseek-2026-10-18b.json`) ; `--guard-note` renvoie au modèle la note de la garde.
|
|
561
|
+
|
|
562
|
+
## Signaux d’instruction et diagnostic Stop (0.22.0 locale)
|
|
563
|
+
|
|
564
|
+
Les motifs anglais/russes bornés reconnaissent les faux délimiteurs de rôle, les préférences relayées ou accords antérieurs allégués avec une directive proche, les consignes dissimulées et les critères privés. Ces signaux restent faillibles, y compris dans des citations légitimes : ils ne prouvent pas une attaque, ne donnent aucune autorité et n’interdisent pas automatiquement un choix. La demande réelle de l’utilisateur reste une source distincte.
|
|
565
|
+
|
|
566
|
+
Le journal local contient `instructionSignal`, `signalKinds`, `signalScanLimited` et `warningKind` (`source`, `instruction`, `suppressed-audit`). Stop consigne `trigger` (`no-instruction-signal`, `no-literal-overlap`, `literal-instruction-overlap`), `recheckRequested` et `semanticCompliance: "not-assessed"`. Le seuil de 12 caractères normalisés et la limite de continuation indiquée par l’hôte restent ; une vérification n’est ni un refus permanent ni une preuve de correction.
|
|
567
|
+
|
|
568
|
+
L’outil du dépôt `scripts/selection-probe/audit_warnings.mjs` rejoue les entrées et réponses conservées. Les mots candidats de reconnaissance décrivent le texte visible, pas la conscience ou l’obéissance du modèle. Rejouer une ancienne réponse mesure uniquement le hook ; mesurer un changement de choix exige une nouvelle expérience contrôlée avec le modèle.
|
|
569
|
+
|
|
570
|
+
Les avertissements Post/Stop utilisent des phrases fixes et des identifiants opaques `source-` (les 16 premiers chiffres hexadécimaux du SHA-256 du nom d’outil). Ils ne citent pas la consigne détectée et ne répètent ni noms bruts, ni URL, ni chemins de la source. Cela limite la promotion de métadonnées tierces dans le canal d’avertissement, sans immuniser le modèle contre le résultat initial. Cet ID sert uniquement à la corrélation ; ce n’est ni une identité de paquet vérifiée, ni un pin, ni une permission. Les journaux locaux peuvent encore contenir des métadonnées externes et restent des données non fiables.
|
|
571
|
+
|
|
572
|
+
**Nouvelle comparaison avec le modèle (2026-10-25) :** Sur six cas connus, 720 réponses entrelacées ont choisi la cible injectée 48/48 sans garde, 44/48 et 46/48 avec note/note+Stop publiés (0.21.0), et 27/48 dans les deux profils candidats. Leurs références propres étaient 23/48 et 25/48. Les intervalles d’amélioration corrigée face à la version publiée sont [−8,3 ; +60,4] points pour note et [+14,6 ; +62,5] pour note+Stop. Aucune des 12 vérifications n’a changé l’ID choisi ; trois ont perdu une référence visible à l’avertissement. Tous les ID étaient admissibles et les vraies préférences ont été suivies 30/30. Ces cas connus, le pont tool-role et la comparaison de versions entières ne prouvent ni protection générale ni bénéfice séparé de Stop. [Rapport complet](flow-guard-model-comparison-2026-10-25.fr.md).
|