@clear-capabilities/agentic-security-scanner 0.151.1 → 0.151.2

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.
package/CHANGELOG.md CHANGED
@@ -9,6 +9,79 @@
9
9
  > make the history less accurate, not more.
10
10
 
11
11
 
12
+ ## 0.151.2 - Real C# SAST accuracy improvements: interprocedural call-graph fixes + new detector coverage
13
+
14
+ Follow-up to 0.151.1's SARD work: a direct effort to improve the scanner's actual code-scanning
15
+ accuracy (not benchmark-shape gaming), using self-authored probe fixtures rather than reading the
16
+ deny-listed SARD corpus. Found and fixed two general engine bugs plus several detector gaps, all
17
+ verified with real self-authored fixtures and zero regressions. Full account, including the
18
+ benchmark-scoring limitation that makes the bigger fix's true impact invisible on the SARD
19
+ number specifically, in `bench/sard/IMPLEMENTATION_STATUS.md`'s "Real accuracy improvement pass"
20
+ section.
21
+
22
+ **Engine fixes (general, not SARD-specific):**
23
+ - **C# `this.method(...)` same-instance calls never resolved in the call graph.** A same-class
24
+ helper call written as `this.badSink(data)` silently blocked all interprocedural taint into
25
+ the callee, for every sink inside it. `parser-cs.js` lowers this to the flat callee string
26
+ `"this.foo"`, but the target method's registered name is bare (`"foo"`) — the opposite
27
+ asymmetry from Java's documented class-qualified-name gap, and unhandled by the existing
28
+ bare-tail fallback (which explicitly skips any callee containing a dot). Fixed in
29
+ `callgraph.js` with a new resolution branch, unconditional (not a guess — `this.` unambiguously
30
+ means "a member of the current instance"). 4 new tests.
31
+ - **C# cross-class calls never resolved at all — same file or not.** `parser-cs.js`'s function
32
+ IDs never recorded which class a method belongs to, so `callgraph.js`'s cross-class index
33
+ (which resolves `new Helper().Sink(x)`, `Helper h = new Helper(); h.Sink(x)`, and bare
34
+ `Helper.Sink(x)`) was permanently empty for C#. Fixed by having the parser track each method's
35
+ enclosing class (matching Java's/JS's existing `"ClassName.method"` convention) plus a
36
+ companion local variable-type-inference pass for the `Helper h = new Helper(); h.Sink(x)`
37
+ shape (refuses to guess when a variable holds more than one distinct constructed type in the
38
+ same function). Also closed a related gap found along the way: a bare
39
+ `new Helper().Sink(data);` statement with no assignment previously dropped entirely. 8 new
40
+ tests, zero regressions across the full test suite.
41
+ - Fixing the class-qualified naming above required also hardening the `this.`-call fix from the
42
+ same session to fall back to the existing bare-tail index, so the two fixes compose correctly
43
+ rather than one silently breaking the other.
44
+
45
+ **Detector coverage:**
46
+ - **CWE-94 code injection: `CSharpCodeProvider.CompileAssemblyFromSource` had zero coverage.**
47
+ The only existing C# code-injection patterns were Roslyn's `CSharpScript` (2014+) and
48
+ `DataTable.Compute` — missing `System.CodeDom.Compiler`'s `CSharpCodeProvider`, the
49
+ historically standard .NET dynamic-compile API, predating Roslyn scripting by a decade and
50
+ still the most commonly documented one. Largest single measured improvement of this release.
51
+ - **CWE-78 command injection: `Process.Start` with a non-shell-literal filename was explicitly
52
+ out of scope.** Missed a real, well-documented .NET Framework gotcha:
53
+ `ProcessStartInfo.UseShellExecute` defaults to `true` on .NET Framework (only .NET Core/5+
54
+ default it to `false`), so `Process.Start("ping", tainted)` goes through the OS shell
55
+ regardless of the filename. Added as a companion sink at `high` (not `critical`) severity to
56
+ reflect the framework-version caveat, alongside the existing shell-literal-gated entry.
57
+ - **LDAP injection attribute matching was a hardcoded 10-item enum** (`uid`/`cn`/`mail`/...).
58
+ Real LDAP/Active Directory schemas define far more attributes than any fixed list can
59
+ enumerate, including custom extensions — a real, general precision/recall bug for production
60
+ LDAP code, not a benchmark-specific one. Widened to a general LDAP-attribute-name shape.
61
+
62
+ **Self-inflicted bug caught by this project's own gate:**
63
+ - The new C# class-boundary-detection regex was a genuine, timing-confirmed ReDoS (30,000
64
+ non-matching modifier-keyword repeats took 5+ real seconds) — caught by `bench:self-scan:check`
65
+ exactly as designed. A first fix (bounding the repetition count) was measurably linear but
66
+ still tripped the static ReDoS detector's "nested quantifier" heuristic; unrolled into explicit
67
+ non-nested optional groups to satisfy both real safety and the detector.
68
+
69
+ **What this release honestly does NOT close:**
70
+ - The cross-class fix is proven correct via direct fixtures and unit tests, but the real SARD
71
+ corpus's macro-F1 for C# barely moved (8.4% → 10.8%, almost entirely from the CWE-94 fix
72
+ above) — traced to a benchmark-scoring limitation, not a detection gap: `bench-realworld.js`'s
73
+ scorer only credits a finding located inside the *expected method's own line range*, and an
74
+ interprocedural finding is, by definition, located in the callee it flows into. The scanner is
75
+ now more accurate; the benchmark's strict per-method scoring can't see it yet. Scoped as a
76
+ concrete next step, not fixed here.
77
+ - Java's own version of the `this.`-call bug (`parser-java.js` lowers it to the literal string
78
+ `"unknown"` before it ever reaches the call graph) is unfixed — a separate, parser-level gap.
79
+ - Weak-crypto/weak-RNG families (`new Random()`, `MD5`/`SHA1` for passwords) were investigated
80
+ and deliberately left alone: the existing precision heuristic (requires a security-suggestive
81
+ identifier nearby) is real and general, and loosening it just to score higher on this one
82
+ benchmark would trade away real-world precision — the exact shortcut this work was asked not
83
+ to take.
84
+
12
85
  ## 0.151.1 - Adversarial premortem on the SARD benchmarking subsystem: 12 real findings, 12 real fixes
13
86
 
14
87
  A structured adversarial premortem ("assume this subsystem has completely failed six months