@clear-capabilities/agentic-security-scanner 0.141.0 → 0.142.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.
package/CHANGELOG.md CHANGED
@@ -10,6 +10,141 @@
10
10
 
11
11
 
12
12
 
13
+
14
+ ## 0.142.0 — The last five PRD items, and three criteria that now fail on evidence
15
+
16
+ 0.141.0 built instruments for the surfaces that had none. This closes the
17
+ remainder of `docs/WORLD_CLASS_HARNESS_PRD.md`: four of the five items found
18
+ live engine bugs, and the fifth re-derived the headline the whole document rests
19
+ on. Three success criteria now **fail** — measured, rather than unknown.
20
+
21
+ ### A sanitizer could be undone and the flow still read as clean
22
+
23
+ `he.decode(escapeHtml(req.query.name))` reaching an HTML sink was reported
24
+ **sanitized**. The decode puts back exactly what the escape removed, so this was
25
+ a missed XSS presented as a clean flow.
26
+
27
+ Nothing modelled reversal: the catalog holds sanitizers, a decoder is the
28
+ opposite, so it was never even recorded on the path. Fixed across three layers —
29
+ the taint walk now collects un-sanitizer callees, the gate maps them to the
30
+ family they reverse (percent-decoding does **not** undo HTML escaping, so a flat
31
+ list would be wrong), and the finding-projection allowlist had to learn the new
32
+ field. That last one is why the fix looked inert through three rounds of
33
+ debugging.
34
+
35
+ Found by the mutation gate, which went from 12 to **34 cases** — the five
36
+ detector families 0.141.0 shipped had owed a metamorphic pair and an adversarial
37
+ near-miss and had none.
38
+
39
+ ### The CloudFormation ingress rule was keyed on YAML key order
40
+
41
+ `- CidrIp:` first and `- IpProtocol:` first are the same template — YAML mappings
42
+ are unordered — and only the second matched. The rule was keyed on the author's
43
+ formatting, which is syntax, not meaning. Also caught by the mutation gate, by
44
+ the metamorphic case that exists for exactly this.
45
+
46
+ ### Every reachability demotion we could adjudicate was wrong
47
+
48
+ Reachability was reported as a demotion *rate*, and that rate was **0 for every
49
+ entry by construction**: `bench/sca-replay` fetched lockfiles, so the analysis
50
+ had no source to walk. A number that is structurally zero looks like a
51
+ measurement and is not one.
52
+
53
+ With source fetched and scored against an import-level oracle: **3 adjudicable
54
+ demotions, 3 false-unreachable — 100% wrong, in the missed-exploit direction.**
55
+ `express`/`cookie`, `express`/`send`, `poetry`/`requests` — each demoted to
56
+ `info` and out of the report, each verified by hand as genuinely imported.
57
+
58
+ Three defects behind it:
59
+
60
+ - **Failure to prove reachability was reported as proof of unreachability.** A
61
+ site the analysis could not reason about became a positive claim. It is now
62
+ `unknown`, a state the code already used elsewhere.
63
+ - **A project with no routes was still asked "reachable from a route?"** For a
64
+ library that question has no answer — its callers are its users, not in the
65
+ tree.
66
+ - **`_enclosingFn` knew two of four declaration forms.** `res.cookie = function
67
+ (…)` — how most of the JS ecosystem defines a public method — was invisible, so
68
+ the scan attributed call sites to unrelated functions further up the file. It
69
+ now also tracks whether the enclosing function is **exported**, because a
70
+ public-API function with no in-tree caller is the normal case, not dead code.
71
+
72
+ **If you use SCA reachability to triage, this affected you**: findings were being
73
+ demoted out of your report on projects that genuinely import the vulnerable
74
+ package.
75
+
76
+ ### The VS Code extension had never been type-checked
77
+
78
+ `typescript` is now a devDependency and `npm run typecheck` runs in CI. It found
79
+ errors immediately: the tsconfig declared no `types` at all, so `process`,
80
+ `setTimeout` and `NodeJS.Timeout` were every one of them unresolved — `@types/node`
81
+ was installed and nothing consumed it — plus two implicit `any` parameters. The
82
+ build is esbuild, which strips types without checking them, so none of this had
83
+ ever surfaced.
84
+
85
+ Neovim and JetBrains are now smoke-tested in CI too. JetBrains is classified
86
+ **informational**: it downloads a full IntelliJ distribution, so red there is more
87
+ often the network than this code, and a habitually-red gate stops being read.
88
+
89
+ ## The population re-measured — and it is worse
90
+
91
+ 991 scored entries at engine 0.141.0 (the code that ships here), against 315 at
92
+ 0.138.0 before:
93
+
94
+ | | before | **now** |
95
+ |---|---:|---:|
96
+ | localized recall | 3.56% | **2.83%** |
97
+ | localized precision | 44.00% | **36.36%** |
98
+ | fix-discrimination | 81.8% | **71.43%** |
99
+ | held-out recall | — | **2.93%** |
100
+
101
+ **The headline fell because the question got harder.** The corpus tripled once
102
+ the advisory miner could page past the first hundred entries per ecosystem, and
103
+ what it pulled in is recent, TypeScript-heavy and dominated by authorization
104
+ classes. Held-out tracks development almost exactly, so nothing is fitted.
105
+
106
+ **Ruby 0% → 3.20%. Go 0% → 1.19%.** Both measured zeros are off zero, on
107
+ populations 8× and 1.2× their old size. **PHP is the new zero, at 0/73.**
108
+
109
+ Two of this release's own fixes are confirmed on real code rather than their own
110
+ fixtures: the Ruby `File.join` rule earns `lsegal/yard`, and `CONVENTION` earns
111
+ its first localized true positive ever on GitPython — the family recorded as
112
+ permanently silent until it turned out to be mislocalized by five lines.
113
+
114
+ ### Three success criteria now fail, on evidence
115
+
116
+ - **Fix-discrimination is 71.43%**, below its 80% floor. 8 of 28 findings still
117
+ fire on the code the fix produced — those detected an API, not a vulnerability.
118
+ - **Taint contributes 1 of 28** localized true positives. It was 1 of 12; the
119
+ count did not move while the population tripled. Deep mode also costs 5 extra
120
+ false positives and **loses** a Go finding that pattern-only makes.
121
+ - **Compliance still has no accuracy instrument** — the last feature measured by
122
+ nothing.
123
+
124
+ ### Measured and deliberately not fixed
125
+
126
+ - **The agent trust-boundary delta is 0 of 0 — undefined, not zero.** The
127
+ population now holds 28 entries of real MCP-server code; the engine produces no
128
+ localized true positives on any of them, so there is nothing for the boundary
129
+ modelling to have contributed to. It is not silent there — 21 findings per
130
+ entry, all on the advisory's own files, none of the labelled class. WRONG-CWE,
131
+ on the most differentiated surface in the product.
132
+ - **Reachability now demotes nothing** on the source-bearing corpus. The false
133
+ demotions are gone; whether the new caution is correct needs applications with
134
+ real routes, which those four entries are not.
135
+
136
+ ## Also
137
+
138
+ - A whole-population benchmark run **wedged** at 0.0% CPU after 4.5 hours, taking
139
+ every already-scored entry with it. `bench/independent/runner.mjs` now takes
140
+ `--offset`/`--limit` and `merge-chunks.mjs` reassembles the slices,
141
+ **recomputing** every aggregate from the per-entry rows and refusing to write
142
+ unless that reproduces each chunk's own numbers exactly. It caught two of its
143
+ own bugs that way.
144
+ - A guard-shaped method NAME on a declaration line (`def check_static_cache(`) no
145
+ longer counts as a containment guard, which had been silently dropping path
146
+ findings inside any method called `check*` / `validate*` / `ensure*`.
147
+
13
148
  ## 0.141.0 — Six new instruments, and the seven live bugs they found
14
149
 
15
150
  The previous release fixed five bugs found by measuring. This one builds the