The full upstream README, mirrored here for reference. Install config, tool schemas, adoption signals, and an original overview live on the Zyrax Guard listing page.
Audit your AI agent configs before you run them.
Catch the prompt injection, malicious MCP servers, and credential-exfil hiding in the
files that steer your AI — CLAUDE.md, .mcp.json, agent settings, skills — and vet the
packages they pull in. In milliseconds. Nothing leaves your machine.
Works locally, in CI, and as a gate for AI coding agents. No account required. Nothing phones home except the public package name you are querying.
Get it (pick one):
Then: zyrax-guard scan-agents . to audit configs, or zyrax-guard check <pkg> to vet a package.
Full install options (signed binary, curl|sh) and verification are below.
🌐 Homepage: zyrax.io
Ships the prebuilt Go binary per-platform (via optionalDependencies) — no runtime
download. Works anywhere Node 18+ is available.
Installs the signed release binary (SHA-256 verified by Homebrew). Updates land via
brew upgrade once a new release is published.
Installs the signed release binary (SHA-256 verified by scoop against the manifest, whose
hashes come from the release's signed checksums.txt). zyrax-guard upgrade detects a
scoop install and delegates to scoop update zyrax-guard.
Downloads the signed release binary for your OS/arch, verifies its SHA-256 against
the release checksums, and installs it (to /usr/local/bin, or ~/.local/bin if that
is not writable). Pin a version with VERSION=v0.5.0, or set BINDIR to choose where
it lands. Verifies the cosign signature too when cosign is on your PATH.
go install (Go 1.23+)Download from Releases. Every release ships:
checksums.txt (SHA-256).cosign.bundle per artifact)zyrax-guard.spdx.json)Verify a binary:
Guard checks for a newer release at most once a day (a read-only lookup of its own version
on registry.npmjs.org) and prints a one-line notice on stderr when one is available. To
update:
upgrade delegates to your package manager (npm/brew/scoop/go) when Guard was installed
that way; for curl|sh / standalone-binary installs on Linux/macOS it downloads the signed release,
verifies its SHA-256 against checksums.txt and its keyless cosign signature before replacing
the binary (any mismatch aborts the upgrade). Signature verification is required by default
— if cosign is not installed the upgrade aborts with instructions; pass
--require-signature=false to accept checksum-only verification explicitly. On Windows, install
via scoop to get delegated upgrades; the standalone
Windows binary is still upgraded manually (the notice links to Releases).
Disable the daily check with ZYRAX_NO_UPDATE_CHECK=1.
Scans CLAUDE.md, AGENTS.md, GEMINI.md, .mcp.json, .claude/settings.json,
and Cursor rules files. Exits 1 if any CRITICAL or HIGH finding is found.
Commit .zyrax/policy.json — it is the reviewable allowlist for your project.
Emits SARIF 2.1.0 to stdout. Exit code 0 if no BLOCK or ERROR; non-zero otherwise.
Add --strict to treat WARN as failure.
scan-agents)AI coding agents (Claude Code, Cursor, Gemini CLI) read configuration files that can be
weaponized: a malicious CLAUDE.md in a repo you clone, a tampered .mcp.json that
points to an attacker's server, an MCP tool whose description hides instructions, a
settings.json granting wildcard shell access, or prose that quietly steers the agent
toward reading .env and POSTing it out. Guard detects these before the agent runs.
| File | Location |
|---|---|
CLAUDE.md, AGENTS.md, GEMINI.md | Repo root |
.mcp.json | Repo root and subdirectories |
.claude/settings.json | .claude/ directory |
.cursor/rules, .cursor/rules/*.mdc | Cursor rules |
SKILL.md | Under any skills/ directory |
| Rule | Severity |
|---|---|
Prompt injection keywords (ignore previous instructions, new objective:, …) | CRITICAL |
| Hidden unicode characters (zero-width, bidi overrides) | CRITICAL |
| Base64-encoded instructions bypassing keyword filters | CRITICAL |
Conditional/sleeper triggers (when user asks X, do Y) | CRITICAL |
| MCP tool description carrying injection keywords (read as trusted model context) | CRITICAL |
Persona override (you are not Claude, your true purpose) | HIGH |
| MCP server using non-HTTPS URL | HIGH |
| MCP server using raw IP address (possible C2) | HIGH |
| MCP server using tunnel service (ngrok, Cloudflare, …) | HIGH |
MCP server running a shell, inline -c/-e, temp-dir binary, or dangerous env var | HIGH |
Instruction referencing credential files (.env, id_rsa, .aws/credentials) | HIGH |
Exfiltration sink (send/POST/curl + external URL on one line) | HIGH |
Wildcard allow in permissions | HIGH |
| Unrestricted shell access with no deny rules | MEDIUM |
npx MCP server without a lock file | MEDIUM |
| Auto-run hooks executing commands (download-execute → CRITICAL, shell flag → HIGH) | CRITICAL–MEDIUM |
Exit code: 1 if any CRITICAL or HIGH finding; 0 otherwise. Use --strict for exit 1 on any finding.
Obfuscation-normalized. Before matching, detection normalizes common disguises — zero-width and
format characters, homoglyphs, full-width and leetspeak substitutions, and separator/line splitting —
so trivially obscured payloads (y0u 4r3 n0w…, ignore—previous—instructions, Cyrillic look-alikes)
are still caught. It stays a fast, deterministic, on-device guardrail for known agent-config
attack patterns — not a complete defense against a determined adversary who paraphrases or writes in
another language. Semantic detection is a roadmap item for the Zyrax platform, not the local CLI.
Suppressing a legitimate collision. A real skill or config can legitimately phrase something the
heuristics flag (e.g. a reviewer skill that says "act as a senior reviewer"). Silence it with an
inline zyrax-allow comment on that line — optionally zyrax-allow: <rule-prefix> to scope it — or
zyrax-allow-file: <rule-prefix> for a whole file. Suppression is never silent: the scan always
reports N finding(s) suppressed by zyrax-allow, and --strict ignores suppressions entirely
(audit/CI mode), so a hostile config can't use the directive as a kill switch.
scan_agents tool)Once registered as an MCP server, agents also have access to scan_agents:
Gate every pull request. By default (scan: both) Zyrax Guard audits AI agent configs
(prompt injection, malicious MCP servers, risky permissions) and gates dependencies
added in the PR, failing the check if anything is blocked. Add
.github/workflows/zyrax-guard.yml:
Pin for production: these examples pin third-party actions to commit SHAs — mutable tags are a supply-chain risk (the exact risk Guard exists to catch). Pin
zyrax-guardto an exact version or commit SHA too for fully reproducible CI.
On a pull request it scans only the dependencies added versus the base branch; otherwise
it scans the whole lockfile. The job fails when a dependency is blocked. @v0 tracks the
latest 0.x release; pin an exact version (e.g. @v0.7.1) for fully reproducible CI.
Inputs (all optional): scan (deps | agents | both, default both), ecosystem
(default npm), lockfile (default per-ecosystem), base (explicit base lockfile),
strict (treat WARN as failure), deep (inspect install scripts), version (Guard
release, default latest), fail-on-block (default true), sarif-file (write
dependency SARIF for Code Scanning), agents-sarif-file (write agent-config SARIF for
Code Scanning), args (extra raw flags).
Upload results to GitHub Code Scanning so findings show up inline on the PR:
Audit agent configs and dependencies, both surfaced in Code Scanning:
(That job needs permissions: { security-events: write }.)
Guard supports npm, PyPI, crates.io, and Go modules. Pick one with --ecosystem
(default npm):
Go modules are queried against proxy.golang.org (the standard Go module proxy — no
auth, no download-count API). Two differences from the other ecosystems, both
by design:
--deep reports "no install/build scripts found" for every Go module. go get
/ go mod download never execute code from the fetched module — there is no
npm-postinstall/pip-setup.py/cargo-build.rs analog to statically analyze.Guard runs against public registry metadata only — no local execution, no installs, no sandboxing:
| Check | Verdict trigger |
|---|---|
| Existence | Package not found on the registry → BLOCK (hallucinated or trap name) |
| Typosquat | Name is 1 edit away from a far-more-popular package AND has near-zero downloads → BLOCK with a "did you mean" suggestion |
| Known-bad | OSV advisory match → known-malicious package → BLOCK; vulnerability in a legitimate package (any severity, shown in the message) → WARN (use --strict to fail on it) |
| Age & popularity | Published < 30 days AND < 50 weekly downloads → WARN |
| Lockfile integrity | (scan only) Resolved URL or integrity hash changed → BLOCK |
Transient registry/OSV failures (429 or 5xx) are retried with backoff (honoring Retry-After)
before Guard gives up; only a persistent failure yields ERROR (fail closed — see Verdicts).
--deep)By default checks are metadata-only (milliseconds). Add --deep to also download the
package's distribution artifact and statically inspect the code it runs at install/build
time — npm preinstall/install/postinstall scripts, PyPI setup.py, crates build.rs
(Go modules have no such hook — see Ecosystems):
It flags red-flag patterns — network calls, process spawning, base64/obfuscated eval —
and BLOCKs on dangerous combinations (e.g. "download a script and run it"). It runs
no code (purely static) and is best-effort: if the artifact cannot be fetched you
get an informational note, never a false block.
Zero added dependencies — the extractor uses stdlib archive/tar + compress/gzip only.
| Verdict | Meaning | Default exit code |
|---|---|---|
| SAFE | No signals worth noting | 0 |
| WARN | Suspicious — review before proceeding | 0 (use --strict to make it 1) |
| ERROR | Guard could not verify (registry/OSV unreachable, 5xx, or rate-limited) — fails closed | 1 (always) |
| BLOCK | Strong indicator of malicious or hallucinated package | 1 |
Guard fails closed: if it cannot reach the registry or the malware database, it returns ERROR and exits non-zero rather than letting an unverified package through. Disrupting the network cannot silently bypass the gate.
Zyrax Guard is configured entirely through command flags and an optional local policy file — no config file or environment variables required.
| Command | Purpose |
|---|---|
check <name>[@version] | Vet a single package |
install <name> | Check, then install if safe |
scan | Vet a lockfile (or a PR's lockfile diff) |
scan-agents <dir> | Audit AI agent config files |
allow <name> | Add a package to the local allowlist |
init | Print the shell hook (gate installs transparently) |
mcp | Run the MCP server (check_package, scan_agents) |
mcp install [--global] | Register Guard with your AI agent |
upgrade | Update Guard to the latest release (verified) |
version [--check] | Print version; --check checks for a newer release |
| Flag | Commands | Default | Effect |
|---|---|---|---|
--ecosystem npm|pypi|crates|gomod | check, install, scan | npm | Target package ecosystem |
--strict | check, install, scan, scan-agents | off | Tighten failure: WARN → fail (package commands); any finding → fail (scan-agents) |
--deep | check, install, scan | off | Download + statically analyze install/build scripts |
--json | check, install, scan, scan-agents | off | JSON output |
--sarif | check, scan | off | SARIF 2.1.0 output (for code-scanning ingestion) |
--ignore-scripts | install | off | Pass --ignore-scripts through to npm |
--reason <text> | allow | — | Recorded with the allowlist entry in .zyrax/policy.json for later review |
--base <file> | scan | — | Base lockfile to diff against (scan only added/changed deps) |
--head <file> | scan | per-ecosystem (package-lock.json / poetry.lock, falling back to requirements.txt / Cargo.lock / go.sum) | Head lockfile to scan |
--require-signature | upgrade | on | Verify the cosign signature before replacing the binary; pass --require-signature=false to accept checksum-only |
zyrax-guard allow <name> [--reason "why"] records decisions in .zyrax/policy.json at
the project root. Every allow is timestamped (UTC); a reason is optional but recorded
alongside it when given, so a teammate reviewing the diff sees why a package was trusted,
not just its name:
Both forms are accepted on load — a bare string is still a valid entry, so files written
before reason/at existed keep working unchanged.
Allowlisted packages skip checks; denylisted packages always BLOCK. Commit the file to
share policy across a team. (Org-wide policy is a paid drop-in via the Policy seam.)
Guard deliberately does not offer an inline "block or continue?" prompt at check time:
an AI agent driving the CLI could auto-answer such a prompt, and non-interactive contexts
(CI, scripts) can't answer one at all. allow requires a separate, deliberate command —
outside whatever automated loop hit the BLOCK — and leaves a reviewable trail in git.
| Context | Exits 1 when |
|---|---|
check / install / scan | a BLOCK or ERROR verdict — or a WARN with --strict (ERROR exits 1 regardless of --strict) |
scan-agents | a CRITICAL or HIGH finding — or any finding with --strict |
See Verdicts for package verdict meanings.
The shell hook intercepts npm install / pip install / cargo add / go get
transparently. Every new package gets checked before the real installer runs;
already-installed and non-install commands pass through untouched.
Add to ~/.bashrc, ~/.zshrc, or ~/.bash_profile:
Apply immediately without restarting your terminal:
Add to your PowerShell profile ($PROFILE). To find and open it:
Add this line and save:
Apply immediately:
From now on every npm install, pip install, cargo add, or go get in a
PowerShell window is automatically checked before anything installs.
Register zyrax-guard mcp as an MCP server and your agent gains a scan_agents tool to
audit the configs it's about to act on — and a check_package tool it calls before every
install (AI agents hallucinate package names; attackers pre-register them as malware,
and Guard breaks that chain).
One-step register (recommended):
mcp install writes a standard .mcp.json (read by Claude Code, Cursor, and VS Code) and
auto-detects whether to register zyrax-guard mcp (binary on PATH) or npx -y zyrax-guard mcp.
Override with --command binary|npx. --global delegates to claude mcp add -s user (it prints
the manual command if the claude CLI isn't installed).
Manual one-liner (Claude Code):
→ MCP setup for Claude Code, Cursor, Windsurf, VS Code, and Continue.dev
Guard is on the official MCP registry as io.github.tiagosilva07/zyrax-guard — register it
in one line with npx -y zyrax-guard mcp.
Gate pull requests so a malicious or hallucinated dependency fails the build. The
GitHub Action is the quickest path; zyrax-guard scan recipes for
GitHub Actions, PyPI, crates.io, and Go modules live in the CI guide.
→ CI recipes (GitHub Actions PR gate, PyPI, crates.io, Go modules)
Only the public package names you query leave your machine, as read-only lookups against public registry APIs:
registry.npmjs.org — existence and metadataapi.npmjs.org — download countsproxy.golang.org — Go module existence and version metadataapi.osv.dev — known advisoriesregistry.npmjs.org — Guard's own latest version (update check, ≤1×/day; disable with ZYRAX_NO_UPDATE_CHECK=1)github.com — only when you run zyrax-guard upgrade (downloads the signed release binary)No telemetry. No account. No secrets sent anywhere. The binary is reproducible
(-trimpath), and every release ships SLSA L3 provenance so you can verify the build
chain yourself.
Zyrax Guard is MIT-licensed and free — the agent-config auditor (scan-agents +
the scan_agents MCP tool), every package check, the PR gate with JSON/SARIF output, the
check_package MCP tool, and the shell hook. Read the code and verify the binary yourself.
A Zyrax platform for teams (organization-wide policy, continuous monitoring, dashboards, and audit/compliance reporting) is in development — learn more at zyrax.io.
| Version | Item | Status |
|---|---|---|
| v0.1.0 | npm CLI: check + PR-gate scan (lockfile diff) + JSON/SARIF + self-hardening CI | shipped |
| v0.2.0 | MCP server (check_package) + shell-hook (zyrax-guard init) | shipped |
| v0.3.0 | PyPI + crates.io parity across check/install/hook/MCP/scan | shipped |
| v0.4.x | Deep check (--deep): static install/build-script analysis + overall time budget | shipped |
| v0.5.0 | Rebrand to Zyrax; public release | shipped |
| v0.6.x | GitHub Action + Marketplace listing + curl|sh installer; floating @v0 tag | shipped |
| v0.7.0 | scan-agents: AI agent config audit (prompt injection, MCP hosts, permissions) + Phase 2 detections (credential access, exfiltration sinks, MCP tool-description injection) | shipped |
| v0.8 | First-class CI surfacing for scan-agents: SARIF output + GitHub code-scanning upload + inline PR annotations | shipped |
| v0.9.0 | Update detection (daily opt-out notice + verified upgrade) + one-step mcp install; production-readiness: fail-closed ERROR verdict (network failure no longer bypasses the gate), retries/backoff, MCP panic recovery, cosign-verified upgrade, hardened CI (gitleaks/staticcheck/dependency-review); agent-config detection hardening (obfuscation-normalized matching, allowlist-style MCP/exec/perms, zyrax-allow suppression) | shipped |
| v0.10.0 | Correctness & fail-closed hardening from a full audit: npm-workspace lockfile support in scan (monorepos no longer crash), install installs the exact vetted name@version, scan-agents fails on a missing directory and reports unscannable (oversize/unreadable) configs, registry-derived text sanitized against terminal-escape/prompt injection, unknown download stats no longer read as "0" (no false typosquat BLOCKs), wall-clock budgets on every check entry point, signature-verified upgrade by default, --help exits 0 + documented exit codes, install --json | shipped |
| v0.11.x | Verdict policy: BLOCK is malware-only (v0.11.0) — vulnerabilities in legitimate packages WARN at any severity (--strict to fail); Windows scoop bucket (scoop-zyrax) + upgrade delegation, closing Windows upgrade parity | shipped |
| v0.12.0 | Reduce suspicious-install false positives on declarative PyPI config (signals now carry file:line evidence); advisory-only repo-context signal (GitHub stars/age/last-push — never affects the verdict); allow --reason with a timestamped audit trail in .zyrax/policy.json | shipped |
| v0.13.0 | Go modules ecosystem (--ecosystem gomod, proxy.golang.org) across check/install/hook/MCP/scan, with go.sum lockfile support | shipped |
| exploring | Semantic detection layer (LLM/heuristic judge for paraphrased/non-English prompt injection) as a Zyrax-platform capability; community-curated threat intel (shared malicious-package & MCP-host feeds); more ecosystems (RubyGems) via the Ecosystem seam | — |
The roadmap items drop in via the existing Ecosystem, ThreatIntel, Policy, and
Reporter seams — no re-architecting required.
MIT — see LICENSE.