Skip to content

v2.87.0: sharper, ranked, framework-aware security candidates

Choose a tag to compare

@BartWaardenburg BartWaardenburg released this 03 Jun 06:41
· 286 commits to main since this release
v2.87.0
d9d22a3

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 via event.data, and fetch() 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, Angular bypassSecurityTrust*, and DOM sinks such as document.write and 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_candidates MCP tool. A read-only tool wraps fallow security --format json and 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.relative containment guards, so allowlisted redirects, allowlisted outbound URLs, and contained path values no longer report. Near misses (mutable allowlists, helper predicates, guards after route use, plain startsWith(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 package sass export. 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 on const svc = useMemo(() => new Svc(), []) are now credited instead of flagged as unused class members.
  • Nested workspace packages under a bare grouping directory (packages/* matching packages/themes, with the real package at packages/themes/my-theme) are now discovered as their own workspace.

Full Changelog: v2.86.0...v2.87.0