CLI reference for fallow security. Surface opt-in local security candidates for agent or human verification.
Surface local security candidates for verification. Two rule families ship: the graph-structural client-server-leak (a "use client" file that directly reads, or transitively imports a module that reads, a non-public process.env secret), and the data-driven tainted-sink catalogue (syntactic dangerous-sink candidates across a catalogue of CWE categories). Both default to off and run only under fallow security.
Findings are candidates, not confirmed vulnerabilities. Fallow reports a structural trace so an agent or human can verify whether the value can actually reach client-bundled code.
Project root directory (default: current working directory)
-c, --config <PATH>
Path to config file (default: auto-detected)
--changed-since <REF> (alias: --base)
Only report candidates whose client anchor or trace hops touch files changed since a git ref
--diff-file <PATH>
Narrow candidates to added hunks on the client anchor or import trace. Secret-source hops use file-level retention because member-access spans are not yet stored. Use - to read from stdin.
--diff-stdin
Read the unified diff from stdin
-w, --workspace <PATTERNS>
Scope output to selected workspace packages
--changed-workspaces <REF>
Scope output to workspace packages touched since the given git ref
The detector starts at files with a top-level "use client" directive and walks static imports. It reports a candidate when the client boundary can reach a module that reads a non-public process.env value.Public-by-convention env values are excluded:
Public prefix
Example
NODE_ENV
process.env.NODE_ENV
NEXT_PUBLIC_*
process.env.NEXT_PUBLIC_API_URL
VITE_*
process.env.VITE_API_URL
NUXT_PUBLIC_*
process.env.NUXT_PUBLIC_SITE_URL
REACT_APP_*
process.env.REACT_APP_API_URL
PUBLIC_*
process.env.PUBLIC_SITE_URL
GATSBY_*
process.env.GATSBY_SITE_URL
EXPO_PUBLIC_*
process.env.EXPO_PUBLIC_API_URL
STORYBOOK_*
process.env.STORYBOOK_THEME
Dynamic import() edges that the graph cannot follow are counted in the output as unresolved edge files. A clean finding list with a non-zero unresolved count is not a clean bill.
A data-driven catalogue of syntactic sink candidates. Where client-server-leak is a graph-reachability rule, tainted-sink flags a call, member assignment, or tagged template that reaches a non-literal argument at a known dangerous sink. A fully literal argument never fires.All catalogue findings carry kind: "tainted-sink" plus a category (the catalogue id) and a cwe number. The catalogue ships these categories:
These are deliberately conservative candidates: a non-literal argument is a signal to verify, not proof of a vulnerability. Fallow does not prove the value is attacker-controlled or reaches the sink unsanitized. Verification is the agent’s job.
Sink-shaped nodes whose callee cannot be resolved to a static path (dynamic dispatch, computed members, aliased bindings) are counted in the output as unresolved_callee_sites. As with client-server-leak, a clean finding list with a non-zero count is not a clean bill.
Both tainted-sink and client-server-leak default to off and are surfaced only by fallow security (never under bare fallow or the audit gate). Scope which catalogue categories run with security.categories in config:
// fallow-ignore-file security-sinkconst el = document.querySelector(".out");el.innerHTML = render(userInput);
One security-sink token covers every catalogue category. Use suppression only after verifying that the value cannot reach the sink unsanitized, for example because the input is a trusted constant, server-only, or sanitized upstream.
Each finding includes kind, path, line, col, evidence, trace, and actions. tainted-sink findings additionally carry category (the catalogue id, for example "dangerous-html") and cwe (the category’s CWE number); client-server-leak findings omit both.