@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.
Files changed (209) hide show
  1. package/CHANGELOG.md +390 -0
  2. package/bin/agentic-security.js +3813 -83
  3. package/dist/1122.index.js +702 -0
  4. package/dist/{301.index.js → 1301.index.js} +2 -2
  5. package/dist/1379.index.js +591 -0
  6. package/dist/{444.index.js → 1444.index.js} +13 -4
  7. package/dist/{660.index.js → 1660.index.js} +2 -2
  8. package/dist/{700.index.js → 1700.index.js} +2 -2
  9. package/dist/{905.index.js → 1905.index.js} +3 -3
  10. package/dist/{920.index.js → 1920.index.js} +3 -3
  11. package/dist/{238.index.js → 2238.index.js} +3 -3
  12. package/dist/2271.index.js +165 -0
  13. package/dist/{985.index.js → 2376.index.js} +1260 -340
  14. package/dist/2432.index.js +793 -0
  15. package/dist/2659.index.js +93 -0
  16. package/dist/{826.index.js → 2826.index.js} +2 -2
  17. package/dist/{830.index.js → 2830.index.js} +2 -2
  18. package/dist/2923.index.js +298 -0
  19. package/dist/{1.index.js → 3001.index.js} +5 -5
  20. package/dist/{117.index.js → 3117.index.js} +3 -3
  21. package/dist/3180.index.js +307 -0
  22. package/dist/3276.index.js +117 -0
  23. package/dist/{415.index.js → 3415.index.js} +2 -2
  24. package/dist/{499.index.js → 3499.index.js} +2 -2
  25. package/dist/3518.index.js +450 -0
  26. package/dist/{526.index.js → 3526.index.js} +14 -6
  27. package/dist/{736.index.js → 3736.index.js} +4 -4
  28. package/dist/{839.index.js → 3839.index.js} +4 -4
  29. package/dist/{113.index.js → 4113.index.js} +14 -6
  30. package/dist/{265.index.js → 4265.index.js} +2 -2
  31. package/dist/{384.index.js → 4384.index.js} +3 -3
  32. package/dist/4547.index.js +268 -0
  33. package/dist/4863.index.js +422 -0
  34. package/dist/{970.index.js → 4970.index.js} +67 -3
  35. package/dist/5051.index.js +770 -0
  36. package/dist/{144.index.js → 5144.index.js} +5 -5
  37. package/dist/{333.index.js → 5333.index.js} +3 -3
  38. package/dist/5343.index.js +185 -0
  39. package/dist/5350.index.js +866 -0
  40. package/dist/5561.index.js +436 -0
  41. package/dist/{637.index.js → 5637.index.js} +29 -7
  42. package/dist/{449.index.js → 5830.index.js} +78 -14
  43. package/dist/6626.index.js +532 -0
  44. package/dist/6662.index.js +297 -0
  45. package/dist/{675.index.js → 6675.index.js} +5 -5
  46. package/dist/{730.index.js → 6730.index.js} +6 -6
  47. package/dist/6829.index.js +225 -0
  48. package/dist/6944.index.js +130 -0
  49. package/dist/{178.index.js → 7178.index.js} +26 -8
  50. package/dist/{227.index.js → 7227.index.js} +2 -2
  51. package/dist/7310.index.js +520 -0
  52. package/dist/{552.index.js → 7552.index.js} +4 -4
  53. package/dist/7709.index.js +78 -0
  54. package/dist/8218.index.js +160 -0
  55. package/dist/{476.index.js → 8476.index.js} +4 -4
  56. package/dist/{513.index.js → 8513.index.js} +5 -5
  57. package/dist/{520.index.js → 8520.index.js} +2 -2
  58. package/dist/{718.index.js → 8718.index.js} +2 -2
  59. package/dist/{752.index.js → 8752.index.js} +2 -2
  60. package/dist/8846.index.js +100 -0
  61. package/dist/{435.index.js → 9091.index.js} +580 -187
  62. package/dist/{207.index.js → 9207.index.js} +2 -2
  63. package/dist/{220.index.js → 9220.index.js} +2 -2
  64. package/dist/9390.index.js +163 -0
  65. package/dist/{503.index.js → 9503.index.js} +2 -2
  66. package/dist/{801.index.js → 9801.index.js} +2 -2
  67. package/dist/{824.index.js → 9824.index.js} +2 -2
  68. package/dist/agentic-security.mjs +16 -16
  69. package/dist/agentic-security.mjs.sha256 +1 -1
  70. package/dist/compliance-frameworks/hipaa-security-rule.json +3 -2
  71. package/package.json +23 -10
  72. package/src/compare.js +6 -1
  73. package/src/dataflow/CLAUDE.md +2 -2
  74. package/src/dataflow/catalog.js +42 -0
  75. package/src/dataflow/orm-write-catalog.js +175 -0
  76. package/src/engine.js +580 -30
  77. package/src/fix/apply-fix-service.js +1 -0
  78. package/src/history-scan.js +22 -5
  79. package/src/ir/CLAUDE.md +2 -1
  80. package/src/ir/chrome-probe.mjs +150 -0
  81. package/src/ir/parser-js.js +94 -7
  82. package/src/lineage/CLAUDE.md +1203 -0
  83. package/src/lineage/DESIGN_DESTINATION_RESOLVER.md +156 -0
  84. package/src/lineage/DESIGN_GRAPH_BUILDER.md +938 -0
  85. package/src/lineage/DESIGN_HANDLING_ANALYZER.md +355 -0
  86. package/src/lineage/DESIGN_INTRAPROCEDURAL.md +628 -0
  87. package/src/lineage/DESIGN_PATH_PROVENANCE.md +3451 -0
  88. package/src/lineage/DESIGN_QUEUE_DETAIL.md +120 -0
  89. package/src/lineage/DESIGN_REGISTRIES.md +880 -0
  90. package/src/lineage/DESIGN_STORE_DETAIL.md +143 -0
  91. package/src/lineage/DESIGN_TRANSIT_PROTECTION.md +245 -0
  92. package/src/lineage/classification.js +56 -0
  93. package/src/lineage/coverage.js +658 -0
  94. package/src/lineage/cross-repo-link.js +107 -0
  95. package/src/lineage/dataflow-graph.schema.json +184 -0
  96. package/src/lineage/decision-story.js +206 -0
  97. package/src/lineage/drift-policy.js +279 -0
  98. package/src/lineage/driver.js +135 -0
  99. package/src/lineage/engine.js +992 -0
  100. package/src/lineage/export-briefing.js +628 -0
  101. package/src/lineage/export-csv.js +62 -0
  102. package/src/lineage/export-json.js +238 -0
  103. package/src/lineage/export-privacy.js +258 -0
  104. package/src/lineage/federation-loader.js +111 -0
  105. package/src/lineage/field-identity.js +78 -0
  106. package/src/lineage/fixtures/build-flagship-fixture.mjs +272 -0
  107. package/src/lineage/fixtures/flagship-graph.json +1453 -0
  108. package/src/lineage/flow-grade.js +221 -0
  109. package/src/lineage/governance-edit.js +169 -0
  110. package/src/lineage/graph-builder.js +1114 -0
  111. package/src/lineage/graph-diff.js +431 -0
  112. package/src/lineage/graph-snapshot.js +180 -0
  113. package/src/lineage/handling-analyzer.js +168 -0
  114. package/src/lineage/ids.js +349 -0
  115. package/src/lineage/impact-assessment.js +76 -0
  116. package/src/lineage/impact-engine.js +268 -0
  117. package/src/lineage/index.js +281 -0
  118. package/src/lineage/language-coverage-tiers.js +58 -0
  119. package/src/lineage/obligation-mapping.js +126 -0
  120. package/src/lineage/obligation-predicates.js +235 -0
  121. package/src/lineage/observation-adapters.js +282 -0
  122. package/src/lineage/observation-correlation.js +622 -0
  123. package/src/lineage/observation-store.js +497 -0
  124. package/src/lineage/path-query.js +410 -0
  125. package/src/lineage/path-store.js +400 -0
  126. package/src/lineage/protection.js +53 -0
  127. package/src/lineage/recipient-profile.js +192 -0
  128. package/src/lineage/recipient-registry.js +394 -0
  129. package/src/lineage/redact-graph.js +224 -0
  130. package/src/lineage/remediation.js +417 -0
  131. package/src/lineage/resolve-destination.js +91 -0
  132. package/src/lineage/runtime-observation.js +464 -0
  133. package/src/lineage/scenario-diff.js +84 -0
  134. package/src/lineage/scenario-engine.js +251 -0
  135. package/src/lineage/scenario.js +101 -0
  136. package/src/lineage/schema.js +167 -0
  137. package/src/lineage/sink-registry.js +427 -0
  138. package/src/lineage/source-registry.js +357 -0
  139. package/src/lineage/source-seeding.js +212 -0
  140. package/src/lineage/summaries.js +590 -0
  141. package/src/lineage/transform-catalog.js +397 -0
  142. package/src/lineage/transit-protection.js +150 -0
  143. package/src/lineage/validate.js +285 -0
  144. package/src/lsp/server.js +49 -2
  145. package/src/mcp/CLAUDE.md +7 -1
  146. package/src/mcp/dataflow-tools.js +160 -0
  147. package/src/mcp/server.js +1 -1
  148. package/src/mcp/tools.js +22 -1
  149. package/src/pipeline/assurance-mode.js +64 -1
  150. package/src/pipeline/finding-schema.js +8 -1
  151. package/src/pipeline/scan-health.js +19 -1
  152. package/src/posture/CLAUDE.md +140 -0
  153. package/src/posture/accuracy-scorecard.js +60 -0
  154. package/src/posture/artifact-registry.js +76 -0
  155. package/src/posture/auditor-walkthrough.js +192 -13
  156. package/src/posture/compliance-frameworks/hipaa-security-rule.json +3 -2
  157. package/src/posture/compliance-policy.js +12 -2
  158. package/src/posture/cross-repo-memory.js +7 -2
  159. package/src/posture/fix-history.js +25 -2
  160. package/src/posture/fix-verify.js +9 -1
  161. package/src/posture/fleet.js +0 -0
  162. package/src/posture/git-history.js +13 -5
  163. package/src/posture/material-change.js +21 -2
  164. package/src/posture/mttr.js +75 -12
  165. package/src/posture/obligation-evidence-pack.js +202 -0
  166. package/src/posture/pre-incident-archaeology.js +39 -7
  167. package/src/posture/privacy-framework.js +14 -0
  168. package/src/posture/provenance/ai-authorship.js +68 -0
  169. package/src/posture/provenance/branch-entry.js +80 -0
  170. package/src/posture/provenance/cache.js +143 -0
  171. package/src/posture/provenance/confidence.js +36 -0
  172. package/src/posture/provenance/coordinator.js +786 -0
  173. package/src/posture/provenance/dag-walk.js +249 -0
  174. package/src/posture/provenance/evidence-attribution.js +59 -0
  175. package/src/posture/provenance/git-evidence.js +310 -0
  176. package/src/posture/provenance/lifecycle.js +208 -0
  177. package/src/posture/provenance/missing-control-resolver.js +137 -0
  178. package/src/posture/provenance/origin-resolver.js +342 -0
  179. package/src/posture/provenance/predicate-replay.js +133 -0
  180. package/src/posture/provenance/providers/config.js +39 -0
  181. package/src/posture/provenance/providers/github.js +62 -0
  182. package/src/posture/provenance/providers/gitlab.js +58 -0
  183. package/src/posture/provenance/repo-lineage.js +74 -0
  184. package/src/posture/provenance/sca-origin.js +139 -0
  185. package/src/posture/provenance/schema.js +255 -0
  186. package/src/posture/provenance/transitive-sca.js +147 -0
  187. package/src/posture/provenance/validate.js +30 -0
  188. package/src/posture/provenance-evidence-bundle.js +144 -0
  189. package/src/posture/remediation-ledger.js +337 -0
  190. package/src/posture/sbom-diff.js +15 -2
  191. package/src/posture/secret-history.js +10 -2
  192. package/src/posture/state-dir.js +38 -14
  193. package/src/posture/vuln-archaeology.js +8 -2
  194. package/src/pr-delta.js +25 -4
  195. package/src/report/index.js +197 -3
  196. package/src/runScan.js +34 -5
  197. package/src/sast/rate-limit.js +33 -3
  198. package/src/server/CLAUDE.md +47 -0
  199. package/src/server/graph-loader.js +141 -0
  200. package/src/server/http-server.js +325 -0
  201. package/src/server/routes.js +129 -0
  202. package/src/server/security.js +111 -0
  203. package/src/server/static-assets.js +139 -0
  204. package/src/util/git-hardening.js +128 -0
  205. package/dist/11.index.js +0 -353
  206. package/dist/259.index.js +0 -975
  207. package/dist/317.index.js +0 -300
  208. package/dist/609.index.js +0 -741
  209. package/dist/838.index.js +0 -152
