circle-ir 3.21.0 → 3.22.1
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.
- package/README.md +5 -1
- package/configs/sinks/golang.json +144 -0
- package/configs/sources/golang.json +150 -0
- package/dist/analysis/config-loader.js +6 -6
- package/dist/analysis/config-loader.js.map +1 -1
- package/dist/analysis/taint-matcher.js +115 -22
- package/dist/analysis/taint-matcher.js.map +1 -1
- package/dist/analyzer.js +9 -0
- package/dist/analyzer.js.map +1 -1
- package/dist/browser/circle-ir.js +1564 -203
- package/dist/core/circle-ir-core.cjs +787 -20
- package/dist/core/circle-ir-core.js +787 -20
- package/dist/core/extractors/calls.js +134 -1
- package/dist/core/extractors/calls.js.map +1 -1
- package/dist/core/extractors/cfg.js +68 -0
- package/dist/core/extractors/cfg.js.map +1 -1
- package/dist/core/extractors/dfg.js +270 -0
- package/dist/core/extractors/dfg.js.map +1 -1
- package/dist/core/extractors/imports.js +78 -0
- package/dist/core/extractors/imports.js.map +1 -1
- package/dist/core/extractors/types.js +160 -0
- package/dist/core/extractors/types.js.map +1 -1
- package/dist/core/parser.d.ts +1 -1
- package/dist/languages/plugins/go.d.ts +61 -0
- package/dist/languages/plugins/go.js +615 -0
- package/dist/languages/plugins/go.js.map +1 -0
- package/dist/languages/plugins/index.d.ts +1 -0
- package/dist/languages/plugins/index.js +3 -0
- package/dist/languages/plugins/index.js.map +1 -1
- package/dist/languages/types.d.ts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/wasm/tree-sitter-go.wasm +0 -0
- package/docs/SPEC.md +1 -1
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ A high-performance Static Application Security Testing (SAST) library for detect
|
|
|
8
8
|
## Features
|
|
9
9
|
|
|
10
10
|
- **Taint Analysis**: Track data flow from sources (user input) to sinks (dangerous operations)
|
|
11
|
-
- **Multi-language Support**: Java, JavaScript/TypeScript, Python, Rust, Bash/Shell, HTML
|
|
11
|
+
- **Multi-language Support**: Java, JavaScript/TypeScript, Python, Go, Rust, Bash/Shell, HTML
|
|
12
12
|
- **High Accuracy**: 100% on OWASP Benchmark, 100% on Juliet Test Suite, 97.7% TPR on SecuriBench Micro
|
|
13
13
|
- **36-Pass Pipeline**: 19 security taint passes + 17 reliability/performance/maintainability/architecture quality passes
|
|
14
14
|
- **Metrics Engine**: 24 software quality metrics (cyclomatic complexity, Halstead, CBO, RFC, LCOM, DIT, and 4 composite scores)
|
|
@@ -205,6 +205,7 @@ const response = await analyzeForAPI(code, 'File.java', 'java');
|
|
|
205
205
|
| **Java** | tree-sitter-java | Spring, JAX-RS, Servlet API |
|
|
206
206
|
| **JavaScript/TypeScript** | tree-sitter-javascript | Express, Fastify, Koa, Node.js |
|
|
207
207
|
| **Python** | tree-sitter-python | Flask, Django, FastAPI |
|
|
208
|
+
| **Go** | tree-sitter-go | net/http, Gin, Echo, Fiber, Chi |
|
|
208
209
|
| **Rust** | tree-sitter-rust | Actix-web, Rocket, Axum |
|
|
209
210
|
| **Bash/Shell** | tree-sitter-bash | Shell scripts (.sh, .bash, .zsh, .ksh) |
|
|
210
211
|
| **HTML** | tree-sitter-html | Web extraction preprocessor (.html, .htm, .xhtml) |
|
|
@@ -220,6 +221,9 @@ const jsResult = await analyze(jsCode, 'server.js', 'javascript');
|
|
|
220
221
|
// Analyze Python
|
|
221
222
|
const pyResult = await analyze(pyCode, 'app.py', 'python');
|
|
222
223
|
|
|
224
|
+
// Analyze Go
|
|
225
|
+
const goResult = await analyze(goCode, 'main.go', 'go');
|
|
226
|
+
|
|
223
227
|
// Analyze Rust
|
|
224
228
|
const rsResult = await analyze(rsCode, 'main.rs', 'rust');
|
|
225
229
|
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Go Sinks",
|
|
3
|
+
"description": "Taint sinks for Go standard library and web frameworks",
|
|
4
|
+
"sinks": [
|
|
5
|
+
{
|
|
6
|
+
"method": "Query",
|
|
7
|
+
"class": "DB",
|
|
8
|
+
"type": "sql_injection",
|
|
9
|
+
"cwe": "CWE-89",
|
|
10
|
+
"severity": "critical",
|
|
11
|
+
"arg_positions": [0]
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"method": "QueryRow",
|
|
15
|
+
"class": "DB",
|
|
16
|
+
"type": "sql_injection",
|
|
17
|
+
"cwe": "CWE-89",
|
|
18
|
+
"severity": "critical",
|
|
19
|
+
"arg_positions": [0]
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"method": "Exec",
|
|
23
|
+
"class": "DB",
|
|
24
|
+
"type": "sql_injection",
|
|
25
|
+
"cwe": "CWE-89",
|
|
26
|
+
"severity": "critical",
|
|
27
|
+
"arg_positions": [0]
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"method": "Query",
|
|
31
|
+
"class": "Tx",
|
|
32
|
+
"type": "sql_injection",
|
|
33
|
+
"cwe": "CWE-89",
|
|
34
|
+
"severity": "critical",
|
|
35
|
+
"arg_positions": [0]
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"method": "Command",
|
|
39
|
+
"class": "exec",
|
|
40
|
+
"type": "command_injection",
|
|
41
|
+
"cwe": "CWE-78",
|
|
42
|
+
"severity": "critical",
|
|
43
|
+
"arg_positions": [0]
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"method": "CommandContext",
|
|
47
|
+
"class": "exec",
|
|
48
|
+
"type": "command_injection",
|
|
49
|
+
"cwe": "CWE-78",
|
|
50
|
+
"severity": "critical",
|
|
51
|
+
"arg_positions": [1]
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"method": "Open",
|
|
55
|
+
"class": "os",
|
|
56
|
+
"type": "path_traversal",
|
|
57
|
+
"cwe": "CWE-22",
|
|
58
|
+
"severity": "high",
|
|
59
|
+
"arg_positions": [0]
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"method": "ReadFile",
|
|
63
|
+
"class": "os",
|
|
64
|
+
"type": "path_traversal",
|
|
65
|
+
"cwe": "CWE-22",
|
|
66
|
+
"severity": "high",
|
|
67
|
+
"arg_positions": [0]
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"method": "WriteFile",
|
|
71
|
+
"class": "os",
|
|
72
|
+
"type": "path_traversal",
|
|
73
|
+
"cwe": "CWE-22",
|
|
74
|
+
"severity": "high",
|
|
75
|
+
"arg_positions": [0]
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"method": "Fprintf",
|
|
79
|
+
"class": "fmt",
|
|
80
|
+
"type": "xss",
|
|
81
|
+
"cwe": "CWE-79",
|
|
82
|
+
"severity": "high",
|
|
83
|
+
"arg_positions": [1]
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"method": "Write",
|
|
87
|
+
"class": "ResponseWriter",
|
|
88
|
+
"type": "xss",
|
|
89
|
+
"cwe": "CWE-79",
|
|
90
|
+
"severity": "high",
|
|
91
|
+
"arg_positions": [0]
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"method": "Get",
|
|
95
|
+
"class": "http",
|
|
96
|
+
"type": "ssrf",
|
|
97
|
+
"cwe": "CWE-918",
|
|
98
|
+
"severity": "high",
|
|
99
|
+
"arg_positions": [0]
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"method": "Post",
|
|
103
|
+
"class": "http",
|
|
104
|
+
"type": "ssrf",
|
|
105
|
+
"cwe": "CWE-918",
|
|
106
|
+
"severity": "high",
|
|
107
|
+
"arg_positions": [0]
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"method": "Unmarshal",
|
|
111
|
+
"class": "json",
|
|
112
|
+
"type": "deserialization",
|
|
113
|
+
"cwe": "CWE-502",
|
|
114
|
+
"severity": "medium",
|
|
115
|
+
"arg_positions": [0]
|
|
116
|
+
}
|
|
117
|
+
],
|
|
118
|
+
"sanitizers": [
|
|
119
|
+
{
|
|
120
|
+
"method": "Prepare",
|
|
121
|
+
"class": "DB",
|
|
122
|
+
"removes": ["sql_injection"],
|
|
123
|
+
"note": "Prepared statements prevent SQL injection"
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"method": "Clean",
|
|
127
|
+
"class": "filepath",
|
|
128
|
+
"removes": ["path_traversal"],
|
|
129
|
+
"note": "filepath.Clean normalizes path, preventing traversal"
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"method": "EscapeString",
|
|
133
|
+
"class": "html",
|
|
134
|
+
"removes": ["xss"],
|
|
135
|
+
"note": "html.EscapeString escapes HTML entities"
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
"method": "HTMLEscapeString",
|
|
139
|
+
"class": "template",
|
|
140
|
+
"removes": ["xss"],
|
|
141
|
+
"note": "template.HTMLEscapeString escapes HTML"
|
|
142
|
+
}
|
|
143
|
+
]
|
|
144
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Go Sources",
|
|
3
|
+
"description": "Taint sources for Go web frameworks and standard library",
|
|
4
|
+
"sources": [
|
|
5
|
+
{
|
|
6
|
+
"method": "FormValue",
|
|
7
|
+
"class": "Request",
|
|
8
|
+
"type": "http_param",
|
|
9
|
+
"severity": "high",
|
|
10
|
+
"return_tainted": true,
|
|
11
|
+
"framework": "net/http"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"method": "PostFormValue",
|
|
15
|
+
"class": "Request",
|
|
16
|
+
"type": "http_param",
|
|
17
|
+
"severity": "high",
|
|
18
|
+
"return_tainted": true,
|
|
19
|
+
"framework": "net/http"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"method": "Get",
|
|
23
|
+
"class": "Header",
|
|
24
|
+
"type": "http_header",
|
|
25
|
+
"severity": "high",
|
|
26
|
+
"return_tainted": true,
|
|
27
|
+
"framework": "net/http"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"method": "Cookie",
|
|
31
|
+
"class": "Request",
|
|
32
|
+
"type": "http_cookie",
|
|
33
|
+
"severity": "high",
|
|
34
|
+
"return_tainted": true,
|
|
35
|
+
"framework": "net/http"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"method": "ReadAll",
|
|
39
|
+
"class": "io",
|
|
40
|
+
"type": "http_body",
|
|
41
|
+
"severity": "high",
|
|
42
|
+
"return_tainted": true,
|
|
43
|
+
"framework": "net/http"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"method": "Query",
|
|
47
|
+
"class": "Context",
|
|
48
|
+
"type": "http_param",
|
|
49
|
+
"severity": "high",
|
|
50
|
+
"return_tainted": true,
|
|
51
|
+
"framework": "gin"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"method": "Param",
|
|
55
|
+
"class": "Context",
|
|
56
|
+
"type": "http_path",
|
|
57
|
+
"severity": "high",
|
|
58
|
+
"return_tainted": true,
|
|
59
|
+
"framework": "gin"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"method": "PostForm",
|
|
63
|
+
"class": "Context",
|
|
64
|
+
"type": "http_param",
|
|
65
|
+
"severity": "high",
|
|
66
|
+
"return_tainted": true,
|
|
67
|
+
"framework": "gin"
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"method": "GetRawData",
|
|
71
|
+
"class": "Context",
|
|
72
|
+
"type": "http_body",
|
|
73
|
+
"severity": "high",
|
|
74
|
+
"return_tainted": true,
|
|
75
|
+
"framework": "gin"
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"method": "BindJSON",
|
|
79
|
+
"class": "Context",
|
|
80
|
+
"type": "http_body",
|
|
81
|
+
"severity": "high",
|
|
82
|
+
"return_tainted": true,
|
|
83
|
+
"framework": "gin"
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"method": "QueryParam",
|
|
87
|
+
"class": "Context",
|
|
88
|
+
"type": "http_param",
|
|
89
|
+
"severity": "high",
|
|
90
|
+
"return_tainted": true,
|
|
91
|
+
"framework": "echo"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"method": "FormValue",
|
|
95
|
+
"class": "Context",
|
|
96
|
+
"type": "http_param",
|
|
97
|
+
"severity": "high",
|
|
98
|
+
"return_tainted": true,
|
|
99
|
+
"framework": "echo"
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"method": "Param",
|
|
103
|
+
"class": "Context",
|
|
104
|
+
"type": "http_path",
|
|
105
|
+
"severity": "high",
|
|
106
|
+
"return_tainted": true,
|
|
107
|
+
"framework": "echo"
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"method": "Getenv",
|
|
111
|
+
"class": "os",
|
|
112
|
+
"type": "env_var",
|
|
113
|
+
"severity": "medium",
|
|
114
|
+
"return_tainted": true,
|
|
115
|
+
"framework": "stdlib"
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"method": "ReadFile",
|
|
119
|
+
"class": "os",
|
|
120
|
+
"type": "file_read",
|
|
121
|
+
"severity": "medium",
|
|
122
|
+
"return_tainted": true,
|
|
123
|
+
"framework": "stdlib"
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"method": "Text",
|
|
127
|
+
"class": "Scanner",
|
|
128
|
+
"type": "stdin",
|
|
129
|
+
"severity": "medium",
|
|
130
|
+
"return_tainted": true,
|
|
131
|
+
"framework": "stdlib"
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
"method": "Scan",
|
|
135
|
+
"class": "fmt",
|
|
136
|
+
"type": "stdin",
|
|
137
|
+
"severity": "medium",
|
|
138
|
+
"return_tainted": true,
|
|
139
|
+
"framework": "stdlib"
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
"method": "Scanln",
|
|
143
|
+
"class": "fmt",
|
|
144
|
+
"type": "stdin",
|
|
145
|
+
"severity": "medium",
|
|
146
|
+
"return_tainted": true,
|
|
147
|
+
"framework": "stdlib"
|
|
148
|
+
}
|
|
149
|
+
]
|
|
150
|
+
}
|
|
@@ -471,9 +471,8 @@ export const DEFAULT_SINKS = [
|
|
|
471
471
|
{ method: 'FlowExecution', class: 'constructor', type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
|
|
472
472
|
// ActiveMQ control commands
|
|
473
473
|
{ method: 'processControlCommand', class: 'TransportConnection', type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
|
|
474
|
-
// XStream deserialization (
|
|
475
|
-
|
|
476
|
-
{ method: 'unmarshal', class: 'XStream', type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
|
|
474
|
+
// XStream deserialization — classified as CWE-502 (deserialization), not CWE-78 (command injection).
|
|
475
|
+
// The deserialization sink entries at lines ~1059 handle this correctly.
|
|
477
476
|
{ method: 'fromString', class: 'FileConverter', type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
|
|
478
477
|
// Plexus command line
|
|
479
478
|
{ method: 'getPosition', class: 'Commandline', type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
|
|
@@ -1156,7 +1155,8 @@ export const DEFAULT_SINKS = [
|
|
|
1156
1155
|
{ method: 'query', class: 'Connection', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0] },
|
|
1157
1156
|
{ method: 'query', class: 'Pool', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0] },
|
|
1158
1157
|
{ method: 'query', class: 'Client', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0] },
|
|
1159
|
-
{ method: 'query'
|
|
1158
|
+
// Note: classless { method: 'query' } removed — too many FPs (UriComponentsBuilder.query(), etc.)
|
|
1159
|
+
// SQL query calls are covered by class-specific patterns above (Connection, Pool, Client, JdbcTemplate)
|
|
1160
1160
|
{ method: 'raw', type: 'sql_injection', cwe: 'CWE-89', severity: 'high', arg_positions: [0] },
|
|
1161
1161
|
// Browser DOM XSS sinks
|
|
1162
1162
|
{ method: 'setAttribute', type: 'xss', cwe: 'CWE-79', severity: 'high', arg_positions: [1] },
|
|
@@ -1353,8 +1353,8 @@ export const DEFAULT_SINKS = [
|
|
|
1353
1353
|
{ method: 'execute', class: 'Connection', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0] },
|
|
1354
1354
|
{ method: 'query_row', class: 'Connection', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0] },
|
|
1355
1355
|
{ method: 'prepare', class: 'Connection', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0] },
|
|
1356
|
-
// sqlx::query macro
|
|
1357
|
-
{ method: 'query', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0] },
|
|
1356
|
+
// sqlx::query macro — use class-specific pattern
|
|
1357
|
+
{ method: 'query', class: 'sqlx', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0] },
|
|
1358
1358
|
// rusqlite specific
|
|
1359
1359
|
{ method: 'prepare', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0] },
|
|
1360
1360
|
{ method: 'execute', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0] },
|