@clear-capabilities/agentic-security-scanner 0.195.21 → 0.195.22
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 +13 -0
- package/bin/agentic-security.js +5 -2
- package/dist/agentic-security.mjs +2 -2
- package/dist/agentic-security.mjs.sha256 +1 -1
- package/dist/{7feb08356355c30181a1.json → c1e282247b06d51c8ffb.json} +2 -2
- package/package.json +2 -2
- package/src/discovery/CLAUDE.md +4 -0
- package/src/discovery/detector-spec-synthesis.js +203 -0
- package/src/engine.js +9 -0
- package/src/integrations/index.js +18 -9
- package/src/pipeline/scan-health.js +15 -2
- package/src/posture/CLAUDE.md +1 -0
- package/src/posture/assurance/config.js +2 -0
- package/src/posture/assurance/decision.js +45 -0
- package/src/posture/assurance/rollout.js +3 -0
- package/src/report/index.js +7 -6
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,19 @@
|
|
|
9
9
|
> make the history less accurate, not more.
|
|
10
10
|
|
|
11
11
|
|
|
12
|
+
## 0.195.22 - GA programme, release B: every model path through the egress policy, one assurance decision on every surface, and unknown is not fresh
|
|
13
|
+
|
|
14
|
+
**Measured, 0.195.21:** `TIMINGS preflight=3s push=5s pr=4s checks=393s merge=5s verify=6s tag=2s release=223s npm=145s total=786s release-clock=236s`, shipped in 14 min 56 s on the third attempt (the first stopped at verify on the new expected-jobs rule because the check-runs query had never been paginated; the second stopped at the warm gate because the CodeQL summary check is not a workflow job). The npm check was re-run once with `--resume`.
|
|
15
|
+
|
|
16
|
+
The safety and semantics items of the GA plan that are code (GA-07.4, GA-07.5, GA-11.7, its day 5 and day 6, and the two contract failures its review found), built on the 0.195.21 ledger.
|
|
17
|
+
|
|
18
|
+
- **Detector-spec synthesis goes through the shared bounded model call.** `scripts/synthesize-detector.mjs` posted its prompt with a bare `fetch`: no egress policy, no redaction, no deadline, a regular-expression JSON extractor that could not parse the nested array it required, and an output path written anywhere. It is now a thin front over `scanner/src/discovery/detector-spec-synthesis.js`: the `detector-spec-synthesis` assurance feature (off by default), the egress policy evaluated BEFORE any sample file is read (a denied call reads nothing), bounded reads, a CSPRNG nonce, `guardedModelCall` (redaction, request cap, deadline with bounded retries, audit entry, output cap), the string-aware JSON parser the validator uses, and a closed-world validation of the proposal (identifiers only, so no field can carry a pattern; unknown fields, a wrong nonce and a bad argument index are refused with reasons, never with the raw reply). A proposal is written only inside the working directory, never under `scanner/src`, never over a file without `--force`; nothing installs it. Exit codes 0, 2, 3, 4. Eleven pins with an injected transport, and the `model-egress-policy` contract test now covers this path.
|
|
19
|
+
- **The autopilot's fix proposals too.** `scripts/autopilot.mjs` was the second model path the 0.195.21 egress check found: its whole-file fix prompt now goes through the egress policy (a denial leaves the finding NEEDS_REVIEW), the redactor and the audit log. The `model-egress-policy:EGRESS-ALL-PATHS` ledger record moves from `failed` to `passed`.
|
|
20
|
+
- **One assurance decision on every surface.** `posture/assurance/decision.js`: `deployable`, `needs_review`, `not_deployable`, or `unknown` when no scan health was recorded. The CLI ship verdict, the Slack, Discord and Teams digests and the pull-request comment all derive their wording from it; `digest` reads the scan health the last scan recorded. A findings file with no scan health now reads "cannot confirm", never "safe to deploy", and a scan object without scan health in the tests was re-pinned to that. The default wording of the three existing states is unchanged (the bounded wording stays the `portfolio-assurance` opt-in).
|
|
21
|
+
- **Unknown feed freshness is a condition.** `freshness.<feed>.stale` is tri-state and documented so; `null` for a feed the scan consulted (`consulted` items for the KEV catalog, `cvesChecked` for EPSS) because it was unavailable, never loaded or cached without a timestamp is a condition like staleness, the result is `partial` and strict mode fails closed on it. A feed the scan had nothing to look up in is not a condition, and neither is `offline-skipped`, the operator's own declared configuration. The catalog metadata is reset per scan so one scan cannot inherit another's. The test that asserted a boolean, and the offline clean-scan pin, now assert the tri-state and the feed-only conditions.
|
|
22
|
+
- **A suppression pragma now reaches privacy-flow findings.** The self-scan of the new synthesis module showed that `agentic-security-ignore` on a credential-to-HTTP line was inert: the privacy flows (`dataflow/privacy-taint.js`) are appended after both pragma passes, against the documented rule that a stage appending findings runs the filter after itself. A third pass runs after the privacy stage; pinned both ways with a deep-mode fixture, and the suppression is logged like every other.
|
|
23
|
+
- **The `proof doctor` exit code is documented.** 0 when an execution environment is usable, 1 when none is (the report is still printed), `--json` always 0. The contract test that demanded 0 on every host, and so failed on one without a confinement backend, now pins the documented contract; the CLI's behaviour is unchanged.
|
|
24
|
+
|
|
12
25
|
## 0.195.21 - The GA programme ledger: every shipped surface owned, every acceptance record machine-checked, every expected hosted job required
|
|
13
26
|
|
|
14
27
|
**Measured, 0.195.20:** `TIMINGS preflight=3s push=6s pr=1s checks=363s merge=5s verify=5s tag=2s release=192s npm=267s total=844s release-clock=204s`, shipped in 15 min 53 s on the second attempt (the first stopped in the hosted checks: the version bump had regenerated the scorecard before the support registry was re-measured, so the two carried different measurement dates; the scorecard was regenerated on the clean tree). The npm check was re-run once with `--resume`.
|
package/bin/agentic-security.js
CHANGED
|
@@ -3578,14 +3578,17 @@ async function cmdDigest(args) {
|
|
|
3578
3578
|
const summary = { critical: 0, high: 0, medium: 0, low: 0, info: 0 };
|
|
3579
3579
|
for (const f of (last.findings || [])) summary[f.severity || 'medium']++;
|
|
3580
3580
|
const project = args.flags.project || path.basename(target);
|
|
3581
|
+
// The digest states the shared assurance decision, which needs the scan health the last scan recorded; a findings file alone says "cannot confirm".
|
|
3582
|
+
let scanHealth = null;
|
|
3583
|
+
try { const ls = statePath(target, 'last-scan.json'); if (fs.existsSync(ls)) scanHealth = JSON.parse(await fsp.readFile(ls, 'utf8')).scanHealth || null; } catch { scanHealth = null; }
|
|
3581
3584
|
if (args.flags.slack) {
|
|
3582
|
-
const payload = buildSlackDigest(findings, summary, { project });
|
|
3585
|
+
const payload = buildSlackDigest(findings, summary, { project, scanHealth });
|
|
3583
3586
|
const r = await postWebhook(args.flags.slack, payload);
|
|
3584
3587
|
console.log(r.ok ? `✓ Slack digest sent` : `✗ Slack failed: ${r.reason || r.status}`);
|
|
3585
3588
|
return r.ok ? 0 : 4;
|
|
3586
3589
|
}
|
|
3587
3590
|
if (args.flags.discord) {
|
|
3588
|
-
const payload = buildDiscordDigest(findings, summary, { project });
|
|
3591
|
+
const payload = buildDiscordDigest(findings, summary, { project, scanHealth });
|
|
3589
3592
|
const r = await postWebhook(args.flags.discord, payload);
|
|
3590
3593
|
console.log(r.ok ? `✓ Discord digest sent` : `✗ Discord failed: ${r.reason || r.status}`);
|
|
3591
3594
|
return r.ok ? 0 : 4;
|