@clear-capabilities/agentic-security-scanner 0.195.13 → 0.195.15
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 +32 -0
- package/dist/{1f01fe10027e772f73a1.json → 9699866704e8a4a5839f.json} +2 -2
- package/dist/agentic-security.mjs +2 -2
- package/dist/agentic-security.mjs.sha256 +1 -1
- package/package.json +2 -2
- package/src/dataflow/engine.js +19 -4
- package/src/language/CLAUDE.md +3 -0
- package/src/language/haskell-ir.js +88 -14
- package/src/language/haskell-models.js +11 -0
- package/src/language/haskell-parser.js +104 -4
- package/src/language/haskell-security-rules.js +41 -2
- package/src/language/haskell-syntax.js +86 -4
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,38 @@
|
|
|
9
9
|
> make the history less accurate, not more.
|
|
10
10
|
|
|
11
11
|
|
|
12
|
+
## 0.195.15 - Haskell rule precision from semantics: total list shapes, guards written as combinators, length tests, and a weak digest chosen by a type annotation
|
|
13
|
+
|
|
14
|
+
**Measured, 0.195.14:** `TIMINGS preflight=3s push=7s pr=4s checks=431s merge=5s verify=6s tag=2s release=223s npm=90s total=771s release-clock=236s`, shipped in 12 min 53 s with the npm listing verified on a resume 15 minutes later. The release clock (merge to published release) was 236 s. The push waited for the background gate to pass before starting (670 s), which avoided the bundle-check race that stopped the two previous ships.
|
|
15
|
+
|
|
16
|
+
Why: plan Phase 3, items 10 and 11, each started with a self-written probe run before any rule was touched. Thirteen partial-function idioms in thirteen exported functions: the rule reported five, of which two were TOTAL calls (`head (x : xs)`, `last (xs ++ [x])`), one a guard written as `when (length xs > 2) ..` (a call argument, not an `if` node), one a `case length xs of 3` size test, and two the unguarded calls it should report. The weak-hash rule did not read a digest chosen by a type annotation (`hash x :: Digest MD5`), a limit its header had stated since the rule was written.
|
|
17
|
+
|
|
18
|
+
- **Total shapes** (`haskell-security-rules.js` `nonEmptyList`, `NONEMPTY_TOTAL`): a partial list function on a cons, a non-empty literal, or a concatenation with one of those is total and not reported. The development-set site that showed the shape is xmonad's `last (["Root"] ++ ..)` (labelled FP in 0.195.11); the rule is general and pinned on synthetic code.
|
|
19
|
+
- **Guards as combinators and length tests** (`COND_COMBINATOR`, `LENGTH_CALL`, `lengthVars`): the first argument of `when`/`unless`/`guard` is a tested condition wherever the call sits; a comparison of a list's length with a number (`case length xs of 3 -> ..`, `length xs == 2`) tests the list, including through the scratch variable the IR puts a case scrutinee in. A test of another value still covers nothing (pinned).
|
|
20
|
+
- **Type-directed digests** (`haskell-syntax.js` `DIGEST_TYPE`, `haskell-ir.js` `hs.digest`): `hash x :: Digest MD5` and `hashlazy x :: Digest SHA1` are the weak hashes they name, judged by the same use analysis as `hashWith MD5` (medium with a comparison or a credential, info without).
|
|
21
|
+
- `hs-unsafe-io-boundary` was found already lowered to `info` for every site by `engine.js` (planned item 9 needed no shape rule; the sealed-set table that lists those sites as flagged predates that lowering and is re-measured at the end of the programme).
|
|
22
|
+
|
|
23
|
+
**Measured on real code** (`bench/dag/dev-haskell`, re-recorded with `bench:haskell-precision:update`): the fresh set is unchanged at 51 flagged, 21 true positives (41.2%); the development remainder lost one false positive (xmonad `DirExec.hs:86`, the total `last` of a literal-prepended list, labelled FP in 0.195.11), 7 to 6, and pandoc gained one info row. No label changed.
|
|
24
|
+
|
|
25
|
+
Gates, from the runs recorded for this entry: `test:haskell` 481/481 (`haskell-rule-precision`, 3 tests, wired into the script), `test:dataflow` 1599/1599, `bench:mutation:check` 460/460, `bench:cve-replay:check` 229/229 and `bench:layer-recall:check` unchanged, `bench:self-scan:check` 690/113/0 unchanged, the support registry re-promoted under GHC 9.4.8 (Haskell 9/9), the sealed set and unseen-v6 not re-scored.
|
|
26
|
+
|
|
27
|
+
## 0.195.14 - Haskell taint, second round: interpolating quasi-quoters, record dot and labels, module-level cells across functions, lambda-form functions, four syntax gaps, three library models
|
|
28
|
+
|
|
29
|
+
**Measured, 0.195.13:** `TIMINGS preflight=3s push=7s pr=1s checks=365s merge=6s verify=6s tag=2s release=223s npm=268s total=881s release-clock=237s`, shipped in 30 min 5 s on the second attempt. The release clock (merge to published release) was 237 s. The first attempt stopped at the hosted checks on two tests this release makes pass for real (a scan of a missing path exited 0; a quoted file name in a guide read as a missing path), and the second stopped before the merge on the background gate's bundle check, which a re-run passed.
|
|
30
|
+
|
|
31
|
+
Why: the plan's taint items, each started with a self-written probe run BEFORE the engine was touched and recorded in the test's header. The probes found every one of these shapes invisible or imprecise; each is fixed generally and pinned both ways.
|
|
32
|
+
|
|
33
|
+
- **String-interpolating quasi-quoters** (`haskell-parser.js` `INTERP_QUOTERS`, `haskell-ir.js` `iQ`): `[i|SELECT .. '#{name}'|]` (string-interpolate, interpolate), `[st|..#{e}..|]` (shakespeare-text), `[text|..$name ${e}..|]` (neat-interpolation), `[fmt|..{e} {e:spec}..|]` (PyF) are read as the concatenation of their interpolations, only under an import of the quoter's module; a literal-only body stays inert, an unknown quoter opaque. Probe: 0 of 5 forms followed before. `haskell-quasiquote-interp.test.js`.
|
|
34
|
+
- **OverloadedRecordDot and OverloadedLabels** (`haskell-syntax.js`): `order.customer` is a field read (a sibling field stays clean), `(.note)` the selector, `#field` a label value. Probe: the flow fired through the composition value by accident, with its source lost (`unattributed`); now the request parameter is the recorded root. `haskell-record-dot.test.js`.
|
|
35
|
+
- **A module-level cell written in one function and read in another** (`haskell-ir.js` `cellBodyOf`, `$cell:<qid>`; `dataflow/engine.js` `_cellSeeds`): `{-# NOINLINE ref #-} ref = unsafePerformIO (newIORef ..)` is one variable for the project; a tainted write anywhere seeds every reader, the fixed-point pre-pass re-running when the set grows; a point-free writer (`remember = writeIORef ref`) is an alias of the library function. Flow-insensitive; the root is not carried across (the reader's verdict is `unattributed`). Probe: 0 of 1 before. `haskell-global-cell.test.js`.
|
|
36
|
+
- **A function written in lambda form** (`lambdaBodied`): `dispatch = \case ..`, `pair = \cases ..`, `run = \x -> ..` at the top level and in `where` are the functions they define, so a call reaches the sink inside them (before, the call applied a closure value and reported nothing). `\cases`, `mdo`, GADT `data T where` constructors and `pattern` synonyms parse (`haskell-syntax-extensions.test.js`). A Haskell tuple literal is assigned component by component in the engine, so a `\cases` or `case` over `(x, y)` keeps a clean component clean.
|
|
37
|
+
- **Models** (names read from Hackage): typed-process `proc` (CWE-78 program, CWE-88 arguments; 0.2.13), esqueleto `rawSql`/`rawExecute` (3.6), optparse-applicative `execParser`/`customExecParser` as a command-line source (0.19). hasql's SQL sits in a `Statement` constructor, not a call, and is not modelled (stated).
|
|
38
|
+
- **The multi-sink chain the fresh set counted as a lost true positive was an aggregation artefact**: `openEditor` has one sink (the command injection labelled TP and flagged since 0.195.11); the "2 sinks" row joined it with an unrelated exported function's parameter because the aggregator groups by source label. Relabelled with that evidence (`LABEL-CHANGES.md`); nothing in the engine was changed for it.
|
|
39
|
+
|
|
40
|
+
**Measured on real code** (`bench/dag/dev-haskell`, re-recorded with `bench:haskell-precision:update`): the fresh set still flags 51 labelled sites, 21 true positives (41.2%, Wilson 28.8% to 54.8%); no flagged site changed. The lost-true-positive count is 0, down from 1, by the relabelling above (logged in `LABEL-CHANGES.md` with its evidence), not by an engine change. More code is read now: cabal2nix, dhall and ormolu each report more sites, all lowered to info (operator paths in command-line programs), so the whole-report rows moved and were re-recorded.
|
|
41
|
+
|
|
42
|
+
Gates, from the runs recorded for this entry: `test:haskell` 478/478 (four new suites, `haskell-quasiquote-interp`, `haskell-record-dot`, `haskell-global-cell`, `haskell-syntax-extensions`, wired into the script), `test:dataflow` 1599/1599, `test:lineage` with the sink and source registry pins re-measured (607 sinks, 416 modeled, 176 unsupported; 682 sources, 524 modeled), `bench:mutation:check` 460/460, `bench:cve-replay:check` 229/229 and `bench:layer-recall:check` unchanged, `bench:self-scan:check` 690/113/0 unchanged, the support registry re-promoted under GHC 9.4.8 (Haskell 9/9), the sealed set and unseen-v6 not re-scored.
|
|
43
|
+
|
|
12
44
|
## 0.195.13 - Haskell discovery set: six never-scanned projects read site by site, two layout rules that hid hoogle's request handler, and a contract detector scoped to its package
|
|
13
45
|
|
|
14
46
|
**Measured, 0.195.12:** `TIMINGS preflight=3s push=6s pr=1s checks=473s merge=6s verify=6s tag=2s release=316s npm=268s total=1081s release-clock=330s`, shipped in 30 min 40 s on the third attempt. The release clock (merge to published release) was 330 s. The first attempt stopped at the hosted checks because `docs/engineering-excellence/DATASET_PROVENANCE.md` still said 228 corpus entries (release-prepare did not regenerate it; it does now, and runs its test); the second stopped before the merge because the background gate recorded a bundle mismatch for the pushed commit that a fresh build did not reproduce, and a re-run of the gate passed (679 s) before `--resume` merged, tagged and released.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clear-capabilities/agentic-security-scanner",
|
|
3
|
-
"version": "0.195.
|
|
3
|
+
"version": "0.195.15",
|
|
4
4
|
"description": "Scanner engine for the agentic-security Claude Code plugin: SAST, SCA with reachability and CISA KEV, secrets, IaC, Haskell and Nix/NixOS, prompt-injection, MCP/agent-tool audit, authZ analysis, SBOM, compliance attestation, and more.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
"test:lineage": "node --test test/lineage/analysis-completion.test.js test/lineage/schema.test.js test/lineage/ids.test.js test/lineage/protection.test.js test/lineage/classification.test.js test/lineage/validate.test.js test/lineage/json-schema-parity.test.js test/lineage/flagship-fixture.test.js test/lineage/flagship-fixture-semantics.test.js test/lineage/field-identity.test.js test/lineage/engine-expr-resolver.test.js test/lineage/engine-walker.test.js test/lineage/engine-integration.test.js test/lineage/engine-receiver-identity.test.js test/lineage/summaries.test.js test/lineage/driver.test.js test/lineage/engine-provenance.test.js test/lineage/engine-provenance-interprocedural.test.js test/lineage/path-store.test.js test/lineage/path-query.test.js test/lineage/flow-grade.test.js test/lineage/source-registry.test.js test/lineage/sink-registry.test.js test/lineage/transform-catalog.test.js test/lineage/handling-analyzer.test.js test/lineage/registry-real-code.test.js test/lineage/source-seeding.test.js test/lineage/graph-builder.test.js test/lineage/coverage.test.js test/lineage/resolve-destination.test.js test/lineage/queue-detail.test.js test/lineage/index.test.js test/lineage/obligation-mapping.test.js test/lineage/obligation-predicates.test.js test/lineage/obligation-predicates-walkthrough.test.js test/lineage/transit-protection.test.js test/lineage/at-rest-protection.test.js test/lineage/protection-summary.test.js test/lineage/ac01-multi-sink.test.js test/lineage/policy-verdict.test.js test/lineage/governance-refs.test.js test/lineage/export-privacy.test.js test/lineage/export-json.test.js test/lineage/export-csv.test.js test/lineage/decision-story.test.js test/lineage/export-briefing.test.js test/lineage/graph-snapshot.test.js test/lineage/graph-diff.test.js test/lineage/drift-policy.test.js test/lineage/recipient-profile.test.js test/lineage/recipient-registry.test.js test/lineage/recipient-wiring.test.js test/lineage/redact-graph.test.js test/lineage-scan-wiring.test.js test/lineage-artifact-write.test.js test/bench-data-lineage-runner.test.js test/bundle-frontend.test.js test/bundle-frontend-golden.test.js test/generate-html-report.test.js test/export-image.test.js test/lineage/scenario.test.js test/lineage/scenario-engine.test.js test/lineage/scenario-diff.test.js test/lineage/scenario-no-obligation-wiring.test.js test/lineage/impact-assessment.test.js test/lineage/impact-engine.test.js test/lineage/impact-no-obligation-wiring.test.js test/lineage/governance-edit.test.js test/lineage/remediation.test.js test/lineage/runtime-observation.test.js test/lineage/observation-correlation.test.js test/lineage/observation-adapters.test.js test/lineage/observation-store.test.js test/lineage/runtime-corroboration-wiring.test.js test/lineage/cross-repo-link.test.js test/lineage/federation-loader.test.js test/lineage/cross-repo-link-wiring.test.js test/lineage/runtime-assurance.test.js test/lineage/runtime-edge-states.test.js test/lineage/runtime-explorer-view.test.js test/cli/runtime-explorer-cli.test.js test/cli/runtime-identity-cli.test.js test/cli/runtime-twin-cli.test.js test/lineage/cut-planner.test.js test/lineage/scc.test.js test/lineage/scc-solver.test.js test/graph/graph-views.test.js test/lineage/dag07-completion.test.js test/lineage/owned-build.test.js test/dataflow/boundary-propagation.test.js test/lineage/boundary-contract.test.js test/lineage/correlation-v2.test.js test/lineage/path-control-evidence.test.js test/lineage/smt-z3-backend.test.js test/cli/dag-commands.test.js",
|
|
94
94
|
"test:bench-modules": "node --test test/phase4-harness.test.js test/pipeline.test.js test/proof-corpus-lib.test.js test/proof-corpus-runner.test.js",
|
|
95
95
|
"test:server": "node --test test/server/graph-loader.test.js test/server/security.test.js test/server/routes.test.js test/server/http-server.test.js test/server/cmd-explore.test.js test/server/cmd-dataflow-export.test.js test/server/static-assets.test.js test/server/dataflow-scenario-cli.test.js test/server/dataflow-impact-cli.test.js",
|
|
96
|
-
"test:haskell": "node --test test/haskell/haskell-reachability.test.js test/haskell/haskell-real-code-shapes.test.js test/haskell/haskell-unseen-v5-shapes.test.js test/haskell/haskell-unseen-v4-shapes.test.js test/haskell/haskell-alias-taint.test.js test/haskell/haskell-weak-hash-names.test.js test/haskell/haskell-models-extended.test.js test/haskell/haskell-rules-extended.test.js test/haskell/haskell-injection.test.js test/haskell/haskell-ir.test.js test/haskell/haskell-manifests.test.js test/haskell/haskell-parser.test.js test/haskell/haskell-remediation.test.js test/haskell/haskell-remediation-0190.test.js test/haskell/haskell-remediation-kdf.test.js test/haskell/haskell-remediation-html-text.test.js test/haskell/haskell-remediation-scotty-body.test.js test/haskell/haskell-taint-shapes.test.js test/haskell/haskell-real-advisory-shapes.test.js test/haskell/haskell-discovery-shapes.test.js test/haskell/haskell-resolved-graph.test.js test/haskell/haskell-sca.test.js test/haskell/haskell-sca-severity.test.js test/haskell/haskell-web-guards.test.js test/haskell/haskell-advisory-feed.test.js test/haskell/haskell-security-rules.test.js test/haskell/haskell-taint.test.js test/haskell/haskell-boundaries.test.js test/haskell/haskell-live-feed-scan.test.js test/haskell/haskell-supply-bounds.test.js test/haskell/haskell-ir-scaling.test.js test/haskell/haskell-boundary-propagation.test.js test/haskell/haskell-generalization.test.js test/haskell/haskell-trust-boundary.test.js test/haskell/haskell-comment-invariance.test.js test/haskell/haskell-remediation-classes.test.js test/haskell/haskell-trust-boundary-frameworks.test.js test/haskell/haskell-generic-detectors.test.js",
|
|
96
|
+
"test:haskell": "node --test test/haskell/haskell-reachability.test.js test/haskell/haskell-real-code-shapes.test.js test/haskell/haskell-unseen-v5-shapes.test.js test/haskell/haskell-unseen-v4-shapes.test.js test/haskell/haskell-alias-taint.test.js test/haskell/haskell-weak-hash-names.test.js test/haskell/haskell-models-extended.test.js test/haskell/haskell-rules-extended.test.js test/haskell/haskell-injection.test.js test/haskell/haskell-ir.test.js test/haskell/haskell-manifests.test.js test/haskell/haskell-parser.test.js test/haskell/haskell-remediation.test.js test/haskell/haskell-remediation-0190.test.js test/haskell/haskell-remediation-kdf.test.js test/haskell/haskell-remediation-html-text.test.js test/haskell/haskell-remediation-scotty-body.test.js test/haskell/haskell-taint-shapes.test.js test/haskell/haskell-real-advisory-shapes.test.js test/haskell/haskell-discovery-shapes.test.js test/haskell/haskell-quasiquote-interp.test.js test/haskell/haskell-record-dot.test.js test/haskell/haskell-global-cell.test.js test/haskell/haskell-syntax-extensions.test.js test/haskell/haskell-rule-precision.test.js test/haskell/haskell-resolved-graph.test.js test/haskell/haskell-sca.test.js test/haskell/haskell-sca-severity.test.js test/haskell/haskell-web-guards.test.js test/haskell/haskell-advisory-feed.test.js test/haskell/haskell-security-rules.test.js test/haskell/haskell-taint.test.js test/haskell/haskell-boundaries.test.js test/haskell/haskell-live-feed-scan.test.js test/haskell/haskell-supply-bounds.test.js test/haskell/haskell-ir-scaling.test.js test/haskell/haskell-boundary-propagation.test.js test/haskell/haskell-generalization.test.js test/haskell/haskell-trust-boundary.test.js test/haskell/haskell-comment-invariance.test.js test/haskell/haskell-remediation-classes.test.js test/haskell/haskell-trust-boundary-frameworks.test.js test/haskell/haskell-generic-detectors.test.js",
|
|
97
97
|
"test:nix": "node --test test/nix/nix-option-types.test.js test/nix/nix-development-shapes.test.js test/nix/nixos-hardening-daemon.test.js test/nix/nixos-hardening-extended.test.js test/nix/nix-build-trust.test.js test/nix/nix-eval-isolation.test.js test/nix/nix-input-inventory.test.js test/nix/nix-parser-ir.test.js test/nix/nix-remediation.test.js test/nix/nix-resolved-closure.test.js test/nix/nix-sca-patches.test.js test/nix/nix-sca-severity.test.js test/nix/nix-haskell-closure-names.test.js test/nix/nix-script-taint.test.js test/nix/nix-secrets-store.test.js test/nix/nixos-hardening.test.js test/nix/nixos-module-resolution.test.js test/nix/nix-fix-multifile.test.js test/nix/nixos-evaluator-forms.test.js test/nix/nix-advisory-feed.test.js test/nix/nix-fix-prewrite.test.js test/nix/nix-boundary-scope.test.js",
|
|
98
98
|
"test:language": "node --test test/bench-haskell-precision.test.js test/bench-independent-haskell-panel.test.js test/language/capability-ledger.test.js test/language/language-accuracy-regression.test.js test/language/language-aibom.test.js test/language/language-assurance.test.js test/language/language-bom.test.js test/language/language-compliance.test.js test/language/language-contracts.test.js test/language/language-corpora-integrity.test.js test/language/language-discovery.test.js test/language/language-doc-coverage.test.js test/language/language-evidence-posture.test.js test/language/language-explorer.test.js test/language/frozen-splits.test.js test/language/language-gap-fixes.test.js test/language/language-gap-fixes-2.test.js test/language/language-governance.test.js test/language/language-integrations.test.js test/language/language-llm-agent.test.js test/language/language-local-ai.test.js test/language/language-parity-haskell.test.js test/language/language-polyglot-bridges.test.js test/language/language-privacy-lineage.test.js test/language/language-proof-remediation.test.js test/language/language-report-formats.test.js test/language/language-secrets.test.js test/language/language-trust-boundary.test.js",
|
|
99
99
|
"test:language-stress": "node --test --test-concurrency=1 test/language/language-stress-offline.test.js",
|