circle-ir 3.27.1 → 3.29.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/dist/analysis/config-loader.d.ts.map +1 -1
- package/dist/analysis/config-loader.js +76 -54
- package/dist/analysis/config-loader.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.d.ts.map +1 -1
- package/dist/analyzer.js +270 -253
- package/dist/analyzer.js.map +1 -1
- package/dist/browser/circle-ir.js +341 -277
- package/dist/core/circle-ir-core.cjs +118 -63
- package/dist/core/circle-ir-core.js +118 -63
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/parser.d.ts +19 -1
- package/dist/core/parser.d.ts.map +1 -1
- package/dist/core/parser.js +53 -2
- package/dist/core/parser.js.map +1 -1
- package/dist/types/config.d.ts +8 -1
- package/dist/types/config.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -4062,6 +4062,7 @@ var parserInitialized = false;
|
|
|
4062
4062
|
var parserInitializing = null;
|
|
4063
4063
|
var loadedLanguages = /* @__PURE__ */ new Map();
|
|
4064
4064
|
var loadingLanguages = /* @__PURE__ */ new Map();
|
|
4065
|
+
var cachedParsers = /* @__PURE__ */ new Map();
|
|
4065
4066
|
var configuredLanguagePaths = {};
|
|
4066
4067
|
var configuredLanguageModules = {};
|
|
4067
4068
|
async function initParser(options = {}) {
|
|
@@ -4131,9 +4132,14 @@ async function loadLanguage(language, wasmPath) {
|
|
|
4131
4132
|
return loadPromise;
|
|
4132
4133
|
}
|
|
4133
4134
|
async function createParser(language) {
|
|
4135
|
+
const cached = cachedParsers.get(language);
|
|
4136
|
+
if (cached) {
|
|
4137
|
+
return cached;
|
|
4138
|
+
}
|
|
4134
4139
|
const lang = await loadLanguage(language);
|
|
4135
4140
|
const parser = new Parser();
|
|
4136
4141
|
parser.setLanguage(lang);
|
|
4142
|
+
cachedParsers.set(language, parser);
|
|
4137
4143
|
return parser;
|
|
4138
4144
|
}
|
|
4139
4145
|
async function parse(code, language) {
|
|
@@ -4230,9 +4236,19 @@ function isLanguageLoaded(language) {
|
|
|
4230
4236
|
return loadedLanguages.has(language);
|
|
4231
4237
|
}
|
|
4232
4238
|
function resetParser() {
|
|
4233
|
-
|
|
4239
|
+
for (const parser of cachedParsers.values()) {
|
|
4240
|
+
try {
|
|
4241
|
+
parser.delete();
|
|
4242
|
+
} catch {
|
|
4243
|
+
}
|
|
4244
|
+
}
|
|
4245
|
+
cachedParsers.clear();
|
|
4234
4246
|
loadedLanguages.clear();
|
|
4247
|
+
loadingLanguages.clear();
|
|
4235
4248
|
configuredLanguagePaths = {};
|
|
4249
|
+
configuredLanguageModules = {};
|
|
4250
|
+
parserInitialized = false;
|
|
4251
|
+
parserInitializing = null;
|
|
4236
4252
|
}
|
|
4237
4253
|
|
|
4238
4254
|
// src/core/extractors/meta.ts
|
|
@@ -10098,7 +10114,9 @@ var DEFAULT_SINKS = [
|
|
|
10098
10114
|
{ method: "ProcessBuilder", class: "constructor", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10099
10115
|
{ method: "command", class: "ProcessBuilder", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10100
10116
|
// Commons Exec
|
|
10101
|
-
|
|
10117
|
+
// Note: bare class 'Executor' removed — it collided with java.util.concurrent.Executor
|
|
10118
|
+
// (Executor.execute(Runnable) is not command injection). Apache Commons Exec users
|
|
10119
|
+
// typically declare DefaultExecutor explicitly, so we match that instead. See issue #14.
|
|
10102
10120
|
{ method: "execute", class: "DefaultExecutor", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10103
10121
|
{ method: "CommandLine", class: "constructor", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10104
10122
|
{ method: "parse", class: "CommandLine", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
@@ -10166,8 +10184,8 @@ var DEFAULT_SINKS = [
|
|
|
10166
10184
|
{ method: "popen", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10167
10185
|
{ method: "system", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10168
10186
|
// Apache Commons Exec
|
|
10169
|
-
|
|
10170
|
-
{ method: "setCommandline", class: "
|
|
10187
|
+
// Note: bare class 'Executor' removed (see comment above) — DefaultExecutor matched explicitly.
|
|
10188
|
+
{ method: "setCommandline", class: "DefaultExecutor", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10171
10189
|
{ method: "parse", class: "CommandLine", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10172
10190
|
{ method: "addArgument", class: "CommandLine", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10173
10191
|
// Process-related utilities
|
|
@@ -10176,7 +10194,10 @@ var DEFAULT_SINKS = [
|
|
|
10176
10194
|
{ method: "redirectOutput", class: "ProcessBuilder", type: "command_injection", cwe: "CWE-78", severity: "medium", arg_positions: [0] },
|
|
10177
10195
|
{ method: "redirectInput", class: "ProcessBuilder", type: "command_injection", cwe: "CWE-78", severity: "medium", arg_positions: [0] },
|
|
10178
10196
|
// Path Traversal (CWE-22)
|
|
10179
|
-
|
|
10197
|
+
// File: covers both File(String pathname) and File(parent, child). The 2-arg
|
|
10198
|
+
// overload's child argument carries CVE-2018-8041 (Camel mail Content-Disposition
|
|
10199
|
+
// filename written to disk).
|
|
10200
|
+
{ method: "File", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0, 1] },
|
|
10180
10201
|
{ method: "FileInputStream", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10181
10202
|
{ method: "FileOutputStream", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10182
10203
|
{ method: "FileReader", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
@@ -10789,11 +10810,14 @@ var DEFAULT_SINKS = [
|
|
|
10789
10810
|
{ method: "spawn", class: "child_process", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10790
10811
|
{ method: "spawnSync", class: "child_process", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10791
10812
|
// Also match without receiver (destructured imports: const { exec } = require('child_process'))
|
|
10813
|
+
// `exec` is intentionally classless: catches Node.js child_process.exec AND
|
|
10814
|
+
// Java Runtime.exec (via `r.exec()` where heuristic can't resolve r → Runtime).
|
|
10792
10815
|
{ method: "exec", type: "command_injection", cwe: "CWE-78", severity: "high", arg_positions: [0] },
|
|
10793
|
-
|
|
10794
|
-
{ method: "
|
|
10795
|
-
{ method: "
|
|
10796
|
-
{ method: "
|
|
10816
|
+
// `execSync`/`spawn`/`spawnSync`/`execFile` are Node-specific — language-scope them.
|
|
10817
|
+
{ method: "execSync", type: "command_injection", cwe: "CWE-78", severity: "high", arg_positions: [0], languages: ["javascript", "typescript"] },
|
|
10818
|
+
{ method: "spawn", type: "command_injection", cwe: "CWE-78", severity: "high", arg_positions: [0], languages: ["javascript", "typescript"] },
|
|
10819
|
+
{ method: "spawnSync", type: "command_injection", cwe: "CWE-78", severity: "high", arg_positions: [0], languages: ["javascript", "typescript"] },
|
|
10820
|
+
{ method: "execFile", type: "command_injection", cwe: "CWE-78", severity: "high", arg_positions: [0], languages: ["javascript", "typescript"] },
|
|
10797
10821
|
// Node.js File System (path traversal)
|
|
10798
10822
|
{ method: "readFile", class: "fs", type: "path_traversal", cwe: "CWE-22", severity: "critical", arg_positions: [0] },
|
|
10799
10823
|
{ method: "readFileSync", class: "fs", type: "path_traversal", cwe: "CWE-22", severity: "critical", arg_positions: [0] },
|
|
@@ -10806,12 +10830,15 @@ var DEFAULT_SINKS = [
|
|
|
10806
10830
|
{ method: "createReadStream", class: "fs", type: "path_traversal", cwe: "CWE-22", severity: "critical", arg_positions: [0] },
|
|
10807
10831
|
{ method: "createWriteStream", class: "fs", type: "path_traversal", cwe: "CWE-22", severity: "critical", arg_positions: [0] },
|
|
10808
10832
|
// Node.js SQL (mysql, pg, sqlite, etc.)
|
|
10809
|
-
|
|
10810
|
-
|
|
10811
|
-
{ method: "query", class: "
|
|
10833
|
+
// Language-scoped: generic class names `Pool`/`Connection`/`Client` substring-match
|
|
10834
|
+
// unrelated Java identifiers like `cachedThreadPool`, `dbConnection`. See issue #14.
|
|
10835
|
+
{ method: "query", class: "Connection", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["javascript", "typescript"] },
|
|
10836
|
+
{ method: "query", class: "Pool", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["javascript", "typescript"] },
|
|
10837
|
+
{ method: "query", class: "Client", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["javascript", "typescript"] },
|
|
10812
10838
|
// Note: classless { method: 'query' } removed — too many FPs (UriComponentsBuilder.query(), etc.)
|
|
10813
10839
|
// SQL query calls are covered by class-specific patterns above (Connection, Pool, Client, JdbcTemplate)
|
|
10814
|
-
|
|
10840
|
+
// Note: `raw` is shared with Python (Django ORM) — scoped to JS+TS to avoid leaking.
|
|
10841
|
+
{ method: "raw", type: "sql_injection", cwe: "CWE-89", severity: "high", arg_positions: [0], languages: ["javascript", "typescript"] },
|
|
10815
10842
|
// Browser DOM XSS sinks
|
|
10816
10843
|
{ method: "setAttribute", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [1] },
|
|
10817
10844
|
// Express.js XSS (response methods)
|
|
@@ -10821,7 +10848,7 @@ var DEFAULT_SINKS = [
|
|
|
10821
10848
|
{ method: "html", class: "Response", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0] },
|
|
10822
10849
|
{ method: "render", class: "Response", type: "xss", cwe: "CWE-79", severity: "medium", arg_positions: [1] },
|
|
10823
10850
|
// Node.js Code Injection (eval, vm, etc.)
|
|
10824
|
-
{ method: "eval", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0] },
|
|
10851
|
+
{ method: "eval", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0], languages: ["javascript", "typescript"] },
|
|
10825
10852
|
{ method: "Function", class: "constructor", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0] },
|
|
10826
10853
|
{ method: "runInContext", class: "vm", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0] },
|
|
10827
10854
|
{ method: "runInNewContext", class: "vm", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0] },
|
|
@@ -10837,7 +10864,7 @@ var DEFAULT_SINKS = [
|
|
|
10837
10864
|
{ method: "get", class: "axios", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
|
|
10838
10865
|
{ method: "post", class: "axios", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
|
|
10839
10866
|
{ method: "request", class: "axios", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
|
|
10840
|
-
{ method: "fetch", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
|
|
10867
|
+
{ method: "fetch", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0], languages: ["javascript", "typescript"] },
|
|
10841
10868
|
{ method: "request", class: "http", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
|
|
10842
10869
|
{ method: "get", class: "http", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
|
|
10843
10870
|
{ method: "request", class: "https", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
|
|
@@ -10866,10 +10893,12 @@ var DEFAULT_SINKS = [
|
|
|
10866
10893
|
{ method: "check_call", class: "subprocess", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10867
10894
|
{ method: "Popen", class: "subprocess", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10868
10895
|
// Python Code Injection
|
|
10869
|
-
|
|
10870
|
-
|
|
10871
|
-
{ method: "
|
|
10872
|
-
{ method: "
|
|
10896
|
+
// Language-scoped: classless `exec`/`eval`/`compile` collide with Java/JS builtins
|
|
10897
|
+
// and Java util.concurrent (e.g. Executor.execute / future.compile).
|
|
10898
|
+
{ method: "eval", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0], languages: ["python"] },
|
|
10899
|
+
{ method: "exec", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0], languages: ["python"] },
|
|
10900
|
+
{ method: "compile", type: "code_injection", cwe: "CWE-94", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
10901
|
+
{ method: "__import__", type: "code_injection", cwe: "CWE-94", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
10873
10902
|
// Python Deserialization
|
|
10874
10903
|
{ method: "loads", class: "pickle", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0] },
|
|
10875
10904
|
{ method: "load", class: "pickle", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0] },
|
|
@@ -10877,36 +10906,39 @@ var DEFAULT_SINKS = [
|
|
|
10877
10906
|
{ method: "load", class: "yaml", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0] },
|
|
10878
10907
|
{ method: "loads", class: "yaml", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0] },
|
|
10879
10908
|
// Python SQL Injection
|
|
10880
|
-
|
|
10881
|
-
|
|
10882
|
-
{ method: "
|
|
10883
|
-
{ method: "
|
|
10909
|
+
// Language-scoped: classless `execute`/`raw` collide with Java util.concurrent
|
|
10910
|
+
// (Executor.execute, ThreadPool.execute) and other languages. See issue #14.
|
|
10911
|
+
{ method: "execute", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["python"] },
|
|
10912
|
+
{ method: "executemany", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["python"] },
|
|
10913
|
+
{ method: "raw", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["python"] },
|
|
10914
|
+
{ method: "extra", type: "sql_injection", cwe: "CWE-89", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
10884
10915
|
// Python Path Traversal
|
|
10885
|
-
|
|
10916
|
+
// Language-scoped: classless `open` collides with Java I/O / JS DOM.
|
|
10917
|
+
{ method: "open", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
10886
10918
|
{ method: "remove", class: "os", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10887
10919
|
{ method: "unlink", class: "os", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10888
10920
|
{ method: "rmdir", class: "os", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10889
10921
|
{ method: "rmtree", class: "shutil", type: "path_traversal", cwe: "CWE-22", severity: "critical", arg_positions: [0] },
|
|
10890
|
-
{ method: "send_file", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10922
|
+
{ method: "send_file", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
10891
10923
|
// Python XSS / SSTI
|
|
10892
|
-
{ method: "render_template_string", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0] },
|
|
10893
|
-
{ method: "Markup", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0] },
|
|
10894
|
-
{ method: "mark_safe", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0] },
|
|
10924
|
+
{ method: "render_template_string", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
10925
|
+
{ method: "Markup", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
10926
|
+
{ method: "mark_safe", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
10895
10927
|
// Python SSRF
|
|
10896
10928
|
{ method: "get", class: "requests", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
|
|
10897
10929
|
{ method: "post", class: "requests", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
|
|
10898
10930
|
{ method: "urlopen", class: "urllib.request", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
|
|
10899
10931
|
// Python Open Redirect
|
|
10900
|
-
{ method: "redirect", type: "open_redirect", cwe: "CWE-601", severity: "medium", arg_positions: [0] },
|
|
10932
|
+
{ method: "redirect", type: "open_redirect", cwe: "CWE-601", severity: "medium", arg_positions: [0], languages: ["python"] },
|
|
10901
10933
|
// Python XPath Injection
|
|
10902
|
-
{ method: "xpath", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0] },
|
|
10934
|
+
{ method: "xpath", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
10903
10935
|
{ method: "find", class: "etree", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0] },
|
|
10904
10936
|
{ method: "findall", class: "etree", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0] },
|
|
10905
10937
|
{ method: "iterfind", class: "etree", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0] },
|
|
10906
10938
|
{ method: "XPath", class: "lxml", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0] },
|
|
10907
10939
|
// elementpath library (XPath 2.0/3.0)
|
|
10908
10940
|
{ method: "select", class: "elementpath", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [1] },
|
|
10909
|
-
{ method: "select", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0] },
|
|
10941
|
+
{ method: "select", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
10910
10942
|
{ method: "iter_select", class: "elementpath", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [1] },
|
|
10911
10943
|
{ method: "Selector", class: "elementpath", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0] },
|
|
10912
10944
|
// Python XXE
|
|
@@ -10998,36 +11030,42 @@ var DEFAULT_SINKS = [
|
|
|
10998
11030
|
{ method: "arg", class: "Command", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10999
11031
|
{ method: "args", class: "Command", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
11000
11032
|
// Rust SQL Injection (sqlx, diesel, rusqlite, tokio-postgres)
|
|
11001
|
-
|
|
11002
|
-
|
|
11003
|
-
{ method: "query", class: "
|
|
11004
|
-
{ method: "execute", class: "
|
|
11005
|
-
{ method: "
|
|
11006
|
-
{ method: "
|
|
11007
|
-
{ method: "
|
|
11008
|
-
{ method: "
|
|
11009
|
-
{ method: "
|
|
11033
|
+
// Language-scoped: generic class names `Pool`/`Connection`/`Client` substring-match
|
|
11034
|
+
// unrelated Java identifiers (cachedThreadPool, dbConnection). See issue #14.
|
|
11035
|
+
{ method: "query", class: "Client", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
11036
|
+
{ method: "execute", class: "Client", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
11037
|
+
{ method: "query", class: "Pool", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
11038
|
+
{ method: "execute", class: "Pool", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
11039
|
+
{ method: "sql_query", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
11040
|
+
{ method: "raw_sql", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
11041
|
+
{ method: "execute", class: "Connection", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
11042
|
+
{ method: "query_row", class: "Connection", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
11043
|
+
{ method: "prepare", class: "Connection", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
11010
11044
|
// sqlx::query macro — use class-specific pattern
|
|
11011
11045
|
{ method: "query", class: "sqlx", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
|
|
11012
11046
|
// rusqlite specific
|
|
11013
|
-
|
|
11014
|
-
|
|
11015
|
-
{ method: "
|
|
11047
|
+
// Language-scoped: classless `execute`/`prepare`/`query_map` collide with
|
|
11048
|
+
// Java util.concurrent (Executor.execute, ExecutorService) and other languages.
|
|
11049
|
+
{ method: "prepare", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
11050
|
+
{ method: "execute", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
11051
|
+
{ method: "query_map", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
11016
11052
|
// Rust Path Traversal
|
|
11017
11053
|
{ method: "open", class: "File", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
11018
11054
|
{ method: "create", class: "File", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
11019
|
-
|
|
11020
|
-
|
|
11021
|
-
{ method: "
|
|
11022
|
-
{ method: "
|
|
11023
|
-
{ method: "
|
|
11024
|
-
{ method: "
|
|
11025
|
-
{ method: "
|
|
11026
|
-
{ method: "
|
|
11027
|
-
{ method: "
|
|
11028
|
-
{ method: "
|
|
11029
|
-
{ method: "
|
|
11030
|
-
{ method: "
|
|
11055
|
+
// Language-scoped: classless std::fs helpers collide with Java/JS method names
|
|
11056
|
+
// (write, copy, rename, metadata, etc.) See issue #14.
|
|
11057
|
+
{ method: "read_dir", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["rust"] },
|
|
11058
|
+
{ method: "remove_file", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["rust"] },
|
|
11059
|
+
{ method: "remove_dir", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["rust"] },
|
|
11060
|
+
{ method: "remove_dir_all", type: "path_traversal", cwe: "CWE-22", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
11061
|
+
{ method: "copy", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0, 1], languages: ["rust"] },
|
|
11062
|
+
{ method: "rename", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0, 1], languages: ["rust"] },
|
|
11063
|
+
{ method: "write", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["rust"] },
|
|
11064
|
+
{ method: "read_to_string", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["rust"] },
|
|
11065
|
+
{ method: "create_dir", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["rust"] },
|
|
11066
|
+
{ method: "create_dir_all", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["rust"] },
|
|
11067
|
+
{ method: "metadata", type: "path_traversal", cwe: "CWE-22", severity: "medium", arg_positions: [0], languages: ["rust"] },
|
|
11068
|
+
{ method: "symlink_metadata", type: "path_traversal", cwe: "CWE-22", severity: "medium", arg_positions: [0], languages: ["rust"] },
|
|
11031
11069
|
// Tokio async fs
|
|
11032
11070
|
{ method: "read_to_string", class: "fs", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
11033
11071
|
{ method: "write", class: "fs", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
@@ -11305,9 +11343,9 @@ var PYTHON_TAINTED_PATTERNS = [
|
|
|
11305
11343
|
{ pattern: /\brequest\.query_params\b/, sourceType: "http_param" },
|
|
11306
11344
|
{ pattern: /\brequest\.path_params\b/, sourceType: "http_param" }
|
|
11307
11345
|
];
|
|
11308
|
-
function analyzeTaint(calls, types, config = getDefaultConfig(), typeHierarchy) {
|
|
11346
|
+
function analyzeTaint(calls, types, config = getDefaultConfig(), typeHierarchy, language) {
|
|
11309
11347
|
const sources = findSources(calls, types, config.sources);
|
|
11310
|
-
const sinks = findSinks(calls, config.sinks, typeHierarchy);
|
|
11348
|
+
const sinks = findSinks(calls, config.sinks, typeHierarchy, language);
|
|
11311
11349
|
const sanitizers = findSanitizers(calls, types, config.sanitizers);
|
|
11312
11350
|
return { sources, sinks, sanitizers };
|
|
11313
11351
|
}
|
|
@@ -11561,11 +11599,11 @@ function isParameterizedQueryCall(call, pattern) {
|
|
|
11561
11599
|
}
|
|
11562
11600
|
return false;
|
|
11563
11601
|
}
|
|
11564
|
-
function findSinks(calls, patterns, typeHierarchy) {
|
|
11602
|
+
function findSinks(calls, patterns, typeHierarchy, language) {
|
|
11565
11603
|
const sinkMap = /* @__PURE__ */ new Map();
|
|
11566
11604
|
for (const call of calls) {
|
|
11567
11605
|
for (const pattern of patterns) {
|
|
11568
|
-
if (matchesSinkPattern(call, pattern, typeHierarchy)) {
|
|
11606
|
+
if (matchesSinkPattern(call, pattern, typeHierarchy, language)) {
|
|
11569
11607
|
if (isParameterizedQueryCall(call, pattern)) {
|
|
11570
11608
|
continue;
|
|
11571
11609
|
}
|
|
@@ -11818,7 +11856,12 @@ function isKnownSafeReceiverForMethod(receiver, method, sinkType) {
|
|
|
11818
11856
|
}
|
|
11819
11857
|
return false;
|
|
11820
11858
|
}
|
|
11821
|
-
function matchesSinkPattern(call, pattern, typeHierarchy) {
|
|
11859
|
+
function matchesSinkPattern(call, pattern, typeHierarchy, language) {
|
|
11860
|
+
if (pattern.languages && pattern.languages.length > 0 && language !== void 0) {
|
|
11861
|
+
if (!pattern.languages.includes(language)) {
|
|
11862
|
+
return false;
|
|
11863
|
+
}
|
|
11864
|
+
}
|
|
11822
11865
|
const callMethodName = call.method_name;
|
|
11823
11866
|
const patternMethod = pattern.method;
|
|
11824
11867
|
let methodMatches = callMethodName === patternMethod;
|
|
@@ -11922,17 +11965,29 @@ function receiverMightBeClass(receiver, className) {
|
|
|
11922
11965
|
}
|
|
11923
11966
|
}
|
|
11924
11967
|
}
|
|
11925
|
-
|
|
11968
|
+
const ambiguousIdentifiers = /* @__PURE__ */ new Set([
|
|
11969
|
+
"executor",
|
|
11970
|
+
"pool",
|
|
11971
|
+
"connection",
|
|
11972
|
+
"manager",
|
|
11973
|
+
"handler",
|
|
11974
|
+
"controller",
|
|
11975
|
+
"task",
|
|
11976
|
+
"thread",
|
|
11977
|
+
"job"
|
|
11978
|
+
]);
|
|
11979
|
+
const isAmbiguous = ambiguousIdentifiers.has(lowerReceiver);
|
|
11980
|
+
if (!isAmbiguous && lowerReceiver.length >= 3 && lowerClass.includes(lowerReceiver)) {
|
|
11926
11981
|
if (lowerReceiver.length >= 5 || lowerReceiver.length / lowerClass.length >= 0.4) {
|
|
11927
11982
|
return true;
|
|
11928
11983
|
}
|
|
11929
11984
|
}
|
|
11930
|
-
if (lowerReceiver.length >= 2) {
|
|
11985
|
+
if (!isAmbiguous && lowerReceiver.length >= 2) {
|
|
11931
11986
|
if (lowerClass.startsWith(lowerReceiver) || lowerClass.endsWith(lowerReceiver)) {
|
|
11932
11987
|
return true;
|
|
11933
11988
|
}
|
|
11934
11989
|
}
|
|
11935
|
-
if (lowerReceiver.length >= 3) {
|
|
11990
|
+
if (!isAmbiguous && lowerReceiver.length >= 3) {
|
|
11936
11991
|
const words = className.replace(/([a-z])([A-Z])/g, "$1\0$2").toLowerCase().split("\0");
|
|
11937
11992
|
for (const word of words) {
|
|
11938
11993
|
if (word.startsWith(lowerReceiver) && lowerReceiver.length / word.length >= 0.4) {
|