circle-ir 3.28.0 → 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.js +1 -1
- package/dist/analyzer.js.map +1 -1
- package/dist/browser/circle-ir.js +103 -64
- package/dist/core/circle-ir-core.cjs +101 -62
- package/dist/core/circle-ir-core.js +101 -62
- package/dist/types/config.d.ts +8 -1
- package/dist/types/config.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -9998,7 +9998,9 @@ var DEFAULT_SINKS = [
|
|
|
9998
9998
|
{ method: "ProcessBuilder", class: "constructor", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
9999
9999
|
{ method: "command", class: "ProcessBuilder", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10000
10000
|
// Commons Exec
|
|
10001
|
-
|
|
10001
|
+
// Note: bare class 'Executor' removed — it collided with java.util.concurrent.Executor
|
|
10002
|
+
// (Executor.execute(Runnable) is not command injection). Apache Commons Exec users
|
|
10003
|
+
// typically declare DefaultExecutor explicitly, so we match that instead. See issue #14.
|
|
10002
10004
|
{ method: "execute", class: "DefaultExecutor", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10003
10005
|
{ method: "CommandLine", class: "constructor", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10004
10006
|
{ method: "parse", class: "CommandLine", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
@@ -10066,8 +10068,8 @@ var DEFAULT_SINKS = [
|
|
|
10066
10068
|
{ method: "popen", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10067
10069
|
{ method: "system", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10068
10070
|
// Apache Commons Exec
|
|
10069
|
-
|
|
10070
|
-
{ method: "setCommandline", class: "
|
|
10071
|
+
// Note: bare class 'Executor' removed (see comment above) — DefaultExecutor matched explicitly.
|
|
10072
|
+
{ method: "setCommandline", class: "DefaultExecutor", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10071
10073
|
{ method: "parse", class: "CommandLine", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10072
10074
|
{ method: "addArgument", class: "CommandLine", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10073
10075
|
// Process-related utilities
|
|
@@ -10076,7 +10078,10 @@ var DEFAULT_SINKS = [
|
|
|
10076
10078
|
{ method: "redirectOutput", class: "ProcessBuilder", type: "command_injection", cwe: "CWE-78", severity: "medium", arg_positions: [0] },
|
|
10077
10079
|
{ method: "redirectInput", class: "ProcessBuilder", type: "command_injection", cwe: "CWE-78", severity: "medium", arg_positions: [0] },
|
|
10078
10080
|
// Path Traversal (CWE-22)
|
|
10079
|
-
|
|
10081
|
+
// File: covers both File(String pathname) and File(parent, child). The 2-arg
|
|
10082
|
+
// overload's child argument carries CVE-2018-8041 (Camel mail Content-Disposition
|
|
10083
|
+
// filename written to disk).
|
|
10084
|
+
{ method: "File", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0, 1] },
|
|
10080
10085
|
{ method: "FileInputStream", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10081
10086
|
{ method: "FileOutputStream", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10082
10087
|
{ method: "FileReader", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
@@ -10689,11 +10694,14 @@ var DEFAULT_SINKS = [
|
|
|
10689
10694
|
{ method: "spawn", class: "child_process", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10690
10695
|
{ method: "spawnSync", class: "child_process", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10691
10696
|
// Also match without receiver (destructured imports: const { exec } = require('child_process'))
|
|
10697
|
+
// `exec` is intentionally classless: catches Node.js child_process.exec AND
|
|
10698
|
+
// Java Runtime.exec (via `r.exec()` where heuristic can't resolve r → Runtime).
|
|
10692
10699
|
{ method: "exec", type: "command_injection", cwe: "CWE-78", severity: "high", arg_positions: [0] },
|
|
10693
|
-
|
|
10694
|
-
{ method: "
|
|
10695
|
-
{ method: "
|
|
10696
|
-
{ method: "
|
|
10700
|
+
// `execSync`/`spawn`/`spawnSync`/`execFile` are Node-specific — language-scope them.
|
|
10701
|
+
{ method: "execSync", type: "command_injection", cwe: "CWE-78", severity: "high", arg_positions: [0], languages: ["javascript", "typescript"] },
|
|
10702
|
+
{ method: "spawn", type: "command_injection", cwe: "CWE-78", severity: "high", arg_positions: [0], languages: ["javascript", "typescript"] },
|
|
10703
|
+
{ method: "spawnSync", type: "command_injection", cwe: "CWE-78", severity: "high", arg_positions: [0], languages: ["javascript", "typescript"] },
|
|
10704
|
+
{ method: "execFile", type: "command_injection", cwe: "CWE-78", severity: "high", arg_positions: [0], languages: ["javascript", "typescript"] },
|
|
10697
10705
|
// Node.js File System (path traversal)
|
|
10698
10706
|
{ method: "readFile", class: "fs", type: "path_traversal", cwe: "CWE-22", severity: "critical", arg_positions: [0] },
|
|
10699
10707
|
{ method: "readFileSync", class: "fs", type: "path_traversal", cwe: "CWE-22", severity: "critical", arg_positions: [0] },
|
|
@@ -10706,12 +10714,15 @@ var DEFAULT_SINKS = [
|
|
|
10706
10714
|
{ method: "createReadStream", class: "fs", type: "path_traversal", cwe: "CWE-22", severity: "critical", arg_positions: [0] },
|
|
10707
10715
|
{ method: "createWriteStream", class: "fs", type: "path_traversal", cwe: "CWE-22", severity: "critical", arg_positions: [0] },
|
|
10708
10716
|
// Node.js SQL (mysql, pg, sqlite, etc.)
|
|
10709
|
-
|
|
10710
|
-
|
|
10711
|
-
{ method: "query", class: "
|
|
10717
|
+
// Language-scoped: generic class names `Pool`/`Connection`/`Client` substring-match
|
|
10718
|
+
// unrelated Java identifiers like `cachedThreadPool`, `dbConnection`. See issue #14.
|
|
10719
|
+
{ method: "query", class: "Connection", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["javascript", "typescript"] },
|
|
10720
|
+
{ method: "query", class: "Pool", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["javascript", "typescript"] },
|
|
10721
|
+
{ method: "query", class: "Client", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["javascript", "typescript"] },
|
|
10712
10722
|
// Note: classless { method: 'query' } removed — too many FPs (UriComponentsBuilder.query(), etc.)
|
|
10713
10723
|
// SQL query calls are covered by class-specific patterns above (Connection, Pool, Client, JdbcTemplate)
|
|
10714
|
-
|
|
10724
|
+
// Note: `raw` is shared with Python (Django ORM) — scoped to JS+TS to avoid leaking.
|
|
10725
|
+
{ method: "raw", type: "sql_injection", cwe: "CWE-89", severity: "high", arg_positions: [0], languages: ["javascript", "typescript"] },
|
|
10715
10726
|
// Browser DOM XSS sinks
|
|
10716
10727
|
{ method: "setAttribute", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [1] },
|
|
10717
10728
|
// Express.js XSS (response methods)
|
|
@@ -10721,7 +10732,7 @@ var DEFAULT_SINKS = [
|
|
|
10721
10732
|
{ method: "html", class: "Response", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0] },
|
|
10722
10733
|
{ method: "render", class: "Response", type: "xss", cwe: "CWE-79", severity: "medium", arg_positions: [1] },
|
|
10723
10734
|
// Node.js Code Injection (eval, vm, etc.)
|
|
10724
|
-
{ method: "eval", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0] },
|
|
10735
|
+
{ method: "eval", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0], languages: ["javascript", "typescript"] },
|
|
10725
10736
|
{ method: "Function", class: "constructor", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0] },
|
|
10726
10737
|
{ method: "runInContext", class: "vm", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0] },
|
|
10727
10738
|
{ method: "runInNewContext", class: "vm", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0] },
|
|
@@ -10737,7 +10748,7 @@ var DEFAULT_SINKS = [
|
|
|
10737
10748
|
{ method: "get", class: "axios", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
|
|
10738
10749
|
{ method: "post", class: "axios", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
|
|
10739
10750
|
{ method: "request", class: "axios", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
|
|
10740
|
-
{ method: "fetch", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
|
|
10751
|
+
{ method: "fetch", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0], languages: ["javascript", "typescript"] },
|
|
10741
10752
|
{ method: "request", class: "http", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
|
|
10742
10753
|
{ method: "get", class: "http", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
|
|
10743
10754
|
{ method: "request", class: "https", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
|
|
@@ -10766,10 +10777,12 @@ var DEFAULT_SINKS = [
|
|
|
10766
10777
|
{ method: "check_call", class: "subprocess", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10767
10778
|
{ method: "Popen", class: "subprocess", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10768
10779
|
// Python Code Injection
|
|
10769
|
-
|
|
10770
|
-
|
|
10771
|
-
{ method: "
|
|
10772
|
-
{ method: "
|
|
10780
|
+
// Language-scoped: classless `exec`/`eval`/`compile` collide with Java/JS builtins
|
|
10781
|
+
// and Java util.concurrent (e.g. Executor.execute / future.compile).
|
|
10782
|
+
{ method: "eval", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0], languages: ["python"] },
|
|
10783
|
+
{ method: "exec", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0], languages: ["python"] },
|
|
10784
|
+
{ method: "compile", type: "code_injection", cwe: "CWE-94", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
10785
|
+
{ method: "__import__", type: "code_injection", cwe: "CWE-94", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
10773
10786
|
// Python Deserialization
|
|
10774
10787
|
{ method: "loads", class: "pickle", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0] },
|
|
10775
10788
|
{ method: "load", class: "pickle", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0] },
|
|
@@ -10777,36 +10790,39 @@ var DEFAULT_SINKS = [
|
|
|
10777
10790
|
{ method: "load", class: "yaml", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0] },
|
|
10778
10791
|
{ method: "loads", class: "yaml", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0] },
|
|
10779
10792
|
// Python SQL Injection
|
|
10780
|
-
|
|
10781
|
-
|
|
10782
|
-
{ method: "
|
|
10783
|
-
{ method: "
|
|
10793
|
+
// Language-scoped: classless `execute`/`raw` collide with Java util.concurrent
|
|
10794
|
+
// (Executor.execute, ThreadPool.execute) and other languages. See issue #14.
|
|
10795
|
+
{ method: "execute", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["python"] },
|
|
10796
|
+
{ method: "executemany", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["python"] },
|
|
10797
|
+
{ method: "raw", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["python"] },
|
|
10798
|
+
{ method: "extra", type: "sql_injection", cwe: "CWE-89", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
10784
10799
|
// Python Path Traversal
|
|
10785
|
-
|
|
10800
|
+
// Language-scoped: classless `open` collides with Java I/O / JS DOM.
|
|
10801
|
+
{ method: "open", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
10786
10802
|
{ method: "remove", class: "os", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10787
10803
|
{ method: "unlink", class: "os", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10788
10804
|
{ method: "rmdir", class: "os", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10789
10805
|
{ method: "rmtree", class: "shutil", type: "path_traversal", cwe: "CWE-22", severity: "critical", arg_positions: [0] },
|
|
10790
|
-
{ method: "send_file", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10806
|
+
{ method: "send_file", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
10791
10807
|
// Python XSS / SSTI
|
|
10792
|
-
{ method: "render_template_string", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0] },
|
|
10793
|
-
{ method: "Markup", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0] },
|
|
10794
|
-
{ method: "mark_safe", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0] },
|
|
10808
|
+
{ method: "render_template_string", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
10809
|
+
{ method: "Markup", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
10810
|
+
{ method: "mark_safe", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
10795
10811
|
// Python SSRF
|
|
10796
10812
|
{ method: "get", class: "requests", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
|
|
10797
10813
|
{ method: "post", class: "requests", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
|
|
10798
10814
|
{ method: "urlopen", class: "urllib.request", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
|
|
10799
10815
|
// Python Open Redirect
|
|
10800
|
-
{ method: "redirect", type: "open_redirect", cwe: "CWE-601", severity: "medium", arg_positions: [0] },
|
|
10816
|
+
{ method: "redirect", type: "open_redirect", cwe: "CWE-601", severity: "medium", arg_positions: [0], languages: ["python"] },
|
|
10801
10817
|
// Python XPath Injection
|
|
10802
|
-
{ method: "xpath", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0] },
|
|
10818
|
+
{ method: "xpath", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
10803
10819
|
{ method: "find", class: "etree", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0] },
|
|
10804
10820
|
{ method: "findall", class: "etree", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0] },
|
|
10805
10821
|
{ method: "iterfind", class: "etree", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0] },
|
|
10806
10822
|
{ method: "XPath", class: "lxml", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0] },
|
|
10807
10823
|
// elementpath library (XPath 2.0/3.0)
|
|
10808
10824
|
{ method: "select", class: "elementpath", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [1] },
|
|
10809
|
-
{ method: "select", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0] },
|
|
10825
|
+
{ method: "select", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
10810
10826
|
{ method: "iter_select", class: "elementpath", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [1] },
|
|
10811
10827
|
{ method: "Selector", class: "elementpath", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0] },
|
|
10812
10828
|
// Python XXE
|
|
@@ -10898,36 +10914,42 @@ var DEFAULT_SINKS = [
|
|
|
10898
10914
|
{ method: "arg", class: "Command", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10899
10915
|
{ method: "args", class: "Command", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10900
10916
|
// Rust SQL Injection (sqlx, diesel, rusqlite, tokio-postgres)
|
|
10901
|
-
|
|
10902
|
-
|
|
10903
|
-
{ method: "query", class: "
|
|
10904
|
-
{ method: "execute", class: "
|
|
10905
|
-
{ method: "
|
|
10906
|
-
{ method: "
|
|
10907
|
-
{ method: "
|
|
10908
|
-
{ method: "
|
|
10909
|
-
{ method: "
|
|
10917
|
+
// Language-scoped: generic class names `Pool`/`Connection`/`Client` substring-match
|
|
10918
|
+
// unrelated Java identifiers (cachedThreadPool, dbConnection). See issue #14.
|
|
10919
|
+
{ method: "query", class: "Client", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
10920
|
+
{ method: "execute", class: "Client", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
10921
|
+
{ method: "query", class: "Pool", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
10922
|
+
{ method: "execute", class: "Pool", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
10923
|
+
{ method: "sql_query", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
10924
|
+
{ method: "raw_sql", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
10925
|
+
{ method: "execute", class: "Connection", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
10926
|
+
{ method: "query_row", class: "Connection", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
10927
|
+
{ method: "prepare", class: "Connection", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
10910
10928
|
// sqlx::query macro — use class-specific pattern
|
|
10911
10929
|
{ method: "query", class: "sqlx", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
|
|
10912
10930
|
// rusqlite specific
|
|
10913
|
-
|
|
10914
|
-
|
|
10915
|
-
{ method: "
|
|
10931
|
+
// Language-scoped: classless `execute`/`prepare`/`query_map` collide with
|
|
10932
|
+
// Java util.concurrent (Executor.execute, ExecutorService) and other languages.
|
|
10933
|
+
{ method: "prepare", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
10934
|
+
{ method: "execute", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
10935
|
+
{ method: "query_map", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
10916
10936
|
// Rust Path Traversal
|
|
10917
10937
|
{ method: "open", class: "File", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10918
10938
|
{ method: "create", class: "File", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10919
|
-
|
|
10920
|
-
|
|
10921
|
-
{ method: "
|
|
10922
|
-
{ method: "
|
|
10923
|
-
{ method: "
|
|
10924
|
-
{ method: "
|
|
10925
|
-
{ method: "
|
|
10926
|
-
{ method: "
|
|
10927
|
-
{ method: "
|
|
10928
|
-
{ method: "
|
|
10929
|
-
{ method: "
|
|
10930
|
-
{ method: "
|
|
10939
|
+
// Language-scoped: classless std::fs helpers collide with Java/JS method names
|
|
10940
|
+
// (write, copy, rename, metadata, etc.) See issue #14.
|
|
10941
|
+
{ method: "read_dir", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["rust"] },
|
|
10942
|
+
{ method: "remove_file", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["rust"] },
|
|
10943
|
+
{ method: "remove_dir", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["rust"] },
|
|
10944
|
+
{ method: "remove_dir_all", type: "path_traversal", cwe: "CWE-22", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
10945
|
+
{ method: "copy", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0, 1], languages: ["rust"] },
|
|
10946
|
+
{ method: "rename", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0, 1], languages: ["rust"] },
|
|
10947
|
+
{ method: "write", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["rust"] },
|
|
10948
|
+
{ method: "read_to_string", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["rust"] },
|
|
10949
|
+
{ method: "create_dir", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["rust"] },
|
|
10950
|
+
{ method: "create_dir_all", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["rust"] },
|
|
10951
|
+
{ method: "metadata", type: "path_traversal", cwe: "CWE-22", severity: "medium", arg_positions: [0], languages: ["rust"] },
|
|
10952
|
+
{ method: "symlink_metadata", type: "path_traversal", cwe: "CWE-22", severity: "medium", arg_positions: [0], languages: ["rust"] },
|
|
10931
10953
|
// Tokio async fs
|
|
10932
10954
|
{ method: "read_to_string", class: "fs", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10933
10955
|
{ method: "write", class: "fs", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
@@ -11292,9 +11314,9 @@ var PYTHON_TAINTED_PATTERNS = [
|
|
|
11292
11314
|
{ pattern: /\brequest\.query_params\b/, sourceType: "http_param" },
|
|
11293
11315
|
{ pattern: /\brequest\.path_params\b/, sourceType: "http_param" }
|
|
11294
11316
|
];
|
|
11295
|
-
function analyzeTaint(calls, types, config = getDefaultConfig(), typeHierarchy) {
|
|
11317
|
+
function analyzeTaint(calls, types, config = getDefaultConfig(), typeHierarchy, language) {
|
|
11296
11318
|
const sources = findSources(calls, types, config.sources);
|
|
11297
|
-
const sinks = findSinks(calls, config.sinks, typeHierarchy);
|
|
11319
|
+
const sinks = findSinks(calls, config.sinks, typeHierarchy, language);
|
|
11298
11320
|
const sanitizers = findSanitizers(calls, types, config.sanitizers);
|
|
11299
11321
|
return { sources, sinks, sanitizers };
|
|
11300
11322
|
}
|
|
@@ -11548,11 +11570,11 @@ function isParameterizedQueryCall(call, pattern) {
|
|
|
11548
11570
|
}
|
|
11549
11571
|
return false;
|
|
11550
11572
|
}
|
|
11551
|
-
function findSinks(calls, patterns, typeHierarchy) {
|
|
11573
|
+
function findSinks(calls, patterns, typeHierarchy, language) {
|
|
11552
11574
|
const sinkMap = /* @__PURE__ */ new Map();
|
|
11553
11575
|
for (const call of calls) {
|
|
11554
11576
|
for (const pattern of patterns) {
|
|
11555
|
-
if (matchesSinkPattern(call, pattern, typeHierarchy)) {
|
|
11577
|
+
if (matchesSinkPattern(call, pattern, typeHierarchy, language)) {
|
|
11556
11578
|
if (isParameterizedQueryCall(call, pattern)) {
|
|
11557
11579
|
continue;
|
|
11558
11580
|
}
|
|
@@ -11805,7 +11827,12 @@ function isKnownSafeReceiverForMethod(receiver, method, sinkType) {
|
|
|
11805
11827
|
}
|
|
11806
11828
|
return false;
|
|
11807
11829
|
}
|
|
11808
|
-
function matchesSinkPattern(call, pattern, typeHierarchy) {
|
|
11830
|
+
function matchesSinkPattern(call, pattern, typeHierarchy, language) {
|
|
11831
|
+
if (pattern.languages && pattern.languages.length > 0 && language !== void 0) {
|
|
11832
|
+
if (!pattern.languages.includes(language)) {
|
|
11833
|
+
return false;
|
|
11834
|
+
}
|
|
11835
|
+
}
|
|
11809
11836
|
const callMethodName = call.method_name;
|
|
11810
11837
|
const patternMethod = pattern.method;
|
|
11811
11838
|
let methodMatches = callMethodName === patternMethod;
|
|
@@ -11909,17 +11936,29 @@ function receiverMightBeClass(receiver, className) {
|
|
|
11909
11936
|
}
|
|
11910
11937
|
}
|
|
11911
11938
|
}
|
|
11912
|
-
|
|
11939
|
+
const ambiguousIdentifiers = /* @__PURE__ */ new Set([
|
|
11940
|
+
"executor",
|
|
11941
|
+
"pool",
|
|
11942
|
+
"connection",
|
|
11943
|
+
"manager",
|
|
11944
|
+
"handler",
|
|
11945
|
+
"controller",
|
|
11946
|
+
"task",
|
|
11947
|
+
"thread",
|
|
11948
|
+
"job"
|
|
11949
|
+
]);
|
|
11950
|
+
const isAmbiguous = ambiguousIdentifiers.has(lowerReceiver);
|
|
11951
|
+
if (!isAmbiguous && lowerReceiver.length >= 3 && lowerClass.includes(lowerReceiver)) {
|
|
11913
11952
|
if (lowerReceiver.length >= 5 || lowerReceiver.length / lowerClass.length >= 0.4) {
|
|
11914
11953
|
return true;
|
|
11915
11954
|
}
|
|
11916
11955
|
}
|
|
11917
|
-
if (lowerReceiver.length >= 2) {
|
|
11956
|
+
if (!isAmbiguous && lowerReceiver.length >= 2) {
|
|
11918
11957
|
if (lowerClass.startsWith(lowerReceiver) || lowerClass.endsWith(lowerReceiver)) {
|
|
11919
11958
|
return true;
|
|
11920
11959
|
}
|
|
11921
11960
|
}
|
|
11922
|
-
if (lowerReceiver.length >= 3) {
|
|
11961
|
+
if (!isAmbiguous && lowerReceiver.length >= 3) {
|
|
11923
11962
|
const words = className.replace(/([a-z])([A-Z])/g, "$1\0$2").toLowerCase().split("\0");
|
|
11924
11963
|
for (const word of words) {
|
|
11925
11964
|
if (word.startsWith(lowerReceiver) && lowerReceiver.length / word.length >= 0.4) {
|
|
@@ -20124,7 +20163,7 @@ var TaintMatcherPass = class {
|
|
|
20124
20163
|
}
|
|
20125
20164
|
const hierarchy = createWithJdkTypes();
|
|
20126
20165
|
hierarchy.addFromIR(graph.ir, graph.ir.meta.file);
|
|
20127
|
-
const taint = analyzeTaint(calls, types, mergedConfig, hierarchy);
|
|
20166
|
+
const taint = analyzeTaint(calls, types, mergedConfig, hierarchy, language);
|
|
20128
20167
|
const sanitizerMethods = [];
|
|
20129
20168
|
for (const type of types) {
|
|
20130
20169
|
for (const method of type.methods) {
|
|
@@ -26286,7 +26325,7 @@ async function analyzeForAPI(code, filePath, language, options = {}) {
|
|
|
26286
26325
|
const calls = extractCalls(tree, nodeCache, language);
|
|
26287
26326
|
const constPropResult = analyzeConstantPropagation(tree, code);
|
|
26288
26327
|
const config = options.taintConfig ?? getDefaultConfig();
|
|
26289
|
-
const taint = analyzeTaint(calls, types, config);
|
|
26328
|
+
const taint = analyzeTaint(calls, types, config, void 0, language);
|
|
26290
26329
|
let filteredSinks = taint.sinks.filter((sink) => !constPropResult.unreachableLines.has(sink.line));
|
|
26291
26330
|
filteredSinks = filterCleanVariableSinks(
|
|
26292
26331
|
filteredSinks,
|