@clear-capabilities/agentic-security-scanner 0.151.3 → 0.153.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/CHANGELOG.md +125 -0
  2. package/dist/1336.index.js +16010 -0
  3. package/dist/agentic-security.mjs +80 -80
  4. package/dist/agentic-security.mjs.sha256 +1 -1
  5. package/package.json +7 -6
  6. package/src/dataflow/CLAUDE.md +1 -1
  7. package/src/dataflow/backward.js +104 -7
  8. package/src/dataflow/catalog.js +802 -13
  9. package/src/dataflow/cross-service-taint.js +154 -11
  10. package/src/dataflow/engine.js +875 -90
  11. package/src/dataflow/exploit-prover.js +111 -23
  12. package/src/dataflow/incremental.js +13 -0
  13. package/src/dataflow/index.js +29 -6
  14. package/src/dataflow/path-feasibility.js +86 -9
  15. package/src/dataflow/string-domain.js +168 -0
  16. package/src/dataflow/summaries.js +69 -8
  17. package/src/engine.js +118 -9
  18. package/src/ir/CLAUDE.md +2 -1
  19. package/src/ir/balanced-call.js +33 -1
  20. package/src/ir/callgraph.js +26 -2
  21. package/src/ir/class-hierarchy.js +261 -7
  22. package/src/ir/csharp-ir.js +97 -8
  23. package/src/ir/index.js +21 -1
  24. package/src/ir/parser-cs.js +706 -24
  25. package/src/ir/parser-java.js +498 -17
  26. package/src/ir/parser-js.js +22 -0
  27. package/src/ir/parser-php.js +446 -43
  28. package/src/ir/parser-rust.js +1338 -0
  29. package/src/ir/php-include-merge.js +190 -0
  30. package/src/lineage/sink-registry.js +18 -0
  31. package/src/lineage/source-registry.js +23 -0
  32. package/src/posture/csharp-analysis.js +341 -43
  33. package/src/posture/finding-defaults.js +5 -1
  34. package/src/posture/fix-coverage.js +1 -0
  35. package/src/posture/proof-coverage.js +1 -0
  36. package/src/report/index.js +12 -0
  37. package/src/sast/CLAUDE.md +1 -1
  38. package/src/sast/authz.js +144 -1
  39. package/src/sast/crypto-protocol.js +65 -7
  40. package/src/sast/csharp-cross-file.js +125 -0
  41. package/src/sast/csharp-structural.js +78 -2
  42. package/src/sast/csharp.js +574 -42
  43. package/src/sast/java-ast-folding.js +268 -11
  44. package/src/sast/java-bench-extras.js +530 -2
  45. package/src/sast/java-deserialization.js +31 -2
  46. package/src/sast/java-structural-cross-file.js +146 -0
  47. package/src/sast/java-structural.js +499 -6
  48. package/src/sast/ldap-injection.js +133 -3
  49. package/src/sast/rust.js +57 -0
  50. package/src/sast/xss-reflected-multilang.js +252 -3
  51. package/src/dataflow/smt-feasibility.js +0 -189
package/CHANGELOG.md CHANGED
@@ -9,6 +9,131 @@
9
9
  > make the history less accurate, not more.
10
10
 
11
11
 
