@clear-capabilities/agentic-security-scanner 0.144.0 → 0.147.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 +390 -0
- package/bin/agentic-security.js +3813 -83
- package/dist/1122.index.js +702 -0
- package/dist/{301.index.js → 1301.index.js} +2 -2
- package/dist/1379.index.js +591 -0
- package/dist/{444.index.js → 1444.index.js} +13 -4
- package/dist/{660.index.js → 1660.index.js} +2 -2
- package/dist/{700.index.js → 1700.index.js} +2 -2
- package/dist/{905.index.js → 1905.index.js} +3 -3
- package/dist/{920.index.js → 1920.index.js} +3 -3
- package/dist/{238.index.js → 2238.index.js} +3 -3
- package/dist/2271.index.js +165 -0
- package/dist/{985.index.js → 2376.index.js} +1260 -340
- package/dist/2432.index.js +793 -0
- package/dist/2659.index.js +93 -0
- package/dist/{826.index.js → 2826.index.js} +2 -2
- package/dist/{830.index.js → 2830.index.js} +2 -2
- package/dist/2923.index.js +298 -0
- package/dist/{1.index.js → 3001.index.js} +5 -5
- package/dist/{117.index.js → 3117.index.js} +3 -3
- package/dist/3180.index.js +307 -0
- package/dist/3276.index.js +117 -0
- package/dist/{415.index.js → 3415.index.js} +2 -2
- package/dist/{499.index.js → 3499.index.js} +2 -2
- package/dist/3518.index.js +450 -0
- package/dist/{526.index.js → 3526.index.js} +14 -6
- package/dist/{736.index.js → 3736.index.js} +4 -4
- package/dist/{839.index.js → 3839.index.js} +4 -4
- package/dist/{113.index.js → 4113.index.js} +14 -6
- package/dist/{265.index.js → 4265.index.js} +2 -2
- package/dist/{384.index.js → 4384.index.js} +3 -3
- package/dist/4547.index.js +268 -0
- package/dist/4863.index.js +422 -0
- package/dist/{970.index.js → 4970.index.js} +67 -3
- package/dist/5051.index.js +770 -0
- package/dist/{144.index.js → 5144.index.js} +5 -5
- package/dist/{333.index.js → 5333.index.js} +3 -3
- package/dist/5343.index.js +185 -0
- package/dist/5350.index.js +866 -0
- package/dist/5561.index.js +436 -0
- package/dist/{637.index.js → 5637.index.js} +29 -7
- package/dist/{449.index.js → 5830.index.js} +78 -14
- package/dist/6626.index.js +532 -0
- package/dist/6662.index.js +297 -0
- package/dist/{675.index.js → 6675.index.js} +5 -5
- package/dist/{730.index.js → 6730.index.js} +6 -6
- package/dist/6829.index.js +225 -0
- package/dist/6944.index.js +130 -0
- package/dist/{178.index.js → 7178.index.js} +26 -8
- package/dist/{227.index.js → 7227.index.js} +2 -2
- package/dist/7310.index.js +520 -0
- package/dist/{552.index.js → 7552.index.js} +4 -4
- package/dist/7709.index.js +78 -0
- package/dist/8218.index.js +160 -0
- package/dist/{476.index.js → 8476.index.js} +4 -4
- package/dist/{513.index.js → 8513.index.js} +5 -5
- package/dist/{520.index.js → 8520.index.js} +2 -2
- package/dist/{718.index.js → 8718.index.js} +2 -2
- package/dist/{752.index.js → 8752.index.js} +2 -2
- package/dist/8846.index.js +100 -0
- package/dist/{435.index.js → 9091.index.js} +580 -187
- package/dist/{207.index.js → 9207.index.js} +2 -2
- package/dist/{220.index.js → 9220.index.js} +2 -2
- package/dist/9390.index.js +163 -0
- package/dist/{503.index.js → 9503.index.js} +2 -2
- package/dist/{801.index.js → 9801.index.js} +2 -2
- package/dist/{824.index.js → 9824.index.js} +2 -2
- package/dist/agentic-security.mjs +16 -16
- package/dist/agentic-security.mjs.sha256 +1 -1
- package/dist/compliance-frameworks/hipaa-security-rule.json +3 -2
- package/package.json +23 -10
- package/src/compare.js +6 -1
- package/src/dataflow/CLAUDE.md +2 -2
- package/src/dataflow/catalog.js +42 -0
- package/src/dataflow/orm-write-catalog.js +175 -0
- package/src/engine.js +580 -30
- package/src/fix/apply-fix-service.js +1 -0
- package/src/history-scan.js +22 -5
- package/src/ir/CLAUDE.md +2 -1
- package/src/ir/chrome-probe.mjs +150 -0
- package/src/ir/parser-js.js +94 -7
- package/src/lineage/CLAUDE.md +1203 -0
- package/src/lineage/DESIGN_DESTINATION_RESOLVER.md +156 -0
- package/src/lineage/DESIGN_GRAPH_BUILDER.md +938 -0
- package/src/lineage/DESIGN_HANDLING_ANALYZER.md +355 -0
- package/src/lineage/DESIGN_INTRAPROCEDURAL.md +628 -0
- package/src/lineage/DESIGN_PATH_PROVENANCE.md +3451 -0
- package/src/lineage/DESIGN_QUEUE_DETAIL.md +120 -0
- package/src/lineage/DESIGN_REGISTRIES.md +880 -0
- package/src/lineage/DESIGN_STORE_DETAIL.md +143 -0
- package/src/lineage/DESIGN_TRANSIT_PROTECTION.md +245 -0
- package/src/lineage/classification.js +56 -0
- package/src/lineage/coverage.js +658 -0
- package/src/lineage/cross-repo-link.js +107 -0
- package/src/lineage/dataflow-graph.schema.json +184 -0
- package/src/lineage/decision-story.js +206 -0
- package/src/lineage/drift-policy.js +279 -0
- package/src/lineage/driver.js +135 -0
- package/src/lineage/engine.js +992 -0
- package/src/lineage/export-briefing.js +628 -0
- package/src/lineage/export-csv.js +62 -0
- package/src/lineage/export-json.js +238 -0
- package/src/lineage/export-privacy.js +258 -0
- package/src/lineage/federation-loader.js +111 -0
- package/src/lineage/field-identity.js +78 -0
- package/src/lineage/fixtures/build-flagship-fixture.mjs +272 -0
- package/src/lineage/fixtures/flagship-graph.json +1453 -0
- package/src/lineage/flow-grade.js +221 -0
- package/src/lineage/governance-edit.js +169 -0
- package/src/lineage/graph-builder.js +1114 -0
- package/src/lineage/graph-diff.js +431 -0
- package/src/lineage/graph-snapshot.js +180 -0
- package/src/lineage/handling-analyzer.js +168 -0
- package/src/lineage/ids.js +349 -0
- package/src/lineage/impact-assessment.js +76 -0
- package/src/lineage/impact-engine.js +268 -0
- package/src/lineage/index.js +281 -0
- package/src/lineage/language-coverage-tiers.js +58 -0
- package/src/lineage/obligation-mapping.js +126 -0
- package/src/lineage/obligation-predicates.js +235 -0
- package/src/lineage/observation-adapters.js +282 -0
- package/src/lineage/observation-correlation.js +622 -0
- package/src/lineage/observation-store.js +497 -0
- package/src/lineage/path-query.js +410 -0
- package/src/lineage/path-store.js +400 -0
- package/src/lineage/protection.js +53 -0
- package/src/lineage/recipient-profile.js +192 -0
- package/src/lineage/recipient-registry.js +394 -0
- package/src/lineage/redact-graph.js +224 -0
- package/src/lineage/remediation.js +417 -0
- package/src/lineage/resolve-destination.js +91 -0
- package/src/lineage/runtime-observation.js +464 -0
- package/src/lineage/scenario-diff.js +84 -0
- package/src/lineage/scenario-engine.js +251 -0
- package/src/lineage/scenario.js +101 -0
- package/src/lineage/schema.js +167 -0
- package/src/lineage/sink-registry.js +427 -0
- package/src/lineage/source-registry.js +357 -0
- package/src/lineage/source-seeding.js +212 -0
- package/src/lineage/summaries.js +590 -0
- package/src/lineage/transform-catalog.js +397 -0
- package/src/lineage/transit-protection.js +150 -0
- package/src/lineage/validate.js +285 -0
- package/src/lsp/server.js +49 -2
- package/src/mcp/CLAUDE.md +7 -1
- package/src/mcp/dataflow-tools.js +160 -0
- package/src/mcp/server.js +1 -1
- package/src/mcp/tools.js +22 -1
- package/src/pipeline/assurance-mode.js +64 -1
- package/src/pipeline/finding-schema.js +8 -1
- package/src/pipeline/scan-health.js +19 -1
- package/src/posture/CLAUDE.md +140 -0
- package/src/posture/accuracy-scorecard.js +60 -0
- package/src/posture/artifact-registry.js +76 -0
- package/src/posture/auditor-walkthrough.js +192 -13
- package/src/posture/compliance-frameworks/hipaa-security-rule.json +3 -2
- package/src/posture/compliance-policy.js +12 -2
- package/src/posture/cross-repo-memory.js +7 -2
- package/src/posture/fix-history.js +25 -2
- package/src/posture/fix-verify.js +9 -1
- package/src/posture/fleet.js +0 -0
- package/src/posture/git-history.js +13 -5
- package/src/posture/material-change.js +21 -2
- package/src/posture/mttr.js +75 -12
- package/src/posture/obligation-evidence-pack.js +202 -0
- package/src/posture/pre-incident-archaeology.js +39 -7
- package/src/posture/privacy-framework.js +14 -0
- package/src/posture/provenance/ai-authorship.js +68 -0
- package/src/posture/provenance/branch-entry.js +80 -0
- package/src/posture/provenance/cache.js +143 -0
- package/src/posture/provenance/confidence.js +36 -0
- package/src/posture/provenance/coordinator.js +786 -0
- package/src/posture/provenance/dag-walk.js +249 -0
- package/src/posture/provenance/evidence-attribution.js +59 -0
- package/src/posture/provenance/git-evidence.js +310 -0
- package/src/posture/provenance/lifecycle.js +208 -0
- package/src/posture/provenance/missing-control-resolver.js +137 -0
- package/src/posture/provenance/origin-resolver.js +342 -0
- package/src/posture/provenance/predicate-replay.js +133 -0
- package/src/posture/provenance/providers/config.js +39 -0
- package/src/posture/provenance/providers/github.js +62 -0
- package/src/posture/provenance/providers/gitlab.js +58 -0
- package/src/posture/provenance/repo-lineage.js +74 -0
- package/src/posture/provenance/sca-origin.js +139 -0
- package/src/posture/provenance/schema.js +255 -0
- package/src/posture/provenance/transitive-sca.js +147 -0
- package/src/posture/provenance/validate.js +30 -0
- package/src/posture/provenance-evidence-bundle.js +144 -0
- package/src/posture/remediation-ledger.js +337 -0
- package/src/posture/sbom-diff.js +15 -2
- package/src/posture/secret-history.js +10 -2
- package/src/posture/state-dir.js +38 -14
- package/src/posture/vuln-archaeology.js +8 -2
- package/src/pr-delta.js +25 -4
- package/src/report/index.js +197 -3
- package/src/runScan.js +34 -5
- package/src/sast/rate-limit.js +33 -3
- package/src/server/CLAUDE.md +47 -0
- package/src/server/graph-loader.js +141 -0
- package/src/server/http-server.js +325 -0
- package/src/server/routes.js +129 -0
- package/src/server/security.js +111 -0
- package/src/server/static-assets.js +139 -0
- package/src/util/git-hardening.js +128 -0
- package/dist/11.index.js +0 -353
- package/dist/259.index.js +0 -975
- package/dist/317.index.js +0 -300
- package/dist/609.index.js +0 -741
- package/dist/838.index.js +0 -152
package/CHANGELOG.md
CHANGED
|
@@ -11,6 +11,396 @@
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
|
|
14
|
+
## 0.147.0 — Documentation overhaul: a cohesive assurance-platform story, verified against the shipped code
|
|
15
|
+
|
|
16
|
+
The 0.144.0 Assurance Hardening release shipped a real 3-state ship verdict,
|
|
17
|
+
a model-egress policy gate, risk-dollar scenario disclosure, and per-artifact
|
|
18
|
+
retention/encryption — but the docs describing it, and the README's whole
|
|
19
|
+
front-door story, hadn't caught up. This release rewrites both, built
|
|
20
|
+
exclusively from real, re-verified source rather than the original
|
|
21
|
+
documentation brief's assumptions (which turned out to contain several
|
|
22
|
+
fabricated CLI flags and vocabularies — a `scan --assurance` flag that
|
|
23
|
+
doesn't exist, `--assurance` is `ci`-only; a fictional `--explain-health`
|
|
24
|
+
flag; nine invented verify-verdict strings; a fictional unified compliance
|
|
25
|
+
state model where three separate, differently-cased vocabularies actually
|
|
26
|
+
exist).
|
|
27
|
+
|
|
28
|
+
**README** rewritten around a 5-capability story (Find It / Prove It / Fix
|
|
29
|
+
It Safely / Govern It / Explain It), a corrected 5-minute quickstart, the
|
|
30
|
+
real 3-state ship verdict as a running example, and persona-based
|
|
31
|
+
navigation (Developer / AppSec / Privacy / Compliance / Platform
|
|
32
|
+
Engineering).
|
|
33
|
+
|
|
34
|
+
**16 new docs**: `docs/walkthroughs/{assurance-modes,scan-health,
|
|
35
|
+
finding-evidence,verified-remediation,privacy-data-flow,model-egress}.md`;
|
|
36
|
+
`docs/architecture/finding-lifecycle.md`; `docs/concepts.md`
|
|
37
|
+
(evidence-before-severity, deterministic-vs-model-assisted);
|
|
38
|
+
`docs/governance/state-and-retention.md`; `docs/guides/risk-dollars.md`;
|
|
39
|
+
`docs/examples/README.md` (a 13-entry gallery); `docs/reference/
|
|
40
|
+
{output-schema,glossary}.md`; `docs/troubleshooting/scan-health.md`; and two
|
|
41
|
+
real, captured Data Flow Explorer browser screenshots at `docs/assets/`.
|
|
42
|
+
|
|
43
|
+
**A new doc-testing tool**, `scripts/verify-doc-examples.mjs`: parses the
|
|
44
|
+
real CLI dispatch table out of `bin/agentic-security.js` at runtime (so it
|
|
45
|
+
can't drift out of sync with the CLI the way a hand-maintained list would)
|
|
46
|
+
to catch fabricated commands and the specific `<subcommand> --help`
|
|
47
|
+
landmine (passing `--help` to a subcommand silently runs the real command
|
|
48
|
+
instead of printing help — only bare `agentic-security help` is valid),
|
|
49
|
+
plus JSON-block and Mermaid-syntax sanity checks. Deliberately not wired
|
|
50
|
+
into any gate — a standalone `npm run docs:verify-examples`.
|
|
51
|
+
|
|
52
|
+
**Existing docs corrected**, not just extended: `docs/guides/
|
|
53
|
+
{quickstart,scanning,compliance,ci-setup,finding-provenance}.md`,
|
|
54
|
+
`docs/reference/{cli,configuration}.md`, `docs/ARCHITECTURE.md`,
|
|
55
|
+
`docs/README.md`, and several `commands/`/`skills/` files carried stale
|
|
56
|
+
claims — the most consequential being that `scan` was documented as
|
|
57
|
+
defaulting finding-provenance ON, when it actually defaults OFF (`ci`
|
|
58
|
+
defaults it ON; this asymmetry exists because plain provenance resolution
|
|
59
|
+
cost a measured 4.5s→45s regression on a 207-file tree, the same
|
|
60
|
+
measurement behind this project's own TTFF benchmark).
|
|
61
|
+
|
|
62
|
+
## 0.146.0 — Data Flow Explorer: trace sensitive data through your architecture, not just through one finding
|
|
63
|
+
|
|
64
|
+
Every prior release answers "is this line of code dangerous?" This one adds a
|
|
65
|
+
different question: "where does this piece of sensitive data actually go, and
|
|
66
|
+
what protects it along the way?" `agentic-security dataflow` builds a
|
|
67
|
+
`DataFlowGraph` from a real scan — sources, sinks, the data elements that
|
|
68
|
+
flow between them, and a verdict per hop on transit/at-rest/handling
|
|
69
|
+
protection — and a new local, read-only, loopback-only server
|
|
70
|
+
(`agentic-security explore`) serves it to a clickable UI. Six milestones,
|
|
71
|
+
built in dependency order over this release cycle:
|
|
72
|
+
|
|
73
|
+
**The graph itself (Milestones 0-2).** A stable-ID'd, schema-versioned graph
|
|
74
|
+
contract; an interprocedural field-identity taint engine purpose-built for
|
|
75
|
+
this graph (deliberately separate from the SAST engine's own taint
|
|
76
|
+
analysis — different state shape, different precision goals) with
|
|
77
|
+
context-sensitive summaries and a compact path-provenance DAG that tracks
|
|
78
|
+
*why* a field reached a sink, not just *that* it did; source/sink/
|
|
79
|
+
transformation registries reclassifying this project's existing detection
|
|
80
|
+
catalogs into the graph's own vocabulary; and protection-verdict analyzers
|
|
81
|
+
for transit (TLS presence and validity), at-rest (encryption-before-store),
|
|
82
|
+
and handling (masking/hashing/tokenization — never treated as synonyms).
|
|
83
|
+
|
|
84
|
+
**A local server and reference UI (Milestone 3).** `agentic-security explore`
|
|
85
|
+
— the first HTTP server anywhere in this codebase (the MCP and LSP servers
|
|
86
|
+
are both stdio) — serves the signed, already-scanned graph read-only,
|
|
87
|
+
loopback-only, to a zero-build-step frontend prototype with architecture,
|
|
88
|
+
privacy-lifecycle, and evidence-trace views.
|
|
89
|
+
|
|
90
|
+
**Export and decision-intelligence surfaces (Milestone 4).** JSON/CSV/HTML/
|
|
91
|
+
PNG/PDF/SVG export; a Regulatory Obligation Overlay mapping graph facts
|
|
92
|
+
against bundled compliance frameworks (never claiming "compliant" from a
|
|
93
|
+
single mapping); an Executive Risk Story mode ranking flows on nine
|
|
94
|
+
transparent, disclosed factors — never a blended, uncalibrated score; a
|
|
95
|
+
Data-Flow Time Machine (`dataflow diff`) comparing two scans with real
|
|
96
|
+
drift-policy alerting on newly-introduced disclosures; and Third-Party and
|
|
97
|
+
Cross-Border Intelligence, keeping legal/jurisdiction facts honestly
|
|
98
|
+
`unknown` rather than inferred from brand recognition.
|
|
99
|
+
|
|
100
|
+
**Simulation, corroboration, and cross-repo linkage (Milestone 5).** A
|
|
101
|
+
What-If Architecture Simulator (`dataflow scenario apply`) that clones and
|
|
102
|
+
overrides a graph to test a hypothetical fix, never mutating the real scan,
|
|
103
|
+
with every simulated verdict marked `HYPOTHETICAL` and `assumed`-graded so
|
|
104
|
+
it can never be mistaken for a real one; Blast-Radius Impact Assessment and
|
|
105
|
+
a Remediation Command Center with a hash-chained ledger enforcing that
|
|
106
|
+
closing an item requires either a clean rescan or an explicit, permitted
|
|
107
|
+
manual attestation — and that a later regression reopens it automatically;
|
|
108
|
+
a Runtime-Corroborated Digital Twin (`dataflow observations import`) that
|
|
109
|
+
layers operator-supplied runtime telemetry onto the static graph through a
|
|
110
|
+
closed-world contract that rejects, not merely redacts, any field capable
|
|
111
|
+
of carrying a payload value; per-language coverage-tier disclosure so a
|
|
112
|
+
partially-supported language is labeled as such rather than silently
|
|
113
|
+
under-reported; and `federate declare` — an operator-declared edge between
|
|
114
|
+
two independently-scanned repositories' own graphs, with each graph staying
|
|
115
|
+
its own separate, unmodified artifact.
|
|
116
|
+
|
|
117
|
+
**New top-level commands:** `explore`, `dataflow`, `governance`,
|
|
118
|
+
`remediation`, `federate` — the latter three write operator-declared
|
|
119
|
+
config through the same reviewable contract (preview, version guard,
|
|
120
|
+
backup, audit event) established for exactly this class of write.
|
|
121
|
+
|
|
122
|
+
**On rigor, again.** As with 0.145.0's own provenance work, a dedicated
|
|
123
|
+
final-review pass — after every task-level review and a green test
|
|
124
|
+
suite — found real Blocking or Important bugs in nearly every one of
|
|
125
|
+
these sub-projects: a remediation item that could be marked verified from
|
|
126
|
+
a snapshot chronologically *older* than the incident it was supposed to
|
|
127
|
+
fix; a runtime-observation payload-refusal grammar that closed single-value
|
|
128
|
+
smuggling but missed the same payload split across array elements; a
|
|
129
|
+
cross-repo link's own self-consistency digest compared against the wrong
|
|
130
|
+
half of a redacted export, so an untampered file permanently read as
|
|
131
|
+
tampered; and — found only in this release's own post-completion
|
|
132
|
+
re-audit, prompted by checking every named acceptance criterion's text
|
|
133
|
+
against the actual shipped code rather than trusting a summary — one
|
|
134
|
+
acceptance criterion (`AC-26`, on the What-If Simulator) that had never
|
|
135
|
+
been checked against its own literal wording by any prior document, and
|
|
136
|
+
was quietly unmet until this audit closed it. Every one of these was
|
|
137
|
+
found, fixed, and independently re-verified — including personally
|
|
138
|
+
reproducing the bug and its fix live, not just re-reading a diff — before
|
|
139
|
+
this release.
|
|
140
|
+
|
|
141
|
+
**Disclosed, not built.** Full graph-merge across repositories (only
|
|
142
|
+
declared, single-edge cross-repo links ship); synthetic node/edge
|
|
143
|
+
insertion for the What-If Simulator (every node/edge today derives from a
|
|
144
|
+
real registry decision or call site — inventing one has no precedent yet);
|
|
145
|
+
automatic destination/schema correlation for cross-repo edges (needs
|
|
146
|
+
prerequisite work — schema-derived edges, fuller destination resolution —
|
|
147
|
+
that isn't built); an HTML-table stress-test pass for the largest graphs;
|
|
148
|
+
config-declared (as opposed to runtime-observed) corroboration for the
|
|
149
|
+
Digital Twin, folded into already-scoped backlog rather than duplicated.
|
|
150
|
+
None of these block the acceptance criteria this release's milestones are
|
|
151
|
+
gated on.
|
|
152
|
+
|
|
153
|
+
## 0.145.0 — Finding Provenance ships, and two audits find what the first one missed
|
|
154
|
+
|
|
155
|
+
Every finding now carries a `findingProvenance` record answering "when did this
|
|
156
|
+
enter the codebase, and how sure are we?" — resolved from Git history, not
|
|
157
|
+
guessed. It is **opt-in**: pass `--provenance` (or any provenance flag, e.g.
|
|
158
|
+
`--provenance-since`, `--require-provenance`) on a scan of a Git repository.
|
|
159
|
+
|
|
160
|
+
It is opt-in rather than on-by-default because the release gate measured what
|
|
161
|
+
on-by-default costs: time-to-first-finding over a 207-file tree went 4.5s to
|
|
162
|
+
45s. That is a 7.6x regression on the one metric this product's own benchmark
|
|
163
|
+
calls the binding constraint for its ICP — "how long until the FIRST useful
|
|
164
|
+
result, not aggregate F1" — and resolving commit history for every finding is
|
|
165
|
+
not what a first-time user is waiting on. CI, compliance and triage callers
|
|
166
|
+
that want provenance ask for it explicitly and pay the cost knowingly.
|
|
167
|
+
|
|
168
|
+
**What it resolves.** For a SAST finding: the commit that introduced it, found
|
|
169
|
+
by replaying the finding's own predicate against historical blobs (`git blame`
|
|
170
|
+
answers "who last touched this line", which is a different and usually wrong
|
|
171
|
+
question) and then confirming the predicate was FALSE in that commit's parent.
|
|
172
|
+
For a direct dependency: the commit that moved the declared version in
|
|
173
|
+
`package.json`/`requirements.txt` into an advisory's vulnerable range. Alongside
|
|
174
|
+
the origin commit: the branch/PR the change entered through, the evidence nodes
|
|
175
|
+
(source/sink/manifest, each as a path:line:commit triple), a confidence level
|
|
176
|
+
with its reasons, and a lifecycle ledger of introduce/remediate/reintroduce
|
|
177
|
+
events at `.agentic-security/provenance/lifecycle.json`.
|
|
178
|
+
|
|
179
|
+
**Only a complete scan can close a finding.** The ledger's remediation pass turns
|
|
180
|
+
a finding's *absence* into the claim "this was fixed," which is sound only when
|
|
181
|
+
the scan actually looked everywhere it could have found it. A `--changed-since` /
|
|
182
|
+
`--pr` scan, or any caller-supplied file list (the MCP `scan_diff` tool, the LSP's
|
|
183
|
+
on-save scan), therefore records new and reintroduced findings normally but closes
|
|
184
|
+
nothing — the entries it did not look at stay open until a full scan says
|
|
185
|
+
otherwise. For the same reason the ledger is written only when the scan target is
|
|
186
|
+
a real directory: a scan of a path that does not exist resolves its state
|
|
187
|
+
directory by walking up from the current working directory, and would otherwise
|
|
188
|
+
write a verdict about a project it never read.
|
|
189
|
+
|
|
190
|
+
**It refuses to guess.** Every record carries a terminal `status`, and there is
|
|
191
|
+
no path that leaves the field absent: `complete`, `partial` (history could not
|
|
192
|
+
confirm a parent boundary — a shallow clone, or an advisory with no `introduced`
|
|
193
|
+
bound), `uncommitted` (the finding exists only in the working tree),
|
|
194
|
+
`not_available`, `budget_exhausted`, or `error`. A shallow clone can never reach
|
|
195
|
+
`complete`. Author emails are redacted from every output format unless
|
|
196
|
+
`--include-author-email` is passed.
|
|
197
|
+
|
|
198
|
+
**New flags** (`agentic-security scan --help` documents all seven):
|
|
199
|
+
`--provenance <standard|deep>`, `--no-provenance`, `--provenance-since <ref>`,
|
|
200
|
+
`--provenance-timeout <ms>`, `--include-author-email`, `--pseudonymize-authors`,
|
|
201
|
+
`--require-provenance`. `deep` mode performs real non-linear DAG analysis (see
|
|
202
|
+
the M3 subsection below) — it is no longer a stub that silently runs `standard`.
|
|
203
|
+
`--require-provenance` reports unresolved provenance as a scan-health condition
|
|
204
|
+
and downgrades `scanHealth.status` to `partial`; it never changes the exit code
|
|
205
|
+
by itself — see the M2 subsection below for the mechanism that does.
|
|
206
|
+
`--verbose --firehose` prints the provenance block per finding in text output.
|
|
207
|
+
See [`docs/guides/finding-provenance.md`](docs/guides/finding-provenance.md)
|
|
208
|
+
for the full user-facing writeup.
|
|
209
|
+
|
|
210
|
+
### M2: format parity, compliance/MTTR/fix-lifecycle surfacing, and `--assurance strict` can now fail the build
|
|
211
|
+
|
|
212
|
+
M0+M1 landed provenance resolution and the JSON/text surfaces above. M2 threads
|
|
213
|
+
that data through every other output and, for the first time, gives provenance
|
|
214
|
+
completeness the power to fail a CI build.
|
|
215
|
+
|
|
216
|
+
- **Format parity.** SARIF, CSV, Markdown, and HTML output now all carry each
|
|
217
|
+
finding's `findingProvenance`, matching what JSON already had — a consumer no
|
|
218
|
+
longer has to switch formats to see it.
|
|
219
|
+
- **Compliance evidence.** Auditor-walkthrough and NIST Privacy Framework gap
|
|
220
|
+
findings now carry `controlRefs` (the finding ids backing a control's gap
|
|
221
|
+
determination) and `derivedProvenance` (the earliest proven open condition
|
|
222
|
+
among those findings, with a `confidence` level and stated `limitations`).
|
|
223
|
+
- **MTTR.** `mttr.js` reports `ageBasis` (`finding_origin` | `earliest_observable`
|
|
224
|
+
| `uncommitted` | `first_observed`) and `provenAgeDays` alongside the existing
|
|
225
|
+
wall-clock `ageDays`, so age-to-remediate can be read against the commit that
|
|
226
|
+
actually introduced the finding, not just when the scanner first saw it.
|
|
227
|
+
- **Fix records.** Every fix-history entry now carries a `provenanceAtFix`
|
|
228
|
+
snapshot — the finding's `findingProvenance` as it stood at the moment the fix
|
|
229
|
+
was applied — so a later audit can see what was known at fix time, not just
|
|
230
|
+
what is knowable now.
|
|
231
|
+
- **`--assurance strict` can now fail the build over incomplete provenance.**
|
|
232
|
+
This is the behavior change that matters most, and it is a genuinely new
|
|
233
|
+
failure mode, not a rewording of `--require-provenance` above: strict mode
|
|
234
|
+
(`--assurance strict`) now treats any finding whose `findingProvenance.status`
|
|
235
|
+
is outside `[complete, uncommitted]` as making the scan incomplete, and fails
|
|
236
|
+
the same way it already fails on a failed or skipped analyzer. `--require-provenance`
|
|
237
|
+
is unchanged by this — it still only flags and never fails the exit code.
|
|
238
|
+
`--assurance strict` is the new, separate mechanism that does fail it. See the
|
|
239
|
+
`KNOWN INTERACTION` comment in `scanner/src/pipeline/assurance-mode.js` for a
|
|
240
|
+
known, disclosed consequence: transitive `vulnerable_dep`, `unpinned_dep`, and
|
|
241
|
+
`no_lockfile` supply-chain findings are stamped `not_available` today (the
|
|
242
|
+
latter two are a category error — there is no commit that introduced a
|
|
243
|
+
*missing* lockfile — not merely a deferral), so `--assurance strict` will fail
|
|
244
|
+
on nearly any real project with a dependency manifest until that gap closes.
|
|
245
|
+
|
|
246
|
+
### M3: real non-linear history, transitive-dependency provenance, missing-control regressions, PR/CODEOWNERS enrichment
|
|
247
|
+
|
|
248
|
+
- **`--provenance deep` now does real work.** Instead of the M0–M2 stub that
|
|
249
|
+
accepted the flag and silently ran `standard`, deep mode walks every parent
|
|
250
|
+
of a merge commit (not just the first), which resolves origins standard
|
|
251
|
+
mode's first-parent-only walk cannot see, and detects reverts and
|
|
252
|
+
cherry-picks — surfaced as `findingOrigin.revertOf` / `.cherryPickOf` — via
|
|
253
|
+
a real unified-diff inversion.
|
|
254
|
+
- **Transitive-dependency provenance is now live-wired**, not merely
|
|
255
|
+
modeled: `transitive-sca.js` re-derives lockfile ancestry per historical
|
|
256
|
+
commit to find the commit that moved a *lockfile-resolved* (not
|
|
257
|
+
manifest-declared) dependency into an advisory's vulnerable range.
|
|
258
|
+
- **Missing-control regressions** — a previously-observed safeguard (today:
|
|
259
|
+
`sast/rate-limit.js`'s findings) disappearing — can now resolve a real
|
|
260
|
+
origin via `missing-control-resolver.js`.
|
|
261
|
+
- **Optional GitHub/GitLab PR-metadata + CODEOWNERS enrichment**
|
|
262
|
+
(`findingProvenance.providerEnrichment`) is live for `complete`-status
|
|
263
|
+
findings, configured via `.agentic-security/provenance-providers.yml` /
|
|
264
|
+
`AGENTIC_SECURITY_GITHUB_TOKEN` / `AGENTIC_SECURITY_GITLAB_TOKEN`, capped
|
|
265
|
+
per scan.
|
|
266
|
+
|
|
267
|
+
### M4: signed provenance evidence bundles, cross-repository lineage, an AI-authorship hook
|
|
268
|
+
|
|
269
|
+
- **`agentic-security attest --provenance`** signs a per-finding provenance
|
|
270
|
+
record (origin commit, confidence, evidence attribution) with the same
|
|
271
|
+
Ed25519 key material as the existing finding-evidence bundle mechanism;
|
|
272
|
+
`verify-attestation` auto-detects and verifies it against a public key
|
|
273
|
+
alone. Note the flag-shape collision with `scan`: on `attest`, `--provenance`
|
|
274
|
+
takes an optional *finding id*, not a mode — `attest --provenance deep`
|
|
275
|
+
looks for a finding literally named `deep`.
|
|
276
|
+
- **Cross-repository lineage.** An operator-declared
|
|
277
|
+
`.agentic-security/repo-lineage.json` can link a root-commit origin (a
|
|
278
|
+
finding whose earliest commit has no parent in the current repo) across a
|
|
279
|
+
prior, local-clone-only fork/split history. Resolution is conservative:
|
|
280
|
+
content at the linked line must actually match, not merely exist, before
|
|
281
|
+
an origin is reported, and the record discloses the boundary crossing
|
|
282
|
+
explicitly.
|
|
283
|
+
- **An extensible AI-authorship verifier registry**
|
|
284
|
+
(`registerAIAuthorshipVerifier` / `resolveAIAuthorship`) now stamps every
|
|
285
|
+
SAST `findingOrigin` with an `aiAuthorship` field; no verifier is
|
|
286
|
+
registered today, so it defaults honestly to `{status:'unknown', verifier:null}`.
|
|
287
|
+
- **Fleet-wide rollups** (`fleet.js`) now surface provenance-proven
|
|
288
|
+
remediation debt. Fleet MTTR is honestly disclosed rather than fabricated:
|
|
289
|
+
real remediation-timing data isn't reachable from the production fleet
|
|
290
|
+
driver without new state, so `rollupFleet` distinguishes "never tracked"
|
|
291
|
+
from "tracked, zero remediations" instead of reporting a misleading number.
|
|
292
|
+
|
|
293
|
+
### PRD completion: injection hardening, evidence-digest binding, retention split, and the first real coverage/accuracy measurements
|
|
294
|
+
|
|
295
|
+
- Author names and commit summaries are now sanitized against terminal
|
|
296
|
+
control-character and Markdown/HTML injection everywhere they reach a
|
|
297
|
+
human (FR-PROV-026).
|
|
298
|
+
- The run-attestation digest and provenance cache key are now genuinely
|
|
299
|
+
bound to the PRD-named inputs they claim to cover, including
|
|
300
|
+
detector/ruleset version.
|
|
301
|
+
- Symlink-escape protection added to the git evidence layer.
|
|
302
|
+
- **`--pseudonymize-authors`** (new flag, listed above) replaces raw
|
|
303
|
+
commit-author names with a stable `Contributor-XXXXXXXX` id — for when you
|
|
304
|
+
need to compare "who introduced what" without a raw name in the output.
|
|
305
|
+
Honored everywhere `--include-author-email`'s redaction already was,
|
|
306
|
+
including PR-reviewer logins and CODEOWNERS entries from provider
|
|
307
|
+
enrichment.
|
|
308
|
+
- The provenance cache now lives in its own top-level, independently-retained
|
|
309
|
+
state directory (`.agentic-security/provenance-cache/`), split from the
|
|
310
|
+
permanent lifecycle ledger (`.agentic-security/provenance/lifecycle.json`),
|
|
311
|
+
so cache eviction can never touch permanent history.
|
|
312
|
+
- **Two PRD success metrics are now genuinely measured and published, not
|
|
313
|
+
just designed:** known-origin accuracy (12/13 = 92.3% on the labeled
|
|
314
|
+
corpus, against a ≥98% target) and provenance coverage (311/341 = 91.2% on
|
|
315
|
+
this repository's own tree, against a ≥95% target — all 30 shortfall
|
|
316
|
+
findings resolve to `partial`, not `error`/`not_available`, so the gap is
|
|
317
|
+
reduced confidence rather than pipeline failure).
|
|
318
|
+
- `scan.secrets` and blameable `scan.logicVulns` entries now go through real
|
|
319
|
+
origin resolution (real stableIds, real git history) instead of a
|
|
320
|
+
permanent `not_available` placeholder.
|
|
321
|
+
|
|
322
|
+
### Second-audit remediation: a hostile-repository RCE closed, and further honesty fixes
|
|
323
|
+
|
|
324
|
+
An independent second audit of the completed Finding Provenance PRD found
|
|
325
|
+
one security-critical gap and several places where a metric or a claim
|
|
326
|
+
wasn't as real as it read. All fixed this release:
|
|
327
|
+
|
|
328
|
+
- **Security fix (1 of 2).** Git subprocess calls in the provenance pipeline
|
|
329
|
+
are now hardened against a hostile repository's own `.git/config` (e.g. a
|
|
330
|
+
malicious `core.fsmonitor`), `.gitattributes` `textconv` drivers, and
|
|
331
|
+
external `diff` drivers — a repository could previously trigger arbitrary
|
|
332
|
+
code execution merely by being scanned, provenance on or off. The sweep
|
|
333
|
+
covers every git invocation in the scanner, not just the provenance
|
|
334
|
+
module, and a source-level guard now fails the build if a future `git
|
|
335
|
+
diff` call site omits `--no-ext-diff`. Removing the shell from two
|
|
336
|
+
remaining `execSync` call sites also closed a command-injection path via
|
|
337
|
+
attacker-controlled filenames.
|
|
338
|
+
- **Security fix (2 of 2), found while reviewing a performance optimization
|
|
339
|
+
in this same release.** A change that fused the parent-commit lookup into
|
|
340
|
+
an existing `git show` placed that field after the author name in a
|
|
341
|
+
delimiter-separated record. Git preserves a literal `0x1f` inside an
|
|
342
|
+
author name, so an outside contributor choosing their own author name
|
|
343
|
+
could shift the parse and select the bytes read as the parent commit.
|
|
344
|
+
Because a parent whose blobs cannot be fetched is indistinguishable from
|
|
345
|
+
one that genuinely lacks the finding, this could manufacture a
|
|
346
|
+
`status: 'complete'` origin with **HIGH confidence** for a boundary that
|
|
347
|
+
was never verified — a fabricated certainty claim that would then flow
|
|
348
|
+
into signed evidence bundles. The field now sits behind the commit hash
|
|
349
|
+
only, with hex validation as defense in depth. Both directions are pinned
|
|
350
|
+
by a regression test.
|
|
351
|
+
- The provenance cache key and evidence digest are now genuinely bound to
|
|
352
|
+
the running detector/ruleset version (previously always `null` in
|
|
353
|
+
practice), so upgrading the scanner correctly invalidates stale cached
|
|
354
|
+
provenance.
|
|
355
|
+
- `ageBasis` and `provenAgeDays` are now rendered wherever a finding's age is
|
|
356
|
+
shown, not only written to `last-scan.json`.
|
|
357
|
+
- Provenance coverage is now wired into the real, running scorecard-generation
|
|
358
|
+
path (see "PRD completion" above for the number) instead of always
|
|
359
|
+
reporting "unmeasured."
|
|
360
|
+
- **Performance measurement is now honest end-to-end**, and the honest
|
|
361
|
+
numbers are a real miss against target: real p95 (n=20) over both cold and
|
|
362
|
+
warm cache arms, and a genuine two-sided memory comparison (not a one-arm
|
|
363
|
+
heap delta). Measured this release — cold-cache time ~27x wall-clock p95
|
|
364
|
+
against a ≤1.3x (≤30% overhead) target, warm-cache ~2x; cold-cache memory
|
|
365
|
+
~13x against a ≤1.2x target. `bench:provenance-accuracy:check` is now
|
|
366
|
+
wired into the pre-push gate so the known-origin-accuracy number can no
|
|
367
|
+
longer silently rot.
|
|
368
|
+
- The PRD's **required compliance-evidence disclaimer** ("Provenance
|
|
369
|
+
establishes repository history for technical evidence. It does not prove
|
|
370
|
+
developer intent, control operation outside code, organizational
|
|
371
|
+
compliance, or certification.") now appears next to every
|
|
372
|
+
provenance-derived origin the auditor walkthrough renders
|
|
373
|
+
(`compliance --walkthrough`), and user-facing documentation for the whole
|
|
374
|
+
feature now exists at
|
|
375
|
+
[`docs/guides/finding-provenance.md`](docs/guides/finding-provenance.md).
|
|
376
|
+
- **Not fixed, disclosed honestly:** a finding in a file renamed after
|
|
377
|
+
introduction still degrades to `status: 'partial'` rather than resolving
|
|
378
|
+
its true pre-rename origin commit. Known and traced, not fixed this round.
|
|
379
|
+
|
|
380
|
+
### Breaking: SCA finding ids change for manifest-declared dependencies
|
|
381
|
+
|
|
382
|
+
Direct dependencies declared in `package.json` / `requirements.txt` now carry the
|
|
383
|
+
manifest **line number** where they are declared, and `report/index.js`'s
|
|
384
|
+
`fingerprint()` folds that line into the finding id. This was necessary for
|
|
385
|
+
provenance — an SCA finding had no line, so every `vulnerable_dep` from one
|
|
386
|
+
manifest previously hashed to the SAME id and could not be told apart — but it
|
|
387
|
+
means those ids are **not stable across this upgrade**.
|
|
388
|
+
|
|
389
|
+
Concretely: any triage verdict, baseline entry, or suppression keyed on the OLD
|
|
390
|
+
id of a `package.json`- or `requirements.txt`-declared dependency finding will no
|
|
391
|
+
longer match and is effectively orphaned. Affected state:
|
|
392
|
+
`.agentic-security/baseline.json`, triage memory, and `disable:`/suppression
|
|
393
|
+
entries naming an SCA finding id. Transitive dependencies (resolved from a
|
|
394
|
+
lockfile, not declared in a manifest) are unaffected, as are all SAST, secrets,
|
|
395
|
+
and business-logic findings.
|
|
396
|
+
|
|
397
|
+
**There is no automatic migration**, and that is deliberate rather than an
|
|
398
|
+
oversight — id aliasing would have to be carried indefinitely to be safe, and
|
|
399
|
+
the orphaned entries fail open (a finding reappears) rather than closed (a real
|
|
400
|
+
finding stays hidden). Re-triage or re-baseline the affected SCA findings after
|
|
401
|
+
upgrading; `agentic-security scan --set-baseline` regenerates the baseline in one
|
|
402
|
+
step.
|
|
403
|
+
|
|
14
404
|
## 0.144.0 — Assurance hardening closes Epic E2, and an independent audit finds what "verified" missed
|
|
15
405
|
|
|
16
406
|
The assurance-hardening PRD (`docs/implementation/assurance-hardening-*`)
|