Auditoria

O zn audit lê os arquivos de configuração de agentes de um repositório, sem executar nada, e informa o que seria executado, para onde iriam as requisições e quais instruções um agente seguiria.

Ver .md
npx -y zn-gate audit ./some-repo

(ou zn audit se você instalou com npm i -g zn-gate; zn-gate audit é o mesmo comando).

Os agentes de código leem configuração do repositório em que trabalham. Vários desses arquivos executam comandos, iniciam servidores MCP, mudam para onde o agente envia suas requisições à API ou ampliam o que ele pode fazer sem perguntar. Atualizar o agente corrige os bugs conhecidos, mas os arquivos continuam no repositório, e o próximo agente, um colega com uma versão mais antiga ou um job de CI ainda pode agir com base neles.

O zn audit lê esses arquivos, sem executar nada, e diz o que seria executado, para onde iriam as requisições e quais instruções um agente seguiria. Ele roda localmente e não envia nada a lugar nenhum. Execute-o antes de abrir um repositório que você acabou de clonar, e no CI.

Opções

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]
Opção Padrão O que faz
path . Diretório a auditar, normalmente a raiz do repositório. Um zn audit sem argumentos examina o diretório atual
--format text text para pessoas, json para scripts, sarif para o code scanning do GitHub
--output saída padrão Grava o relatório em um arquivo
--fail-on high Termina com código 1 se algum achado tiver esta gravidade ou uma maior. none nunca falha
--agents all Verifica apenas os arquivos lidos por estes agentes: claude, codex, cursor, opencode, amazonq, copilot, gemini ou all. Os achados que afetam todos os agentes (AGENTS.md, executáveis plantados, workflows de CI) são sempre exibidos
--include-home desligado Verifica também as suas próprias configurações de usuário, como ~/.claude/settings.json e ~/.codex/config.toml

Exemplos:

# Antes de abrir um repositório que você acabou de clonar
npx -y zn-gate audit ./some-repo

# No CI: grava um arquivo SARIF para o code scanning do GitHub e nunca falha
zn audit --format sarif --output zn-audit.sarif --fail-on none

# Só o que o Claude Code e o Codex leem; falha apenas em critical
zn audit --agents claude,codex --fail-on critical

Na 1.5, o zn audit mostrava o registro local de uso de segredos. Esse registro agora é zn vault log (também zn secret log). zn audit log e zn audit --since DATE terminam com código 2 e dizem para usar zn vault log.

Códigos de saída

Código Significado
0 Nenhum achado em --fail-on ou acima
1 Pelo menos um achado em --fail-on ou acima
2 Erro de uso ou de execução: opção inválida, caminho não encontrado, saída não gravável

O que ele lê

Arquivos do projeto em qualquer profundidade, porque a configuração de um subdiretório vale quando um agente inicia ali. As pastas de agentes (.claude, .codex, .cursor, .github, skills e semelhantes) são lidas primeiro. Fora delas, node_modules, vendor e as pastas de build e de ambientes virtuais são ignoradas. O .git nunca é lido.

