v2.87.0: sharper, ranked, framework-aware security candidates
Security candidates: sharper, ranked, framework-aware
This release builds out the opt-in fallow security candidate layer with source modeling, reachability ranking, framework-aware sinks, five more CWE categories, and an MCP tool for agent handoff. As before, results are candidates for verification, not confirmed vulnerabilities: detection stays deterministic and syntactic, and fallow prefers false-negatives over false-positives.
Security candidate engine
- Untrusted source modeling. Candidates are sharpened by recognizing untrusted sources (
req.query/req.params/req.body, route parameters,process.argv,message-event / WebSocket / worker payloads viaevent.data, andfetch()responses) and walking backward from a sink argument to a source within the same function. A sink fed from an untrusted source is a stronger candidate; values derived only from constants or config no longer fire on the source axis. This approximates taint without a full inter-procedural data-flow engine. - Reachability-weighted ranking. Candidates on a path reachable from an entry point (HTTP route handlers, request entry points) now rank above candidates in one-off scripts or isolated helpers, turning a flat list into a prioritized one.
- Framework-aware sinks. Per-framework idioms are recognized via the plugin system: React
dangerouslySetInnerHTML, AngularbypassSecurityTrust*, and DOM sinks such asdocument.writeand jQuery-style.html(). - Five new CWE categories. Prototype pollution (CWE-1321), zip-slip / tar path traversal (CWE-22), NoSQL injection (CWE-943), server-side template injection (CWE-1336), and XML external entity expansion (CWE-611).
Agent integration
security_candidatesMCP tool. A read-only tool wrapsfallow security --format jsonand returns the security JSON envelope (category, CWE, evidence, structural trace, blind-spot counters), framed explicitly as unverified candidates so agents verify before editing. SARIF, CI, baseline, summary, failure, and fix behavior stay CLI-only.
Bug fixes
- Sanitizer-aware suppression. DOMPurify-backed HTML suppression now shares a domain-scoped sanitizer model with literal-allowlist URL guards and
path.relativecontainment guards, so allowlisted redirects, allowlisted outbound URLs, and contained path values no longer report. Near misses (mutable allowlists, helper predicates, guards after route use, plainstartsWith(base)checks) still report. - Accurate SFC sink spans. Security sink candidates in Vue and Svelte single-file components now point at the real component source line instead of a line inside the isolated script body.
- Firebase Messaging service workers are no longer reported as unused files. Thanks @rbalet for the report.
- Ionic Angular page lifecycle methods (
ionViewWillEnter,ionViewDidEnter,ionViewWillLeave,ionViewDidLeave) are no longer flagged as unused class members. Thanks @rbalet for the report. - Angular Material Sass entrypoints such as
@use "@angular/material" as mat;now resolve through the packagesassexport. Thanks @rbalet for the report. - VS Code sidebar switches from a search icon to a reload icon once results exist, clarifying that the button reruns analysis. Thanks @rbalet for the report.
useMemo-bound class instances: methods onconst svc = useMemo(() => new Svc(), [])are now credited instead of flagged as unused class members.- Nested workspace packages under a bare grouping directory (
packages/*matchingpackages/themes, with the real package atpackages/themes/my-theme) are now discovered as their own workspace.
Full Changelog: v2.86.0...v2.87.0