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,67 @@
1
+ /**
2
+ * Taint Propagation Engine
3
+ *
4
+ * Tracks taint through variable assignments, method returns, and field accesses
5
+ * using the DFG (Data Flow Graph) to find precise source-to-sink paths.
6
+ */
7
+ import type { DFG, CallInfo, TaintSource, TaintSink, TaintSanitizer } from '../types/index.js';
8
+ /**
9
+ * Represents a tainted variable at a specific point in the code.
10
+ */
11
+ export interface TaintedVariable {
12
+ variable: string;
13
+ defId: number;
14
+ line: number;
15
+ sourceType: string;
16
+ sourceLine: number;
17
+ confidence: number;
18
+ }
19
+ /**
20
+ * Represents a taint flow from source to sink.
21
+ */
22
+ export interface TaintFlow {
23
+ source: TaintSource;
24
+ sink: TaintSink;
25
+ path: TaintFlowStep[];
26
+ sanitized: boolean;
27
+ sanitizer?: TaintSanitizer;
28
+ confidence: number;
29
+ }
30
+ /**
31
+ * A step in the taint flow path.
32
+ */
33
+ export interface TaintFlowStep {
34
+ variable: string;
35
+ line: number;
36
+ type: 'source' | 'assignment' | 'use' | 'return' | 'field' | 'sink';
37
+ description: string;
38
+ }
39
+ /**
40
+ * Result of taint propagation analysis.
41
+ */
42
+ export interface TaintPropagationResult {
43
+ taintedVars: TaintedVariable[];
44
+ flows: TaintFlow[];
45
+ reachableSinks: Map<TaintSink, TaintSource[]>;
46
+ }
47
+ /**
48
+ * Propagate taint through the dataflow graph.
49
+ */
50
+ export declare function propagateTaint(dfg: DFG, calls: CallInfo[], sources: TaintSource[], sinks: TaintSink[], sanitizers: TaintSanitizer[]): TaintPropagationResult;
51
+ /**
52
+ * Analyze method returns to propagate taint through return values.
53
+ */
54
+ export declare function analyzeMethodReturns(dfg: DFG, calls: CallInfo[], taintedVars: TaintedVariable[]): TaintedVariable[];
55
+ /**
56
+ * Calculate confidence score for a taint flow.
57
+ */
58
+ export declare function calculateFlowConfidence(flow: TaintFlow): number;
59
+ /**
60
+ * Get summary statistics for taint propagation.
61
+ */
62
+ export declare function getTaintStats(result: TaintPropagationResult): {
63
+ totalTaintedVars: number;
64
+ totalFlows: number;
65
+ flowsBySinkType: Map<string, number>;
66
+ avgConfidence: number;
67
+ };
@@ -0,0 +1,298 @@
1
+ /**
2
+ * Taint Propagation Engine
3
+ *
4
+ * Tracks taint through variable assignments, method returns, and field accesses
5
+ * using the DFG (Data Flow Graph) to find precise source-to-sink paths.
6
+ */
7
+ /**
8
+ * Propagate taint through the dataflow graph.
9
+ */
10
+ export function propagateTaint(dfg, calls, sources, sinks, sanitizers) {
11
+ const taintedVars = [];
12
+ const flows = [];
13
+ const reachableSinks = new Map();
14
+ // Build lookup maps
15
+ const defById = new Map();
16
+ const defsByLine = new Map();
17
+ const usesByLine = new Map();
18
+ const callsByLine = new Map();
19
+ const sanitizersByLine = new Map();
20
+ for (const def of dfg.defs) {
21
+ defById.set(def.id, def);
22
+ const existing = defsByLine.get(def.line) ?? [];
23
+ existing.push(def);
24
+ defsByLine.set(def.line, existing);
25
+ }
26
+ for (const use of dfg.uses) {
27
+ const existing = usesByLine.get(use.line) ?? [];
28
+ existing.push(use);
29
+ usesByLine.set(use.line, existing);
30
+ }
31
+ for (const call of calls) {
32
+ const existing = callsByLine.get(call.location.line) ?? [];
33
+ existing.push(call);
34
+ callsByLine.set(call.location.line, existing);
35
+ }
36
+ for (const san of sanitizers) {
37
+ const existing = sanitizersByLine.get(san.line) ?? [];
38
+ existing.push(san);
39
+ sanitizersByLine.set(san.line, existing);
40
+ }
41
+ // Step 1: Identify initial tainted definitions (from sources)
42
+ const initialTaint = findInitialTaint(sources, dfg, callsByLine, defsByLine);
43
+ taintedVars.push(...initialTaint);
44
+ // Step 2: Propagate taint through def-use chains
45
+ const propagatedTaint = propagateThroughChains(initialTaint, dfg.chains ?? [], defById, sanitizersByLine);
46
+ taintedVars.push(...propagatedTaint);
47
+ // Combine all tainted definitions
48
+ const allTaintedDefIds = new Set();
49
+ const taintByDefId = new Map();
50
+ for (const tv of taintedVars) {
51
+ allTaintedDefIds.add(tv.defId);
52
+ taintByDefId.set(tv.defId, tv);
53
+ }
54
+ // Step 3: Check which sinks are reachable from tainted variables
55
+ for (const sink of sinks) {
56
+ const usesAtSink = usesByLine.get(sink.line) ?? [];
57
+ const callsAtSink = callsByLine.get(sink.line) ?? [];
58
+ // Check if any argument to the sink call is tainted
59
+ for (const call of callsAtSink) {
60
+ for (const arg of call.arguments) {
61
+ if (arg.variable) {
62
+ // Find if this variable use is tainted
63
+ for (const use of usesAtSink) {
64
+ if (use.variable === arg.variable && use.def_id !== null) {
65
+ if (allTaintedDefIds.has(use.def_id)) {
66
+ const taintInfo = taintByDefId.get(use.def_id);
67
+ if (taintInfo) {
68
+ // Check if sanitized
69
+ const isSanitized = checkSanitized(taintInfo.line, sink.line, sink.type, sanitizersByLine);
70
+ if (!isSanitized.sanitized) {
71
+ // Find the source
72
+ const source = sources.find(s => s.line === taintInfo.sourceLine);
73
+ if (source) {
74
+ // Record the flow
75
+ const flow = buildTaintFlow(source, sink, taintInfo, dfg, defById);
76
+ flows.push(flow);
77
+ // Record reachable sink
78
+ const existingSources = reachableSinks.get(sink) ?? [];
79
+ if (!existingSources.some(s => s.line === source.line)) {
80
+ existingSources.push(source);
81
+ }
82
+ reachableSinks.set(sink, existingSources);
83
+ }
84
+ }
85
+ }
86
+ }
87
+ }
88
+ }
89
+ }
90
+ }
91
+ }
92
+ }
93
+ return { taintedVars, flows, reachableSinks };
94
+ }
95
+ /**
96
+ * Find initial tainted definitions from sources.
97
+ */
98
+ function findInitialTaint(sources, dfg, callsByLine, defsByLine) {
99
+ const tainted = [];
100
+ for (const source of sources) {
101
+ // Find definitions on the same line as the source
102
+ const defsOnLine = defsByLine.get(source.line) ?? [];
103
+ for (const def of defsOnLine) {
104
+ tainted.push({
105
+ variable: def.variable,
106
+ defId: def.id,
107
+ line: def.line,
108
+ sourceType: source.type,
109
+ sourceLine: source.line,
110
+ confidence: source.confidence,
111
+ });
112
+ }
113
+ // Also check the next line (for cases like: String x = request.getParameter("foo"))
114
+ const defsNextLine = defsByLine.get(source.line + 1) ?? [];
115
+ for (const def of defsNextLine) {
116
+ // Only include if there's a call on the source line
117
+ const callsOnSourceLine = callsByLine.get(source.line) ?? [];
118
+ if (callsOnSourceLine.length > 0) {
119
+ tainted.push({
120
+ variable: def.variable,
121
+ defId: def.id,
122
+ line: def.line,
123
+ sourceType: source.type,
124
+ sourceLine: source.line,
125
+ confidence: source.confidence * 0.9, // Slightly lower confidence
126
+ });
127
+ }
128
+ }
129
+ }
130
+ return tainted;
131
+ }
132
+ /**
133
+ * Propagate taint through def-use chains.
134
+ */
135
+ function propagateThroughChains(initialTaint, chains, defById, sanitizersByLine) {
136
+ const propagated = [];
137
+ const taintedDefIds = new Set(initialTaint.map(t => t.defId));
138
+ const taintInfoByDefId = new Map();
139
+ for (const t of initialTaint) {
140
+ taintInfoByDefId.set(t.defId, t);
141
+ }
142
+ // Build adjacency list for chains
143
+ const chainsByFromDef = new Map();
144
+ for (const chain of chains) {
145
+ const existing = chainsByFromDef.get(chain.from_def) ?? [];
146
+ existing.push(chain);
147
+ chainsByFromDef.set(chain.from_def, existing);
148
+ }
149
+ // BFS to propagate taint
150
+ const queue = [...initialTaint.map(t => t.defId)];
151
+ const visited = new Set(queue);
152
+ while (queue.length > 0) {
153
+ const currentDefId = queue.shift();
154
+ const currentTaint = taintInfoByDefId.get(currentDefId);
155
+ if (!currentTaint)
156
+ continue;
157
+ const outgoingChains = chainsByFromDef.get(currentDefId) ?? [];
158
+ for (const chain of outgoingChains) {
159
+ if (visited.has(chain.to_def))
160
+ continue;
161
+ const targetDef = defById.get(chain.to_def);
162
+ if (!targetDef)
163
+ continue;
164
+ // Check if there's a sanitizer between source and this def
165
+ const sanitizeCheck = checkSanitized(currentTaint.sourceLine, targetDef.line, currentTaint.sourceType, sanitizersByLine);
166
+ if (!sanitizeCheck.sanitized) {
167
+ const newTaint = {
168
+ variable: targetDef.variable,
169
+ defId: targetDef.id,
170
+ line: targetDef.line,
171
+ sourceType: currentTaint.sourceType,
172
+ sourceLine: currentTaint.sourceLine,
173
+ confidence: currentTaint.confidence * 0.95, // Decay confidence slightly
174
+ };
175
+ propagated.push(newTaint);
176
+ taintedDefIds.add(targetDef.id);
177
+ taintInfoByDefId.set(targetDef.id, newTaint);
178
+ visited.add(targetDef.id);
179
+ queue.push(targetDef.id);
180
+ }
181
+ }
182
+ }
183
+ return propagated;
184
+ }
185
+ /**
186
+ * Check if a taint flow is sanitized between two points.
187
+ */
188
+ function checkSanitized(_fromLine, _toLine, _sinkType, _sanitizersByLine) {
189
+ // NOTE: The previous line-based sanitizer check was too aggressive.
190
+ // It would mark a flow as sanitized if ANY sanitizer existed between
191
+ // source and sink lines, even if that sanitizer was applied to a
192
+ // different variable (e.g., clean = sanitize(name); println(name);)
193
+ //
194
+ // The correct approach is to rely on:
195
+ // 1. DFG-based tracking - the tainted variable must flow through a sanitizer
196
+ // 2. The analyzer's sanitizedVars from constant propagation - which correctly
197
+ // tracks which specific variables were sanitized
198
+ //
199
+ // For now, return false and let the higher-level filtering handle sanitization.
200
+ // This prevents false negatives where unsanitized variables are incorrectly
201
+ // marked as safe just because a sanitizer exists somewhere on adjacent lines.
202
+ return { sanitized: false };
203
+ }
204
+ /**
205
+ * Build a taint flow path from source to sink.
206
+ */
207
+ function buildTaintFlow(source, sink, taintInfo, dfg, defById) {
208
+ const path = [];
209
+ // Start with source
210
+ path.push({
211
+ variable: taintInfo.variable,
212
+ line: source.line,
213
+ type: 'source',
214
+ description: `Tainted data enters via ${source.type}`,
215
+ });
216
+ // Add intermediate assignments if we can trace them
217
+ // For now, just add the tainted variable assignment
218
+ if (taintInfo.line !== source.line) {
219
+ path.push({
220
+ variable: taintInfo.variable,
221
+ line: taintInfo.line,
222
+ type: 'assignment',
223
+ description: `Tainted value assigned to ${taintInfo.variable}`,
224
+ });
225
+ }
226
+ // End with sink
227
+ path.push({
228
+ variable: taintInfo.variable,
229
+ line: sink.line,
230
+ type: 'sink',
231
+ description: `Tainted value reaches ${sink.type} sink`,
232
+ });
233
+ return {
234
+ source,
235
+ sink,
236
+ path,
237
+ sanitized: false,
238
+ confidence: taintInfo.confidence * 0.9, // Factor in path length
239
+ };
240
+ }
241
+ /**
242
+ * Analyze method returns to propagate taint through return values.
243
+ */
244
+ export function analyzeMethodReturns(dfg, calls, taintedVars) {
245
+ const additionalTaint = [];
246
+ const taintedDefIds = new Set(taintedVars.map(t => t.defId));
247
+ // Find return statements that return tainted values
248
+ const returnDefs = dfg.defs.filter(d => d.kind === 'return');
249
+ // For each return def, check if the returned value is tainted
250
+ for (const returnDef of returnDefs) {
251
+ // Find uses on the same line that might be the returned value
252
+ const usesOnLine = dfg.uses.filter(u => u.line === returnDef.line);
253
+ for (const use of usesOnLine) {
254
+ if (use.def_id !== null && taintedDefIds.has(use.def_id)) {
255
+ // This return statement returns a tainted value
256
+ // Now find calls to this method and taint their results
257
+ // (This would require method-level analysis which we'll add later)
258
+ }
259
+ }
260
+ }
261
+ return additionalTaint;
262
+ }
263
+ /**
264
+ * Calculate confidence score for a taint flow.
265
+ */
266
+ export function calculateFlowConfidence(flow) {
267
+ let confidence = 1.0;
268
+ // Factor 1: Source confidence
269
+ confidence *= flow.source.confidence;
270
+ // Factor 2: Path length (longer paths = less confident)
271
+ const pathLength = flow.path.length;
272
+ confidence *= Math.pow(0.95, pathLength - 2); // -2 for source and sink
273
+ // Factor 3: Sanitization
274
+ if (flow.sanitized) {
275
+ confidence = 0;
276
+ }
277
+ return Math.max(0, Math.min(1, confidence));
278
+ }
279
+ /**
280
+ * Get summary statistics for taint propagation.
281
+ */
282
+ export function getTaintStats(result) {
283
+ const flowsBySinkType = new Map();
284
+ for (const flow of result.flows) {
285
+ const count = flowsBySinkType.get(flow.sink.type) ?? 0;
286
+ flowsBySinkType.set(flow.sink.type, count + 1);
287
+ }
288
+ const avgConfidence = result.flows.length > 0
289
+ ? result.flows.reduce((sum, f) => sum + f.confidence, 0) / result.flows.length
290
+ : 0;
291
+ return {
292
+ totalTaintedVars: result.taintedVars.length,
293
+ totalFlows: result.flows.length,
294
+ flowsBySinkType,
295
+ avgConfidence,
296
+ };
297
+ }
298
+ //# sourceMappingURL=taint-propagation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"taint-propagation.js","sourceRoot":"","sources":["../../src/analysis/taint-propagation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Unresolved item detector
3
+ *
4
+ * Identifies code patterns that require LLM assistance to resolve:
5
+ * - Virtual dispatch (interface methods)
6
+ * - Taint propagation through collections
7
+ * - Reflection calls
8
+ * - Dynamic method invocations
9
+ */
10
+ import type { CallInfo, TypeInfo, DFG, UnresolvedItem } from '../types/index.js';
11
+ /**
12
+ * Detect unresolved items that would benefit from LLM analysis.
13
+ */
14
+ export declare function detectUnresolved(calls: CallInfo[], types: TypeInfo[], dfg: DFG): UnresolvedItem[];
@@ -0,0 +1,202 @@
1
+ /**
2
+ * Unresolved item detector
3
+ *
4
+ * Identifies code patterns that require LLM assistance to resolve:
5
+ * - Virtual dispatch (interface methods)
6
+ * - Taint propagation through collections
7
+ * - Reflection calls
8
+ * - Dynamic method invocations
9
+ */
10
+ /**
11
+ * Detect unresolved items that would benefit from LLM analysis.
12
+ */
13
+ export function detectUnresolved(calls, types, dfg) {
14
+ const unresolved = [];
15
+ // Detect virtual dispatch (unresolved interface/abstract method calls)
16
+ unresolved.push(...detectVirtualDispatch(calls));
17
+ // Detect reflection patterns
18
+ unresolved.push(...detectReflection(calls));
19
+ // Detect taint propagation uncertainty (collections, etc.)
20
+ unresolved.push(...detectTaintPropagationUncertainty(calls, dfg));
21
+ // Detect dynamic calls
22
+ unresolved.push(...detectDynamicCalls(calls));
23
+ return unresolved;
24
+ }
25
+ /**
26
+ * Detect virtual dispatch - interface method calls that can't be statically resolved.
27
+ */
28
+ function detectVirtualDispatch(calls) {
29
+ const items = [];
30
+ for (const call of calls) {
31
+ if (call.resolution?.status === 'interface_method') {
32
+ items.push({
33
+ type: 'virtual_dispatch',
34
+ call_id: calls.indexOf(call),
35
+ reason: 'interface_method_unknown_impl',
36
+ context: {
37
+ code: formatCallCode(call),
38
+ line: call.location.line,
39
+ candidates: call.resolution.candidates,
40
+ },
41
+ llm_question: `Which implementation of ${call.method_name} is called when invoked on ${call.receiver}? Consider the context and common patterns.`,
42
+ });
43
+ }
44
+ }
45
+ return items;
46
+ }
47
+ /**
48
+ * Detect reflection patterns that need runtime analysis.
49
+ */
50
+ function detectReflection(calls) {
51
+ const items = [];
52
+ const reflectionMethods = new Set([
53
+ 'forName', // Class.forName
54
+ 'newInstance', // Class.newInstance
55
+ 'invoke', // Method.invoke
56
+ 'get', // Field.get
57
+ 'set', // Field.set
58
+ 'getMethod', // Class.getMethod
59
+ 'getDeclaredMethod',
60
+ 'getField',
61
+ 'getDeclaredField',
62
+ 'getConstructor',
63
+ ]);
64
+ const reflectionReceivers = new Set([
65
+ 'Class',
66
+ 'Method',
67
+ 'Field',
68
+ 'Constructor',
69
+ ]);
70
+ for (const call of calls) {
71
+ const isReflectionMethod = reflectionMethods.has(call.method_name);
72
+ const isReflectionReceiver = call.receiver && reflectionReceivers.has(call.receiver);
73
+ if (isReflectionMethod || isReflectionReceiver) {
74
+ items.push({
75
+ type: 'reflection',
76
+ call_id: calls.indexOf(call),
77
+ reason: 'reflection_call',
78
+ context: {
79
+ code: formatCallCode(call),
80
+ line: call.location.line,
81
+ },
82
+ llm_question: `What class/method is being accessed via reflection at ${formatCallCode(call)}? What are the security implications?`,
83
+ });
84
+ }
85
+ }
86
+ return items;
87
+ }
88
+ /**
89
+ * Detect taint propagation uncertainty through collections and complex data flows.
90
+ */
91
+ function detectTaintPropagationUncertainty(calls, dfg) {
92
+ const items = [];
93
+ // Collection methods that might propagate or lose taint
94
+ const collectionMethods = new Map([
95
+ ['add', 'collection_add'],
96
+ ['put', 'map_put'],
97
+ ['get', 'collection_get'],
98
+ ['remove', 'collection_remove'],
99
+ ['addAll', 'collection_addAll'],
100
+ ['putAll', 'map_putAll'],
101
+ ['toArray', 'collection_toArray'],
102
+ ['stream', 'collection_stream'],
103
+ ['iterator', 'collection_iterator'],
104
+ ]);
105
+ // Receivers that are likely collections
106
+ const collectionPatterns = [
107
+ /list/i,
108
+ /set/i,
109
+ /map/i,
110
+ /collection/i,
111
+ /array/i,
112
+ /queue/i,
113
+ /stack/i,
114
+ /vector/i,
115
+ ];
116
+ for (const call of calls) {
117
+ if (!collectionMethods.has(call.method_name))
118
+ continue;
119
+ // Check if receiver looks like a collection
120
+ const isCollection = call.receiver && collectionPatterns.some(p => p.test(call.receiver));
121
+ if (!isCollection && call.receiver)
122
+ continue;
123
+ const methodType = collectionMethods.get(call.method_name);
124
+ // For add/put, check if argument might be tainted
125
+ if (methodType === 'collection_add' || methodType === 'map_put') {
126
+ const hasVariableArg = call.arguments.some(arg => arg.variable !== null);
127
+ if (hasVariableArg) {
128
+ items.push({
129
+ type: 'taint_propagation',
130
+ call_id: calls.indexOf(call),
131
+ reason: 'collection_taint_in',
132
+ context: {
133
+ code: formatCallCode(call),
134
+ line: call.location.line,
135
+ },
136
+ llm_question: `Does taint propagate into ${call.receiver} when ${call.method_name} is called? Will subsequent retrievals from this collection be tainted?`,
137
+ });
138
+ }
139
+ }
140
+ // For get operations, question if result carries taint
141
+ if (methodType === 'collection_get' || methodType === 'collection_toArray') {
142
+ items.push({
143
+ type: 'taint_propagation',
144
+ call_id: calls.indexOf(call),
145
+ reason: 'collection_taint_out',
146
+ context: {
147
+ code: formatCallCode(call),
148
+ line: call.location.line,
149
+ },
150
+ llm_question: `Does the value retrieved from ${call.receiver}.${call.method_name}() carry taint from previously added elements?`,
151
+ });
152
+ }
153
+ }
154
+ return items;
155
+ }
156
+ /**
157
+ * Detect dynamic method calls that can't be statically analyzed.
158
+ */
159
+ function detectDynamicCalls(calls) {
160
+ const items = [];
161
+ // Patterns that suggest dynamic dispatch
162
+ const dynamicPatterns = [
163
+ { method: 'execute', reason: 'command_pattern' },
164
+ { method: 'handle', reason: 'handler_pattern' },
165
+ { method: 'process', reason: 'processor_pattern' },
166
+ { method: 'dispatch', reason: 'dispatcher_pattern' },
167
+ { method: 'run', reason: 'runnable_pattern' },
168
+ { method: 'call', reason: 'callable_pattern' },
169
+ { method: 'apply', reason: 'function_pattern' },
170
+ { method: 'accept', reason: 'consumer_pattern' },
171
+ ];
172
+ for (const call of calls) {
173
+ // Skip if already resolved
174
+ if (call.resolved)
175
+ continue;
176
+ const pattern = dynamicPatterns.find(p => p.method === call.method_name);
177
+ if (pattern) {
178
+ items.push({
179
+ type: 'dynamic_call',
180
+ call_id: calls.indexOf(call),
181
+ reason: pattern.reason,
182
+ context: {
183
+ code: formatCallCode(call),
184
+ line: call.location.line,
185
+ },
186
+ llm_question: `What concrete implementation handles this ${call.method_name}() call? Analyze the code context to determine the actual target.`,
187
+ });
188
+ }
189
+ }
190
+ return items;
191
+ }
192
+ /**
193
+ * Format a call for display in context.
194
+ */
195
+ function formatCallCode(call) {
196
+ const args = call.arguments.map(a => a.expression).join(', ');
197
+ if (call.receiver) {
198
+ return `${call.receiver}.${call.method_name}(${args})`;
199
+ }
200
+ return `${call.method_name}(${args})`;
201
+ }
202
+ //# sourceMappingURL=unresolved.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unresolved.js","sourceRoot":"","sources":["../../src/analysis/unresolved.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Circle-IR Analyzer
3
+ *
4
+ * Main entry point for analyzing source code and producing Circle-IR output.
5
+ * This is the core analyzer - for LLM-enhanced analysis, use circle-ir-ai.
6
+ */
7
+ import type { CircleIR, AnalysisResponse } from './types/index.js';
8
+ import type { TaintConfig } from './types/config.js';
9
+ import { type SupportedLanguage } from './core/index.js';
10
+ export interface AnalyzerOptions {
11
+ /**
12
+ * Path to tree-sitter.wasm for parser initialization.
13
+ */
14
+ wasmPath?: string;
15
+ /**
16
+ * Paths to language-specific WASM files.
17
+ */
18
+ languagePaths?: Partial<Record<SupportedLanguage, string>>;
19
+ /**
20
+ * Custom taint configuration.
21
+ */
22
+ taintConfig?: TaintConfig;
23
+ }
24
+ /**
25
+ * Initialize the analyzer. Must be called before analyze().
26
+ */
27
+ export declare function initAnalyzer(options?: AnalyzerOptions): Promise<void>;
28
+ /**
29
+ * Analyze source code and produce Circle-IR output.
30
+ */
31
+ export declare function analyze(code: string, filePath: string, language: SupportedLanguage, options?: AnalyzerOptions): Promise<CircleIR>;
32
+ /**
33
+ * Analyze code and return a simplified API response format.
34
+ */
35
+ export declare function analyzeForAPI(code: string, filePath: string, language: SupportedLanguage, options?: AnalyzerOptions): Promise<AnalysisResponse>;
36
+ /**
37
+ * Check if the analyzer is initialized.
38
+ */
39
+ export declare function isAnalyzerInitialized(): boolean;
40
+ /**
41
+ * Reset the analyzer (mainly for testing).
42
+ */
43
+ export declare function resetAnalyzer(): void;