Audit

zn audit reads the agent configuration files of a repository, without running anything, and reports what would run, where requests would go and which instructions an agent would follow.

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

(or zn audit if you installed it with npm i -g zn-gate; zn-gate audit is the same command).

Coding agents read configuration from the repository they work in. Several of those files run commands, start MCP servers, change where the agent sends its API requests or widen what it may do without asking. Updating the agent fixes known bugs, but the files stay in the repository, and the next agent, a team member on an older version or a CI job may still act on them.

zn audit reads those files, without running anything, and tells you what would run, where requests would go and which instructions an agent would follow. It runs locally and sends nothing anywhere. Run it before you open a repository you just cloned, and in 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 Default What it does
path . Directory to audit, usually the repository root. A bare zn audit reviews the current directory
--format text text for people, json for scripts, sarif for GitHub code scanning
--output standard output Writes the report to a file
--fail-on high Exits with 1 if any finding has this severity or a higher one. none never fails
--agents all Checks only the files these agents read: claude, codex, cursor, opencode, amazonq, copilot, gemini or all. Findings that concern every agent (AGENTS.md, planted executables, CI workflows) are always shown
--include-home off Also checks your own user-level configs, such as ~/.claude/settings.json and ~/.codex/config.toml

Examples:

# Before opening a repository you just cloned
npx -y zn-gate audit ./some-repo

# In CI: write a SARIF file for GitHub code scanning and never fail the job
zn audit --format sarif --output zn-audit.sarif --fail-on none

# Only what Claude Code and Codex read; fail on critical only
zn audit --agents claude,codex --fail-on critical

In 1.5 zn audit showed the local log of secret use. That log is now zn vault log (also zn secret log). zn audit log and zn audit --since DATE exit with code 2 and tell you to use zn vault log.

Exit codes

Code Meaning
0 No finding at or above --fail-on
1 At least one finding at or above --fail-on
2 Usage or runtime error: bad option, path not found, output not writable

What it reads

Project files at any depth, because the configuration of a subdirectory applies when an agent starts there. Agent folders (.claude, .codex, .cursor, .github, skills and similar) are read first. Outside them, node_modules, vendor, build and virtual-environment folders are skipped. .git is never read.

