v9.5.0 — intra-file taint tracking, multi-line context fix, OAuth/LDAP/cmd/proto
[9.5.0] - 2026-04-21
Phase 3 of the roadmap. Caspian gains its first dataflow-aware analysis (intra-file taint tracking), a multi-line context fix that unblocks strict CI gating, and four new vulnerability-class families. The single biggest detection-quality jump since v8.0.
Added — taint tracking (the moat)
-
Intra-file taint engine (src/taint.ts) — Caspian's first dataflow-aware analysis. Tracks user-input sources (
req.body / query / params / headers, Flaskrequest.*, PHP$_GET / $_POST,process.argv / env, Pythonsys.argv / os.environ) through simple variable assignments forward to dangerous sinks within the same function. Findings are emitted as 8 new rule codes:TAINT001command injection (exec / spawn)TAINT002eval /new Function/vm.runInNewContextTAINT003filesystem path (path traversal)TAINT004SQL sinks (.query / .execute / .raw)TAINT005open redirect (res.redirect / sendRedirect)TAINT006reflected XSS (res.send / .innerHTML / document.write)TAINT007SSRF with provenance (fetch / axios / requestswith tainted URL)TAINT008prototype pollution viaObject.assign / _.merge / jQuery.extend
Sanitiser-aware: drops taint when the value passes through
validator.*,DOMPurify.sanitize,escape*,Number / parseInt, Zod / Joi.parse,new URL(...),path.resolve(...)+startsWith,express-validator. Performance-bounded: 200 lines / function, 50 in-flight tainted vars, 100 ms / file deadline. New settingcaspianSecurity.enableTaintTracking(defaulttrue) gates the pass. -
Limits documented openly in the rule messages: no cross-function, no cross-file, no aliasing through arrays / objects / destructuring. Catches the 60–70 % of vulns that happen in a single controller; the rest needs a real taint analyser (Semgrep / CodeQL).
Added — vulnerability coverage
- OAuth hygiene (
OAUTH001–OAUTH006) — callback handlescodewithoutstateverification (CSRF), authorize URL missingstate, code exchange without PKCE, open-redirect viaredirect_uri, deprecated implicit flow, wildcardscope. Slotted into AuthAccessControl. - LDAP injection (
LDAP001–LDAP003) — filter built via concatenation / template literal / Python f-string; JavaDirContext.searchwithoutLdapEncoder.filterEncode; Pythonpython-ldap.search_swithoutescape_filter_chars. Slotted into AuthAccessControl. - Command injection (
CMD001–CMD007) — Nodeexecwith concatenated input,spawn({shell:true}), Pythonos.system / subprocess(shell=True), PHPshell_exec / passthruwith$_GET / $_POST, Ruby string-formsystem / backticks / IO.popen, JavaRuntime.exec / ProcessBuilderwith concatenation. Slotted into APISecurity. - Prototype pollution expansion (
FE007a/FE007b/FE007c) —Object.assign({}, req.body), lodash_.merge / _.defaultsDeepwith untrusted source,{...req.body}spread without schema validation. OriginalFE007(__proto__literal) gainscontextAware: true.
Fixed — F11 multi-line context awareness
- New shared module src/scanContext.ts with
buildLineStates(text)— one-pass char-by-char walker that records per-line state (inside template literal, inside block comment, inside${}expression). Handles JS regex literals correctly, including character classes (/[...]/), so/\/g` no longer cascades the walker into a phantom template-literal state for the rest of the file. - Both
analyzer.ts(extension host) andcli/scan.tsconsume it.contextAwarerules now correctly skip matches inside multi-line template literals, JSDoc blocks, and across${...}expressions. Removes ~70 lines of duplicated context logic. XSS001/XSS002/CRED001markedcontextAware: trueso doc examples and webview-generation template literals stop false-positiving in projects that emit HTML to webviews.- Self-scan CI flipped back to
--fail-on error(was softened in v9.3.0). Caspian's own source now passes the strict gate.
Changed
- Rule totals: 240+ → 270+. Test suite: 812 → 880. Two new test suites (
scanContext.test.ts,taint.test.ts). .github/workflows/self-scan.ymlexcludes__tests__,rules,cli(rationale documented in the workflow file — each is its own intentional design).