Skip to content

Latest commit

 

History

History
75 lines (63 loc) · 17.5 KB

env.md

File metadata and controls

75 lines (63 loc) · 17.5 KB

Environment variables

Every GUARDIAN_* variable the MCP server, the hooks, the CLI and the developer tooling read, with its default. mcp/test/docs/docs.test.ts fails when the code reads one this page does not name.

Set them where the process that reads them starts: in the env block of the MCP server entry (.claude-plugin/plugin.json for the plugin, your host's MCP config otherwise), in the shell that launches Claude Code for the hooks, or in the CI job for the CLI.

Runtime

Variable Read by Default Effect
GUARDIAN_OFFLINE MCP server, CLI (scan, baseline update), hooks unset 1 switches off the lookups dev-guardian makes on its own initiative: CISA KEV / FIRST EPSS (prioritize_findings, risk_score, create_fix_pr), the registries and OSV for vetting (vet_packages, the install hook), scan_skill's OSV lookup (check_deps), verify_live, Wordfence / wordpress.org (wp_vuln_check with mode: "source"), and cosign's signature and provenance check of an image (scan_containers: cosign skipped and in missing_tools). What could not be measured is reported as unknown / unavailable / partial coverage, never as clean. It does not stop requests to a target you named (scan_dast, wp_vuln_check with mode: "rest", perf_check, a scan_skill URL) or the scanners' own network use (Semgrep registry, Trivy database) — see SECURITY.md.
GUARDIAN_RETENTION_SCANS MCP server 50 Scans kept per (project, scan type) in .guardian/guardian.db; 0 keeps everything. Scoped scans (a diff, --staged) and scans that measured nothing (failed, cancelled, coverage none) are counted apart, N of each, so the newest scan that did measure is never pushed out. A baseline's scan, a running scan, the scans a baselined security_scan_full or audit_executive run stands on (its children, its sub-scans), and every scan the project's open findings are read from (including an older one whose findings newer, partial scans did not measure again) are never pruned. Pruning runs in the background after the server starts.
GUARDIAN_SCAN_TIMEOUT_MS MCP server, CLI 600000 (10 min) Timeout for a scanner process when the tool sets none of its own. On timeout the whole process tree is killed. scan_containers' cosign check gives each image this as ONE budget shared by all its cosign calls (each call also capped at 3 min); what the budget cuts short is reported as no verdict, naming it.
GUARDIAN_ENGINE_LOAD_DEADLINE_MS CLI 60000 (1 min) How long cli/dev-guardian.mjs waits for its engine (mcp/dist/engine.js) to load, at least 1000. An engine that does not finish loading in that time — like one that cannot be loaded, or one from another build that lacks what the CLI uses — is a damaged install: one line saying so, exit 3.
GUARDIAN_MCP_AUDIT_BUDGET_MS MCP server 600000 (10 min) The whole budget of one audit_mcp_tools call. Each server gets the smaller of its timeout_ms and what is left; the servers left when it runs out are skipped with that reason, never passed.
GUARDIAN_KEEP_REPORTS MCP server, CLI 3 Report directories of each kind (sast-…, deps-…, surface-…, …) kept under a project's .guardian/reports/; a scan removes the older ones when it starts its own. Never pruned: an SBOM, a VEX document, a perf_check report or DAST evidence (a stored finding points at it). At least 1.
GUARDIAN_MAX_CONCURRENT_SCANS MCP server, CLI 2 Scanner processes allowed to run at once; further calls queue. security_scan_full holds no slot itself.
GUARDIAN_SEMGREP_IMAGE MCP server, CLI semgrep/semgrep Docker image for the Semgrep fallback that scan_sast and map_attack_surface use when semgrep is not installed but Docker is. Pin a tag here for reproducible runs.
GUARDIAN_CACHE_DIR MCP server per-OS user cache Where wp_vuln_check (mode: "source") keeps the Wordfence feed, used as given — and where a wp_vuln_check run against a site with no install on this machine (live mode, a URL only) writes its WPScan report: <cache>/wp-vuln-check/<host>-<hash>/wpvuln-…/, the newest GUARDIAN_RETENTION_SCANS of each site kept. Those reports are not under GUARDIAN_DATA_DIR, even though on Windows the default cache sits inside the default data directory: to keep a run out of your profile (a test, a sandbox), set both. Default: %LOCALAPPDATA%\dev-guardian\cache on Windows, $XDG_CACHE_HOME/dev-guardian or ~/Library/Caches/dev-guardian on macOS, $XDG_CACHE_HOME/dev-guardian or ~/.cache/dev-guardian elsewhere.
GUARDIAN_DATA_DIR MCP server, CLI (status, dashboard, db adopt), hooks per-OS user data dir dev-guardian's per-user data: the registry of the databases it created (registry/<db_id>.json — a project's .guardian/guardian.db is trusted only when its id is registered there for that very path: created by dev-guardian there, or registered by you with node "<plugin root>/cli/dev-guardian.mjs" db adopt --project <dir> --yes — one from 3.0.0 is not, until you do), and the database a project uses when its own cannot be used — foreign, not writable, tracked by git, or holding schema objects the migrations never create — as <dir>/<hash of the project path>/guardian.db. Default: %LOCALAPPDATA%\dev-guardian on Windows, $XDG_DATA_HOME/dev-guardian or ~/.local/share/dev-guardian elsewhere — one resolution, which the hooks share. Its directories are created 0700 and, on POSIX, must belong to you; a symbolic link or another user's directory there is refused. When it cannot be used at all (it cannot be created — a container user with no home, HOME=/ — or it is refused), the server does not exit: the session runs on an in-memory database, and health_status and every scan say history will not persist until this points at a writable directory. The hooks read it to find that registry/, which an assistant may not write — with the Write tool or from the shell (see hooks.md); set it in the shell that launches Claude Code as well as in the server's env, or the hooks guard the default directory.
GUARDIAN_HOOKS hooks unset off disables every hook. The user-level ~/.config/dev-guardian/hooks.json with "enabled": false does the same; a project's .guardian/hooks.config.json cannot (its enabled: false is ignored).
GUARDIAN_HOOKS_BASH_BLOCK hooks unset 0 / false: catastrophic commands are only warned about; 1 / true: always blocked. Wins over both config files. A project's .guardian/hooks.config.json cannot switch the block off — see hooks.md.
GUARDIAN_HOOKS_DEBUG hooks unset 1 writes the hooks' diagnostics to stderr (they are silent and fail open otherwise).
GUARDIAN_PKG_VET hooks unset 0 turns off install-time package vetting in the PreToolUse hook. No project file can do it — not even with "enabled": false; the user-level config's "enabled": false turns it off along with every other hook. The vet_packages tool is unaffected.
GUARDIAN_PKG_VET_DEADLINE_MS hooks 8000 The one deadline for install-time package vetting in a PreToolUse hook call, in ms from the start of the call (at least 3000, the network budget — a smaller value left no time to look a package up, and a malicious one went through with a "not verified" note; at most 12000: Claude Code kills a hook at 15 s, and the command then runs with no verdict — the answer and the hook's exit need the rest). The 3 s network budget is cut to it; what is left when it passes reads "vetting time budget exhausted" — not verified, never ok.

Set by dev-guardian, not by you

Variable Where Purpose
GUARDIAN_SCAN_ID environment of the scripts a scan runs the id of the scan row the run belongs to
GUARDIAN_PROC_TREE_ID every child process on Windows a per-run token the runner uses to find and kill the whole process tree, including MSYS descendants taskkill cannot see
GIT_CONFIG_COUNT, GIT_CONFIG_KEY_<n>, GIT_CONFIG_VALUE_<n> every process dev-guardian starts — git, the scanners, the package managers, the scripts — except the test command create_fix_pr runs and the DAST application git configuration overrides that keep a scanned repository's own git configuration and hooks from running anything (SECURITY.md). Appended after the entries your own environment sets, which are kept.
GIT_PAGER, GIT_EDITOR, GIT_SEQUENCE_EDITOR the same processes cat, :, : — git's own "no pager" and "no editor".
GIT_PROXY_COMMAND, GIT_NO_LAZY_FETCH the same processes, only in a repository that sets core.gitProxy or a remote.<name>.uploadpack empty (no proxy command — unless you set one, which is kept) and 1 (no lazy fetch).

Developer tooling

Read only by the test suite, npm run ablate and npm run eval:llm-scan; nothing at runtime looks at them.

Variable Read by Effect
GUARDIAN_REQUIRE_COSIGN test suite 1 turns a missing (or pre-3.0) cosign in test/e2e/cosignRegistry.test.ts — the real cosign against a registry that fails on purpose — from a visible skip into a hard failure. With 1, the verify cases' need for Sigstore's TUF trust root (cosign initialize, network) is a hard requirement too: it fails rather than skips them.
GUARDIAN_REQUIRE_SEMGREP test suite 1 turns a missing Semgrep (or Trivy, for the Trivy e2e) from a visible skip into a hard failure — set it when you need to know a rule pack was actually exercised. A Semgrep that is on PATH but does not answer semgrep --version fails the rule-pack tests with or without it: only absence is a skip.
GUARDIAN_REQUIRE_LINTERS test suite 1 turns a missing actionlint or zizmor — the real linters test/e2e/ciInitCli.test.ts runs over the rendered GitHub workflow — from a visible skip into a hard failure.
GUARDIAN_REQUIRE_ISOLATED_HOME test suite 1 fails the run when ~/.semgrep/semgrep.log, ~/.semgrep/settings.yml or ~/.cache/semgrep_version changed during it. The suite points Semgrep's settings, log and version cache at its own temporary directory (test/setup/semgrepHome.ts); without the variable a change is printed as a warning, because a Semgrep run outside the suite (by you, or by an open session's MCP server) writes the same files.
GUARDIAN_PERF_STRICT test suite, through test/helpers/timing.ts 1 is for a quiet machine. It runs the absolute time bounds of test/unit/hooks/bashGuard.test.ts, secretScan.test.ts, test/unit/pkgvet/parseCommand.test.ts and test/unit/secrets/verify/rawReport.test.ts — each its own test, a visible skip without it — tightens the wait bounds of the tests whose defect is a wait (a FIFO, /dev/zero, a network path, a budget ignored: hangBound in test/helpers/timing.ts, 12 s without it), and tightens the bounds that always run in test/unit/runners/processRunner.test.ts, test/e2e/hooksDispatcher.test.ts, test/e2e/hooksPkgVet.test.ts and test/integration/auditMcpToolsBounds.test.ts, which without it sit under what the property allows (the hook's 15 s kill, for the hooks) and far under the defect each was written for. What the timing tests exist for is asserted without it: a ratio — eight times the input must cost under 22.6 times as much — and, where a 16 KB cap bounds the cost, a ceiling against a benign input of the same size. Both are measured in alternated chunks of equal duration, each side's cheapest chunk per call, and a reading over the bound is measured again, up to three comparisons: a loaded machine only adds time, and in bursts, while each defect reintroduced reads over its bound every time. That is what a busy runner and v8 coverage move least — not "not at all": every probe's distribution over 20 runs at 100% CPU is in the review 3.0 R7 round-2 commit.
GUARDIAN_SEMGREP npm run ablate Semgrep binary to use (after --semgrep=, before PATH).
GUARDIAN_RUST_SRC, GUARDIAN_CS_SRC, GUARDIAN_JAVA_SRC, GUARDIAN_PY_SRC, GUARDIAN_GO_SRC, GUARDIAN_PHP_SRC npm run ablate Real-code corpus for axis 3 of the bugfix-rs, -cs, -java, -py, -go and -php packs. Unset: axis 3 prints N/A. Set to a path that does not exist: the run throws.
GUARDIAN_RGPD_SRC npm run ablate Axis-3 corpus for the rgpd pack; unset falls back to mcp/src.
GUARDIAN_LLM_SRC npm run ablate Axis-3 corpus for the llm pack: a tree of real LLM-application code, Python and JS/TS (the pack header names the one it was measured on). Unset: axis 3 prints N/A. Set to a path that does not exist: the run throws.
GUARDIAN_WEBJS_SRC npm run ablate Axis-3 corpus for the web-js pack: a tree of real Node application code, JS/TS, with raw SQL and Express handlers (the pack header names the one it was measured on). Unset: axis 3 prints N/A. Set to a path that does not exist: the run throws.
GUARDIAN_LLMSCAN_SPIKE, GUARDIAN_VAMPI_SRC, GUARDIAN_BENCHMARK_PY_SRC, GUARDIAN_JUICESHOP_SRC, GUARDIAN_DVWA_SRC npm run eval:llm-scan Corpora of the LLM-scan evals: the spike folder (the synthetic app-s and its key), VAmPI at f16052d, OWASP BenchmarkPython at f129148, Juice Shop at 1618a61 and DVWA at 43b0f8b. None is copied into the repository; a run copies each one, blinded, into a temp directory. Unset: that corpus's items print N/A and the run reports itself incomplete. Set to a path that does not exist, or to a checkout at another commit: the run throws.
GUARDIAN_CI_INIT_PIN_SHA cli/dev-guardian.mjs ci-init Test seam: a 40-hex commit used instead of resolving the release tag. Production never sets it.
GUARDIAN_TEST_* individual tests Test-internal switches (live network e2e, fetch mocks, raw temp paths, the run's own directory, GUARDIAN_TEST_TIMING_LOG=<file> to record every timing measurement as a JSON line). Not for users.

The suite itself runs with GUARDIAN_OFFLINE=1 (mcp/vitest.config.ts); a test that exercises a network path clears it and supplies its own mocked fetch.

Other variables dev-guardian reads

Variable Read by Effect
WORDFENCE_API_KEY wp_vuln_check (mode: "source") Wordfence Intelligence v3 token. Without it the Wordfence pass is skipped and coverage is partial; the wordpress.org checks still run.
WPSCAN_API_TOKEN wp_vuln_check WPScan API token when api_token is not passed; without one the public rate limit applies.
the variable named by auth_header_env scan_dast The Authorization header for authenticated probes, so the credential never enters the transcript.
XDG_CACHE_HOME, LOCALAPPDATA wp_vuln_check (the Wordfence feed, and a live-mode run's report) Base of the default cache directory (see GUARDIAN_CACHE_DIR).
CLAUDE_CONFIG_DIR audit_agent_config, audit_mcp_tools (with include_user_config), hooks Where Claude Code keeps its global .claude.json and settings.json, read from there instead of ~/.claude.json and ~/.claude/settings.json, as Claude Code does. The hooks guard settings.json / settings.local.json there like ~/.claude/settings*.json.
CLAUDE_PROJECT_DIR hooks Set by Claude Code for every hook: the project whose .guardian/ configuration applies, wherever the session has cd-ed to (without it, the nearest ancestor holding .guardian or .git, never the home directory, its ancestors or the temp directory).
NO_COLOR dev-guardian status Disables colour in the terminal summary.
SEMGREP_SEND_METRICS scan_sast, security_scan_full, the CLI's scan (Semgrep reads it) off makes Semgrep refuse its registry rules (--config=auto, used unless local-only): the Semgrep run fails, and its reason says this variable is why — unset it for the scan, or scan local-only. dev-guardian never turns metrics back on; a local-only scan passes --metrics=off itself.
GIT_CONFIG_COUNT every git dev-guardian starts Your own configuration entries: dev-guardian's overrides are appended after them. A value git would refuse ("bogus count") makes dev-guardian refuse to run git or any process in a repository, naming it.
GIT_SSH create_fix_pr's push Used, quoted, as core.sshCommand when the repository sets its own core.sshCommand (which is never used) and your configuration sets none.
https_proxy, HTTPS_PROXY, http_proxy, all_proxy, ALL_PROXY every git dev-guardian starts When the repository sets its own http.proxy, http.<url>.proxy or remote.<name>.proxy (never used) and your configuration sets none: the proxy git uses instead — as git would have read these variables without the repository's setting — or none.
GIT_CONFIG every git dev-guardian starts Removed from the one git config read of the repository's configuration: it would make that read, and only that one, look at another file.
npm_config_*registry*, NPM_CONFIG_REGISTRY, NPM_CONFIG_USERCONFIG, NPM_CONFIG_GLOBALCONFIG, NPM_CONFIG_PREFIX, YARN_NPM_REGISTRY_SERVER, YARN_REGISTRY, BUN_CONFIG_REGISTRY, PIP_*INDEX*, PIP_FIND_LINKS, PIP_NO_INDEX, PIP_CONFIG_FILE, VIRTUAL_ENV, UV_*INDEX*, UV_FIND_LINKS, UV_CONFIG_FILE, CONDA_PREFIX, COMPOSER_HOME, NUGET_*SOURCE*, NUGET_*FEED*, NUGET_*CONFIG*, NuGetPackageSourceCredentials_*, ProgramFiles(x86) vet_packages, the install hook Evidence of a private registry: a name missing from the public registry is then unknown, never denied. See hooks.md.