Agent Files
Claude Code .claude/settings.json, .claude/settings.local.json, .mcp.json, CLAUDE.md, CLAUDE.local.md, .claude/commands/, .claude/agents/, .claude/skills/, .claude-plugin/, plugin hooks/hooks.json
Codex .codex/config.toml, .codex/hooks.json, .codex/prompts/, .env (only endpoint and code-loading variables), AGENTS.md
Cursor .cursor/mcp.json, .cursor/hooks.json, .cursor/cli.json, .cursor/rules/, .cursor/commands/, .cursorrules, the hooks in .claude/settings*.json (Cursor runs them), .vscode/tasks.json, AGENTS.md
OpenCode opencode.json, opencode.jsonc, .opencode/ config, plugins, commands and agents, 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
Any agent Executables in the audited root, .github/workflows/*.yml, .windsurfrules, .clinerules

Nothing the repository controls can make a file disappear from the report silently:

  • A symbolic link that leaves the repository is reported (ZNA020), not followed.
  • An agent file over 1 MB is reported (ZNA020) instead of skipped.
  • The scan stops after 50,000 directory entries or 120 seconds, and says so with a ZNA020 high finding, so the run fails at the default threshold.
  • A committed root .env that sets CODEX_HOME or CLAUDE_CONFIG_DIR to a folder inside the repository makes zn audit read the configs there too.
  • A root .env is audited even when .gitignore lists it, because in a fresh clone it exists only if it was committed. Its findings are one level lower and say that they do not apply to your own local .env.

With --include-home it also reads ~/.claude/settings.json, ~/.claude.json, ~/.codex/config.toml, ~/.cursor/mcp.json, ~/.cursor/hooks.json, ~/.aws/amazonq/mcp.json, ~/.config/opencode/opencode.json[c] and ~/.gemini/settings.json. It honours CODEX_HOME and XDG_CONFIG_HOME the way the agents do. Commands you configured yourself are expected there, so only the riskier variants are reported: code downloaded and run, unpinned packages, endpoint overrides, secrets and broad permissions. Endpoint, environment and permission findings are capped at medium.

Rules

Rule ids are stable: a rule may get better, but its id never changes meaning. Severities are critical, high, medium and low; when a rule lists several, the finding gets the one that fits the case.

Id Severity What it finds
ZNA001 high / medium / low A command that runs automatically from a project config: hooks, statusLine, Codex notify, OpenCode plugin files, VS Code tasks with runOn: folderOpen. Medium for hooks of a plugin, which run only once the plugin is enabled. The hook that zn hooks install writes is reported as low
ZNA002 critical An automatic command that downloads code and runs it (curl ... | sh, iwr ... | iex, bash <(curl ...))
ZNA003 high / medium / low A project MCP server that starts a local command. High for Codex and Amazon Q; low for zn's own secrets server when it is verified on disk
ZNA004 high / medium Project settings that approve MCP servers in advance (enableAllProjectMcpServers, enabledMcpjsonServers)
ZNA005 medium An MCP server or agent plugin that is not pinned: npx -y pkg, @latest, uvx pkg without ==, container images without a tag or digest, OpenCode plugins without a version
ZNA006 medium / low A remote MCP server, or instructions loaded from a URL. Medium for plain http, low for https
ZNA007 critical / high / medium / low The model API endpoint is overridden (ANTHROPIC_BASE_URL, OPENAI_BASE_URL, any *_BASE_URL, provider base URLs in Codex and OpenCode) or a proxy is set (HTTPS_PROXY). Critical for a remote host, high for a proxy, medium for a loopback address. Inside the env of one MCP server it only redirects that server: medium, or low for loopback
ZNA008 high An environment variable that loads code or certificates (NODE_OPTIONS, LD_PRELOAD, DYLD_INSERT_LIBRARIES, PYTHONSTARTUP, BASH_ENV, PATH, GIT_SSH_COMMAND, NODE_EXTRA_CA_CERTS and similar) or that moves where the agent reads its config (CODEX_HOME, CLAUDE_CONFIG_DIR, XDG_CONFIG_HOME, OPENCODE_CONFIG). Also checked in the env of every MCP server
ZNA009 high A credential helper command in project settings (apiKeyHelper, awsAuthRefresh, awsCredentialExport, otelHeadersHelper)
ZNA010 high / medium Broad permissions: Bash(*), Bash, *, interpreter wildcards such as Bash(python:*), defaultMode: bypassPermissions, Codex approval_policy = "never" with full access, OpenCode "bash": "allow", VS Code chat.tools.autoApprove
ZNA011 high A secret value in an agent config or instruction file. The report never prints the value
ZNA012 high / medium / low A prompt-injection pattern in agent instructions: instruction overrides, fake system tags, hidden HTML, invisible Unicode, markdown image beacons. In the files an agent reads as instructions (AGENTS.md, CLAUDE.md, GEMINI.md, rules, skills, commands, prompts) a strong pattern is never lowered, quoted or not
ZNA013 medium / low Instructions that tell the agent to download and run code. Low for well-known installers such as rustup, uv, bun, deno, nvm and Homebrew
ZNA014 high Instructions that tell the agent to send secrets or files out (.env, ~/.ssh, tokens to a URL, curl -d @.env)
ZNA015 medium Instructions that tell the agent to skip safety checks or hide what it does (--no-verify, --dangerously-skip-permissions, "disable the sandbox", "do not tell the user")
ZNA016 critical / high An executable in the audited root that shares its name with a common tool (git.exe, node.exe, npm.cmd, python, zn.cmd). Critical for Windows executables. Windows and some tools search the current folder first, so the planted file runs instead of the real tool
ZNA017 medium Project settings that add plugin marketplaces or enable plugins (extraKnownMarketplaces, enabledPlugins)
ZNA018 low The repository ships agent extensions (commands, subagents, skills, plugins). It is an inventory: the other rules review them, but you should know they are there
ZNA019 high / medium A CI workflow that runs an AI agent on input anyone can write (issues, issue_comment, pull_request_target, discussions). High with pull_request_target, issue or comment text pasted into the workflow, an action opened to users without write access, or a CLI step with write permissions and no author filter
ZNA020 high / low An agent file could not be checked: a syntax error, a size over 1 MB, a symbolic link leaving the repository, or a scan that stopped early. High when the file can run commands or redirect the agent, or when the scan did not finish; low for a syntax error in a file that cannot run anything

Output

Text

zn audit  ./some-repo  (zn-gate 1.12.0 or later)

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.

Colors are used only on a terminal and never when NO_COLOR is set. Control characters and escape sequences that come from the repository are printed as \x1b, never sent to your terminal.

JSON

--format json prints one object with the findings and a 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 is relative to root with forward slashes; files from --include-home start with ~/. agent is the agent that reads the file, or any when several do. evidence is the matching line, cut to 160 characters, with secrets replaced by [REDACTED:<TYPE>]. URLs lose their user, password, query string and fragment.

SARIF

--format sarif writes SARIF 2.1.0 for GitHub code scanning: one rule per ZNA id with help text and a severity score, and results located relative to the repository root. Each result has a fingerprint, so alerts survive line moves. Findings from --include-home are marked as coming from the home folder and GitHub ignores them, so keep that flag off in CI.

Use it in CI

The simplest way is the zn-gate GitHub Action with mode: audit. See GitHub Actions.

To run the CLI yourself, write a SARIF file and upload it to 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

Drop --fail-on none (the default is high) if you want the job to fail on high and critical findings. Add security-events: write to the job only when you upload SARIF.

Limits

  • It reads files; it does not run them, start servers or resolve packages. A pinned package can still be malicious, and a hook that calls a local script is reported as a hook, not judged by what the script does.
  • Instruction rules match patterns line by line. A determined author can phrase an instruction that no pattern catches, and documentation that quotes a dangerous command is reported too, for example an install guide with curl ... | sh. Review the evidence before you act.
  • The workflow rule reads YAML line by line. It knows common agent actions and the trigger and permission keys, not reusable workflows or composite actions.
  • Git configuration (.git/config, .gitattributes filters) and editor extensions are not checked.
  • Agents change their config formats often. Unknown keys are ignored, not reported.
  • Secrets are found by format and by sensitive key name. A secret with no known format under an innocent key name is not found, and passwords written in prose are not redacted from the evidence.