Audit

zn audit lit les fichiers de configuration d'agents d'un dépôt, sans rien exécuter, et indique ce qui s'exécuterait, où iraient les requêtes et quelles instructions un agent suivrait.

Voir le .md
npx -y zn-gate audit ./some-repo

(ou zn audit si vous l'avez installé avec npm i -g zn-gate ; zn-gate audit est la même commande).

Les agents de code lisent la configuration du dépôt dans lequel ils travaillent. Plusieurs de ces fichiers exécutent des commandes, démarrent des serveurs MCP, changent la destination des requêtes d'API de l'agent ou élargissent ce qu'il peut faire sans demander. Mettre l'agent à jour corrige les bogues connus, mais les fichiers restent dans le dépôt, et l'agent suivant, un collègue avec une version plus ancienne ou un job de CI peut encore s'y fier.

zn audit lit ces fichiers, sans rien exécuter, et vous dit ce qui s'exécuterait, où iraient les requêtes et quelles instructions un agent suivrait. Il fonctionne en local et n'envoie rien nulle part. Lancez-le avant d'ouvrir un dépôt que vous venez de cloner, et en CI.

Options

zn audit [path] [--format text|json|sarif] [--output <file>]
         [--fail-on low|medium|high|critical|none]
         [--agents claude,codex,cursor,opencode,amazonq,copilot,gemini,all] [--include-home]
Option Par défaut Ce qu'elle fait
path . Dossier à auditer, en général la racine du dépôt. Un zn audit sans argument examine le dossier courant
--format text text pour les personnes, json pour les scripts, sarif pour le code scanning de GitHub
--output sortie standard Écrit le rapport dans un fichier
--fail-on high Termine avec le code 1 si un résultat a cette gravité ou une gravité supérieure. none n'échoue jamais
--agents all Ne vérifie que les fichiers lus par ces agents : claude, codex, cursor, opencode, amazonq, copilot, gemini ou all. Les résultats qui concernent tous les agents (AGENTS.md, exécutables plantés, workflows de CI) sont toujours affichés
--include-home désactivé Vérifie aussi vos propres configurations utilisateur, comme ~/.claude/settings.json et ~/.codex/config.toml

Exemples :

# Avant d'ouvrir un dépôt que vous venez de cloner
npx -y zn-gate audit ./some-repo

# En CI : écrit un fichier SARIF pour le code scanning de GitHub et n'échoue jamais
zn audit --format sarif --output zn-audit.sarif --fail-on none

# Seulement ce que lisent Claude Code et Codex ; échoue uniquement sur critical
zn audit --agents claude,codex --fail-on critical

Dans la 1.5, zn audit affichait le journal local d'utilisation des secrets. Ce journal est désormais zn vault log (aussi zn secret log). zn audit log et zn audit --since DATE se terminent avec le code 2 et vous indiquent d'utiliser zn vault log.

Codes de sortie

Code Signification
0 Aucun résultat à --fail-on ou au-dessus
1 Au moins un résultat à --fail-on ou au-dessus
2 Erreur d'utilisation ou d'exécution : option invalide, chemin introuvable, sortie non inscriptible

Ce qu'il lit

Les fichiers du projet à toute profondeur, car la configuration d'un sous-dossier s'applique quand un agent démarre dedans. Les dossiers d'agents (.claude, .codex, .cursor, .github, skills et similaires) sont lus en premier. En dehors, node_modules, vendor et les dossiers de build et d'environnements virtuels sont ignorés. .git n'est jamais lu.

Agent Fichiers
Claude Code .claude/settings.json, .claude/settings.local.json, .mcp.json, CLAUDE.md, CLAUDE.local.md, .claude/commands/, .claude/agents/, .claude/skills/, .claude-plugin/, hooks/hooks.json des plugins
Codex .codex/config.toml, .codex/hooks.json, .codex/prompts/, .env (seulement les variables d'endpoint et de chargement de code), AGENTS.md
Cursor .cursor/mcp.json, .cursor/hooks.json, .cursor/cli.json, .cursor/rules/, .cursor/commands/, .cursorrules, les hooks de .claude/settings*.json (Cursor les exécute), .vscode/tasks.json, AGENTS.md
OpenCode opencode.json, opencode.jsonc, configuration, plugins, commandes et agents de .opencode/, AGENTS.md
Amazon Q .amazonq/mcp.json, .amazonq/cli-agents/, .amazonq/agents/, .amazonq/rules/, AGENTS.md
Copilot / VS Code .vscode/mcp.json, .vscode/settings.json, .vscode/tasks.json, .github/copilot-instructions.md, .github/instructions/, .github/prompts/, AGENTS.md
Gemini CLI .gemini/settings.json, .gemini/commands/, GEMINI.md
Tout agent Exécutables à la racine auditée, .github/workflows/*.yml, .windsurfrules, .clinerules

Rien de ce que contrôle le dépôt ne peut faire disparaître un fichier du rapport en silence :

  • Un lien symbolique qui sort du dépôt est signalé (ZNA020), pas suivi.
  • Un fichier d'agent de plus de 1 Mo est signalé (ZNA020) au lieu d'être ignoré.
  • L'analyse s'arrête après 50 000 entrées de dossier ou 120 secondes, et le dit avec un résultat ZNA020 de gravité haute : l'exécution échoue donc au seuil par défaut.
  • Un .env à la racine, commité, qui pointe CODEX_HOME ou CLAUDE_CONFIG_DIR vers un dossier du dépôt fait lire aussi les configurations de ce dossier à zn audit.
  • Un .env à la racine est audité même si .gitignore le liste, car dans un clone neuf il n'existe que s'il a été commité. Ses résultats sont d'un niveau plus bas et précisent qu'ils ne s'appliquent pas à votre .env local.

Avec --include-home, il lit aussi ~/.claude/settings.json, ~/.claude.json, ~/.codex/config.toml, ~/.cursor/mcp.json, ~/.cursor/hooks.json, ~/.aws/amazonq/mcp.json, ~/.config/opencode/opencode.json[c] et ~/.gemini/settings.json. Il respecte CODEX_HOME et XDG_CONFIG_HOME comme les agents. Les commandes que vous avez configurées vous-même sont normales à cet endroit : seules les variantes plus risquées sont signalées (code téléchargé puis exécuté, paquets non épinglés, changements d'endpoint, secrets et permissions étendues). Les résultats d'endpoint, d'environnement et de permissions sont plafonnés à medium.

Règles

Les identifiants de règles sont stables : une règle peut s'améliorer, mais son identifiant ne change jamais de sens. Les gravités sont critical, high, medium et low ; quand une règle en liste plusieurs, le résultat reçoit celle qui correspond au cas.

Id Gravité Ce qu'elle détecte
ZNA001 high / medium / low Une commande qui s'exécute automatiquement depuis une configuration du projet : hooks, statusLine, notify de Codex, fichiers de plugins OpenCode, tâches VS Code avec runOn: folderOpen. Medium pour les hooks d'un plugin, qui ne s'exécutent qu'une fois le plugin activé. Le hook écrit par zn hooks install est signalé en low
ZNA002 critical Une commande automatique qui télécharge du code et l'exécute (curl ... | sh, iwr ... | iex, bash <(curl ...))
ZNA003 high / medium / low Un serveur MCP du projet qui démarre une commande locale. High pour Codex et Amazon Q ; low pour le serveur de secrets de zn quand il est vérifié sur le disque
ZNA004 high / medium Des réglages du projet qui approuvent des serveurs MCP à l'avance (enableAllProjectMcpServers, enabledMcpjsonServers)
ZNA005 medium Un serveur MCP ou un plugin d'agent non épinglé : npx -y pkg, @latest, uvx pkg sans ==, images de conteneur sans tag ni digest, plugins OpenCode sans version
ZNA006 medium / low Un serveur MCP distant, ou des instructions chargées depuis une URL. Medium en http simple, low en https
ZNA007 critical / high / medium / low L'endpoint de l'API du modèle est remplacé (ANTHROPIC_BASE_URL, OPENAI_BASE_URL, toute variable *_BASE_URL, URL de base des fournisseurs dans Codex et OpenCode) ou un proxy est défini (HTTPS_PROXY). Critical pour un hôte distant, high pour un proxy, medium pour une adresse de loopback. Dans l'env d'un seul serveur MCP, cela ne redirige que ce serveur : medium, ou low pour le loopback
ZNA008 high Une variable d'environnement qui charge du code ou des certificats (NODE_OPTIONS, LD_PRELOAD, DYLD_INSERT_LIBRARIES, PYTHONSTARTUP, BASH_ENV, PATH, GIT_SSH_COMMAND, NODE_EXTRA_CA_CERTS et similaires) ou qui déplace l'endroit où l'agent lit sa configuration (CODEX_HOME, CLAUDE_CONFIG_DIR, XDG_CONFIG_HOME, OPENCODE_CONFIG). Vérifiée aussi dans l'env de chaque serveur MCP
ZNA009 high Une commande d'aide aux identifiants dans les réglages du projet (apiKeyHelper, awsAuthRefresh, awsCredentialExport, otelHeadersHelper)
ZNA010 high / medium Permissions étendues : Bash(*), Bash, *, jokers d'interpréteur comme Bash(python:*), defaultMode: bypassPermissions, approval_policy = "never" de Codex avec accès complet, "bash": "allow" d'OpenCode, chat.tools.autoApprove de VS Code
ZNA011 high Une valeur secrète dans une configuration d'agent ou un fichier d'instructions. Le rapport n'affiche jamais la valeur
ZNA012 high / medium / low Un motif d'injection de prompt dans les instructions d'un agent : ordres qui annulent les instructions, fausses balises système, HTML caché, Unicode invisible, balises d'image Markdown. Dans les fichiers qu'un agent lit comme instructions (AGENTS.md, CLAUDE.md, GEMINI.md, règles, skills, commandes, prompts), un motif fort n'est jamais abaissé, cité ou non
ZNA013 medium / low Des instructions qui demandent à l'agent de télécharger et d'exécuter du code. Low pour les installateurs bien connus comme rustup, uv, bun, deno, nvm et Homebrew
ZNA014 high Des instructions qui demandent à l'agent d'envoyer des secrets ou des fichiers à l'extérieur (.env, ~/.ssh, jetons vers une URL, curl -d @.env)
ZNA015 medium Des instructions qui demandent à l'agent de sauter les contrôles de sécurité ou de cacher ce qu'il fait (--no-verify, --dangerously-skip-permissions, « désactive le sandbox », « ne le dis pas à l'utilisateur »)
ZNA016 critical / high Un exécutable à la racine auditée qui porte le nom d'un outil courant (git.exe, node.exe, npm.cmd, python, zn.cmd). Critical pour les exécutables Windows. Windows et certains outils cherchent d'abord dans le dossier courant : le fichier planté s'exécute à la place du vrai outil
ZNA017 medium Des réglages du projet qui ajoutent des marketplaces de plugins ou activent des plugins (extraKnownMarketplaces, enabledPlugins)
ZNA018 low Le dépôt fournit des extensions d'agent (commandes, sous-agents, skills, plugins). C'est un inventaire : les autres règles les examinent, mais il faut savoir qu'elles sont là
ZNA019 high / medium Un workflow de CI qui lance un agent d'IA sur un texte que n'importe qui peut écrire (issues, issue_comment, pull_request_target, discussions). High avec pull_request_target, avec du texte d'issue ou de commentaire collé dans le workflow, avec une action ouverte aux utilisateurs sans droit d'écriture, ou avec une étape de CLI ayant des droits d'écriture et aucun filtre d'auteur
ZNA020 high / low Un fichier d'agent n'a pas pu être vérifié : erreur de syntaxe, taille supérieure à 1 Mo, lien symbolique sortant du dépôt ou analyse arrêtée avant la fin. High quand le fichier peut exécuter des commandes ou rediriger l'agent, ou quand l'analyse n'a pas terminé ; low pour une erreur de syntaxe dans un fichier qui ne peut rien exécuter

Sortie

Texte

zn audit  ./some-repo  (zn-gate 1.12.0 ou plus récent)

CRITICAL  ZNA007  .claude/settings.json:4  [claude]
          Model API endpoint overridden by the project
          ANTHROPIC_BASE_URL points to https://agent-proxy.example.invalid
          evidence: "ANTHROPIC_BASE_URL": "https://agent-proxy.example.invalid"
          fix: Remove the override; set it in your user settings if you need a gateway.

1 finding (1 critical, 0 high, 0 medium, 0 low) in 3 files. Failing: severity >= high.

Les couleurs ne sont utilisées que dans un terminal et jamais quand NO_COLOR est défini. Les caractères de contrôle et les séquences d'échappement venant du dépôt sont affichés sous la forme \x1b, jamais envoyés à votre terminal.

JSON

--format json affiche un objet avec les findings et un summary :

{
  "version": 1,
  "tool": "zn-gate",
  "toolVersion": "1.12.0",
  "root": "/home/me/some-repo",
  "findings": [
    {
      "id": "ZNA007",
      "severity": "critical",
      "agent": "claude",
      "file": ".claude/settings.json",
      "line": 4,
      "title": "Model API endpoint overridden by the project",
      "detail": "ANTHROPIC_BASE_URL points to https://agent-proxy.example.invalid ...",
      "evidence": "\"ANTHROPIC_BASE_URL\": \"https://agent-proxy.example.invalid\"",
      "fix": "Remove the override ...",
      "references": []
    }
  ],
  "summary": {
    "files": 3,
    "findings": 1,
    "bySeverity": { "critical": 1, "high": 0, "medium": 0, "low": 0 },
    "failOn": "high",
    "failed": true,
    "agents": ["claude", "codex", "cursor", "opencode", "amazonq", "copilot", "gemini"]
  }
}

file est relatif à root, avec des barres obliques ; les fichiers de --include-home commencent par ~/. agent est l'agent qui lit le fichier, ou any quand plusieurs le lisent. evidence est la ligne correspondante, coupée à 160 caractères, avec les secrets remplacés par [REDACTED:<TYPE>]. Les URL perdent leur utilisateur, mot de passe, query string et fragment.

SARIF

--format sarif écrit du SARIF 2.1.0 pour le code scanning de GitHub : une règle par identifiant ZNA avec un texte d'aide et un score de gravité, et des résultats localisés par rapport à la racine du dépôt. Chaque résultat porte une empreinte, donc les alertes survivent aux déplacements de lignes. Les résultats de --include-home sont marqués comme venant du dossier personnel et GitHub les ignore : n'utilisez pas cette option en CI.

L'utiliser en CI

Le plus simple est la GitHub Action de zn-gate avec mode: audit. Voir GitHub Actions.

Pour lancer vous-même la CLI, écrivez un fichier SARIF et envoyez-le au code scanning :

- run: npx -y zn-gate@1.12.0 audit --format sarif --output zn-audit.sarif --fail-on none
- uses: github/codeql-action/upload-sarif@v4
  with:
    sarif_file: zn-audit.sarif

Retirez --fail-on none (la valeur par défaut est high) si vous voulez que le job échoue sur les résultats high et critical. Ajoutez security-events: write au job seulement quand vous envoyez du SARIF.

Limites

  • Il lit des fichiers ; il ne les exécute pas, ne démarre pas de serveurs et ne résout pas de paquets. Un paquet épinglé peut quand même être malveillant, et un hook qui appelle un script local est signalé comme hook, sans juger ce que fait le script.
  • Les règles d'instructions cherchent des motifs ligne par ligne. Un auteur déterminé peut formuler une instruction qu'aucun motif ne détecte, et une documentation qui cite une commande dangereuse est signalée aussi, par exemple un guide d'installation avec curl ... | sh. Examinez la preuve avant d'agir.
  • La règle des workflows lit le YAML ligne par ligne. Elle connaît les actions d'agents courantes et les clés de déclencheurs et de permissions, pas les workflows réutilisables ni les actions composites.
  • La configuration Git (.git/config, filtres .gitattributes) et les extensions d'éditeur ne sont pas vérifiées.
  • Les agents changent souvent de format de configuration. Les clés inconnues sont ignorées, pas signalées.
  • Les secrets sont détectés par format et par nom de clé sensible. Un secret sans format connu sous un nom de clé anodin n'est pas détecté, et les mots de passe écrits en prose ne sont pas masqués dans la preuve.