circle-ir 3.28.0 → 3.30.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.
- package/configs/sinks/path.yaml +6 -4
- package/configs/sources/http_sources.yaml +24 -0
- package/dist/analysis/config-loader.d.ts.map +1 -1
- package/dist/analysis/config-loader.js +83 -54
- package/dist/analysis/config-loader.js.map +1 -1
- package/dist/analysis/constant-propagation/patterns.d.ts.map +1 -1
- package/dist/analysis/constant-propagation/patterns.js +14 -0
- package/dist/analysis/constant-propagation/patterns.js.map +1 -1
- package/dist/analysis/passes/taint-matcher-pass.js +1 -1
- package/dist/analysis/passes/taint-matcher-pass.js.map +1 -1
- package/dist/analysis/taint-matcher.d.ts +2 -2
- package/dist/analysis/taint-matcher.d.ts.map +1 -1
- package/dist/analysis/taint-matcher.js +27 -8
- package/dist/analysis/taint-matcher.js.map +1 -1
- package/dist/analyzer.js +1 -1
- package/dist/analyzer.js.map +1 -1
- package/dist/browser/circle-ir.js +125 -65
- package/dist/core/circle-ir-core.cjs +123 -63
- package/dist/core/circle-ir-core.js +123 -63
- package/dist/types/config.d.ts +8 -1
- package/dist/types/config.d.ts.map +1 -1
- package/package.json +1 -1
package/configs/sinks/path.yaml
CHANGED
|
@@ -52,9 +52,10 @@
|
|
|
52
52
|
"cwe": "CWE-022",
|
|
53
53
|
"severity": "medium",
|
|
54
54
|
"arg_positions": [
|
|
55
|
-
0
|
|
55
|
+
0,
|
|
56
|
+
1
|
|
56
57
|
],
|
|
57
|
-
"note": "File object creation - check usage"
|
|
58
|
+
"note": "File object creation - check usage. arg 1 covers File(parent, child) overload (CVE-2018-8041 Camel mail)"
|
|
58
59
|
},
|
|
59
60
|
{
|
|
60
61
|
"method": "delete",
|
|
@@ -424,9 +425,10 @@
|
|
|
424
425
|
"cwe": "CWE-22",
|
|
425
426
|
"severity": "high",
|
|
426
427
|
"arg_positions": [
|
|
427
|
-
0
|
|
428
|
+
0,
|
|
429
|
+
1
|
|
428
430
|
],
|
|
429
|
-
"note": "Auto-mined from CVE analysis"
|
|
431
|
+
"note": "Auto-mined from CVE analysis. arg 1 covers File(parent, child) overload (CVE-2018-8041)"
|
|
430
432
|
},
|
|
431
433
|
{
|
|
432
434
|
"method": "openStream",
|
|
@@ -64,6 +64,30 @@
|
|
|
64
64
|
"return_tainted": true,
|
|
65
65
|
"note": "Extra path information"
|
|
66
66
|
},
|
|
67
|
+
{
|
|
68
|
+
"method": "getPathWithinApplication",
|
|
69
|
+
"class": "WebUtils",
|
|
70
|
+
"type": "http_path",
|
|
71
|
+
"severity": "high",
|
|
72
|
+
"return_tainted": true,
|
|
73
|
+
"note": "Apache Shiro path extractor - internally URL-decodes request URI via decodeRequestString → URLDecoder.decode. Tainted because the decoded form can re-introduce path-traversal sequences (%2e%2e → ..) after auth-time normalization. CVE-2023-34478, CVE-2023-46749 (#8)."
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"method": "getRequestUri",
|
|
77
|
+
"class": "WebUtils",
|
|
78
|
+
"type": "http_path",
|
|
79
|
+
"severity": "high",
|
|
80
|
+
"return_tainted": true,
|
|
81
|
+
"note": "Apache Shiro URL-decoded request URI helper. Lowercase 'Uri' differentiates from HttpServletRequest.getRequestURI."
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"method": "decodeRequestString",
|
|
85
|
+
"class": "WebUtils",
|
|
86
|
+
"type": "http_path",
|
|
87
|
+
"severity": "high",
|
|
88
|
+
"return_tainted": true,
|
|
89
|
+
"note": "Apache Shiro URLDecoder wrapper - explicit single-pass decode of an attacker-controlled string."
|
|
90
|
+
},
|
|
67
91
|
{
|
|
68
92
|
"method": "getCookies",
|
|
69
93
|
"class": "HttpServletRequest",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../src/analysis/config-loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EACV,WAAW,EACX,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,UAAU,EACX,MAAM,oBAAoB,CAAC;AAE5B;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,CAAC,CAEjD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,aAAa,EAAE,CAiB1E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG;IACtD,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,UAAU,EAAE,gBAAgB,EAAE,CAAC;CAChC,CAcA;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,cAAc,EAAE,MAAM,EAAE,EACxB,YAAY,EAAE,MAAM,EAAE,GACrB,WAAW,CAQb;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../src/analysis/config-loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EACV,WAAW,EACX,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,UAAU,EACX,MAAM,oBAAoB,CAAC;AAE5B;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,CAAC,CAEjD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,aAAa,EAAE,CAiB1E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG;IACtD,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,UAAU,EAAE,gBAAgB,EAAE,CAAC;CAChC,CAcA;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,cAAc,EAAE,MAAM,EAAE,EACxB,YAAY,EAAE,MAAM,EAAE,GACrB,WAAW,CAQb;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,aAAa,EAoa1C,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,WAAW,EA6nCtC,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,gBAAgB,EA6LhD,CAAC;AAEF;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,WAAW,CAM9C;AAMD;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,EAAE,UAAU,EA8F5C,CAAC"}
|
|
@@ -79,6 +79,13 @@ export const DEFAULT_SOURCES = [
|
|
|
79
79
|
{ method: 'getContextPath', class: 'HttpServletRequest', type: 'http_path', severity: 'medium', return_tainted: true },
|
|
80
80
|
{ method: 'getRemoteHost', class: 'HttpServletRequest', type: 'http_header', severity: 'medium', return_tainted: true },
|
|
81
81
|
{ method: 'getRemoteAddr', class: 'HttpServletRequest', type: 'http_header', severity: 'medium', return_tainted: true },
|
|
82
|
+
// Apache Shiro WebUtils helpers — return URL-decoded request data. The internal
|
|
83
|
+
// decodeRequestString → URLDecoder.decode chain can re-introduce ../ from
|
|
84
|
+
// %2e%2e payloads that bypassed auth-time normalization. CVE-2023-34478,
|
|
85
|
+
// CVE-2023-46749 (issue #8).
|
|
86
|
+
{ method: 'getPathWithinApplication', class: 'WebUtils', type: 'http_path', severity: 'high', return_tainted: true },
|
|
87
|
+
{ method: 'getRequestUri', class: 'WebUtils', type: 'http_path', severity: 'high', return_tainted: true },
|
|
88
|
+
{ method: 'decodeRequestString', class: 'WebUtils', type: 'http_path', severity: 'high', return_tainted: true },
|
|
82
89
|
// Additional HTTP request methods that can be attacker-controlled
|
|
83
90
|
{ method: 'getProtocol', class: 'HttpServletRequest', type: 'http_header', severity: 'medium', return_tainted: true },
|
|
84
91
|
{ method: 'getScheme', class: 'HttpServletRequest', type: 'http_header', severity: 'medium', return_tainted: true },
|
|
@@ -451,7 +458,9 @@ export const DEFAULT_SINKS = [
|
|
|
451
458
|
{ method: 'ProcessBuilder', class: 'constructor', type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
|
|
452
459
|
{ method: 'command', class: 'ProcessBuilder', type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
|
|
453
460
|
// Commons Exec
|
|
454
|
-
|
|
461
|
+
// Note: bare class 'Executor' removed — it collided with java.util.concurrent.Executor
|
|
462
|
+
// (Executor.execute(Runnable) is not command injection). Apache Commons Exec users
|
|
463
|
+
// typically declare DefaultExecutor explicitly, so we match that instead. See issue #14.
|
|
455
464
|
{ method: 'execute', class: 'DefaultExecutor', type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
|
|
456
465
|
{ method: 'CommandLine', class: 'constructor', type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
|
|
457
466
|
{ method: 'parse', class: 'CommandLine', type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
|
|
@@ -519,8 +528,8 @@ export const DEFAULT_SINKS = [
|
|
|
519
528
|
{ method: 'popen', type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
|
|
520
529
|
{ method: 'system', type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
|
|
521
530
|
// Apache Commons Exec
|
|
522
|
-
|
|
523
|
-
{ method: 'setCommandline', class: '
|
|
531
|
+
// Note: bare class 'Executor' removed (see comment above) — DefaultExecutor matched explicitly.
|
|
532
|
+
{ method: 'setCommandline', class: 'DefaultExecutor', type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
|
|
524
533
|
{ method: 'parse', class: 'CommandLine', type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
|
|
525
534
|
{ method: 'addArgument', class: 'CommandLine', type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
|
|
526
535
|
// Process-related utilities
|
|
@@ -529,7 +538,10 @@ export const DEFAULT_SINKS = [
|
|
|
529
538
|
{ method: 'redirectOutput', class: 'ProcessBuilder', type: 'command_injection', cwe: 'CWE-78', severity: 'medium', arg_positions: [0] },
|
|
530
539
|
{ method: 'redirectInput', class: 'ProcessBuilder', type: 'command_injection', cwe: 'CWE-78', severity: 'medium', arg_positions: [0] },
|
|
531
540
|
// Path Traversal (CWE-22)
|
|
532
|
-
|
|
541
|
+
// File: covers both File(String pathname) and File(parent, child). The 2-arg
|
|
542
|
+
// overload's child argument carries CVE-2018-8041 (Camel mail Content-Disposition
|
|
543
|
+
// filename written to disk).
|
|
544
|
+
{ method: 'File', class: 'constructor', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0, 1] },
|
|
533
545
|
{ method: 'FileInputStream', class: 'constructor', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0] },
|
|
534
546
|
{ method: 'FileOutputStream', class: 'constructor', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0] },
|
|
535
547
|
{ method: 'FileReader', class: 'constructor', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0] },
|
|
@@ -1141,11 +1153,14 @@ export const DEFAULT_SINKS = [
|
|
|
1141
1153
|
{ method: 'spawn', class: 'child_process', type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
|
|
1142
1154
|
{ method: 'spawnSync', class: 'child_process', type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
|
|
1143
1155
|
// Also match without receiver (destructured imports: const { exec } = require('child_process'))
|
|
1156
|
+
// `exec` is intentionally classless: catches Node.js child_process.exec AND
|
|
1157
|
+
// Java Runtime.exec (via `r.exec()` where heuristic can't resolve r → Runtime).
|
|
1144
1158
|
{ method: 'exec', type: 'command_injection', cwe: 'CWE-78', severity: 'high', arg_positions: [0] },
|
|
1145
|
-
|
|
1146
|
-
{ method: '
|
|
1147
|
-
{ method: '
|
|
1148
|
-
{ method: '
|
|
1159
|
+
// `execSync`/`spawn`/`spawnSync`/`execFile` are Node-specific — language-scope them.
|
|
1160
|
+
{ method: 'execSync', type: 'command_injection', cwe: 'CWE-78', severity: 'high', arg_positions: [0], languages: ['javascript', 'typescript'] },
|
|
1161
|
+
{ method: 'spawn', type: 'command_injection', cwe: 'CWE-78', severity: 'high', arg_positions: [0], languages: ['javascript', 'typescript'] },
|
|
1162
|
+
{ method: 'spawnSync', type: 'command_injection', cwe: 'CWE-78', severity: 'high', arg_positions: [0], languages: ['javascript', 'typescript'] },
|
|
1163
|
+
{ method: 'execFile', type: 'command_injection', cwe: 'CWE-78', severity: 'high', arg_positions: [0], languages: ['javascript', 'typescript'] },
|
|
1149
1164
|
// Node.js File System (path traversal)
|
|
1150
1165
|
{ method: 'readFile', class: 'fs', type: 'path_traversal', cwe: 'CWE-22', severity: 'critical', arg_positions: [0] },
|
|
1151
1166
|
{ method: 'readFileSync', class: 'fs', type: 'path_traversal', cwe: 'CWE-22', severity: 'critical', arg_positions: [0] },
|
|
@@ -1158,12 +1173,15 @@ export const DEFAULT_SINKS = [
|
|
|
1158
1173
|
{ method: 'createReadStream', class: 'fs', type: 'path_traversal', cwe: 'CWE-22', severity: 'critical', arg_positions: [0] },
|
|
1159
1174
|
{ method: 'createWriteStream', class: 'fs', type: 'path_traversal', cwe: 'CWE-22', severity: 'critical', arg_positions: [0] },
|
|
1160
1175
|
// Node.js SQL (mysql, pg, sqlite, etc.)
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
{ method: 'query', class: '
|
|
1176
|
+
// Language-scoped: generic class names `Pool`/`Connection`/`Client` substring-match
|
|
1177
|
+
// unrelated Java identifiers like `cachedThreadPool`, `dbConnection`. See issue #14.
|
|
1178
|
+
{ method: 'query', class: 'Connection', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0], languages: ['javascript', 'typescript'] },
|
|
1179
|
+
{ method: 'query', class: 'Pool', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0], languages: ['javascript', 'typescript'] },
|
|
1180
|
+
{ method: 'query', class: 'Client', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0], languages: ['javascript', 'typescript'] },
|
|
1164
1181
|
// Note: classless { method: 'query' } removed — too many FPs (UriComponentsBuilder.query(), etc.)
|
|
1165
1182
|
// SQL query calls are covered by class-specific patterns above (Connection, Pool, Client, JdbcTemplate)
|
|
1166
|
-
|
|
1183
|
+
// Note: `raw` is shared with Python (Django ORM) — scoped to JS+TS to avoid leaking.
|
|
1184
|
+
{ method: 'raw', type: 'sql_injection', cwe: 'CWE-89', severity: 'high', arg_positions: [0], languages: ['javascript', 'typescript'] },
|
|
1167
1185
|
// Browser DOM XSS sinks
|
|
1168
1186
|
{ method: 'setAttribute', type: 'xss', cwe: 'CWE-79', severity: 'high', arg_positions: [1] },
|
|
1169
1187
|
// Express.js XSS (response methods)
|
|
@@ -1173,7 +1191,7 @@ export const DEFAULT_SINKS = [
|
|
|
1173
1191
|
{ method: 'html', class: 'Response', type: 'xss', cwe: 'CWE-79', severity: 'high', arg_positions: [0] },
|
|
1174
1192
|
{ method: 'render', class: 'Response', type: 'xss', cwe: 'CWE-79', severity: 'medium', arg_positions: [1] },
|
|
1175
1193
|
// Node.js Code Injection (eval, vm, etc.)
|
|
1176
|
-
{ method: 'eval', type: 'code_injection', cwe: 'CWE-94', severity: 'critical', arg_positions: [0] },
|
|
1194
|
+
{ method: 'eval', type: 'code_injection', cwe: 'CWE-94', severity: 'critical', arg_positions: [0], languages: ['javascript', 'typescript'] },
|
|
1177
1195
|
{ method: 'Function', class: 'constructor', type: 'code_injection', cwe: 'CWE-94', severity: 'critical', arg_positions: [0] },
|
|
1178
1196
|
{ method: 'runInContext', class: 'vm', type: 'code_injection', cwe: 'CWE-94', severity: 'critical', arg_positions: [0] },
|
|
1179
1197
|
{ method: 'runInNewContext', class: 'vm', type: 'code_injection', cwe: 'CWE-94', severity: 'critical', arg_positions: [0] },
|
|
@@ -1189,7 +1207,7 @@ export const DEFAULT_SINKS = [
|
|
|
1189
1207
|
{ method: 'get', class: 'axios', type: 'ssrf', cwe: 'CWE-918', severity: 'high', arg_positions: [0] },
|
|
1190
1208
|
{ method: 'post', class: 'axios', type: 'ssrf', cwe: 'CWE-918', severity: 'high', arg_positions: [0] },
|
|
1191
1209
|
{ method: 'request', class: 'axios', type: 'ssrf', cwe: 'CWE-918', severity: 'high', arg_positions: [0] },
|
|
1192
|
-
{ method: 'fetch', type: 'ssrf', cwe: 'CWE-918', severity: 'high', arg_positions: [0] },
|
|
1210
|
+
{ method: 'fetch', type: 'ssrf', cwe: 'CWE-918', severity: 'high', arg_positions: [0], languages: ['javascript', 'typescript'] },
|
|
1193
1211
|
{ method: 'request', class: 'http', type: 'ssrf', cwe: 'CWE-918', severity: 'high', arg_positions: [0] },
|
|
1194
1212
|
{ method: 'get', class: 'http', type: 'ssrf', cwe: 'CWE-918', severity: 'high', arg_positions: [0] },
|
|
1195
1213
|
{ method: 'request', class: 'https', type: 'ssrf', cwe: 'CWE-918', severity: 'high', arg_positions: [0] },
|
|
@@ -1218,10 +1236,12 @@ export const DEFAULT_SINKS = [
|
|
|
1218
1236
|
{ method: 'check_call', class: 'subprocess', type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
|
|
1219
1237
|
{ method: 'Popen', class: 'subprocess', type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
|
|
1220
1238
|
// Python Code Injection
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
{ method: '
|
|
1224
|
-
{ method: '
|
|
1239
|
+
// Language-scoped: classless `exec`/`eval`/`compile` collide with Java/JS builtins
|
|
1240
|
+
// and Java util.concurrent (e.g. Executor.execute / future.compile).
|
|
1241
|
+
{ method: 'eval', type: 'code_injection', cwe: 'CWE-94', severity: 'critical', arg_positions: [0], languages: ['python'] },
|
|
1242
|
+
{ method: 'exec', type: 'code_injection', cwe: 'CWE-94', severity: 'critical', arg_positions: [0], languages: ['python'] },
|
|
1243
|
+
{ method: 'compile', type: 'code_injection', cwe: 'CWE-94', severity: 'high', arg_positions: [0], languages: ['python'] },
|
|
1244
|
+
{ method: '__import__', type: 'code_injection', cwe: 'CWE-94', severity: 'high', arg_positions: [0], languages: ['python'] },
|
|
1225
1245
|
// Python Deserialization
|
|
1226
1246
|
{ method: 'loads', class: 'pickle', type: 'deserialization', cwe: 'CWE-502', severity: 'critical', arg_positions: [0] },
|
|
1227
1247
|
{ method: 'load', class: 'pickle', type: 'deserialization', cwe: 'CWE-502', severity: 'critical', arg_positions: [0] },
|
|
@@ -1229,36 +1249,39 @@ export const DEFAULT_SINKS = [
|
|
|
1229
1249
|
{ method: 'load', class: 'yaml', type: 'deserialization', cwe: 'CWE-502', severity: 'critical', arg_positions: [0] },
|
|
1230
1250
|
{ method: 'loads', class: 'yaml', type: 'deserialization', cwe: 'CWE-502', severity: 'critical', arg_positions: [0] },
|
|
1231
1251
|
// Python SQL Injection
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
{ method: '
|
|
1235
|
-
{ method: '
|
|
1252
|
+
// Language-scoped: classless `execute`/`raw` collide with Java util.concurrent
|
|
1253
|
+
// (Executor.execute, ThreadPool.execute) and other languages. See issue #14.
|
|
1254
|
+
{ method: 'execute', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0], languages: ['python'] },
|
|
1255
|
+
{ method: 'executemany', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0], languages: ['python'] },
|
|
1256
|
+
{ method: 'raw', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0], languages: ['python'] },
|
|
1257
|
+
{ method: 'extra', type: 'sql_injection', cwe: 'CWE-89', severity: 'high', arg_positions: [0], languages: ['python'] },
|
|
1236
1258
|
// Python Path Traversal
|
|
1237
|
-
|
|
1259
|
+
// Language-scoped: classless `open` collides with Java I/O / JS DOM.
|
|
1260
|
+
{ method: 'open', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0], languages: ['python'] },
|
|
1238
1261
|
{ method: 'remove', class: 'os', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0] },
|
|
1239
1262
|
{ method: 'unlink', class: 'os', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0] },
|
|
1240
1263
|
{ method: 'rmdir', class: 'os', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0] },
|
|
1241
1264
|
{ method: 'rmtree', class: 'shutil', type: 'path_traversal', cwe: 'CWE-22', severity: 'critical', arg_positions: [0] },
|
|
1242
|
-
{ method: 'send_file', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0] },
|
|
1265
|
+
{ method: 'send_file', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0], languages: ['python'] },
|
|
1243
1266
|
// Python XSS / SSTI
|
|
1244
|
-
{ method: 'render_template_string', type: 'xss', cwe: 'CWE-79', severity: 'high', arg_positions: [0] },
|
|
1245
|
-
{ method: 'Markup', type: 'xss', cwe: 'CWE-79', severity: 'high', arg_positions: [0] },
|
|
1246
|
-
{ method: 'mark_safe', type: 'xss', cwe: 'CWE-79', severity: 'high', arg_positions: [0] },
|
|
1267
|
+
{ method: 'render_template_string', type: 'xss', cwe: 'CWE-79', severity: 'high', arg_positions: [0], languages: ['python'] },
|
|
1268
|
+
{ method: 'Markup', type: 'xss', cwe: 'CWE-79', severity: 'high', arg_positions: [0], languages: ['python'] },
|
|
1269
|
+
{ method: 'mark_safe', type: 'xss', cwe: 'CWE-79', severity: 'high', arg_positions: [0], languages: ['python'] },
|
|
1247
1270
|
// Python SSRF
|
|
1248
1271
|
{ method: 'get', class: 'requests', type: 'ssrf', cwe: 'CWE-918', severity: 'high', arg_positions: [0] },
|
|
1249
1272
|
{ method: 'post', class: 'requests', type: 'ssrf', cwe: 'CWE-918', severity: 'high', arg_positions: [0] },
|
|
1250
1273
|
{ method: 'urlopen', class: 'urllib.request', type: 'ssrf', cwe: 'CWE-918', severity: 'high', arg_positions: [0] },
|
|
1251
1274
|
// Python Open Redirect
|
|
1252
|
-
{ method: 'redirect', type: 'open_redirect', cwe: 'CWE-601', severity: 'medium', arg_positions: [0] },
|
|
1275
|
+
{ method: 'redirect', type: 'open_redirect', cwe: 'CWE-601', severity: 'medium', arg_positions: [0], languages: ['python'] },
|
|
1253
1276
|
// Python XPath Injection
|
|
1254
|
-
{ method: 'xpath', type: 'xpath_injection', cwe: 'CWE-643', severity: 'high', arg_positions: [0] },
|
|
1277
|
+
{ method: 'xpath', type: 'xpath_injection', cwe: 'CWE-643', severity: 'high', arg_positions: [0], languages: ['python'] },
|
|
1255
1278
|
{ method: 'find', class: 'etree', type: 'xpath_injection', cwe: 'CWE-643', severity: 'high', arg_positions: [0] },
|
|
1256
1279
|
{ method: 'findall', class: 'etree', type: 'xpath_injection', cwe: 'CWE-643', severity: 'high', arg_positions: [0] },
|
|
1257
1280
|
{ method: 'iterfind', class: 'etree', type: 'xpath_injection', cwe: 'CWE-643', severity: 'high', arg_positions: [0] },
|
|
1258
1281
|
{ method: 'XPath', class: 'lxml', type: 'xpath_injection', cwe: 'CWE-643', severity: 'high', arg_positions: [0] },
|
|
1259
1282
|
// elementpath library (XPath 2.0/3.0)
|
|
1260
1283
|
{ method: 'select', class: 'elementpath', type: 'xpath_injection', cwe: 'CWE-643', severity: 'high', arg_positions: [1] },
|
|
1261
|
-
{ method: 'select', type: 'xpath_injection', cwe: 'CWE-643', severity: 'high', arg_positions: [0] },
|
|
1284
|
+
{ method: 'select', type: 'xpath_injection', cwe: 'CWE-643', severity: 'high', arg_positions: [0], languages: ['python'] },
|
|
1262
1285
|
{ method: 'iter_select', class: 'elementpath', type: 'xpath_injection', cwe: 'CWE-643', severity: 'high', arg_positions: [1] },
|
|
1263
1286
|
{ method: 'Selector', class: 'elementpath', type: 'xpath_injection', cwe: 'CWE-643', severity: 'high', arg_positions: [0] },
|
|
1264
1287
|
// Python XXE
|
|
@@ -1350,36 +1373,42 @@ export const DEFAULT_SINKS = [
|
|
|
1350
1373
|
{ method: 'arg', class: 'Command', type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
|
|
1351
1374
|
{ method: 'args', class: 'Command', type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
|
|
1352
1375
|
// Rust SQL Injection (sqlx, diesel, rusqlite, tokio-postgres)
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
{ method: 'query', class: '
|
|
1356
|
-
{ method: 'execute', class: '
|
|
1357
|
-
{ method: '
|
|
1358
|
-
{ method: '
|
|
1359
|
-
{ method: '
|
|
1360
|
-
{ method: '
|
|
1361
|
-
{ method: '
|
|
1376
|
+
// Language-scoped: generic class names `Pool`/`Connection`/`Client` substring-match
|
|
1377
|
+
// unrelated Java identifiers (cachedThreadPool, dbConnection). See issue #14.
|
|
1378
|
+
{ method: 'query', class: 'Client', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0], languages: ['rust'] },
|
|
1379
|
+
{ method: 'execute', class: 'Client', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0], languages: ['rust'] },
|
|
1380
|
+
{ method: 'query', class: 'Pool', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0], languages: ['rust'] },
|
|
1381
|
+
{ method: 'execute', class: 'Pool', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0], languages: ['rust'] },
|
|
1382
|
+
{ method: 'sql_query', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0], languages: ['rust'] },
|
|
1383
|
+
{ method: 'raw_sql', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0], languages: ['rust'] },
|
|
1384
|
+
{ method: 'execute', class: 'Connection', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0], languages: ['rust'] },
|
|
1385
|
+
{ method: 'query_row', class: 'Connection', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0], languages: ['rust'] },
|
|
1386
|
+
{ method: 'prepare', class: 'Connection', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0], languages: ['rust'] },
|
|
1362
1387
|
// sqlx::query macro — use class-specific pattern
|
|
1363
1388
|
{ method: 'query', class: 'sqlx', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0] },
|
|
1364
1389
|
// rusqlite specific
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
{ method: '
|
|
1390
|
+
// Language-scoped: classless `execute`/`prepare`/`query_map` collide with
|
|
1391
|
+
// Java util.concurrent (Executor.execute, ExecutorService) and other languages.
|
|
1392
|
+
{ method: 'prepare', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0], languages: ['rust'] },
|
|
1393
|
+
{ method: 'execute', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0], languages: ['rust'] },
|
|
1394
|
+
{ method: 'query_map', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0], languages: ['rust'] },
|
|
1368
1395
|
// Rust Path Traversal
|
|
1369
1396
|
{ method: 'open', class: 'File', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0] },
|
|
1370
1397
|
{ method: 'create', class: 'File', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0] },
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
{ method: '
|
|
1374
|
-
{ method: '
|
|
1375
|
-
{ method: '
|
|
1376
|
-
{ method: '
|
|
1377
|
-
{ method: '
|
|
1378
|
-
{ method: '
|
|
1379
|
-
{ method: '
|
|
1380
|
-
{ method: '
|
|
1381
|
-
{ method: '
|
|
1382
|
-
{ method: '
|
|
1398
|
+
// Language-scoped: classless std::fs helpers collide with Java/JS method names
|
|
1399
|
+
// (write, copy, rename, metadata, etc.) See issue #14.
|
|
1400
|
+
{ method: 'read_dir', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0], languages: ['rust'] },
|
|
1401
|
+
{ method: 'remove_file', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0], languages: ['rust'] },
|
|
1402
|
+
{ method: 'remove_dir', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0], languages: ['rust'] },
|
|
1403
|
+
{ method: 'remove_dir_all', type: 'path_traversal', cwe: 'CWE-22', severity: 'critical', arg_positions: [0], languages: ['rust'] },
|
|
1404
|
+
{ method: 'copy', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0, 1], languages: ['rust'] },
|
|
1405
|
+
{ method: 'rename', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0, 1], languages: ['rust'] },
|
|
1406
|
+
{ method: 'write', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0], languages: ['rust'] },
|
|
1407
|
+
{ method: 'read_to_string', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0], languages: ['rust'] },
|
|
1408
|
+
{ method: 'create_dir', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0], languages: ['rust'] },
|
|
1409
|
+
{ method: 'create_dir_all', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0], languages: ['rust'] },
|
|
1410
|
+
{ method: 'metadata', type: 'path_traversal', cwe: 'CWE-22', severity: 'medium', arg_positions: [0], languages: ['rust'] },
|
|
1411
|
+
{ method: 'symlink_metadata', type: 'path_traversal', cwe: 'CWE-22', severity: 'medium', arg_positions: [0], languages: ['rust'] },
|
|
1383
1412
|
// Tokio async fs
|
|
1384
1413
|
{ method: 'read_to_string', class: 'fs', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0] },
|
|
1385
1414
|
{ method: 'write', class: 'fs', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0] },
|