circle-ir 3.1.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 (194) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +200 -0
  3. package/configs/sinks/code_injection.yaml +672 -0
  4. package/configs/sinks/command.yaml +917 -0
  5. package/configs/sinks/deserialization.yaml +105 -0
  6. package/configs/sinks/ldap.yaml +136 -0
  7. package/configs/sinks/nodejs.json +629 -0
  8. package/configs/sinks/path.yaml +715 -0
  9. package/configs/sinks/python.json +501 -0
  10. package/configs/sinks/rust.json +339 -0
  11. package/configs/sinks/sql.yaml +233 -0
  12. package/configs/sinks/ssrf.yaml +160 -0
  13. package/configs/sinks/xpath.yaml +121 -0
  14. package/configs/sinks/xss.yaml +727 -0
  15. package/configs/sources/db_sources.yaml +90 -0
  16. package/configs/sources/env_sources.yaml +94 -0
  17. package/configs/sources/express.json +197 -0
  18. package/configs/sources/file_sources.yaml +164 -0
  19. package/configs/sources/http_sources.yaml +379 -0
  20. package/configs/sources/io_sources.yaml +519 -0
  21. package/configs/sources/network_sources.yaml +99 -0
  22. package/configs/sources/python.json +230 -0
  23. package/configs/sources/rust.json +286 -0
  24. package/configs/sources/spring.yaml +70 -0
  25. package/dist/analysis/advisory-db.d.ts +86 -0
  26. package/dist/analysis/advisory-db.js +104 -0
  27. package/dist/analysis/advisory-db.js.map +1 -0
  28. package/dist/analysis/cargo-parser.d.ts +42 -0
  29. package/dist/analysis/cargo-parser.js +102 -0
  30. package/dist/analysis/cargo-parser.js.map +1 -0
  31. package/dist/analysis/config-loader.d.ts +37 -0
  32. package/dist/analysis/config-loader.js +1561 -0
  33. package/dist/analysis/config-loader.js.map +1 -0
  34. package/dist/analysis/constant-propagation/ast-utils.d.ts +25 -0
  35. package/dist/analysis/constant-propagation/ast-utils.js +34 -0
  36. package/dist/analysis/constant-propagation/ast-utils.js.map +1 -0
  37. package/dist/analysis/constant-propagation/evaluator.d.ts +32 -0
  38. package/dist/analysis/constant-propagation/evaluator.js +296 -0
  39. package/dist/analysis/constant-propagation/evaluator.js.map +1 -0
  40. package/dist/analysis/constant-propagation/index.d.ts +62 -0
  41. package/dist/analysis/constant-propagation/index.js +152 -0
  42. package/dist/analysis/constant-propagation/index.js.map +1 -0
  43. package/dist/analysis/constant-propagation/patterns.d.ts +8 -0
  44. package/dist/analysis/constant-propagation/patterns.js +126 -0
  45. package/dist/analysis/constant-propagation/patterns.js.map +1 -0
  46. package/dist/analysis/constant-propagation/propagator.d.ts +180 -0
  47. package/dist/analysis/constant-propagation/propagator.js +1985 -0
  48. package/dist/analysis/constant-propagation/propagator.js.map +1 -0
  49. package/dist/analysis/constant-propagation/types.d.ts +63 -0
  50. package/dist/analysis/constant-propagation/types.js +5 -0
  51. package/dist/analysis/constant-propagation/types.js.map +1 -0
  52. package/dist/analysis/constant-propagation.d.ts +9 -0
  53. package/dist/analysis/constant-propagation.js +18 -0
  54. package/dist/analysis/constant-propagation.js.map +1 -0
  55. package/dist/analysis/dependency-scanner.d.ts +79 -0
  56. package/dist/analysis/dependency-scanner.js +122 -0
  57. package/dist/analysis/dependency-scanner.js.map +1 -0
  58. package/dist/analysis/dfg-verifier.d.ts +116 -0
  59. package/dist/analysis/dfg-verifier.js +399 -0
  60. package/dist/analysis/dfg-verifier.js.map +1 -0
  61. package/dist/analysis/findings.d.ts +11 -0
  62. package/dist/analysis/findings.js +228 -0
  63. package/dist/analysis/findings.js.map +1 -0
  64. package/dist/analysis/index.d.ts +16 -0
  65. package/dist/analysis/index.js +18 -0
  66. package/dist/analysis/index.js.map +1 -0
  67. package/dist/analysis/interprocedural.d.ts +99 -0
  68. package/dist/analysis/interprocedural.js +526 -0
  69. package/dist/analysis/interprocedural.js.map +1 -0
  70. package/dist/analysis/path-finder.d.ts +133 -0
  71. package/dist/analysis/path-finder.js +354 -0
  72. package/dist/analysis/path-finder.js.map +1 -0
  73. package/dist/analysis/rules.d.ts +75 -0
  74. package/dist/analysis/rules.js +332 -0
  75. package/dist/analysis/rules.js.map +1 -0
  76. package/dist/analysis/semver.d.ts +27 -0
  77. package/dist/analysis/semver.js +127 -0
  78. package/dist/analysis/semver.js.map +1 -0
  79. package/dist/analysis/taint-matcher.d.ts +15 -0
  80. package/dist/analysis/taint-matcher.js +634 -0
  81. package/dist/analysis/taint-matcher.js.map +1 -0
  82. package/dist/analysis/taint-propagation.d.ts +67 -0
  83. package/dist/analysis/taint-propagation.js +298 -0
  84. package/dist/analysis/taint-propagation.js.map +1 -0
  85. package/dist/analysis/unresolved.d.ts +14 -0
  86. package/dist/analysis/unresolved.js +202 -0
  87. package/dist/analysis/unresolved.js.map +1 -0
  88. package/dist/analyzer.d.ts +43 -0
  89. package/dist/analyzer.js +1010 -0
  90. package/dist/analyzer.js.map +1 -0
  91. package/dist/browser/circle-ir.js +16576 -0
  92. package/dist/browser.d.ts +38 -0
  93. package/dist/browser.js +38 -0
  94. package/dist/browser.js.map +1 -0
  95. package/dist/core/circle-ir-core.cjs +13626 -0
  96. package/dist/core/circle-ir-core.d.ts +59 -0
  97. package/dist/core/circle-ir-core.js +13591 -0
  98. package/dist/core/extractors/calls.d.ts +13 -0
  99. package/dist/core/extractors/calls.js +1429 -0
  100. package/dist/core/extractors/calls.js.map +1 -0
  101. package/dist/core/extractors/cfg.d.ts +9 -0
  102. package/dist/core/extractors/cfg.js +519 -0
  103. package/dist/core/extractors/cfg.js.map +1 -0
  104. package/dist/core/extractors/dfg.d.ts +12 -0
  105. package/dist/core/extractors/dfg.js +1081 -0
  106. package/dist/core/extractors/dfg.js.map +1 -0
  107. package/dist/core/extractors/exports.d.ts +14 -0
  108. package/dist/core/extractors/exports.js +80 -0
  109. package/dist/core/extractors/exports.js.map +1 -0
  110. package/dist/core/extractors/imports.d.ts +9 -0
  111. package/dist/core/extractors/imports.js +739 -0
  112. package/dist/core/extractors/imports.js.map +1 -0
  113. package/dist/core/extractors/index.d.ts +10 -0
  114. package/dist/core/extractors/index.js +11 -0
  115. package/dist/core/extractors/index.js.map +1 -0
  116. package/dist/core/extractors/meta.d.ts +10 -0
  117. package/dist/core/extractors/meta.js +109 -0
  118. package/dist/core/extractors/meta.js.map +1 -0
  119. package/dist/core/extractors/types.d.ts +10 -0
  120. package/dist/core/extractors/types.js +1479 -0
  121. package/dist/core/extractors/types.js.map +1 -0
  122. package/dist/core/index.d.ts +5 -0
  123. package/dist/core/index.js +8 -0
  124. package/dist/core/index.js.map +1 -0
  125. package/dist/core/parser.d.ts +84 -0
  126. package/dist/core/parser.js +250 -0
  127. package/dist/core/parser.js.map +1 -0
  128. package/dist/core-lib.d.ts +59 -0
  129. package/dist/core-lib.js +62 -0
  130. package/dist/core-lib.js.map +1 -0
  131. package/dist/index.d.ts +15 -0
  132. package/dist/index.js +20 -0
  133. package/dist/index.js.map +1 -0
  134. package/dist/languages/index.d.ts +11 -0
  135. package/dist/languages/index.js +14 -0
  136. package/dist/languages/index.js.map +1 -0
  137. package/dist/languages/plugins/base.d.ts +44 -0
  138. package/dist/languages/plugins/base.js +82 -0
  139. package/dist/languages/plugins/base.js.map +1 -0
  140. package/dist/languages/plugins/index.d.ts +14 -0
  141. package/dist/languages/plugins/index.js +25 -0
  142. package/dist/languages/plugins/index.js.map +1 -0
  143. package/dist/languages/plugins/java.d.ts +49 -0
  144. package/dist/languages/plugins/java.js +402 -0
  145. package/dist/languages/plugins/java.js.map +1 -0
  146. package/dist/languages/plugins/javascript.d.ts +48 -0
  147. package/dist/languages/plugins/javascript.js +445 -0
  148. package/dist/languages/plugins/javascript.js.map +1 -0
  149. package/dist/languages/plugins/python.d.ts +47 -0
  150. package/dist/languages/plugins/python.js +480 -0
  151. package/dist/languages/plugins/python.js.map +1 -0
  152. package/dist/languages/plugins/rust.d.ts +47 -0
  153. package/dist/languages/plugins/rust.js +405 -0
  154. package/dist/languages/plugins/rust.js.map +1 -0
  155. package/dist/languages/registry.d.ts +30 -0
  156. package/dist/languages/registry.js +80 -0
  157. package/dist/languages/registry.js.map +1 -0
  158. package/dist/languages/types.d.ts +184 -0
  159. package/dist/languages/types.js +8 -0
  160. package/dist/languages/types.js.map +1 -0
  161. package/dist/resolution/cross-file.d.ts +146 -0
  162. package/dist/resolution/cross-file.js +439 -0
  163. package/dist/resolution/cross-file.js.map +1 -0
  164. package/dist/resolution/index.d.ts +12 -0
  165. package/dist/resolution/index.js +10 -0
  166. package/dist/resolution/index.js.map +1 -0
  167. package/dist/resolution/symbol-table.d.ts +136 -0
  168. package/dist/resolution/symbol-table.js +336 -0
  169. package/dist/resolution/symbol-table.js.map +1 -0
  170. package/dist/resolution/type-hierarchy.d.ts +124 -0
  171. package/dist/resolution/type-hierarchy.js +515 -0
  172. package/dist/resolution/type-hierarchy.js.map +1 -0
  173. package/dist/types/config.d.ts +45 -0
  174. package/dist/types/config.js +5 -0
  175. package/dist/types/config.js.map +1 -0
  176. package/dist/types/index.d.ts +392 -0
  177. package/dist/types/index.js +7 -0
  178. package/dist/types/index.js.map +1 -0
  179. package/dist/utils/logger.d.ts +85 -0
  180. package/dist/utils/logger.js +198 -0
  181. package/dist/utils/logger.js.map +1 -0
  182. package/dist/wasm/tree-sitter-java.wasm +0 -0
  183. package/dist/wasm/tree-sitter-javascript.wasm +0 -0
  184. package/dist/wasm/tree-sitter-python.wasm +0 -0
  185. package/dist/wasm/tree-sitter-rust.wasm +0 -0
  186. package/dist/wasm/web-tree-sitter.wasm +0 -0
  187. package/docs/SPEC.md +1021 -0
  188. package/examples/browser-example.html +610 -0
  189. package/examples/node-example.ts +215 -0
  190. package/package.json +107 -0
  191. package/wasm/tree-sitter-java.wasm +0 -0
  192. package/wasm/tree-sitter-javascript.wasm +0 -0
  193. package/wasm/tree-sitter-python.wasm +0 -0
  194. package/wasm/tree-sitter-rust.wasm +0 -0