@@ -0,0 +1,156 @@
1
+ # DESIGN_DESTINATION_RESOLVER.md — Sub-project A's binding design record (increment 1)
2
+
3
+ **Status:** landed as Milestone 2, Sub-project A, increment **1** — a
4
+ design-spike-sized first slice, per
5
+ `docs/superpowers/plans/2026-08-31-data-flow-explorer-m2-subproject-a1-plan.md`.
6
+ Binding on later Sub-project A increments the same way `DESIGN_
7
+ INTRAPROCEDURAL.md` binds A/B, `DESIGN_PATH_PROVENANCE.md` binds C, and
8
+ `DESIGN_GRAPH_BUILDER.md` binds E — but MUCH shorter, on purpose: this is
9
+ the first slice of a "Large" sub-project (FR-202), not the whole thing.
10
+
11
+ ---
12
+
13
+ ## 1. What this increment actually is
14
+
15
+ Every `DataFlowGraph v1` node has carried `destination: null` unconditionally
16
+ since Milestone 1, and every edge `protocol.destinationResolution: 'unknown'`
17
+ unconditionally — deliberately unimplemented (`graph-builder.js`'s own
18
+ header, `DESIGN_GRAPH_BUILDER.md`'s `graph.limitations` entry). This
19
+ increment fills in a real, non-null `destination` object for exactly two
20
+ shapes of call site: a literal destination argument/receiver, and a
21
+ call site FR-203 (Sub-project E, increment 4) already proved is NOT
22
+ statically resolvable. Everything else stays `unknown` — the same answer
23
+ Milestone 1 always gave.
24
+
25
+ No new detection. Both real outcomes below are built entirely from two
26
+ primitives `coverage.js` already shipped for FR-203: `detectUnresolvedDestination`
27
+ (the receiver/arg0 unresolvability heuristic) and `renderExpr` (expression →
28
+ string). This increment does not re-derive a second opinion on "is this
29
+ expression statically nameable" — it reuses FR-203's own answer.
30
+
31
+ ---
32
+
33
+ ## 2. The `destination` object shape
34
+
35
+ The single source of truth both `resolve-destination.js` and
36
+ `graph-builder.js` target:
37
+
38
+ ```
39
+ {
40
+ resolutionStatus: DestinationResolutionValue, // schema.js's DESTINATION_RESOLUTION_VALUES
41
+ raw: string | null, // renderExpr() of the resolved expression;
42
+ // null only when resolutionStatus === 'unknown'
43
+ literalValue: string | null, // String(value) of the literal; null unless
44
+ // resolutionStatus === 'literal'
45
+ blockingExpression: string | null, // FR-203's own blockingExpression, carried
46
+ // straight through; null unless
47
+ // resolutionStatus === 'dynamic'
48
+ }
49
+ ```
50
+
51
+ `raw` and `blockingExpression` are byte-identical for the `'dynamic'` case —
52
+ `raw` exists as its own field (rather than callers reading
53
+ `blockingExpression` for the same information) because a LATER increment
54
+ resolving `resolved_from_constant`/`resolved_from_config`/etc. will populate
55
+ `raw` with something that is NOT a "the resolution failed, here's why"
56
+ string, and `blockingExpression` must stay reserved for exactly that meaning
57
+ across every resolution status.
58
+
59
+ `raw` for the `'literal'` case is `renderExpr(expr)`, which JSON-stringifies
60
+ a literal's value (`renderExpr({kind:'literal', value:'https://x'})` →
61
+ `'"https://x"'`, quotes included) — the same rendering FR-203's own
62
+ `blockingExpression` strings already use for consistency. `literalValue` is
63
+ the unwrapped, human-usable form (`'https://x'`, no quotes) — a caller
64
+ displaying "resolves to X" wants `literalValue`; a caller wanting the exact
65
+ source-text rendering (for a diagnostic message, matching FR-203's own
66
+ `reason` string convention) wants `raw`.
67
+
68
+ ## 3. The two real resolution rules
69
+
70
+ 1. **`'literal'`** — the destination-bearing argument (arg0, but ONLY when
71
+ `site.decision.category` is one of `FR203_ARG0_DESTINATION_CATEGORIES`
72
+ — `external-api`/`file`/`object-storage`, the exact same narrower set
73
+ MUST-FIX 1 established for FR-203, since arg0 is a PAYLOAD everywhere
74
+ else) or the call's receiver (a member callee's `object`) is itself a
75
+ `literal`-kind expression.
76
+ 2. **`'dynamic'`** — anything `detectUnresolvedDestination(site)` already
77
+ flags, respecting the SAME arg0 category gate: a `via: 'arg0'` result
78
+ only counts when the category is eligible (otherwise a non-literal SQL/
79
+ HTML payload on a database/client-storage call would be misread as a
80
+ "dynamic destination", reintroducing the exact false positive MUST-FIX 1
81
+ fixed for FR-203's own ledger). A `via: 'receiver'` result always counts
82
+ — the receiver signal carries no narrower category gate in FR-203 either.
83
+ 3. **`'unknown'`** — everything else. Deliberately the same answer
84
+ Milestone 1 always gave; this increment only upgrades the two cases
85
+ above.
86
+
87
+ The literal check runs BEFORE the `detectUnresolvedDestination` check, on
88
+ purpose: a literal receiver (`"https://x".request()`, unusual but
89
+ IR-representable) is not a plain identifier either, so
90
+ `detectUnresolvedDestination` would flag it via `'receiver'` — checking
91
+ literal-ness first means it resolves as `'literal'`, not `'dynamic'`.
92
+
93
+ ## 4. Wiring — two independent, composable hooks
94
+
95
+ `opts.resolveDestination(site) -> destination | undefined` is a SEPARATE
96
+ hook from `opts.resolveSiteDecision` (FR-203's own hook), applied at the
97
+ same point in `graph-builder.js`'s pipeline, right after it. The two must
98
+ never collapse into one: `resolveSiteDecision` answers "is this sink's
99
+ CLASSIFICATION (`kind`/`category`/`coverageStatus`) still trustworthy", and
100
+ `resolveDestination` answers "what does this call site's destination
101
+ EXPRESSION look like" — a site can be BOTH `decision.kind: 'unresolved'`
102
+ (FR-203) AND carry `destination.resolutionStatus: 'dynamic'` (this
103
+ increment) at once; they are not restatements of each other; a future site
104
+ could plausibly have a `'modeled'`/non-unresolved decision AND still only
105
+ resolve to `'unknown'` here (e.g. a well-classified sink whose destination
106
+ argument is a plain, un-flagged variable reference).
107
+
108
+ `node.destination` is set once, at node MINT time — never part of the
109
+ node's own identity discriminator (`ids.nodeId`'s inputs are unchanged).
110
+ This is a deliberate, disclosed coarsening: when two different call sites
111
+ collide onto one node (same `kind`/`subtypeKey`/`coverageStatus`/
112
+ `externality`), that node's `destination` is whichever site's resolution
113
+ was applied first, not a set/union of every site's destination. Widening
114
+ the node identity to include `destination` — so distinct literal
115
+ destinations mint distinct nodes — is real, undecided scope for a later
116
+ increment, not attempted here (it changes every downstream node id, a much
117
+ larger blast radius than this increment's stated goal).
118
+
119
+ ## 5. Explicitly deferred (named, not silently skipped)
120
+
121
+ Every one of these needs its own extraction/resolution rule and its own
122
+ increment — bundling them into increment 1 risks the exact "Very Large, do
123
+ it all at once" trap Milestone 1's own sub-projects deliberately avoided:
124
+
125
+ - **Hostname/port/route/SDK-provider/model/cloud-resource-id/trust-zone
126
+ extraction** — FR-202's full nine-fact destination profile. This
127
+ increment resolves only WHETHER a destination is knowable and its raw
128
+ string form, never structured facts parsed out of it.
129
+ - **`resolved_from_constant`** (local-const folding, e.g. `const URL =
130
+ 'https://x'; fetch(URL)`) — needs a constant-propagation pass this
131
+ increment does not build.
132
+ - **`resolved_from_config`** (env var / config-object chain resolution,
133
+ e.g. `fetch(config.apiUrl)`) — needs config-shape resolution.
134
+ - **`resolved_from_schema`** / **`declared_service`** — needs schema
135
+ correlation or an operator-declared service registry; plausibly a later
136
+ Sub-project A increment, or Sub-projects E/F's own schema-correlation
137
+ work.
138
+ - **`runtime_corroborated`** — never in Milestone 2 at all; this is
139
+ Milestone 5's Digital Twin.
140
+ - **AI-provider/model resolution** (AC-01/AC-07's "provider, model when
141
+ known" clause, Decision 5 of the M2 scoping doc) — this increment's
142
+ literal-URL case is a real but partial step toward it (an AI SDK call's
143
+ base URL, when literal, now resolves), not a claim that AI-provider
144
+ resolution itself is done.
145
+ - **Node-identity widening by destination** (§4 above) — the node stays
146
+ category-granular, not per-destination-granular, in this increment.
147
+ - **A kind/category eligibility gate on the RECEIVER signal** — unlike the
148
+ arg0 signal (gated by `FR203_ARG0_DESTINATION_CATEGORIES`), a computed
149
+ receiver on a `log`/`sink`-kind site (categories FR-203's own
150
+ `FR203_ELIGIBLE_KINDS` excludes from the coverage ledger, since those
151
+ destinations are always fixed) can still resolve to `'dynamic'` here —
152
+ mirroring `coverage.js`'s own disclosed imprecision for the RECEIVER
153
+ signal in general ("will inflate `unresolvedDestinations` on any repo
154
+ using an ORM/repository pattern ... not narrowed in this increment").
155
+ Narrowing this to match `FR203_ELIGIBLE_KINDS` exactly is a natural
156
+ follow-up if it proves noisy in practice, not attempted here.