12
+ ## 0.153.0 - Taint-engine points-to precision, and two default-adjacent capabilities rebuilt from broken to sound
13
+
14
+ Four taint-engine capabilities landed since 0.152.0, continuing the "next-generation taint analysis
15
+ capabilities" initiative: two narrow points-to-precision fixes for JS/TS class-hierarchy resolution,
16
+ and two substantial rebuilds of capabilities found to be structurally non-functional on real data —
17
+ one opt-in (SMT path feasibility), one running by default (cross-service schema-driven taint).
18
+
19
+ - **Cross-call-site parameter type inference for CHA** (`dataflow/class-hierarchy.js`): JS/TS gains
20
+ the same "driver constructs a concrete instance, passes it as a parameter to a helper that invokes
21
+ a virtual method" resolution Java/C# already had via declared parameter types — a narrow,
22
+ well-scoped slice of Andersen-style points-to analysis, not the full thing. A call site's literal
23
+ `new ClassName(...)` argument, or an identifier whose type was already established, now propagates
24
+ onto the callee's parameter; two call sites disagreeing on the class permanently refuse to resolve
25
+ it rather than guess.
26
+ - **Factory-function return-type inference for CHA**: the sibling gap on the RETURN side —
27
+ `function makeHelper() { return new Helper(); } const h = makeHelper();` — closed with the same
28
+ "never guess" discipline: a function only qualifies when every reachable `return` is a `new
29
+ ClassName(...)` of the same class.
30
+ - **SMT/exploit-proof path feasibility, rebuilt from the ground up** (`dataflow/exploit-prover.js`,
31
+ `dataflow/backward.js`): the pre-existing SMT-lite infeasibility check was fed a flat list of
32
+ taint sources reaching a sink, never a real sequential source-to-sink path, so its own
33
+ (correctly-written) metacharacter-exclusion logic had nothing genuine to walk — confirmed by
34
+ direct code reading, and by its own tests only ever exercising hand-fabricated fixtures the real
35
+ engine never produces. A second, parallel, independently-broken module (`smt-feasibility.js`, also
36
+ opt-in) had the identical defect plus a direct `severity` mutation that violated this codebase's
37
+ recall-preserving-demotion convention; retired outright rather than fixed twice. Three real engine
38
+ bugs were found and fixed to make the rebuild work on real data: `sliceBackward` couldn't trace
39
+ through a call-shaped sanitizer RHS, `engine.js`'s own finding-normalization allowlist silently
40
+ dropped `argIndex`, and a compound (string-concatenation) sink argument couldn't be resolved. The
41
+ rebuilt check now refuses to conclude safety the moment an opaque, unmodeled call sits between a
42
+ trusted sanitizer and a sink, verified via direct adversarial reproduction. `z3-solver` is added as
43
+ a genuine `optionalDependencies` entry, with its current (load-only, not yet query-discharging)
44
+ scope documented honestly rather than overclaimed. Opt-in via `AGENTIC_SECURITY_SYMEXEC=1`.
45
+ - **Cross-service schema-driven taint, rebuilt from a complete no-op** (`dataflow/cross-service-taint.js`):
46
+ this module runs BY DEFAULT (opt-out via `AGENTIC_SECURITY_NO_CROSS_SERVICE=1`) but was found, via
47
+ direct reproduction, to have never worked at all for real findings — an HTTP path-template matcher
48
+ that failed on the module's own documented example (a `:param` vs. `{param}` placeholder-syntax
49
+ mismatch), a field-name correlation check that read finding properties (`source.snippet`/
50
+ `source.expr`) that do not exist on any real finding, and a report-layer allowlist that silently
51
+ dropped the annotation even when it did fire. Rebuilt with structural path-template matching and
52
+ provenance-based correlation for HTTP transport (a real, catalog-backed signal, since a real
53
+ finding never retains the specific field name that reached a sink) with a best-effort text-match
54
+ fallback for other transports; the report-layer allowlist fix means the annotation now actually
55
+ reaches SARIF/JSON/HTML output. A genuine remaining scope limitation — no mechanism seeds a NEW
56
+ taint source from a `consumes` declaration — is documented in the module's own header rather than
57
+ left implicit.
58
+ - **Measured**: both rebuilds verified via full real-corpus TEST-split runs for all three
59
+ SARD/Juliet languages, byte-identical to the 0.152.0 baseline in every case (Java macroF1=59.1%,
60
+ C# macroF1=68.6%, PHP macroF1=48.2%) — neither the SARD fixtures nor the CVE-replay/self-scan/
61
+ mutation/layer-recall corpora exercise these specific capabilities, so this release ships real,
62
+ adversarially-tested engine correctness with no corpus-visible movement, consistent with this
63
+ project's own established precedent for capability work independent of any one benchmark.
64
+
65
+
66
+ ## 0.152.0 - Rust: first-class language, and the SARD 80% F1 push's taint-engine architecture work
67
+
68
+ Rust joins the first-class language set (JS/TS, Python, Java, Kotlin, Go, Ruby, PHP, C#) with both
69
+ a hand-rolled IR frontend (`scanner/src/ir/parser-rust.js`, the `parser-go.js`/`parser-cs.js`
70
+ pattern) feeding the Layer-2 taint engine, and dedicated SAST rules — Rust previously had only the
71
+ opt-in, WASM-based tree-sitter long-tail path, which nothing in the taint engine ever consumed.
72
+
73
+ - **Taint coverage** (`dataflow/catalog.js`, ~90 new source/sink/sanitizer entries): SQL injection
74
+ (sqlx/diesel/rusqlite/postgres, distinguishing the compile-checked `query!` macro and `.bind()`
75
+ parameterization from `format!`-built SQL text), command injection (`Command::new("sh").arg("-c")`
76
+ vs. safe argv-array execution), path traversal (`std::fs`/`tokio::fs`, recognizing a
77
+ canonicalize+`starts_with` containment guard), SSRF (reqwest/ureq), reflected XSS
78
+ (actix/axum/rocket/warp response bodies), open redirect, log injection, insecure deserialization,
79
+ and uncontrolled resource consumption. Sources include axum/actix/rocket extractor-typed
80
+ parameters (`Query`/`Path`/`Json`/`Form`/`HeaderMap`) via a new `paramAnnotations` side-channel
81
+ and route-attributed handlers (`#[get("/<x>")]`).
82
+ - **SAST rules** (`sast/rust.js`): TLS verification disabled, weak hash/cipher (MD5/SHA-1/DES/RC4),
83
+ weak randomness feeding a token/secret identifier, and unsafe raw-memory operations
84
+ (`transmute`/`from_raw_parts`/`get_unchecked`) — alongside the pre-existing sqlx-format/shell-form
85
+ command-injection/zero-seed-RNG/unsafe-block regex rules.
86
+ - **A real parser design lesson, not specific to Rust's own correctness**: `.unwrap()`/`.expect(msg)`
87
+ chained onto a sink call shift the chain's terminal segment away from the sink's own name (the same
88
+ "terminal segment shift" defect class already documented for Go/Java/Kotlin) — nearly every
89
+ real-world async Rust call site ends this way, so they are popped from the parsed call chain
90
+ rather than merely treated as taint-transparent.
91
+ - **Measured**: `bench/layer-recall` — 5/5 (100%) whole-corpus, 3/3 (100%) deep-tier on first
92
+ measurement (see `docs/METRICS.md`; the corpus is small today, so this reflects the corpus's own
93
+ composition, not general ecosystem coverage). `bench/cve-replay` — 5 new entries (2 capability,
94
+ 3 deep), all `pre:TP post:TN`. `bench/mutation` — 1 new detection-dimension baseline/adversarial
95
+ pair (`format!`-built SQL fires; the parameterized `.bind()` form does not).
96
+
97
+ ### SARD/Juliet 80% macro-F1 push (`bench/sard/EXECUTION_STATUS.md`) — substantial progress, DoD not yet met
98
+
99
+ A long-running execution PRD targeting macro-F1 >= 80% on the held-out TEST split for Java, C#, and
100
+ PHP against the SARD/Juliet benchmark corpus. **Honest status: real, verified, substantial gains for
101
+ all three languages, but the 80% target is not yet reached** — Java macroF1=59.1%, C#
102
+ macroF1=68.6% (clears the 50% M2 gate), PHP macroF1=48.2% (all measured on TEST split, never on
103
+ gold/answer-key signals — see the PRD's own integrity rules). This release ships the engine and
104
+ scoring work; the PRD stays open.
105
+
106
+ - **Measurement integrity first**: fixed truncation-masking in the benchmark harness (a truncated
107
+ scan was silently scoring as if complete), added per-CWE batched scanning to eliminate it in
108
+ practice, and made the scan surface match the gold surface exactly.
109
+ - **Structural class resolution**: real `ir.classes` emission and class-hierarchy-based method
110
+ resolution replacing regex heuristics, across the languages that lacked it.
111
+ - **Interprocedural completeness**: cross-file field/chain taint for C# (`csharp-cross-file.js`) and
112
+ Java, collection-element taint (typed reads, for-each binding), abstract/interface dispatch via
113
+ declared base type, and real branch+join CFGs for Java `if`/`switch` (previously linear
114
+ fall-through — a real correctness bug, not just a recall gap).
115
+ - **Precision**: guard-predicate narrowing (`is_numeric`/`ctype_digit`/`int.TryParse`/etc. on an
116
+ if-statement's TRUE branch only), a proven-clean ledger, and dozens of per-CWE false-positive
117
+ fixes across Java/C# (many rooted in Juliet's own "dead code by construction" idioms —
118
+ `if(true)`/`if(5==5)`/constant-folded fields/methods — defeating naive literal-tracking heuristics).
119
+ - **Call-string context-sensitivity, built from scratch this push**: `dataflow/engine.js` now
120
+ narrows a shared static/class field's taint to only the callers that can actually reach it
121
+ (previously any writer anywhere in the class tainted every reader), closing a real
122
+ context-sensitivity gap independently identified across all three languages. A second,
123
+ previously-built-but-never-validated k=1 call-string mechanism (`AGENTIC_SECURITY_KCFA_CALLSTRING`,
124
+ opt-in) was found broken, root-caused, and repaired.
125
+ - **Two new "next-generation taint analysis" capabilities**, requested and scoped independently of
126
+ the SARD benchmark itself: (1) sound regex-validation-guard narrowing for JS/TS — a
127
+ fully-anchored pattern like `/^[a-zA-Z0-9]+$/` used as `if (pattern.test(x))` now provably proves
128
+ `x` metacharacter-free on the true branch, via a new conservative character-class parser
129
+ (`dataflow/string-domain.js`'s `isSafeValidationPattern`); (2) object-instance field taint via
130
+ method calls, a general (not JS-specific) engine capability — `bad.setData(tainted)` now taints
131
+ `bad`'s own field, read back correctly through `bad.getData()`, while a **different** instance of
132
+ the same class stays untainted (real object-instance sensitivity, without a full
133
+ allocation-site-keyed heap model).
134
+ - PHP: closed total blackouts for LFI/RFI (`include`/`require` result assignment), several IDOR
135
+ sub-shapes, and a cross-file variable-scope-merging capability for split include chains.
136
+
12
137
  ## 0.151.3 - Adversarial premortem on the SARD benchmarking PROGRAM itself: full remediation, first genuine held-out numbers
13
138
 
14
139
  A structured adversarial premortem ("assume this has completely failed six months from now — work