@clear-capabilities/agentic-security-scanner 0.150.2 → 0.151.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 +61 -0
- package/dist/9560.index.js +11 -0
- package/dist/agentic-security.mjs +1 -1
- package/dist/agentic-security.mjs.sha256 +1 -1
- package/package.json +19 -2
- package/src/dataflow/catalog.js +52 -0
- package/src/lineage/source-registry.js +8 -0
- package/src/posture/deterministic-fix.js +11 -0
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,67 @@
|
|
|
9
9
|
> make the history less accurate, not more.
|
|
10
10
|
|
|
11
11
|
|
|
12
|
+
## 0.151.0 - SARD/Juliet benchmarking: leakage-clean scoring, macro-F1, mutation testing, and fix verification (SARD_AGENTIC_SECURITY_PRD.md)
|
|
13
|
+
|
|
14
|
+
Builds a full benchmarking subsystem against NIST SARD's Juliet (Java/C#) and PHP Vulnerability
|
|
15
|
+
Test Suite corpora, extending the pre-existing `bench-realworld.js` harness rather than
|
|
16
|
+
duplicating it. New: `bench/sard/` (dataset lockfile, PHP ingestion, leakage audit, macro-F1 +
|
|
17
|
+
per-CWE + CWE-confusion-matrix + localization-accuracy scoring, structural train/dev/test
|
|
18
|
+
splitting with a duplicate-crossing audit, semantic mutation testing, and independent fix
|
|
19
|
+
verification), plus a `--cwe` targeted/smoke-run flag and a new CI job (`sard-blind-smoke`)
|
|
20
|
+
measuring genuine leakage-clean detection quality separately from the pre-existing
|
|
21
|
+
non-blind `sard-juliet-java` job (which tracks a different thing: whether the corpus-shape-aware
|
|
22
|
+
fallback code still works, not detection quality).
|
|
23
|
+
|
|
24
|
+
**Real, measured numbers** (all reproduced, none quoted without a fresh run — see
|
|
25
|
+
`bench/sard/IMPLEMENTATION_STATUS.md` for the full ledger and every command that produced them):
|
|
26
|
+
Java macro-F1 45.6% (P=66.5%, R=36.9%, leakage-clean, vulnerability-level scoring); C# macro-F1
|
|
27
|
+
8.4% (26/32 CWE families found to have zero detector coverage at all — a real, root-caused gap,
|
|
28
|
+
not yet fixed); Semantic Robustness Rate 100% (84/84 real mutations survived, sanity-checked
|
|
29
|
+
against a deliberately-safe negative control); Fully Verified Fix Rate 100% (32/32 real Java
|
|
30
|
+
weak-hash fixes); leakage reduced from 907,516 to 3 residual hits (99.9997%).
|
|
31
|
+
|
|
32
|
+
**Real engine fixes found via this benchmarking work** (general capability improvements, not
|
|
33
|
+
SARD-specific shortcuts — each verified with `bench:layer-recall`/`test:dataflow` before and
|
|
34
|
+
after):
|
|
35
|
+
- PHP: `$_SESSION`/`$_ENV` added as taint sources (previously entirely absent from the catalog),
|
|
36
|
+
`mysql_query()` given a real taint-dataflow sink (previously only a same-line structural
|
|
37
|
+
regex, missing the dominant assign-then-call-later shape). `bench:layer-recall` PHP taint
|
|
38
|
+
recall moved 12→13; baseline re-recorded (a real improvement, not silently left stale — this
|
|
39
|
+
gate compares for equality, not a floor, precisely to prevent that).
|
|
40
|
+
- Java: `BufferedReader.readLine()`/`Console.readLine()` and `ResultSet.getString`/`getObject`
|
|
41
|
+
added as taint sources, root-caused from real, evidence-based error-cluster analysis (grouping
|
|
42
|
+
false negatives by Juliet's own filename descriptor) rather than guessed.
|
|
43
|
+
- `deterministic-fix.js`'s weak-hash rule had a real Java coverage gap: its `applies()` gate
|
|
44
|
+
already matched Java CWE-327/328/916 findings, but `transform()` had no Java branch at all, so
|
|
45
|
+
every Java weak-hash finding silently produced no fix. Added
|
|
46
|
+
`MessageDigest.getInstance("MD5"|"SHA1")` → `"SHA-256"`.
|
|
47
|
+
- `bench-realworld.js` and `leakage-audit.mjs` both had an unconditional top-level `main()` (and,
|
|
48
|
+
in `bench-realworld.js`'s case, a separate top-level usage-check) with no `import.meta.url`
|
|
49
|
+
guard — importing either file's helper functions as a module silently ran the ENTIRE CLI
|
|
50
|
+
against the *importer's* own `process.argv`. Found the hard way when a new mutation-testing
|
|
51
|
+
script's own `--app`/`--cwe` flags happened to also be valid `bench-realworld.js` flags,
|
|
52
|
+
triggering an unwanted ~160s benchmark run as a side effect of a function import. Both files
|
|
53
|
+
now guard their top-level side effects the same way every other multi-purpose script in
|
|
54
|
+
`bench/sard/scripts/` already did.
|
|
55
|
+
- Root `CLAUDE.md` described `bench:layer-recall:check` as "a FLOOR, not an equality check...
|
|
56
|
+
silent on a rise" — stale documentation of a design the gate itself had already moved past
|
|
57
|
+
(its own code comment says "PRD F12.2 — compares for EQUALITY, not against a floor"). Fixed.
|
|
58
|
+
- `src/lineage/source-registry.js`'s `NO_PROVENANCE_OVERRIDES` table (Data Flow Explorer) had no
|
|
59
|
+
entries for the new `java-io-readline`/`java-resultset-getstring`/`java-resultset-getobject`
|
|
60
|
+
catalog sources, or for the pre-existing `php-session`/`php-env` sources — all five failed the
|
|
61
|
+
registry's own completeness guard (`source-registry.test.js`), which fails loudly rather than
|
|
62
|
+
silently producing an uncategorized graph node. Added (`user-input`/`database-read`/
|
|
63
|
+
`http-cookie`/`env-value` respectively); pinned coverage counts re-measured and updated
|
|
64
|
+
(185 total source entries, 87 `candidate`). Two `bench/sard/scripts/` helpers
|
|
65
|
+
(`analyze-errors.mjs`, `score-php.mjs`) were also wired into `scanner/package.json` after
|
|
66
|
+
`no-orphan-scripts.test.js` flagged them as unreachable from any npm script.
|
|
67
|
+
|
|
68
|
+
14 new automated tests (`java-taint-flow.test.js` +3, `deterministic-fix.test.js` +3, new
|
|
69
|
+
`sard-leakage-pipeline.test.js` +8 covering PRD §62's literal leakage-injection list and a
|
|
70
|
+
synthetic-fixture integration test through the real neutralization pipeline).
|
|
71
|
+
|
|
72
|
+
|
|
12
73
|
|
|
13
74
|
## 0.150.2 - Two adversarial-review passes on 0.150.0's Ollama support: redaction, disclosure, and robustness fixes
|
|
14
75
|
|
package/dist/9560.index.js
CHANGED
|
@@ -2864,6 +2864,7 @@ const _internals = { CACHE_DIR, CVE_RE, _stalenessTier };
|
|
|
2864
2864
|
|
|
2865
2865
|
const JS_EXT = /\.(?:js|jsx|ts|tsx|mjs|cjs)$/i;
|
|
2866
2866
|
const PY_EXT = /\.py$/i;
|
|
2867
|
+
const JAVA_EXT = /\.java$/i;
|
|
2867
2868
|
|
|
2868
2869
|
// Each rule gates on the finding's cwe/family, then rewrites the whole-file
|
|
2869
2870
|
// content. transform() returns the new content, or null when nothing changed
|
|
@@ -2875,12 +2876,22 @@ const RULES = [
|
|
|
2875
2876
|
// swapping them all is safe; the verifier confirms the weak-hash finding is
|
|
2876
2877
|
// gone and nothing worse appeared.
|
|
2877
2878
|
applies: (f) => /CWE-(?:327|328|916)/.test(f.cwe || '') || /weak.?hash/i.test(f.family || ''),
|
|
2879
|
+
// SARD_AGENTIC_SECURITY_PRD.md Phase 8 bench work found this rule's
|
|
2880
|
+
// `applies()` gate matched Java findings (CWE-327/328) by cwe/family, but
|
|
2881
|
+
// `transform()` had no Java branch at all — every Java weak-hash finding
|
|
2882
|
+
// silently produced `null` (no fix), a coverage gap invisible from the
|
|
2883
|
+
// gate alone. `MessageDigest.getInstance("MD5"|"SHA1"|"SHA-1")` ->
|
|
2884
|
+
// `"SHA-256"` is the same class of context-independent literal swap as
|
|
2885
|
+
// the existing JS/Python branches (the algorithm name is a string
|
|
2886
|
+
// literal, not something requiring surrounding-code understanding).
|
|
2878
2887
|
transform: (content, file) => {
|
|
2879
2888
|
let out = content;
|
|
2880
2889
|
if (JS_EXT.test(file)) {
|
|
2881
2890
|
out = out.replace(/(\bcreateHash\s*\(\s*['"`])(?:md5|sha1)(['"`])/gi, '$1sha256$2');
|
|
2882
2891
|
} else if (PY_EXT.test(file)) {
|
|
2883
2892
|
out = out.replace(/\bhashlib\.(?:md5|sha1)\s*\(/g, 'hashlib.sha256(');
|
|
2893
|
+
} else if (JAVA_EXT.test(file)) {
|
|
2894
|
+
out = out.replace(/(\bMessageDigest\.getInstance\s*\(\s*")(?:MD5|SHA-?1)(")/gi, '$1SHA-256$2');
|
|
2884
2895
|
}
|
|
2885
2896
|
return out !== content ? out : null;
|
|
2886
2897
|
},
|