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 @@
1
+ {"version":3,"file":"findings.js","sourceRoot":"","sources":["../../src/analysis/findings.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Analysis module index
3
+ */
4
+ export { parseConfig, loadSourceConfigs, loadSinkConfigs, createTaintConfig, getDefaultConfig, DEFAULT_SOURCES, DEFAULT_SINKS, DEFAULT_SANITIZERS, } from './config-loader.js';
5
+ export { analyzeTaint, isInDangerousPosition, } from './taint-matcher.js';
6
+ export { detectUnresolved, } from './unresolved.js';
7
+ export { generateFindings, } from './findings.js';
8
+ export { propagateTaint, type TaintPropagationResult, type TaintedVariable, type TaintFlow, } from './taint-propagation.js';
9
+ export { analyzeInterprocedural, getInterproceduralSummary, findTaintBridges, getMethodTaintPaths, hasMethod, getMethod, isMethodTainted, type InterproceduralResult, type MethodNode, type CallEdge, } from './interprocedural.js';
10
+ export { analyzeConstantPropagation, isFalsePositive, isCorrelatedPredicateFP, ConstantPropagator, isKnown, createUnknown, createConstant, getNodeText, getNodeLine, type ConstantValue, type ConstantType, type ConstantPropagatorResult, type ConstantPropagationOptions, } from './constant-propagation.js';
11
+ export { PathFinder, findTaintPaths, formatTaintPath, type TaintHop, type TaintPath, type PathFinderResult, type PathFinderConfig, } from './path-finder.js';
12
+ export { DFGVerifier, verifyTaintFlow, formatVerificationResult, type VerificationResult, type VerificationPath, type VerificationStep, type VerifierConfig, } from './dfg-verifier.js';
13
+ export { loadBundledAdvisories, parseAdvisoryJson, categoryToSeverity, getAdvisoriesForCrate, findAdvisoryByCve, getVulnerableCrates, type AdvisoryVulnerability, type AdvisoryDatabase, } from './advisory-db.js';
14
+ export { parseCargoLock, parseCargoToml, filterRegistryDeps, type CargoLock, type CargoLockDependency, type CargoToml, type CargoTomlDependency, } from './cargo-parser.js';
15
+ export { scanCargoLock, checkCrateVulnerability, formatFinding, formatScanReport, type DependencyFinding, type ScanOptions, type ScanResult, } from './dependency-scanner.js';
16
+ export { parseVersion, compareVersions, semverSatisfies, isVersionVulnerable, type ParsedVersion, } from './semver.js';
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Analysis module index
3
+ */
4
+ export { parseConfig, loadSourceConfigs, loadSinkConfigs, createTaintConfig, getDefaultConfig, DEFAULT_SOURCES, DEFAULT_SINKS, DEFAULT_SANITIZERS, } from './config-loader.js';
5
+ export { analyzeTaint, isInDangerousPosition, } from './taint-matcher.js';
6
+ export { detectUnresolved, } from './unresolved.js';
7
+ export { generateFindings, } from './findings.js';
8
+ export { propagateTaint, } from './taint-propagation.js';
9
+ export { analyzeInterprocedural, getInterproceduralSummary, findTaintBridges, getMethodTaintPaths, hasMethod, getMethod, isMethodTainted, } from './interprocedural.js';
10
+ export { analyzeConstantPropagation, isFalsePositive, isCorrelatedPredicateFP, ConstantPropagator, isKnown, createUnknown, createConstant, getNodeText, getNodeLine, } from './constant-propagation.js';
11
+ export { PathFinder, findTaintPaths, formatTaintPath, } from './path-finder.js';
12
+ export { DFGVerifier, verifyTaintFlow, formatVerificationResult, } from './dfg-verifier.js';
13
+ // RustSec Advisory Database
14
+ export { loadBundledAdvisories, parseAdvisoryJson, categoryToSeverity, getAdvisoriesForCrate, findAdvisoryByCve, getVulnerableCrates, } from './advisory-db.js';
15
+ export { parseCargoLock, parseCargoToml, filterRegistryDeps, } from './cargo-parser.js';
16
+ export { scanCargoLock, checkCrateVulnerability, formatFinding, formatScanReport, } from './dependency-scanner.js';
17
+ export { parseVersion, compareVersions, semverSatisfies, isVersionVulnerable, } from './semver.js';
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/analysis/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,YAAY,EACZ,qBAAqB,GACtB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,gBAAgB,GACjB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,gBAAgB,GACjB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,cAAc,GAIf,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,sBAAsB,EACtB,yBAAyB,EACzB,gBAAgB,EAChB,mBAAmB,EACnB,SAAS,EACT,SAAS,EACT,eAAe,GAIhB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,0BAA0B,EAC1B,eAAe,EACf,uBAAuB,EACvB,kBAAkB,EAClB,OAAO,EACP,aAAa,EACb,cAAc,EACd,WAAW,EACX,WAAW,GAKZ,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,UAAU,EACV,cAAc,EACd,eAAe,GAKhB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,WAAW,EACX,eAAe,EACf,wBAAwB,GAKzB,MAAM,mBAAmB,CAAC;AAE3B,4BAA4B;AAC5B,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,GAGpB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,cAAc,EACd,cAAc,EACd,kBAAkB,GAKnB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,aAAa,EACb,uBAAuB,EACvB,aAAa,EACb,gBAAgB,GAIjB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,YAAY,EACZ,eAAe,EACf,eAAe,EACf,mBAAmB,GAEpB,MAAM,aAAa,CAAC"}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Inter-procedural Taint Analysis
3
+ *
4
+ * Tracks taint flow through method calls within the same file.
5
+ * - Propagates taint from arguments to parameters
6
+ * - Tracks taint through return values
7
+ * - Handles method call chains
8
+ */
9
+ import type { CallInfo, TypeInfo, DFG, TaintSource, TaintSink, TaintSanitizer } from '../types/index.js';
10
+ /**
11
+ * Represents a method in the call graph.
12
+ */
13
+ export interface MethodNode {
14
+ /** Simple method name */
15
+ name: string;
16
+ /** Fully qualified name: ClassName.methodName */
17
+ fqn: string;
18
+ /** Class/type this method belongs to */
19
+ className: string | null;
20
+ /** Package name if available */
21
+ packageName: string | null;
22
+ parameters: ParameterTaint[];
23
+ returnsTainted: boolean;
24
+ returnTaintType: string | null;
25
+ /** Which parameter positions flow to the return value (null = all potentially taint) */
26
+ returnTaintedFromParams: number[] | null;
27
+ startLine: number;
28
+ endLine: number;
29
+ }
30
+ /**
31
+ * Parameter taint information.
32
+ */
33
+ export interface ParameterTaint {
34
+ name: string;
35
+ position: number;
36
+ isTainted: boolean;
37
+ taintType: string | null;
38
+ sourceLine: number | null;
39
+ }
40
+ /**
41
+ * A call edge in the call graph.
42
+ */
43
+ export interface CallEdge {
44
+ callerMethod: string;
45
+ calleeMethod: string;
46
+ callLine: number;
47
+ taintedArgs: number[];
48
+ }
49
+ /**
50
+ * Result of inter-procedural analysis.
51
+ */
52
+ export interface InterproceduralResult {
53
+ methodNodes: Map<string, MethodNode>;
54
+ callEdges: CallEdge[];
55
+ taintedMethods: Set<string>;
56
+ taintedReturns: Map<string, string>;
57
+ propagatedSinks: TaintSink[];
58
+ }
59
+ /**
60
+ * Options for interprocedural analysis.
61
+ */
62
+ export interface InterproceduralOptions {
63
+ /** Variables marked as tainted by constant propagation (e.g., collections with tainted elements) */
64
+ taintedVariables?: Set<string>;
65
+ }
66
+ /**
67
+ * Perform inter-procedural taint analysis.
68
+ */
69
+ export declare function analyzeInterprocedural(types: TypeInfo[], calls: CallInfo[], dfg: DFG, sources: TaintSource[], sinks: TaintSink[], sanitizers: TaintSanitizer[], options?: InterproceduralOptions): InterproceduralResult;
70
+ /**
71
+ * Get summary of inter-procedural analysis.
72
+ */
73
+ export declare function getInterproceduralSummary(result: InterproceduralResult): {
74
+ totalMethods: number;
75
+ taintedMethods: number;
76
+ callEdges: number;
77
+ methodsReturningTaint: number;
78
+ };
79
+ /**
80
+ * Check if a method exists in the interprocedural result.
81
+ * Accepts either simple name or FQN.
82
+ */
83
+ export declare function hasMethod(result: InterproceduralResult, nameOrFqn: string): boolean;
84
+ /**
85
+ * Get a method node by simple name or FQN.
86
+ */
87
+ export declare function getMethod(result: InterproceduralResult, nameOrFqn: string): MethodNode | undefined;
88
+ /**
89
+ * Check if a method is tainted (by simple name or FQN).
90
+ */
91
+ export declare function isMethodTainted(result: InterproceduralResult, nameOrFqn: string): boolean;
92
+ /**
93
+ * Find methods that act as "taint bridges" - receiving taint and passing it on.
94
+ */
95
+ export declare function findTaintBridges(result: InterproceduralResult): string[];
96
+ /**
97
+ * Get taint flow paths through methods.
98
+ */
99
+ export declare function getMethodTaintPaths(result: InterproceduralResult, maxDepth?: number): string[][];
@@ -0,0 +1,526 @@
1
+ /**
2
+ * Inter-procedural Taint Analysis
3
+ *
4
+ * Tracks taint flow through method calls within the same file.
5
+ * - Propagates taint from arguments to parameters
6
+ * - Tracks taint through return values
7
+ * - Handles method call chains
8
+ */
9
+ /**
10
+ * Perform inter-procedural taint analysis.
11
+ */
12
+ export function analyzeInterprocedural(types, calls, dfg, sources, sinks, sanitizers, options = {}) {
13
+ // Build method nodes from type information
14
+ const methodNodes = buildMethodNodes(types);
15
+ // Build call graph edges with receiver type resolution
16
+ const callEdges = buildCallEdges(calls, methodNodes, types);
17
+ // Identify initially tainted parameters (from sources)
18
+ const taintedMethods = new Set();
19
+ const taintedReturns = new Map();
20
+ // Mark methods containing sources as tainted (using FQN)
21
+ for (const source of sources) {
22
+ const methodInfo = findMethodAtLine(types, source.line);
23
+ if (methodInfo) {
24
+ const fqn = buildMethodFQN(methodInfo.packageName, methodInfo.className, methodInfo.methodName);
25
+ taintedMethods.add(fqn);
26
+ }
27
+ }
28
+ // Build taint map from DFG
29
+ const taintedDefIds = buildTaintedDefIds(dfg, sources);
30
+ // Get tainted variables from constant propagation (tracks collections with tainted elements)
31
+ const taintedVarsFromCP = options.taintedVariables ?? new Set();
32
+ // Analyze each call to propagate taint
33
+ const propagatedSinks = [];
34
+ // Track which method names are collection methods (should not create external escape sinks)
35
+ const collectionMethods = new Set([
36
+ 'add', 'addLast', 'addFirst', 'addAll', 'put', 'putAll', 'set', 'push', 'offer',
37
+ 'get', 'getLast', 'getFirst', 'peek', 'poll', 'pop', 'remove', 'removeFirst', 'removeLast',
38
+ 'iterator', 'listIterator', 'next', 'hasNext', 'size', 'isEmpty', 'contains', 'containsKey',
39
+ 'toString', 'valueOf', 'hashCode', 'equals', 'clone', 'clear',
40
+ ]);
41
+ // Build set of sanitizer method names (methods that clean tainted data)
42
+ // Sanitizer methods may be in formats like "encode" or "URLEncoder.encode()"
43
+ const sanitizerMethods = new Set();
44
+ for (const san of sanitizers) {
45
+ sanitizerMethods.add(san.method);
46
+ // Also extract just the method name if formatted as "Class.method()"
47
+ const match = san.method.match(/\.(\w+)\(\)$/);
48
+ if (match) {
49
+ sanitizerMethods.add(match[1]);
50
+ }
51
+ }
52
+ for (const call of calls) {
53
+ // Check if any arguments are tainted
54
+ const taintedArgPositions = [];
55
+ const taintedArgVars = [];
56
+ for (const arg of call.arguments) {
57
+ if (arg.variable) {
58
+ // Check 1: DFG-based taint tracking
59
+ const use = findUseAtLine(dfg, arg.variable, call.location.line);
60
+ const isTaintedByDFG = use && use.def_id !== null && taintedDefIds.has(use.def_id);
61
+ // Check 2: Constant propagation taint tracking (for collections with tainted elements)
62
+ const isTaintedByCP = taintedVarsFromCP.has(arg.variable);
63
+ if (isTaintedByDFG || isTaintedByCP) {
64
+ taintedArgPositions.push(arg.position);
65
+ taintedArgVars.push(arg.variable);
66
+ }
67
+ }
68
+ }
69
+ // Check if this is an internal method call (resolve using FQN or simple name)
70
+ const targetMethod = getMethodNode(methodNodes, call.method_name);
71
+ if (!targetMethod) {
72
+ // External method call - check if tainted data is escaping
73
+ // Skip collection methods (data manipulation) and sanitizer methods (data cleaning)
74
+ if (taintedArgPositions.length > 0 &&
75
+ !collectionMethods.has(call.method_name) &&
76
+ !sanitizerMethods.has(call.method_name)) {
77
+ // Create an "external_taint_escape" sink for this call
78
+ // This represents tainted data being passed to code we can't analyze
79
+ const sink = {
80
+ type: 'external_taint_escape',
81
+ cwe: 'CWE-668', // Exposure of Resource to Wrong Sphere
82
+ location: `Tainted data (${taintedArgVars.join(', ')}) passed to external method ${call.receiver ? call.receiver + '.' : ''}${call.method_name}()`,
83
+ line: call.location.line,
84
+ confidence: 0.7, // Lower confidence since we can't verify the external method is dangerous
85
+ method: call.method_name,
86
+ argPositions: taintedArgPositions,
87
+ };
88
+ // Only add if not already present
89
+ if (!propagatedSinks.some(s => s.line === sink.line && s.type === sink.type)) {
90
+ propagatedSinks.push(sink);
91
+ }
92
+ }
93
+ continue;
94
+ }
95
+ if (taintedArgPositions.length > 0) {
96
+ // Mark corresponding parameters as tainted
97
+ for (const pos of taintedArgPositions) {
98
+ if (pos < targetMethod.parameters.length) {
99
+ targetMethod.parameters[pos].isTainted = true;
100
+ targetMethod.parameters[pos].sourceLine = call.location.line;
101
+ }
102
+ }
103
+ taintedMethods.add(targetMethod.fqn);
104
+ // Check if target method has sinks
105
+ const methodSinks = sinks.filter(s => s.line >= targetMethod.startLine && s.line <= targetMethod.endLine);
106
+ // These sinks are now reachable via inter-procedural flow
107
+ for (const sink of methodSinks) {
108
+ // Check if not already in the list
109
+ if (!propagatedSinks.some(s => s.line === sink.line)) {
110
+ propagatedSinks.push({
111
+ ...sink,
112
+ confidence: sink.confidence * 0.85, // Slightly lower confidence for inter-proc
113
+ });
114
+ }
115
+ }
116
+ }
117
+ }
118
+ // Propagate taint through return values
119
+ propagateReturnTaint(types, dfg, taintedDefIds, taintedReturns, taintedMethods, methodNodes);
120
+ // Iteratively propagate taint through call chains
121
+ propagateThroughCallChains(callEdges, methodNodes, taintedMethods, taintedReturns, dfg, taintedDefIds);
122
+ return {
123
+ methodNodes: methodNodes.byFqn,
124
+ callEdges,
125
+ taintedMethods,
126
+ taintedReturns,
127
+ propagatedSinks,
128
+ };
129
+ }
130
+ /**
131
+ * Build a fully qualified name for a method.
132
+ * Format: [package.]ClassName.methodName
133
+ */
134
+ function buildMethodFQN(packageName, className, methodName) {
135
+ if (packageName) {
136
+ return `${packageName}.${className}.${methodName}`;
137
+ }
138
+ return `${className}.${methodName}`;
139
+ }
140
+ /**
141
+ * Build method nodes from type information.
142
+ * Uses fully qualified names (FQN) as keys for precise method resolution.
143
+ */
144
+ function buildMethodNodes(types) {
145
+ const byFqn = new Map();
146
+ const byName = new Map();
147
+ for (const type of types) {
148
+ for (const method of type.methods) {
149
+ const fqn = buildMethodFQN(type.package, type.name, method.name);
150
+ const node = {
151
+ name: method.name,
152
+ fqn,
153
+ className: type.name,
154
+ packageName: type.package,
155
+ parameters: method.parameters.map((p, i) => ({
156
+ name: p.name,
157
+ position: i,
158
+ isTainted: false,
159
+ taintType: null,
160
+ sourceLine: null,
161
+ })),
162
+ returnsTainted: false,
163
+ returnTaintType: null,
164
+ returnTaintedFromParams: null, // Will be computed during analysis
165
+ startLine: method.start_line,
166
+ endLine: method.end_line,
167
+ };
168
+ // Store with FQN as primary key
169
+ byFqn.set(fqn, node);
170
+ // Store with simple name for fallback (first occurrence wins)
171
+ if (!byName.has(method.name)) {
172
+ byName.set(method.name, node);
173
+ }
174
+ }
175
+ }
176
+ return { byFqn, byName };
177
+ }
178
+ /**
179
+ * Get a method node by FQN or simple name.
180
+ */
181
+ function getMethodNode(maps, key) {
182
+ return maps.byFqn.get(key) ?? maps.byName.get(key);
183
+ }
184
+ /**
185
+ * Resolve a method call to its target node, considering receiver type.
186
+ * Returns the FQN of the resolved method, or null if not found.
187
+ */
188
+ function resolveMethodCall(call, methodNodes, types) {
189
+ const methodName = call.method_name;
190
+ // If receiver type is known, try FQN resolution first
191
+ if (call.receiver_type) {
192
+ // Try exact FQN match
193
+ const fqn = `${call.receiver_type}.${methodName}`;
194
+ if (methodNodes.byFqn.has(fqn)) {
195
+ return fqn;
196
+ }
197
+ // Try with common package prefixes
198
+ for (const type of types) {
199
+ if (type.name === call.receiver_type && type.package) {
200
+ const fullFqn = `${type.package}.${type.name}.${methodName}`;
201
+ if (methodNodes.byFqn.has(fullFqn)) {
202
+ return fullFqn;
203
+ }
204
+ }
205
+ }
206
+ }
207
+ // If receiver is known, try ClassName.methodName
208
+ if (call.receiver) {
209
+ // Receiver might be a variable - try to infer its type from types
210
+ for (const type of types) {
211
+ const fqn = type.package
212
+ ? `${type.package}.${type.name}.${methodName}`
213
+ : `${type.name}.${methodName}`;
214
+ if (methodNodes.byFqn.has(fqn)) {
215
+ const node = methodNodes.byFqn.get(fqn);
216
+ // Check if this could be a match (same method name, right class)
217
+ if (node.name === methodName) {
218
+ return fqn;
219
+ }
220
+ }
221
+ }
222
+ }
223
+ // Fallback: simple method name
224
+ if (methodNodes.byName.has(methodName)) {
225
+ const node = methodNodes.byName.get(methodName);
226
+ return node.fqn;
227
+ }
228
+ return null;
229
+ }
230
+ /**
231
+ * Build call edges from call information.
232
+ * Uses receiver type information for precise method resolution.
233
+ */
234
+ function buildCallEdges(calls, methodNodes, types) {
235
+ const edges = [];
236
+ for (const call of calls) {
237
+ // Resolve the call target using receiver type
238
+ const resolvedFqn = resolveMethodCall(call, methodNodes, types);
239
+ if (!resolvedFqn)
240
+ continue;
241
+ // Find the caller method
242
+ const callerMethod = call.in_method;
243
+ if (!callerMethod)
244
+ continue;
245
+ edges.push({
246
+ callerMethod,
247
+ calleeMethod: resolvedFqn,
248
+ callLine: call.location.line,
249
+ taintedArgs: [],
250
+ });
251
+ }
252
+ return edges;
253
+ }
254
+ /**
255
+ * Build set of tainted definition IDs from sources.
256
+ */
257
+ function buildTaintedDefIds(dfg, sources) {
258
+ const taintedDefIds = new Set();
259
+ // Find definitions on source lines
260
+ // Only mark defs on the EXACT source line as tainted
261
+ // (The previous +1 heuristic incorrectly marked unrelated defs as tainted)
262
+ for (const source of sources) {
263
+ for (const def of dfg.defs) {
264
+ if (def.line === source.line) {
265
+ taintedDefIds.add(def.id);
266
+ }
267
+ }
268
+ }
269
+ // Propagate through chains
270
+ if (dfg.chains) {
271
+ let changed = true;
272
+ while (changed) {
273
+ changed = false;
274
+ for (const chain of dfg.chains) {
275
+ if (taintedDefIds.has(chain.from_def) && !taintedDefIds.has(chain.to_def)) {
276
+ taintedDefIds.add(chain.to_def);
277
+ changed = true;
278
+ }
279
+ }
280
+ }
281
+ }
282
+ return taintedDefIds;
283
+ }
284
+ /**
285
+ * Find a use at a specific line.
286
+ */
287
+ function findUseAtLine(dfg, variable, line) {
288
+ for (const use of dfg.uses) {
289
+ if (use.variable === variable && use.line === line) {
290
+ return use;
291
+ }
292
+ }
293
+ return null;
294
+ }
295
+ /**
296
+ * Find the method containing a specific line.
297
+ * Returns method info along with class and package context.
298
+ */
299
+ function findMethodAtLine(types, line) {
300
+ for (const type of types) {
301
+ for (const method of type.methods) {
302
+ if (line >= method.start_line && line <= method.end_line) {
303
+ return {
304
+ method,
305
+ methodName: method.name,
306
+ className: type.name,
307
+ packageName: type.package,
308
+ };
309
+ }
310
+ }
311
+ }
312
+ return null;
313
+ }
314
+ /**
315
+ * Propagate taint through return values.
316
+ * Tracks which parameters flow to the return value for precise taint mapping.
317
+ */
318
+ function propagateReturnTaint(types, dfg, taintedDefIds, taintedReturns, taintedMethods, methodNodes) {
319
+ // Find return statements that return tainted values
320
+ const returnDefs = dfg.defs.filter(d => d.kind === 'return');
321
+ for (const returnDef of returnDefs) {
322
+ // Find the method this return is in
323
+ const methodCtx = findMethodAtLine(types, returnDef.line);
324
+ if (!methodCtx)
325
+ continue;
326
+ const fqn = buildMethodFQN(methodCtx.packageName, methodCtx.className, methodCtx.methodName);
327
+ // Find uses on the same line (the returned value)
328
+ const usesOnLine = dfg.uses.filter(u => u.line === returnDef.line);
329
+ for (const use of usesOnLine) {
330
+ if (use.def_id !== null && taintedDefIds.has(use.def_id)) {
331
+ // This method returns a tainted value
332
+ taintedReturns.set(fqn, 'tainted');
333
+ taintedMethods.add(fqn);
334
+ // Track which parameter this return value came from
335
+ const methodNode = methodNodes.byFqn.get(fqn);
336
+ if (methodNode) {
337
+ // Check if the returned variable matches a parameter name
338
+ const paramIndex = methodNode.parameters.findIndex(p => p.name === use.variable);
339
+ if (paramIndex >= 0) {
340
+ // This return value comes from this parameter
341
+ if (methodNode.returnTaintedFromParams === null) {
342
+ methodNode.returnTaintedFromParams = [paramIndex];
343
+ }
344
+ else if (!methodNode.returnTaintedFromParams.includes(paramIndex)) {
345
+ methodNode.returnTaintedFromParams.push(paramIndex);
346
+ }
347
+ }
348
+ }
349
+ break;
350
+ }
351
+ }
352
+ }
353
+ }
354
+ /**
355
+ * Propagate taint through call chains iteratively.
356
+ */
357
+ function propagateThroughCallChains(callEdges, methodNodes, taintedMethods, taintedReturns, dfg, taintedDefIds) {
358
+ // Build reverse call graph (callee -> callers)
359
+ const callersOf = new Map();
360
+ for (const edge of callEdges) {
361
+ const existing = callersOf.get(edge.calleeMethod) ?? [];
362
+ existing.push(edge);
363
+ callersOf.set(edge.calleeMethod, existing);
364
+ }
365
+ // Iteratively propagate until fixed point
366
+ let changed = true;
367
+ let iterations = 0;
368
+ const maxIterations = 10; // Prevent infinite loops
369
+ while (changed && iterations < maxIterations) {
370
+ changed = false;
371
+ iterations++;
372
+ // For each method that returns tainted data
373
+ for (const [methodName, taintType] of taintedReturns) {
374
+ // Find all callers of this method
375
+ const callers = callersOf.get(methodName) ?? [];
376
+ for (const edge of callers) {
377
+ // The call site now produces tainted data
378
+ // Find definitions at the call line (the variable receiving the return value)
379
+ for (const def of dfg.defs) {
380
+ if (def.line === edge.callLine && !taintedDefIds.has(def.id)) {
381
+ taintedDefIds.add(def.id);
382
+ changed = true;
383
+ // Mark the caller method as tainted
384
+ if (!taintedMethods.has(edge.callerMethod)) {
385
+ taintedMethods.add(edge.callerMethod);
386
+ }
387
+ }
388
+ }
389
+ }
390
+ }
391
+ // Propagate through chains again
392
+ if (dfg.chains) {
393
+ for (const chain of dfg.chains) {
394
+ if (taintedDefIds.has(chain.from_def) && !taintedDefIds.has(chain.to_def)) {
395
+ taintedDefIds.add(chain.to_def);
396
+ changed = true;
397
+ }
398
+ }
399
+ }
400
+ }
401
+ }
402
+ /**
403
+ * Get summary of inter-procedural analysis.
404
+ */
405
+ export function getInterproceduralSummary(result) {
406
+ return {
407
+ totalMethods: result.methodNodes.size,
408
+ taintedMethods: result.taintedMethods.size,
409
+ callEdges: result.callEdges.length,
410
+ methodsReturningTaint: result.taintedReturns.size,
411
+ };
412
+ }
413
+ /**
414
+ * Check if a method exists in the interprocedural result.
415
+ * Accepts either simple name or FQN.
416
+ */
417
+ export function hasMethod(result, nameOrFqn) {
418
+ // Try exact match first (FQN)
419
+ if (result.methodNodes.has(nameOrFqn)) {
420
+ return true;
421
+ }
422
+ // Try matching by simple name
423
+ for (const [fqn, node] of result.methodNodes) {
424
+ if (node.name === nameOrFqn) {
425
+ return true;
426
+ }
427
+ }
428
+ return false;
429
+ }
430
+ /**
431
+ * Get a method node by simple name or FQN.
432
+ */
433
+ export function getMethod(result, nameOrFqn) {
434
+ // Try exact match first (FQN)
435
+ if (result.methodNodes.has(nameOrFqn)) {
436
+ return result.methodNodes.get(nameOrFqn);
437
+ }
438
+ // Try matching by simple name
439
+ for (const [fqn, node] of result.methodNodes) {
440
+ if (node.name === nameOrFqn) {
441
+ return node;
442
+ }
443
+ }
444
+ return undefined;
445
+ }
446
+ /**
447
+ * Check if a method is tainted (by simple name or FQN).
448
+ */
449
+ export function isMethodTainted(result, nameOrFqn) {
450
+ // Try exact match first (FQN)
451
+ if (result.taintedMethods.has(nameOrFqn)) {
452
+ return true;
453
+ }
454
+ // Try matching by simple name - check if any tainted method has this name
455
+ for (const fqn of result.taintedMethods) {
456
+ const node = result.methodNodes.get(fqn);
457
+ if (node && node.name === nameOrFqn) {
458
+ return true;
459
+ }
460
+ }
461
+ return false;
462
+ }
463
+ /**
464
+ * Find methods that act as "taint bridges" - receiving taint and passing it on.
465
+ */
466
+ export function findTaintBridges(result) {
467
+ const bridges = [];
468
+ for (const [name, node] of result.methodNodes) {
469
+ const hasTaintedParams = node.parameters.some(p => p.isTainted);
470
+ const returnsTainted = result.taintedReturns.has(name);
471
+ if (hasTaintedParams && returnsTainted) {
472
+ bridges.push(name);
473
+ }
474
+ }
475
+ return bridges;
476
+ }
477
+ /**
478
+ * Get taint flow paths through methods.
479
+ */
480
+ export function getMethodTaintPaths(result, maxDepth = 5) {
481
+ const paths = [];
482
+ // Find entry points (methods with tainted parameters from external sources)
483
+ const entryMethods = Array.from(result.methodNodes.entries())
484
+ .filter(([_, node]) => node.parameters.some(p => p.isTainted && p.sourceLine !== null))
485
+ .map(([name]) => name);
486
+ // Build call graph adjacency
487
+ const callsTo = new Map();
488
+ for (const edge of result.callEdges) {
489
+ const existing = callsTo.get(edge.callerMethod) ?? [];
490
+ if (!existing.includes(edge.calleeMethod)) {
491
+ existing.push(edge.calleeMethod);
492
+ }
493
+ callsTo.set(edge.callerMethod, existing);
494
+ }
495
+ // DFS to find paths
496
+ function dfs(current, path, visited) {
497
+ if (path.length > maxDepth)
498
+ return;
499
+ if (visited.has(current))
500
+ return;
501
+ visited.add(current);
502
+ path.push(current);
503
+ // If this method returns taint and has callees, continue
504
+ const callees = callsTo.get(current) ?? [];
505
+ if (callees.length === 0 || !result.taintedMethods.has(current)) {
506
+ // End of path
507
+ if (path.length > 1) {
508
+ paths.push([...path]);
509
+ }
510
+ }
511
+ else {
512
+ for (const callee of callees) {
513
+ if (result.taintedMethods.has(callee)) {
514
+ dfs(callee, path, visited);
515
+ }
516
+ }
517
+ }
518
+ path.pop();
519
+ visited.delete(current);
520
+ }
521
+ for (const entry of entryMethods) {
522
+ dfs(entry, [], new Set());
523
+ }
524
+ return paths;
525
+ }
526
+ //# sourceMappingURL=interprocedural.js.map