@clear-capabilities/agentic-security-scanner 0.155.0 → 0.156.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 +16 -0
- package/dist/8798.index.js +4 -2
- package/dist/agentic-security.mjs +3 -3
- package/dist/agentic-security.mjs.sha256 +1 -1
- package/package.json +2 -2
- package/src/language/haskell-guards.js +12 -5
- package/src/language/haskell-ir.js +8 -1
- package/src/language/haskell-models.js +8 -0
- package/src/language/haskell-security-rules.js +23 -2
- package/src/language/haskell-web.js +3 -0
- package/src/language/nix-secrets.js +2 -0
- package/src/language/nixos-hardening.js +32 -1
- package/src/language/support-registry.js +5 -1
- package/src/language/witness.js +4 -2
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,22 @@
|
|
|
9
9
|
> make the history less accurate, not more.
|
|
10
10
|
|
|
11
11
|
|
|
12
|
+
## 0.156.0 - the three below-target rows fixed, measured on a fresh unseen set
|
|
13
|
+
|
|
14
|
+
0.155.0 reported Haskell SAST recall (79.2%), Haskell taint precision (77.8%) and Nix config-sast precision (86.1%) below target on shapes the templates did not contain, while the frozen holdout said 100%. Each gap was read against the code and fixed in the engine, not in the scoring.
|
|
15
|
+
|
|
16
|
+
- **Haskell, structural rules.** A function named for a PIN or password is a security value for the randomness rule (matched as a whole word, so `spinWheel` is not); `replicateM`/`replicateM_` sized by parsed caller text is an unbounded allocation; `xs !! n` on a caller-supplied list is a partial function; a log argument labelled `"token=" ++ x` or `"password: " ++ x` is a credential, unless it is redacted.
|
|
17
|
+
- **Haskell, route authentication.** A wrapper guard (`guarded $ do ...`) now dominates the handler it encloses: program order is source order, not control-flow node order. A guard that runs AFTER the write is still reported.
|
|
18
|
+
- **Haskell, taint.** `lookup key table` returns an element of the table, so only the table flows to the result (the key stays visible to rules as `hs.selector`, so `fromJust (lookup key t)` is still a partial-function finding); `length`, `null`, `ord` and similar return numbers and carry no caller text; a host allow-list (`uriRegName a `elem` [...]`) over a URL parsed from the checked value is a URL guard.
|
|
19
|
+
- **Nix.** `security.sudo.extraRules` with `NOPASSWD` for `ALL` is a finding (one named command is not); a TLS key produced by `writeText`/`toFile` is in the store like a path literal; wpa_supplicant's `ext:NAME` is a reference to a runtime variable, not a credential.
|
|
20
|
+
- **The measurement.** The unseen-v1 shapes were used to make these fixes, so they are now the `shape-dev` regression set. A fresh unseen-v2 set (3 vulnerable and 3 safe NEW single-flaw shapes per family, 2 nouns each, written after the fixes) was measured ONCE with the fixed engine: Haskell SAST P 91.7% / R 91.7%, Haskell taint P 93.3% / R 93.3%, Nix config-sast P 100% / R 97.0%; all three meet the targets (precision 90%, recall 85%). The frozen holdout is unchanged at 100% (re-measured after the engine change, which counts as repeated holdout use; nothing was tuned against it). Intervals on the unseen numbers are now over shapes, not near-identical cases.
|
|
21
|
+
- **What the fresh set still misses (not fixed, because fixing them would consume it).** Haskell: `strictRequestBody` read through an explicit import list, `fromJust (lookup k t)` (measured before the key-visibility fix above), `when (isNothing h) (... >> finish)` and `X-Api-Key` header checks reported as missing authentication, `getWith opts url` (the URL is the second argument), and duplicate findings for `readCreateProcess (shell ...)`. Nix: a firewall opened by a full-range `allowedTCPPortRanges`. The causes were not investigated (that would consume the set); these are the next known gaps. One engine change, the `fromJust (lookup ...)` regression fix, was made after the unseen measurement because the `lookup` change itself had caused it; the stored numbers were not re-measured, so they are conservative, and the set should be treated as consumed for anything after this release (an unseen-v3 is needed for the next round).
|
|
22
|
+
- **Author errors in the retired set, named.** A cookie called `usersses` (nothing in the code says it is a session), an HTML shape that prints to stdout, vulnerable Nix shapes with a second real flaw, and a path shape with two sinks. They stay in `shape-dev` with a note; they were not "fixed" in the engine.
|
|
23
|
+
|
|
24
|
+
- **A flaky probe, fixed.** The Haskell witness runner's `runghc --version` probe gave up after 10 s, which a cold CI runner exceeded once: the toolchain then read as absent in one call and present in the next, failing a test that asked twice. The probe now allows 60 s, says so when it times out, and the test decides availability once.
|
|
25
|
+
|
|
26
|
+
Partial release: the loop controller still lists NIX-011, NIX-012 and REL-001 as not verified. NIX-011 and NIX-012 passed on hosted CI (the NIX-012 suite inside a real NixOS guest on x86_64; no aarch64 guest was run), which is CI evidence, not controller-signed evidence. REL-001 needs those to be controller-verified first.
|
|
27
|
+
|
|
12
28
|
## 0.155.0 - premortem remediation (trust boundary, unseen-shape measurement), NixOS VM check
|
|
13
29
|
|
|
14
30
|
An adversarial premortem of 0.154.0 found the following; each is fixed here and covered by `test/language/language-trust-boundary.test.js`.
|
package/dist/8798.index.js
CHANGED
|
@@ -174,8 +174,10 @@ function judgeFixWitness(before, after) {
|
|
|
174
174
|
function haskellRunner() {
|
|
175
175
|
const p = which('runghc') || which('runhaskell');
|
|
176
176
|
if (!p) return { available: false, reason: 'no Haskell toolchain (runghc) on PATH; witnesses for Haskell findings are unavailable here' };
|
|
177
|
-
|
|
178
|
-
|
|
177
|
+
// GHC's first start on a cold, loaded machine (a CI runner) has taken more than 10 s; a probe that gives up there reports a toolchain
|
|
178
|
+
// that is installed as absent, and the answer then differs between two calls in one run.
|
|
179
|
+
const v = (0,node_child_process__WEBPACK_IMPORTED_MODULE_3__.spawnSync)(p, ['--version'], { encoding: 'utf8', timeout: 60_000 });
|
|
180
|
+
return v.status === 0 ? { available: true, path: p, version: String(v.stdout || v.stderr).trim() } : { available: false, reason: v.error && v.error.code === 'ETIMEDOUT' ? 'the Haskell runner did not start within 60 s' : 'the Haskell runner did not start' };
|
|
179
181
|
}
|
|
180
182
|
|
|
181
183
|
/**
|