@@ -0,0 +1,399 @@
1
+ /**
2
+ * DFG Verifier - Track 2 validation using def-use chains
3
+ *
4
+ * Verifies that taint actually flows from source to sink by following
5
+ * the data flow graph. This provides a more precise validation than
6
+ * pattern matching alone.
7
+ */
8
+ /**
9
+ * DFGVerifier - Verifies taint flows using def-use chains
10
+ */
11
+ export class DFGVerifier {
12
+ dfg;
13
+ calls;
14
+ sanitizers;
15
+ config;
16
+ // Lookup maps
17
+ defById = new Map();
18
+ defsByLine = new Map();
19
+ defsByVar = new Map();
20
+ usesByDefId = new Map();
21
+ usesByLine = new Map();
22
+ callsByLine = new Map();
23
+ sanitizerLines = new Set();
24
+ // Chain lookup for faster traversal
25
+ chainsByFromDef = new Map();
26
+ constructor(dfg, calls, sanitizers, config = {}) {
27
+ this.dfg = dfg;
28
+ this.calls = calls;
29
+ this.sanitizers = sanitizers;
30
+ this.config = {
31
+ maxDepth: config.maxDepth ?? 30,
32
+ requireDirectFlow: config.requireDirectFlow ?? false,
33
+ allowFieldFlows: config.allowFieldFlows ?? true,
34
+ };
35
+ this.buildLookupMaps();
36
+ }
37
+ /**
38
+ * Build lookup maps for efficient querying
39
+ */
40
+ buildLookupMaps() {
41
+ for (const def of this.dfg.defs) {
42
+ this.defById.set(def.id, def);
43
+ const byLine = this.defsByLine.get(def.line) ?? [];
44
+ byLine.push(def);
45
+ this.defsByLine.set(def.line, byLine);
46
+ const byVar = this.defsByVar.get(def.variable) ?? [];
47
+ byVar.push(def);
48
+ this.defsByVar.set(def.variable, byVar);
49
+ }
50
+ for (const use of this.dfg.uses) {
51
+ const byLine = this.usesByLine.get(use.line) ?? [];
52
+ byLine.push(use);
53
+ this.usesByLine.set(use.line, byLine);
54
+ if (use.def_id !== null) {
55
+ const byDefId = this.usesByDefId.get(use.def_id) ?? [];
56
+ byDefId.push(use);
57
+ this.usesByDefId.set(use.def_id, byDefId);
58
+ }
59
+ }
60
+ for (const call of this.calls) {
61
+ const byLine = this.callsByLine.get(call.location.line) ?? [];
62
+ byLine.push(call);
63
+ this.callsByLine.set(call.location.line, byLine);
64
+ }
65
+ for (const sanitizer of this.sanitizers) {
66
+ this.sanitizerLines.add(sanitizer.line);
67
+ }
68
+ // Build chain lookup
69
+ if (this.dfg.chains) {
70
+ for (const chain of this.dfg.chains) {
71
+ const byFromDef = this.chainsByFromDef.get(chain.from_def) ?? [];
72
+ byFromDef.push(chain);
73
+ this.chainsByFromDef.set(chain.from_def, byFromDef);
74
+ }
75
+ }
76
+ }
77
+ /**
78
+ * Verify if taint flows from source to sink
79
+ */
80
+ verify(source, sink) {
81
+ // Find definitions at the source line
82
+ const sourceDefs = this.defsByLine.get(source.line) ?? [];
83
+ if (sourceDefs.length === 0) {
84
+ return {
85
+ verified: false,
86
+ confidence: 0,
87
+ reason: `No variable definition found at source line ${source.line}`,
88
+ };
89
+ }
90
+ // Try to find a path from any source definition to the sink
91
+ const allPaths = [];
92
+ for (const sourceDef of sourceDefs) {
93
+ const path = this.findPath(sourceDef, sink);
94
+ if (path) {
95
+ allPaths.push(path);
96
+ }
97
+ }
98
+ if (allPaths.length === 0) {
99
+ return {
100
+ verified: false,
101
+ confidence: 0.2, // Some confidence since pattern matched
102
+ reason: `No def-use chain found from source (line ${source.line}) to sink (line ${sink.line})`,
103
+ };
104
+ }
105
+ // Find the best path (shortest, direct if possible)
106
+ const bestPath = this.selectBestPath(allPaths);
107
+ // Check for sanitizers in path
108
+ const sanitizerInPath = this.checkSanitizers(bestPath);
109
+ if (sanitizerInPath) {
110
+ return {
111
+ verified: false,
112
+ confidence: 0.1,
113
+ reason: `Flow sanitized at line ${sanitizerInPath.line} by ${sanitizerInPath.method}`,
114
+ path: bestPath,
115
+ alternativePaths: allPaths.length - 1,
116
+ };
117
+ }
118
+ // Calculate confidence based on path characteristics
119
+ const confidence = this.calculateConfidence(bestPath);
120
+ return {
121
+ verified: true,
122
+ confidence,
123
+ reason: `Verified: ${bestPath.length}-step flow from line ${source.line} to line ${sink.line}`,
124
+ path: bestPath,
125
+ alternativePaths: allPaths.length - 1,
126
+ };
127
+ }
128
+ /**
129
+ * Find a path from a definition to a sink using BFS
130
+ */
131
+ findPath(sourceDef, sink) {
132
+ const initialStep = {
133
+ defId: sourceDef.id,
134
+ variable: sourceDef.variable,
135
+ line: sourceDef.line,
136
+ kind: sourceDef.kind,
137
+ flowType: 'direct',
138
+ };
139
+ const queue = [{
140
+ def: sourceDef,
141
+ steps: [initialStep],
142
+ visited: new Set([sourceDef.id]),
143
+ }];
144
+ while (queue.length > 0) {
145
+ const state = queue.shift();
146
+ // Check depth limit
147
+ if (state.steps.length > this.config.maxDepth) {
148
+ continue;
149
+ }
150
+ // Check if current definition reaches the sink
151
+ if (this.reachesSink(state.def, sink)) {
152
+ return {
153
+ steps: state.steps,
154
+ length: state.steps.length,
155
+ hasDirectFlow: state.steps.every(s => s.flowType === 'direct' || s.flowType === 'assignment'),
156
+ };
157
+ }
158
+ // Explore via def-use chains (if available)
159
+ const chains = this.chainsByFromDef.get(state.def.id) ?? [];
160
+ for (const chain of chains) {
161
+ const nextDef = this.defById.get(chain.to_def);
162
+ if (!nextDef || state.visited.has(nextDef.id))
163
+ continue;
164
+ const step = {
165
+ defId: nextDef.id,
166
+ variable: nextDef.variable,
167
+ line: nextDef.line,
168
+ kind: nextDef.kind,
169
+ flowType: 'assignment',
170
+ };
171
+ const newVisited = new Set(state.visited);
172
+ newVisited.add(nextDef.id);
173
+ queue.push({
174
+ def: nextDef,
175
+ steps: [...state.steps, step],
176
+ visited: newVisited,
177
+ });
178
+ }
179
+ // Explore via uses of the current definition
180
+ const uses = this.usesByDefId.get(state.def.id) ?? [];
181
+ for (const use of uses) {
182
+ // Find definitions at the use line
183
+ const nextDefs = this.defsByLine.get(use.line) ?? [];
184
+ for (const nextDef of nextDefs) {
185
+ if (state.visited.has(nextDef.id))
186
+ continue;
187
+ // Skip field flows if not allowed
188
+ if (!this.config.allowFieldFlows && nextDef.kind === 'field') {
189
+ continue;
190
+ }
191
+ const flowType = this.determineFlowType(state.def, nextDef, use.line);
192
+ const step = {
193
+ defId: nextDef.id,
194
+ variable: nextDef.variable,
195
+ line: nextDef.line,
196
+ kind: nextDef.kind,
197
+ flowType,
198
+ };
199
+ const newVisited = new Set(state.visited);
200
+ newVisited.add(nextDef.id);
201
+ queue.push({
202
+ def: nextDef,
203
+ steps: [...state.steps, step],
204
+ visited: newVisited,
205
+ });
206
+ }
207
+ }
208
+ // Explore same-variable definitions at later lines
209
+ const laterDefs = (this.defsByVar.get(state.def.variable) ?? [])
210
+ .filter(d => d.line > state.def.line && d.line <= sink.line && !state.visited.has(d.id))
211
+ .slice(0, 5); // Limit branching
212
+ for (const nextDef of laterDefs) {
213
+ const step = {
214
+ defId: nextDef.id,
215
+ variable: nextDef.variable,
216
+ line: nextDef.line,
217
+ kind: nextDef.kind,
218
+ flowType: 'assignment',
219
+ };
220
+ const newVisited = new Set(state.visited);
221
+ newVisited.add(nextDef.id);
222
+ queue.push({
223
+ def: nextDef,
224
+ steps: [...state.steps, step],
225
+ visited: newVisited,
226
+ });
227
+ }
228
+ }
229
+ return null;
230
+ }
231
+ /**
232
+ * Check if a definition reaches a sink
233
+ */
234
+ reachesSink(def, sink) {
235
+ // Check uses at sink line
236
+ const uses = this.usesByLine.get(sink.line) ?? [];
237
+ for (const use of uses) {
238
+ if (use.variable === def.variable || use.def_id === def.id) {
239
+ return true;
240
+ }
241
+ }
242
+ // Check call arguments at sink line
243
+ const calls = this.callsByLine.get(sink.line) ?? [];
244
+ for (const call of calls) {
245
+ for (const arg of call.arguments) {
246
+ if (arg.variable === def.variable) {
247
+ return true;
248
+ }
249
+ }
250
+ }
251
+ // Check if definition is at or before sink line with same variable
252
+ if (def.line <= sink.line) {
253
+ const laterDefs = (this.defsByVar.get(def.variable) ?? [])
254
+ .filter(d => d.line > def.line && d.line <= sink.line);
255
+ // If no redefinition between def and sink, it reaches
256
+ if (laterDefs.length === 0) {
257
+ return true;
258
+ }
259
+ }
260
+ return false;
261
+ }
262
+ /**
263
+ * Determine the type of flow between two definitions
264
+ */
265
+ determineFlowType(fromDef, toDef, useLine) {
266
+ // Check for call at the line
267
+ const calls = this.callsByLine.get(useLine) ?? [];
268
+ if (calls.length > 0) {
269
+ // If the variable changed, it's a return assignment
270
+ if (fromDef.variable !== toDef.variable) {
271
+ return 'return';
272
+ }
273
+ return 'call';
274
+ }
275
+ // Check for field access
276
+ if (toDef.kind === 'field') {
277
+ return 'field';
278
+ }
279
+ // Simple assignment
280
+ if (fromDef.variable === toDef.variable) {
281
+ return 'direct';
282
+ }
283
+ return 'assignment';
284
+ }
285
+ /**
286
+ * Select the best path from multiple candidates
287
+ */
288
+ selectBestPath(paths) {
289
+ // Prefer direct flows
290
+ const directPaths = paths.filter(p => p.hasDirectFlow);
291
+ if (directPaths.length > 0) {
292
+ return directPaths.reduce((a, b) => a.length <= b.length ? a : b);
293
+ }
294
+ // Otherwise, prefer shortest path
295
+ return paths.reduce((a, b) => a.length <= b.length ? a : b);
296
+ }
297
+ /**
298
+ * Check if any sanitizer is in the path
299
+ */
300
+ checkSanitizers(path) {
301
+ for (const step of path.steps) {
302
+ if (this.sanitizerLines.has(step.line)) {
303
+ return this.sanitizers.find(s => s.line === step.line) || null;
304
+ }
305
+ }
306
+ return null;
307
+ }
308
+ /**
309
+ * Calculate confidence based on path characteristics
310
+ */
311
+ calculateConfidence(path) {
312
+ let confidence = 0.9; // Base confidence for verified flow
313
+ // Bonus for direct flow
314
+ if (path.hasDirectFlow) {
315
+ confidence += 0.05;
316
+ }
317
+ // Penalty for long paths
318
+ if (path.length > 5) {
319
+ confidence -= 0.05;
320
+ }
321
+ if (path.length > 10) {
322
+ confidence -= 0.1;
323
+ }
324
+ // Penalty for field flows
325
+ const fieldSteps = path.steps.filter(s => s.flowType === 'field').length;
326
+ confidence -= fieldSteps * 0.05;
327
+ return Math.max(0.5, Math.min(1.0, confidence));
328
+ }
329
+ /**
330
+ * Batch verify multiple source-sink pairs
331
+ */
332
+ verifyAll(sources, sinks) {
333
+ const results = new Map();
334
+ for (const source of sources) {
335
+ for (const sink of sinks) {
336
+ const key = `${source.line}:${sink.line}`;
337
+ const result = this.verify(source, sink);
338
+ results.set(key, result);
339
+ }
340
+ }
341
+ return results;
342
+ }
343
+ /**
344
+ * Get verification statistics
345
+ */
346
+ getStats(results) {
347
+ let verified = 0;
348
+ let notVerified = 0;
349
+ let sanitized = 0;
350
+ let totalConfidence = 0;
351
+ for (const result of results.values()) {
352
+ if (result.verified) {
353
+ verified++;
354
+ totalConfidence += result.confidence;
355
+ }
356
+ else if (result.reason.includes('sanitized')) {
357
+ sanitized++;
358
+ }
359
+ else {
360
+ notVerified++;
361
+ }
362
+ }
363
+ return {
364
+ total: results.size,
365
+ verified,
366
+ notVerified,
367
+ sanitized,
368
+ avgConfidence: verified > 0 ? totalConfidence / verified : 0,
369
+ };
370
+ }
371
+ }
372
+ /**
373
+ * Convenience function to verify a single flow
374
+ */
375
+ export function verifyTaintFlow(dfg, calls, source, sink, sanitizers = [], config = {}) {
376
+ const verifier = new DFGVerifier(dfg, calls, sanitizers, config);
377
+ return verifier.verify(source, sink);
378
+ }
379
+ /**
380
+ * Format verification result for display
381
+ */
382
+ export function formatVerificationResult(result) {
383
+ const lines = [];
384
+ const status = result.verified ? '✓ VERIFIED' : '✗ NOT VERIFIED';
385
+ lines.push(`${status} (${Math.round(result.confidence * 100)}% confidence)`);
386
+ lines.push(`Reason: ${result.reason}`);
387
+ if (result.path) {
388
+ lines.push(`Path length: ${result.path.length} steps`);
389
+ lines.push('Steps:');
390
+ for (const step of result.path.steps) {
391
+ lines.push(` - Line ${step.line}: ${step.variable} (${step.flowType})`);
392
+ }
393
+ }
394
+ if (result.alternativePaths && result.alternativePaths > 0) {
395
+ lines.push(`Alternative paths found: ${result.alternativePaths}`);
396
+ }
397
+ return lines.join('\n');
398
+ }
399
+ //# sourceMappingURL=dfg-verifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dfg-verifier.js","sourceRoot":"","sources":["../../src/analysis/dfg-verifier.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Finding generator
3
+ *
4
+ * Combines taint sources, sinks, and data flow analysis to generate
5
+ * vulnerability findings with paths and remediation suggestions.
6
+ */
7
+ import type { TaintSource, TaintSink, DFG, Finding } from '../types/index.js';
8
+ /**
9
+ * Generate vulnerability findings from taint analysis results.
10
+ */
11
+ export declare function generateFindings(sources: TaintSource[], sinks: TaintSink[], dfg: DFG, fileName: string): Finding[];
@@ -0,0 +1,228 @@
1
+ /**
2
+ * Finding generator
3
+ *
4
+ * Combines taint sources, sinks, and data flow analysis to generate
5
+ * vulnerability findings with paths and remediation suggestions.
6
+ */
7
+ import { calculateSeverity as calcSeverity, getRemediation, getSourceDescription, getSinkDescription, } from './rules.js';
8
+ /**
9
+ * Generate vulnerability findings from taint analysis results.
10
+ */
11
+ export function generateFindings(sources, sinks, dfg, fileName) {
12
+ const findings = [];
13
+ let findingId = 1;
14
+ // For each source, find potential paths to sinks
15
+ for (const source of sources) {
16
+ for (const sink of sinks) {
17
+ // Check if this source type can reach this sink type
18
+ if (!canSourceReachSink(source.type, sink.type)) {
19
+ continue;
20
+ }
21
+ // Try to find a path through the DFG
22
+ const pathResult = findTaintPath(source, sink, dfg);
23
+ if (pathResult.pathExists || isProximityVulnerability(source, sink)) {
24
+ const severity = calcSeverity({
25
+ sourceType: source.type,
26
+ sinkType: sink.type,
27
+ pathExists: pathResult.pathExists,
28
+ });
29
+ const confidence = calculateConfidence(source, sink, pathResult);
30
+ findings.push({
31
+ id: `vuln${findingId++}`,
32
+ type: sink.type,
33
+ cwe: sink.cwe,
34
+ severity,
35
+ confidence,
36
+ source: {
37
+ file: fileName,
38
+ line: source.line,
39
+ code: source.location,
40
+ },
41
+ sink: {
42
+ file: fileName,
43
+ line: sink.line,
44
+ code: sink.location,
45
+ },
46
+ path: pathResult.hops.length > 0 ? pathResult.hops : undefined,
47
+ exploitable: pathResult.pathExists && confidence > 0.7,
48
+ explanation: generateExplanation(source, sink, pathResult),
49
+ remediation: getRemediation(sink.type),
50
+ verification: {
51
+ graph_path_exists: pathResult.pathExists,
52
+ llm_verified: false,
53
+ llm_confidence: 0,
54
+ },
55
+ });
56
+ }
57
+ }
58
+ }
59
+ // Sort by severity and confidence
60
+ findings.sort((a, b) => {
61
+ const severityOrder = { critical: 0, high: 1, medium: 2, low: 3 };
62
+ const severityDiff = severityOrder[a.severity] - severityOrder[b.severity];
63
+ if (severityDiff !== 0)
64
+ return severityDiff;
65
+ return b.confidence - a.confidence;
66
+ });
67
+ return findings;
68
+ }
69
+ /**
70
+ * Check if a source type can potentially reach a sink type.
71
+ */
72
+ function canSourceReachSink(sourceType, sinkType) {
73
+ const sourceToSinkMapping = {
74
+ http_param: ['sql_injection', 'command_injection', 'path_traversal', 'xss', 'xpath_injection', 'ldap_injection', 'ssrf'],
75
+ http_body: ['sql_injection', 'command_injection', 'deserialization', 'xxe', 'xss', 'code_injection'],
76
+ http_header: ['sql_injection', 'xss', 'ssrf'],
77
+ http_cookie: ['sql_injection', 'xss'],
78
+ http_path: ['path_traversal', 'sql_injection', 'ssrf'],
79
+ http_query: ['sql_injection', 'command_injection', 'xss', 'ssrf'],
80
+ io_input: ['command_injection', 'path_traversal', 'deserialization', 'xxe', 'code_injection', 'xss'],
81
+ env_input: ['command_injection', 'path_traversal'],
82
+ db_input: ['xss', 'sql_injection'], // Second-order injection
83
+ file_input: ['deserialization', 'xxe', 'path_traversal', 'command_injection', 'code_injection'],
84
+ network_input: ['sql_injection', 'command_injection', 'xss', 'ssrf'],
85
+ config_param: ['sql_injection', 'command_injection', 'path_traversal', 'xss', 'ssrf'], // Servlet init params
86
+ interprocedural_param: ['sql_injection', 'command_injection', 'path_traversal', 'xss', 'xpath_injection', 'ldap_injection', 'ssrf', 'code_injection'], // Cross-method taint
87
+ plugin_param: ['sql_injection', 'command_injection', 'path_traversal', 'xss', 'code_injection'], // Plugin/config parameters
88
+ };
89
+ const validSinks = sourceToSinkMapping[sourceType];
90
+ return validSinks ? validSinks.includes(sinkType) : false;
91
+ }
92
+ /**
93
+ * Find a taint path from source to sink through the DFG.
94
+ */
95
+ function findTaintPath(source, sink, dfg) {
96
+ const hops = [];
97
+ const variables = [];
98
+ // Find definitions near the source line
99
+ const sourceDefs = dfg.defs.filter(d => d.line >= source.line - 1 && d.line <= source.line + 1);
100
+ // Find uses near the sink line
101
+ const sinkUses = dfg.uses.filter(u => u.line >= sink.line - 1 && u.line <= sink.line + 1);
102
+ if (sourceDefs.length === 0 || sinkUses.length === 0) {
103
+ return { pathExists: false, hops: [], variables: [] };
104
+ }
105
+ // Use DFG chains to find path
106
+ const chains = dfg.chains ?? [];
107
+ // Try to find a path from any source def to any sink use
108
+ for (const sourceDef of sourceDefs) {
109
+ for (const sinkUse of sinkUses) {
110
+ const path = findPathThroughChains(sourceDef.id, sinkUse.def_id, chains, dfg);
111
+ if (path.length > 0) {
112
+ // Build hops from path
113
+ for (const defId of path) {
114
+ const def = dfg.defs.find(d => d.id === defId);
115
+ if (def) {
116
+ hops.push({
117
+ file: '', // Will be filled by caller
118
+ method: '',
119
+ line: def.line,
120
+ code: `${def.variable} = ...`,
121
+ variable: def.variable,
122
+ });
123
+ variables.push(def.variable);
124
+ }
125
+ }
126
+ return { pathExists: true, hops, variables };
127
+ }
128
+ }
129
+ }
130
+ // Fallback: check for simple proximity-based path
131
+ // If source and sink are close, there might be a direct flow
132
+ if (Math.abs(source.line - sink.line) <= 10) {
133
+ // Look for common variables
134
+ const sourceVars = new Set(sourceDefs.map(d => d.variable));
135
+ const sinkVars = new Set(sinkUses.map(u => u.variable));
136
+ for (const v of sourceVars) {
137
+ if (sinkVars.has(v)) {
138
+ hops.push({
139
+ file: '',
140
+ method: '',
141
+ line: source.line,
142
+ code: `${v} = <source>`,
143
+ variable: v,
144
+ });
145
+ hops.push({
146
+ file: '',
147
+ method: '',
148
+ line: sink.line,
149
+ code: `sink(${v})`,
150
+ variable: v,
151
+ });
152
+ variables.push(v);
153
+ return { pathExists: true, hops, variables };
154
+ }
155
+ }
156
+ }
157
+ return { pathExists: false, hops: [], variables: [] };
158
+ }
159
+ /**
160
+ * Find a path through DFG chains from source def to target def.
161
+ */
162
+ function findPathThroughChains(fromDefId, toDefId, chains, dfg, visited = new Set(), path = []) {
163
+ if (toDefId === null)
164
+ return [];
165
+ if (fromDefId === toDefId)
166
+ return [...path, fromDefId];
167
+ if (visited.has(fromDefId))
168
+ return [];
169
+ visited.add(fromDefId);
170
+ path.push(fromDefId);
171
+ // Find chains that start from this def
172
+ const outgoingChains = chains.filter(c => c.from_def === fromDefId);
173
+ for (const chain of outgoingChains) {
174
+ const result = findPathThroughChains(chain.to_def, toDefId, chains, dfg, visited, [...path]);
175
+ if (result.length > 0) {
176
+ return result;
177
+ }
178
+ }
179
+ return [];
180
+ }
181
+ /**
182
+ * Check if source and sink are close enough to suggest vulnerability.
183
+ */
184
+ function isProximityVulnerability(source, sink) {
185
+ // Within same method (roughly 50 lines for complex functions)
186
+ return Math.abs(source.line - sink.line) <= 50;
187
+ }
188
+ /**
189
+ * Calculate confidence score.
190
+ */
191
+ function calculateConfidence(source, sink, pathResult) {
192
+ let confidence = 0.5; // Base confidence
193
+ // Path exists: high confidence
194
+ if (pathResult.pathExists) {
195
+ confidence += 0.3;
196
+ }
197
+ // More hops = more confidence in the path
198
+ if (pathResult.hops.length > 0) {
199
+ confidence += Math.min(pathResult.hops.length * 0.05, 0.1);
200
+ }
201
+ // Source and sink confidence
202
+ confidence = confidence * source.confidence * sink.confidence;
203
+ // Proximity bonus
204
+ const lineDiff = Math.abs(source.line - sink.line);
205
+ if (lineDiff <= 5) {
206
+ confidence += 0.1;
207
+ }
208
+ else if (lineDiff <= 15) {
209
+ confidence += 0.05;
210
+ }
211
+ return Math.min(confidence, 1.0);
212
+ }
213
+ /**
214
+ * Generate explanation for the finding.
215
+ */
216
+ function generateExplanation(source, sink, pathResult) {
217
+ const sourceDesc = getSourceDescription(source.type);
218
+ const sinkDesc = getSinkDescription(sink.type);
219
+ if (pathResult.pathExists && pathResult.variables.length > 0) {
220
+ const vars = pathResult.variables.join(' -> ');
221
+ return `${sourceDesc} flows through variables (${vars}) to ${sinkDesc} without proper sanitization.`;
222
+ }
223
+ if (pathResult.pathExists) {
224
+ return `${sourceDesc} flows to ${sinkDesc} without proper sanitization.`;
225
+ }
226
+ return `${sourceDesc} may reach ${sinkDesc}. Manual verification recommended.`;
227
+ }
228
+ //# sourceMappingURL=findings.js.map