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,610 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Circle-IR | Cognium Security Analysis</title>
7
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Space+Grotesk:wght@500;600;700&display=swap" rel="stylesheet">
8
+ <style>
9
+ :root {
10
+ --blue: #3B82F6;
11
+ --cyan: #06B6D4;
12
+ --purple: #8B5CF6;
13
+ --green: #10B981;
14
+ --red: #EF4444;
15
+ --orange: #F59E0B;
16
+ }
17
+ * { margin: 0; padding: 0; box-sizing: border-box; }
18
+ body {
19
+ font-family: 'Inter', sans-serif;
20
+ background: linear-gradient(180deg, #080810 0%, #030306 100%);
21
+ color: #fff;
22
+ min-height: 100vh;
23
+ padding: 24px;
24
+ }
25
+
26
+ .grid-bg {
27
+ position: fixed;
28
+ inset: 0;
29
+ background-image:
30
+ linear-gradient(rgba(255,255,255,0.015) 1px, transparent 1px),
31
+ linear-gradient(90deg, rgba(255,255,255,0.015) 1px, transparent 1px);
32
+ background-size: 50px 50px;
33
+ pointer-events: none;
34
+ z-index: 0;
35
+ }
36
+
37
+ .glow {
38
+ position: fixed;
39
+ border-radius: 50%;
40
+ filter: blur(120px);
41
+ opacity: 0.15;
42
+ pointer-events: none;
43
+ z-index: 0;
44
+ }
45
+
46
+ .container {
47
+ position: relative;
48
+ z-index: 1;
49
+ max-width: 1400px;
50
+ margin: 0 auto;
51
+ }
52
+
53
+ /* Header */
54
+ .header {
55
+ display: flex;
56
+ align-items: center;
57
+ gap: 16px;
58
+ margin-bottom: 8px;
59
+ }
60
+ h1 {
61
+ font-family: 'Space Grotesk', sans-serif;
62
+ font-size: 36px;
63
+ font-weight: 700;
64
+ background: linear-gradient(135deg, #fff, var(--cyan));
65
+ -webkit-background-clip: text;
66
+ -webkit-text-fill-color: transparent;
67
+ }
68
+ .subtitle {
69
+ font-size: 16px;
70
+ color: rgba(255,255,255,0.5);
71
+ margin-bottom: 24px;
72
+ }
73
+ .bar {
74
+ width: 80px;
75
+ height: 4px;
76
+ background: linear-gradient(90deg, var(--blue), var(--cyan));
77
+ border-radius: 2px;
78
+ margin-bottom: 24px;
79
+ }
80
+
81
+ h2 {
82
+ font-family: 'Space Grotesk', sans-serif;
83
+ font-size: 20px;
84
+ font-weight: 600;
85
+ color: var(--cyan);
86
+ margin-bottom: 12px;
87
+ }
88
+
89
+ /* Status */
90
+ #status {
91
+ display: inline-flex;
92
+ padding: 8px 16px;
93
+ border-radius: 50px;
94
+ font-size: 13px;
95
+ font-weight: 600;
96
+ margin-bottom: 20px;
97
+ }
98
+ .loading {
99
+ background: rgba(59,130,246,0.1);
100
+ border: 1px solid rgba(59,130,246,0.3);
101
+ color: var(--blue);
102
+ }
103
+ .ready {
104
+ background: rgba(16,185,129,0.1);
105
+ border: 1px solid rgba(16,185,129,0.3);
106
+ color: var(--green);
107
+ }
108
+ .error {
109
+ background: rgba(239,68,68,0.1);
110
+ border: 1px solid rgba(239,68,68,0.3);
111
+ color: var(--red);
112
+ }
113
+
114
+ /* Main grid */
115
+ .main-grid {
116
+ display: grid;
117
+ grid-template-columns: 1fr 1fr;
118
+ gap: 24px;
119
+ margin-bottom: 24px;
120
+ }
121
+
122
+ /* Cards */
123
+ .card {
124
+ background: rgba(255,255,255,0.02);
125
+ border: 1px solid rgba(255,255,255,0.06);
126
+ border-radius: 16px;
127
+ padding: 20px;
128
+ }
129
+ .card-glow {
130
+ background: linear-gradient(135deg, rgba(6,182,212,0.08), rgba(59,130,246,0.04));
131
+ border-color: rgba(6,182,212,0.2);
132
+ }
133
+
134
+ /* Code textarea */
135
+ textarea {
136
+ width: 100%;
137
+ height: 320px;
138
+ font-family: 'Monaco', 'Menlo', 'Consolas', monospace;
139
+ font-size: 13px;
140
+ background: rgba(0,0,0,0.4);
141
+ color: rgba(255,255,255,0.8);
142
+ border: 1px solid rgba(255,255,255,0.1);
143
+ border-radius: 8px;
144
+ padding: 16px;
145
+ resize: vertical;
146
+ line-height: 1.5;
147
+ }
148
+ textarea:focus {
149
+ outline: none;
150
+ border-color: var(--cyan);
151
+ box-shadow: 0 0 0 2px rgba(6,182,212,0.2);
152
+ }
153
+
154
+ /* Button */
155
+ button.analyze-btn {
156
+ background: linear-gradient(135deg, var(--blue), var(--cyan));
157
+ color: #fff;
158
+ border: none;
159
+ padding: 12px 28px;
160
+ font-size: 15px;
161
+ font-weight: 600;
162
+ font-family: 'Inter', sans-serif;
163
+ border-radius: 8px;
164
+ cursor: pointer;
165
+ margin-top: 12px;
166
+ transition: all 0.3s;
167
+ }
168
+ button.analyze-btn:hover {
169
+ transform: translateY(-2px);
170
+ box-shadow: 0 8px 24px rgba(6,182,212,0.3);
171
+ }
172
+ button.analyze-btn:disabled {
173
+ background: rgba(255,255,255,0.1);
174
+ color: rgba(255,255,255,0.3);
175
+ cursor: not-allowed;
176
+ transform: none;
177
+ box-shadow: none;
178
+ }
179
+
180
+ /* Tabs */
181
+ .tabs {
182
+ display: flex;
183
+ gap: 4px;
184
+ margin-bottom: 12px;
185
+ }
186
+ .tab {
187
+ padding: 8px 16px;
188
+ background: rgba(255,255,255,0.05);
189
+ border: 1px solid rgba(255,255,255,0.08);
190
+ border-radius: 6px 6px 0 0;
191
+ color: rgba(255,255,255,0.5);
192
+ cursor: pointer;
193
+ font-size: 13px;
194
+ font-weight: 500;
195
+ font-family: 'Inter', sans-serif;
196
+ transition: all 0.2s;
197
+ }
198
+ .tab:hover {
199
+ color: rgba(255,255,255,0.8);
200
+ }
201
+ .tab.active {
202
+ background: rgba(6,182,212,0.1);
203
+ border-color: rgba(6,182,212,0.3);
204
+ color: var(--cyan);
205
+ }
206
+ .tab-content {
207
+ display: none;
208
+ }
209
+ .tab-content.active {
210
+ display: block;
211
+ }
212
+
213
+ /* Results */
214
+ #results, #irJson {
215
+ background: rgba(0,0,0,0.4);
216
+ border: 1px solid rgba(255,255,255,0.1);
217
+ border-radius: 8px;
218
+ padding: 16px;
219
+ font-family: 'Monaco', 'Menlo', 'Consolas', monospace;
220
+ font-size: 12px;
221
+ max-height: 360px;
222
+ overflow-y: auto;
223
+ line-height: 1.6;
224
+ }
225
+ #results {
226
+ white-space: pre-wrap;
227
+ }
228
+ #irJson {
229
+ white-space: pre;
230
+ color: rgba(255,255,255,0.6);
231
+ }
232
+
233
+ /* Result highlighting */
234
+ .vuln { color: var(--red); font-weight: 600; }
235
+ .safe { color: var(--green); font-weight: 600; }
236
+ .source { color: var(--orange); }
237
+ .sink { color: var(--purple); }
238
+ .info { color: var(--cyan); }
239
+
240
+ /* JSON highlighting */
241
+ .json-key { color: var(--purple); }
242
+ .json-string { color: var(--green); }
243
+ .json-number { color: var(--orange); }
244
+ .json-boolean { color: var(--cyan); }
245
+ .json-null { color: rgba(255,255,255,0.4); }
246
+
247
+ /* Info section */
248
+ .info-section {
249
+ margin-top: 24px;
250
+ }
251
+ .info-card {
252
+ background: linear-gradient(135deg, rgba(16,185,129,0.08), rgba(6,182,212,0.04));
253
+ border: 1px solid rgba(16,185,129,0.2);
254
+ border-radius: 12px;
255
+ padding: 20px 24px;
256
+ }
257
+ .info-card h3 {
258
+ font-family: 'Space Grotesk', sans-serif;
259
+ font-size: 18px;
260
+ font-weight: 600;
261
+ color: var(--green);
262
+ margin-bottom: 12px;
263
+ }
264
+ .info-card ol {
265
+ margin-left: 20px;
266
+ color: rgba(255,255,255,0.7);
267
+ font-size: 14px;
268
+ line-height: 1.8;
269
+ }
270
+ .info-card li strong {
271
+ color: var(--cyan);
272
+ }
273
+ .info-card em {
274
+ display: block;
275
+ margin-top: 12px;
276
+ color: rgba(255,255,255,0.5);
277
+ font-size: 13px;
278
+ }
279
+
280
+ /* Scrollbar */
281
+ ::-webkit-scrollbar {
282
+ width: 6px;
283
+ height: 6px;
284
+ }
285
+ ::-webkit-scrollbar-track {
286
+ background: rgba(255,255,255,0.05);
287
+ border-radius: 3px;
288
+ }
289
+ ::-webkit-scrollbar-thumb {
290
+ background: rgba(255,255,255,0.15);
291
+ border-radius: 3px;
292
+ }
293
+ ::-webkit-scrollbar-thumb:hover {
294
+ background: rgba(255,255,255,0.25);
295
+ }
296
+
297
+ @media (max-width: 900px) {
298
+ .main-grid {
299
+ grid-template-columns: 1fr;
300
+ }
301
+ }
302
+ </style>
303
+ </head>
304
+ <body>
305
+ <div class="grid-bg"></div>
306
+ <div class="glow" style="width:600px;height:600px;top:-200px;right:-100px;background:var(--blue);"></div>
307
+ <div class="glow" style="width:500px;height:500px;bottom:-200px;left:-100px;background:var(--cyan);"></div>
308
+
309
+ <!-- Master Logo Definition -->
310
+ <svg style="position:absolute;width:0;height:0;">
311
+ <defs>
312
+ <linearGradient id="logoGradient" x1="0%" y1="0%" x2="100%" y2="100%">
313
+ <stop offset="0%" stop-color="#60A5FA"/>
314
+ <stop offset="100%" stop-color="#06B6D4"/>
315
+ </linearGradient>
316
+ <symbol id="cognium-logo" viewBox="0 0 100 100">
317
+ <g transform="translate(50,50)">
318
+ <path d="M-28,0 C-28,-15 -15,-15 0,0 C15,15 28,15 28,0 C28,-15 15,-15 0,0 C-15,15 -28,15 -28,0 Z"
319
+ fill="none" stroke="url(#logoGradient)" stroke-width="4" stroke-linecap="round"/>
320
+ <circle cx="-18" cy="0" r="4" fill="#60A5FA"/>
321
+ <circle cx="18" cy="0" r="4" fill="#06B6D4"/>
322
+ <circle cx="0" cy="0" r="5" fill="#FFFFFF"/>
323
+ </g>
324
+ </symbol>
325
+ </defs>
326
+ </svg>
327
+
328
+ <div class="container">
329
+ <div class="header">
330
+ <svg width="48" height="48"><use href="#cognium-logo"/></svg>
331
+ <h1>Circle-IR</h1>
332
+ </div>
333
+ <p class="subtitle">Security vulnerability detection powered by taint analysis</p>
334
+ <div class="bar"></div>
335
+
336
+ <div id="status" class="loading">Initializing analyzer...</div>
337
+
338
+ <div class="main-grid">
339
+ <div class="card">
340
+ <h2>Java Code</h2>
341
+ <textarea id="code">package com.example;
342
+
343
+ import javax.servlet.http.*;
344
+ import java.sql.*;
345
+
346
+ public class UserController extends HttpServlet {
347
+
348
+ public void doGet(HttpServletRequest request, HttpServletResponse response) {
349
+ // User input from HTTP parameter
350
+ String userId = request.getParameter("id");
351
+
352
+ // Direct string concatenation - SQL injection!
353
+ String query = "SELECT * FROM users WHERE id = '" + userId + "'";
354
+
355
+ try {
356
+ Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/db");
357
+ Statement stmt = conn.createStatement();
358
+
359
+ // Vulnerable: executing unsanitized query
360
+ ResultSet rs = stmt.executeQuery(query);
361
+
362
+ while (rs.next()) {
363
+ response.getWriter().println(rs.getString("name"));
364
+ }
365
+ } catch (Exception e) {
366
+ e.printStackTrace();
367
+ }
368
+ }
369
+ }</textarea>
370
+ <button id="analyzeBtn" class="analyze-btn" onclick="analyzeCode()" disabled>Analyze Code</button>
371
+ </div>
372
+
373
+ <div class="card card-glow">
374
+ <h2>Analysis Results</h2>
375
+ <div class="tabs">
376
+ <button class="tab active" onclick="showTab('summary')">Summary</button>
377
+ <button class="tab" onclick="showTab('ir')">Circle-IR JSON</button>
378
+ </div>
379
+ <div id="summaryTab" class="tab-content active">
380
+ <div id="results">Click "Analyze Code" to start...</div>
381
+ </div>
382
+ <div id="irTab" class="tab-content">
383
+ <div id="irJson">Circle-IR output will appear here after analysis...</div>
384
+ </div>
385
+ </div>
386
+ </div>
387
+
388
+ <div class="info-section">
389
+ <div class="info-card">
390
+ <h3>How It Works</h3>
391
+ <ol>
392
+ <li><strong>Parsing</strong> - Tree-sitter WASM parses Java code into an AST</li>
393
+ <li><strong>IR Extraction</strong> - Extracts types, method calls, CFG, and DFG</li>
394
+ <li><strong>Taint Analysis</strong> - Identifies sources (user input) and sinks (dangerous operations)</li>
395
+ <li><strong>Flow Detection</strong> - Traces data flow from sources to sinks</li>
396
+ </ol>
397
+ <em>No server required - all analysis happens locally in your browser!</em>
398
+ </div>
399
+ </div>
400
+ </div>
401
+
402
+ <script type="module">
403
+ import {
404
+ initParser,
405
+ parse,
406
+ collectAllNodes,
407
+ extractMeta,
408
+ extractTypes,
409
+ extractCalls,
410
+ buildCFG,
411
+ buildDFG,
412
+ analyzeTaint,
413
+ propagateTaint,
414
+ analyzeConstantPropagation,
415
+ isFalsePositive,
416
+ getDefaultConfig,
417
+ } from '../dist/core/circle-ir-core.js';
418
+
419
+ const statusEl = document.getElementById('status');
420
+ const resultsEl = document.getElementById('results');
421
+ const irJsonEl = document.getElementById('irJson');
422
+ const analyzeBtn = document.getElementById('analyzeBtn');
423
+
424
+ // Tab switching
425
+ window.showTab = function(tab) {
426
+ document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
427
+ document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
428
+ if (tab === 'summary') {
429
+ document.querySelector('.tab:first-child').classList.add('active');
430
+ document.getElementById('summaryTab').classList.add('active');
431
+ } else {
432
+ document.querySelector('.tab:last-child').classList.add('active');
433
+ document.getElementById('irTab').classList.add('active');
434
+ }
435
+ };
436
+
437
+ // Syntax highlight JSON
438
+ function syntaxHighlight(json) {
439
+ return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
440
+ let cls = 'json-number';
441
+ if (/^"/.test(match)) {
442
+ if (/:$/.test(match)) {
443
+ cls = 'json-key';
444
+ } else {
445
+ cls = 'json-string';
446
+ }
447
+ } else if (/true|false/.test(match)) {
448
+ cls = 'json-boolean';
449
+ } else if (/null/.test(match)) {
450
+ cls = 'json-null';
451
+ }
452
+ return '<span class="' + cls + '">' + match + '</span>';
453
+ });
454
+ }
455
+
456
+ // Initialize parser on load
457
+ async function init() {
458
+ try {
459
+ statusEl.textContent = 'Initializing Tree-sitter parser...';
460
+ await initParser({
461
+ wasmPath: '../dist/wasm/web-tree-sitter.wasm',
462
+ languagePaths: {
463
+ java: '../dist/wasm/tree-sitter-java.wasm'
464
+ }
465
+ });
466
+ statusEl.textContent = 'Ready to analyze';
467
+ statusEl.className = 'ready';
468
+ analyzeBtn.disabled = false;
469
+ } catch (error) {
470
+ statusEl.textContent = `Error: ${error.message}`;
471
+ statusEl.className = 'error';
472
+ console.error('Init error:', error);
473
+ }
474
+ }
475
+
476
+ // Make analyzeCode available globally
477
+ window.analyzeCode = async function() {
478
+ const code = document.getElementById('code').value;
479
+ resultsEl.innerHTML = '<span class="info">Analyzing...</span>';
480
+
481
+ try {
482
+ const startTime = performance.now();
483
+
484
+ const NODE_TYPES = new Set([
485
+ 'method_invocation',
486
+ 'object_creation_expression',
487
+ 'class_declaration',
488
+ 'method_declaration',
489
+ 'constructor_declaration',
490
+ 'field_declaration',
491
+ 'import_declaration',
492
+ 'interface_declaration',
493
+ 'enum_declaration',
494
+ ]);
495
+
496
+ // Parse code
497
+ const tree = await parse(code, 'java');
498
+ const nodeCache = collectAllNodes(tree.rootNode, NODE_TYPES);
499
+
500
+ // Extract IR
501
+ const meta = extractMeta(code, tree, 'input.java', 'java');
502
+ const types = extractTypes(tree, nodeCache);
503
+ const calls = extractCalls(tree, nodeCache);
504
+ const cfg = buildCFG(tree);
505
+ const dfg = buildDFG(tree, nodeCache);
506
+
507
+ // Analyze taint
508
+ const config = getDefaultConfig();
509
+ const taint = analyzeTaint(calls, types, config);
510
+
511
+ // Find flows
512
+ const propagationResult = propagateTaint(
513
+ dfg,
514
+ calls,
515
+ taint.sources,
516
+ taint.sinks,
517
+ taint.sanitizers || []
518
+ );
519
+
520
+ // Filter false positives
521
+ const constPropResult = analyzeConstantPropagation(tree, code);
522
+ const verifiedFlows = propagationResult.flows.filter(flow => {
523
+ for (const step of flow.path) {
524
+ const fpCheck = isFalsePositive(constPropResult, step.line, step.variable);
525
+ if (fpCheck.isFalsePositive) {
526
+ return false;
527
+ }
528
+ }
529
+ return true;
530
+ });
531
+
532
+ const elapsed = (performance.now() - startTime).toFixed(0);
533
+
534
+ // Format results
535
+ let output = `<span class="info">Analysis completed in ${elapsed}ms</span>\n\n`;
536
+
537
+ output += `<strong>IR Summary:</strong>\n`;
538
+ output += ` Lines of code: ${meta.loc}\n`;
539
+ output += ` Classes: ${types.length}\n`;
540
+ output += ` Method calls: ${calls.length}\n`;
541
+ output += ` CFG blocks: ${cfg.blocks.length}\n`;
542
+ output += ` DFG definitions: ${dfg.defs.length}\n\n`;
543
+
544
+ output += `<strong>Taint Analysis:</strong>\n`;
545
+ output += `<span class="source"> Sources: ${taint.sources.length}</span>\n`;
546
+ taint.sources.forEach(s => {
547
+ output += ` Line ${s.line}: ${s.type}\n`;
548
+ });
549
+
550
+ output += `<span class="sink"> Sinks: ${taint.sinks.length}</span>\n`;
551
+ taint.sinks.forEach(s => {
552
+ output += ` Line ${s.line}: ${s.type}\n`;
553
+ });
554
+
555
+ output += ` Sanitizers: ${taint.sanitizers.length}\n\n`;
556
+
557
+ output += `<strong>Vulnerability Detection:</strong>\n`;
558
+ if (verifiedFlows.length > 0) {
559
+ output += `<span class="vuln">Found ${verifiedFlows.length} potential vulnerabilities!</span>\n\n`;
560
+ verifiedFlows.forEach((flow, i) => {
561
+ output += `<span class="vuln">[${i + 1}] ${flow.sink.type.toUpperCase()}</span>\n`;
562
+ output += ` Source: Line ${flow.source.line} (${flow.source.type})\n`;
563
+ output += ` Sink: Line ${flow.sink.line} (${flow.sink.type})\n`;
564
+ output += ` Confidence: ${(flow.confidence * 100).toFixed(0)}%\n`;
565
+ if (flow.path && flow.path.length > 0) {
566
+ output += ` Path:\n`;
567
+ flow.path.forEach(step => {
568
+ output += ` -> ${step.variable} (line ${step.line})\n`;
569
+ });
570
+ }
571
+ output += '\n';
572
+ });
573
+ } else {
574
+ output += `<span class="safe">No vulnerabilities detected.</span>\n`;
575
+ }
576
+
577
+ resultsEl.innerHTML = output;
578
+
579
+ // Build Circle-IR JSON object
580
+ const circleIR = {
581
+ meta,
582
+ types,
583
+ calls,
584
+ cfg,
585
+ dfg,
586
+ taint: {
587
+ sources: taint.sources,
588
+ sinks: taint.sinks,
589
+ sanitizers: taint.sanitizers,
590
+ flows: verifiedFlows
591
+ }
592
+ };
593
+
594
+ // Display Circle-IR JSON with syntax highlighting
595
+ const jsonStr = JSON.stringify(circleIR, null, 2);
596
+ irJsonEl.innerHTML = syntaxHighlight(jsonStr);
597
+
598
+ console.log('Circle-IR:', circleIR);
599
+ } catch (error) {
600
+ resultsEl.innerHTML = `<span class="vuln">Error: ${error.message}</span>\n\n${error.stack}`;
601
+ irJsonEl.textContent = `Error: ${error.message}`;
602
+ console.error('Analysis error:', error);
603
+ }
604
+ };
605
+
606
+ // Initialize on load
607
+ init();
608
+ </script>
609
+ </body>
610
+ </html>