v2.90.0: agent-actionable security candidates, LSP pull diagnostics
v2.90.0 turns the opt-in fallow security surface into an agent-actionable layer: every candidate now carries a structured record an AI agent can act on, a new exfiltration category, an editor diagnostic path, and a PR regression gate. It also modernizes the LSP server (pull diagnostics for Neovim, Zed, and Helix), adds editor controls for diagnostic noise, and ships two CLI ergonomics flags.
Security findings remain candidates for verification, not confirmed vulnerabilities. The whole surface stays default-off and never appears under bare fallow or fallow audit.
Security: agent-actionable candidates
- Structured candidate records (
--format json). Every finding now carries acandidateobject with three slots an agent can act on directly:source_kind(the untrusted input that reaches the sink, as a stable catalogue id likehttp-request-inputorprocess-env), a self-containedsink(path, line, column, category, CWE, callee), and aboundary(client/server or module crossing, plus the architecture zone). Findings with a traced flow also carry a compacttaint_flow. Each finding has a stablefinding_id(identical to its SARIFpartialFingerprintsvalue) so an agent can correlate a candidate across runs after a rebase. All additive and output-only. secret-to-networkexfil category (opt-in). Detects a non-publicprocess.env/import.meta.envsecret reaching the body or options argument of a network call (fetch,axios,got,http.request, ...) when the same identifier carries the secret into the request, the classic data-exfiltration shape. Because legitimate auth is also "a secret reaching a network call," it is opt-in viasecurity.categories.include: ["secret-to-network"]. Each candidate carriescandidate.network.destination(the request URL when literal, or absent when dynamic, the higher-signal case). The same change stops treating public-by-convention env vars (NEXT_PUBLIC_,VITE_, ...) as secrets across the catalogue and adds Vite'simport.meta.envas a recognized source.- Editor diagnostics (opt-in). Raise the
security-sinkorsecurity-client-server-leakrule towarn/errorand the fallow LSP server reports each candidate as aninformation-level diagnostic in any LSP editor. The hover leads with confidence signals (source-backed, entry-reachable) and a pointer tofallow security --file; a quick-fix dismisses the candidate. Structureddatalets agents reading editor diagnostics triage without re-running the CLI. --gate newregression gate.fallow security --gate new --changed-since <ref>(orgit diff --cached --unified=0 | fallow security --gate new --diff-stdin) gates a PR only on candidates introduced on changed lines, exiting 8 when any exist. A refactor that merely touches a file with an existing sink passes; a diff the gate cannot compute is a loud exit 2, never a green gate. Exit code 8 is dedicated so CI can soft-gate it (GitLaballow_failure: exit_codes: [8]).- More catalogue coverage. Source-backed resource amplification (CWE-400,
new Array(n)/Buffer.alloc/String.prototype.repeatfrom request input), ReDoS regex (CWE-1333), dynamicRegExpconstruction, disabled TLS validation,jsonwebtokenverify without an algorithm allowlist, secrets or PII reaching logs (source-gated), Viteimport.meta.envclient reads, one-hop helper-return source flows, dead-code cross-linking, more entry-point source inputs (GraphQLargs, tRPCinput, webhooks, DOM-XSS reads), and MCP path scoping for agent edit loops.
Editors
- LSP modernization with pull diagnostics. The server moved to the maintained
tower-lsp-server+ls-types, unlocking LSP 3.17 pull diagnostics withworkspace/diagnostic/refresh. Pull clients (Neovim, Zed, Helix) avoid duplicate push/pull namespaces while push-only clients keep working, and the docs now cover Neovim setup. Thanks @tris203 for the patch (#1033). - VS Code complexity breakdown is now progressive disclosure. A compact lens sits above each over-threshold function and the dense per-line breakdown is revealed per function (via Health-view selection, lens click, or hover) instead of all at once.
- Quieter diagnostics, on your terms. Set
fallow.diagnostics.severitytoinformationorhint, commit a team mute baseline withfallow.diagnostics.mutedCategories, and toggle all squiggles from a one-click status-bar button. The Security Candidates view groups candidates by kind / CWE with per-group counts. - Sidebar and editor now agree on production mode.
fallow.productionis a tri-stateauto/on/offforwarded to both the CLI-driven sidebar and the LSP server; the CLI gains a global--no-productionflag to force it off.
CLI
--output-file/-owrites the rendered report to a file for any--format(ANSI-free even on a TTY), with progress kept on stderr.- Configurable cache location. Set
cache.dirin config orFALLOW_CACHE_DIRto keep the analysis cache outside the default.fallow/directory.
Bug fixes
- pnpm workspace dependencies imported through symlinked workspace packages are now credited when analyzing a package directly. Thanks @alvis for the report (#1008).
- Prose
import("...")examples inside JSDoc comments no longer create false unresolved-import findings. Thanks @jsgoldman for the patch (#1010). - User-facing messages now name the canonical
fallow dead-codecommand instead of the deprecatedcheckalias.
Full Changelog: v2.89.0...v2.90.0