Agente Arquivos
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 dos plugins
Codex .codex/config.toml, .codex/hooks.json, .codex/prompts/, .env (somente as variáveis de endpoint e de carregamento de código), AGENTS.md
Cursor .cursor/mcp.json, .cursor/hooks.json, .cursor/cli.json, .cursor/rules/, .cursor/commands/, .cursorrules, os hooks de .claude/settings*.json (o Cursor os executa), .vscode/tasks.json, AGENTS.md
OpenCode opencode.json, opencode.jsonc, configuração, plugins, comandos e agentes 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
Qualquer agente Executáveis na raiz auditada, .github/workflows/*.yml, .windsurfrules, .clinerules

Nada do que o repositório controla pode fazer um arquivo sumir do relatório em silêncio:

  • Um link simbólico que sai do repositório é reportado (ZNA020), não seguido.
  • Um arquivo de agente maior que 1 MB é reportado (ZNA020) em vez de ignorado.
  • A verificação para após 50.000 entradas de diretório ou 120 segundos, e avisa com um achado ZNA020 de gravidade alta, então a execução falha no limite padrão.
  • Um .env na raiz, commitado, que aponta CODEX_HOME ou CLAUDE_CONFIG_DIR para uma pasta dentro do repositório faz o zn audit ler também as configurações dessa pasta.
  • Um .env na raiz é auditado mesmo que o .gitignore o liste, porque num clone novo ele só existe se foi commitado. Os achados dele ficam um nível abaixo e dizem que não se aplicam ao seu .env local.

Com --include-home, ele lê também ~/.claude/settings.json, ~/.claude.json, ~/.codex/config.toml, ~/.cursor/mcp.json, ~/.cursor/hooks.json, ~/.aws/amazonq/mcp.json, ~/.config/opencode/opencode.json[c] e ~/.gemini/settings.json. Ele respeita CODEX_HOME e XDG_CONFIG_HOME como os agentes. Os comandos que você mesmo configurou são esperados ali, então só as variantes mais arriscadas são reportadas: código baixado e executado, pacotes sem versão fixa, mudanças de endpoint, segredos e permissões amplas. Os achados de endpoint, ambiente e permissões ficam limitados a medium.

Regras

Os ids das regras são estáveis: uma regra pode melhorar, mas o id nunca muda de significado. As gravidades são critical, high, medium e low; quando uma regra lista várias, o achado recebe a que corresponde ao caso.

Id Gravidade O que detecta
ZNA001 high / medium / low Um comando que roda automaticamente a partir de uma configuração do projeto: hooks, statusLine, notify do Codex, arquivos de plugin do OpenCode, tarefas do VS Code com runOn: folderOpen. Medium para hooks de um plugin, que só rodam depois que o plugin é ativado. O hook que o zn hooks install grava é reportado como low
ZNA002 critical Um comando automático que baixa código e o executa (curl ... | sh, iwr ... | iex, bash <(curl ...))
ZNA003 high / medium / low Um servidor MCP do projeto que inicia um comando local. High para Codex e Amazon Q; low para o servidor de segredos do próprio zn quando verificado em disco
ZNA004 high / medium Configurações do projeto que aprovam servidores MCP antecipadamente (enableAllProjectMcpServers, enabledMcpjsonServers)
ZNA005 medium Um servidor MCP ou plugin de agente sem versão fixa: npx -y pkg, @latest, uvx pkg sem ==, imagens de contêiner sem tag nem digest, plugins do OpenCode sem versão
ZNA006 medium / low Um servidor MCP remoto, ou instruções carregadas de uma URL. Medium com http simples, low com https
ZNA007 critical / high / medium / low O endpoint da API do modelo é substituído (ANTHROPIC_BASE_URL, OPENAI_BASE_URL, qualquer *_BASE_URL, URLs base de provedores no Codex e no OpenCode) ou um proxy é definido (HTTPS_PROXY). Critical para um host remoto, high para um proxy, medium para um endereço de loopback. No env de um único servidor MCP, redireciona só aquele servidor: medium, ou low para loopback
ZNA008 high Uma variável de ambiente que carrega código ou certificados (NODE_OPTIONS, LD_PRELOAD, DYLD_INSERT_LIBRARIES, PYTHONSTARTUP, BASH_ENV, PATH, GIT_SSH_COMMAND, NODE_EXTRA_CA_CERTS e semelhantes) ou que muda onde o agente lê sua configuração (CODEX_HOME, CLAUDE_CONFIG_DIR, XDG_CONFIG_HOME, OPENCODE_CONFIG). Também verificada no env de cada servidor MCP
ZNA009 high Um comando auxiliar de credenciais nas configurações do projeto (apiKeyHelper, awsAuthRefresh, awsCredentialExport, otelHeadersHelper)
ZNA010 high / medium Permissões amplas: Bash(*), Bash, *, curingas de interpretador como Bash(python:*), defaultMode: bypassPermissions, approval_policy = "never" do Codex com acesso total, "bash": "allow" do OpenCode, chat.tools.autoApprove do VS Code
ZNA011 high Um valor secreto numa configuração de agente ou num arquivo de instruções. O relatório nunca imprime o valor
ZNA012 high / medium / low Um padrão de injeção de prompt nas instruções de um agente: ordens que anulam instruções, tags de sistema falsas, HTML oculto, Unicode invisível, beacons de imagem em Markdown. Nos arquivos que um agente lê como instruções (AGENTS.md, CLAUDE.md, GEMINI.md, regras, skills, comandos, prompts), um padrão forte nunca é rebaixado, citado ou não
ZNA013 medium / low Instruções que mandam o agente baixar e executar código. Low para instaladores conhecidos como rustup, uv, bun, deno, nvm e Homebrew
ZNA014 high Instruções que mandam o agente enviar segredos ou arquivos para fora (.env, ~/.ssh, tokens para uma URL, curl -d @.env)
ZNA015 medium Instruções que mandam o agente pular verificações de segurança ou esconder o que faz (--no-verify, --dangerously-skip-permissions, "desative o sandbox", "não conte ao usuário")
ZNA016 critical / high Um executável na raiz auditada com o mesmo nome de uma ferramenta comum (git.exe, node.exe, npm.cmd, python, zn.cmd). Critical para executáveis do Windows. O Windows e algumas ferramentas procuram primeiro na pasta atual, então o arquivo plantado roda no lugar da ferramenta real
ZNA017 medium Configurações do projeto que adicionam marketplaces de plugins ou ativam plugins (extraKnownMarketplaces, enabledPlugins)
ZNA018 low O repositório traz extensões de agente (comandos, subagentes, skills, plugins). É um inventário: as outras regras as examinam, mas convém saber que estão ali
ZNA019 high / medium Um workflow de CI que executa um agente de IA com texto que qualquer pessoa pode escrever (issues, issue_comment, pull_request_target, discussions). High com pull_request_target, com texto de issue ou comentário colado no workflow, com uma action aberta a usuários sem permissão de escrita, ou com um passo de CLI com permissões de escrita e sem filtro de autor
ZNA020 high / low Um arquivo de agente não pôde ser verificado: erro de sintaxe, tamanho acima de 1 MB, link simbólico que sai do repositório ou verificação interrompida antes do fim. High quando o arquivo pode executar comandos ou redirecionar o agente, ou quando a verificação não terminou; low para erro de sintaxe num arquivo que não pode executar nada

Saída

Texto

zn audit  ./some-repo  (zn-gate 1.12.0 ou posterior)

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.

As cores só são usadas num terminal e nunca com NO_COLOR definido. Caracteres de controle e sequências de escape vindos do repositório são impressos como \x1b, nunca enviados ao seu terminal.

JSON

--format json imprime um objeto com os findings e um 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 é relativo a root, com barras normais; os arquivos de --include-home começam com ~/. agent é o agente que lê o arquivo, ou any quando vários o leem. evidence é a linha correspondente, cortada em 160 caracteres, com os segredos trocados por [REDACTED:<TYPE>]. As URLs perdem usuário, senha, query string e fragmento.

SARIF

--format sarif grava SARIF 2.1.0 para o code scanning do GitHub: uma regra por id ZNA com texto de ajuda e uma pontuação de gravidade, e resultados localizados em relação à raiz do repositório. Cada resultado tem uma impressão digital, então os alertas sobrevivem a mudanças de linha. Os achados de --include-home são marcados como vindos da pasta pessoal e o GitHub os ignora, então não use essa opção no CI.

Use no CI

O mais simples é a GitHub Action do zn-gate com mode: audit. Veja GitHub Actions.

Para rodar a CLI você mesmo, grave um arquivo SARIF e envie-o ao 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

Retire --fail-on none (o padrão é high) se quiser que o job falhe em achados high e critical. Adicione security-events: write ao job só quando enviar SARIF.

Limites

  • Ele lê arquivos; não os executa, não inicia servidores nem resolve pacotes. Um pacote com versão fixa ainda pode ser malicioso, e um hook que chama um script local é reportado como hook, sem julgar o que o script faz.
  • As regras de instruções procuram padrões linha a linha. Um autor determinado pode redigir uma instrução que nenhum padrão detecte, e a documentação que cita um comando perigoso também é reportada, por exemplo um guia de instalação com curl ... | sh. Revise a evidência antes de agir.
  • A regra de workflows lê o YAML linha a linha. Ela conhece as actions de agentes comuns e as chaves de gatilhos e permissões, não workflows reutilizáveis nem actions compostas.
  • A configuração do Git (.git/config, filtros do .gitattributes) e as extensões de editor não são verificadas.
  • Os agentes mudam seus formatos de configuração com frequência. Chaves desconhecidas são ignoradas, não reportadas.
  • Os segredos são encontrados por formato e por nome de chave sensível. Um segredo sem formato conhecido sob um nome de chave inocente não é encontrado, e senhas escritas em prosa não são ocultadas na evidência.