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
|
@@ -9626,6 +9626,13 @@ var DEFAULT_SOURCES = [
|
|
|
9626
9626
|
{ method: "getContextPath", class: "HttpServletRequest", type: "http_path", severity: "medium", return_tainted: true },
|
|
9627
9627
|
{ method: "getRemoteHost", class: "HttpServletRequest", type: "http_header", severity: "medium", return_tainted: true },
|
|
9628
9628
|
{ method: "getRemoteAddr", class: "HttpServletRequest", type: "http_header", severity: "medium", return_tainted: true },
|
|
9629
|
+
// Apache Shiro WebUtils helpers — return URL-decoded request data. The internal
|
|
9630
|
+
// decodeRequestString → URLDecoder.decode chain can re-introduce ../ from
|
|
9631
|
+
// %2e%2e payloads that bypassed auth-time normalization. CVE-2023-34478,
|
|
9632
|
+
// CVE-2023-46749 (issue #8).
|
|
9633
|
+
{ method: "getPathWithinApplication", class: "WebUtils", type: "http_path", severity: "high", return_tainted: true },
|
|
9634
|
+
{ method: "getRequestUri", class: "WebUtils", type: "http_path", severity: "high", return_tainted: true },
|
|
9635
|
+
{ method: "decodeRequestString", class: "WebUtils", type: "http_path", severity: "high", return_tainted: true },
|
|
9629
9636
|
// Additional HTTP request methods that can be attacker-controlled
|
|
9630
9637
|
{ method: "getProtocol", class: "HttpServletRequest", type: "http_header", severity: "medium", return_tainted: true },
|
|
9631
9638
|
{ method: "getScheme", class: "HttpServletRequest", type: "http_header", severity: "medium", return_tainted: true },
|
|
@@ -9998,7 +10005,9 @@ var DEFAULT_SINKS = [
|
|
|
9998
10005
|
{ method: "ProcessBuilder", class: "constructor", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
9999
10006
|
{ method: "command", class: "ProcessBuilder", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10000
10007
|
// Commons Exec
|
|
10001
|
-
|
|
10008
|
+
// Note: bare class 'Executor' removed — it collided with java.util.concurrent.Executor
|
|
10009
|
+
// (Executor.execute(Runnable) is not command injection). Apache Commons Exec users
|
|
10010
|
+
// typically declare DefaultExecutor explicitly, so we match that instead. See issue #14.
|
|
10002
10011
|
{ method: "execute", class: "DefaultExecutor", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10003
10012
|
{ method: "CommandLine", class: "constructor", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10004
10013
|
{ method: "parse", class: "CommandLine", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
@@ -10066,8 +10075,8 @@ var DEFAULT_SINKS = [
|
|
|
10066
10075
|
{ method: "popen", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10067
10076
|
{ method: "system", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10068
10077
|
// Apache Commons Exec
|
|
10069
|
-
|
|
10070
|
-
{ method: "setCommandline", class: "
|
|
10078
|
+
// Note: bare class 'Executor' removed (see comment above) — DefaultExecutor matched explicitly.
|
|
10079
|
+
{ method: "setCommandline", class: "DefaultExecutor", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10071
10080
|
{ method: "parse", class: "CommandLine", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10072
10081
|
{ method: "addArgument", class: "CommandLine", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10073
10082
|
// Process-related utilities
|
|
@@ -10076,7 +10085,10 @@ var DEFAULT_SINKS = [
|
|
|
10076
10085
|
{ method: "redirectOutput", class: "ProcessBuilder", type: "command_injection", cwe: "CWE-78", severity: "medium", arg_positions: [0] },
|
|
10077
10086
|
{ method: "redirectInput", class: "ProcessBuilder", type: "command_injection", cwe: "CWE-78", severity: "medium", arg_positions: [0] },
|
|
10078
10087
|
// Path Traversal (CWE-22)
|
|
10079
|
-
|
|
10088
|
+
// File: covers both File(String pathname) and File(parent, child). The 2-arg
|
|
10089
|
+
// overload's child argument carries CVE-2018-8041 (Camel mail Content-Disposition
|
|
10090
|
+
// filename written to disk).
|
|
10091
|
+
{ method: "File", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0, 1] },
|
|
10080
10092
|
{ method: "FileInputStream", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10081
10093
|
{ method: "FileOutputStream", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10082
10094
|
{ method: "FileReader", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
@@ -10689,11 +10701,14 @@ var DEFAULT_SINKS = [
|
|
|
10689
10701
|
{ method: "spawn", class: "child_process", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10690
10702
|
{ method: "spawnSync", class: "child_process", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10691
10703
|
// Also match without receiver (destructured imports: const { exec } = require('child_process'))
|
|
10704
|
+
// `exec` is intentionally classless: catches Node.js child_process.exec AND
|
|
10705
|
+
// Java Runtime.exec (via `r.exec()` where heuristic can't resolve r → Runtime).
|
|
10692
10706
|
{ method: "exec", type: "command_injection", cwe: "CWE-78", severity: "high", arg_positions: [0] },
|
|
10693
|
-
|
|
10694
|
-
{ method: "
|
|
10695
|
-
{ method: "
|
|
10696
|
-
{ method: "
|
|
10707
|
+
// `execSync`/`spawn`/`spawnSync`/`execFile` are Node-specific — language-scope them.
|
|
10708
|
+
{ method: "execSync", type: "command_injection", cwe: "CWE-78", severity: "high", arg_positions: [0], languages: ["javascript", "typescript"] },
|
|
10709
|
+
{ method: "spawn", type: "command_injection", cwe: "CWE-78", severity: "high", arg_positions: [0], languages: ["javascript", "typescript"] },
|
|
10710
|
+
{ method: "spawnSync", type: "command_injection", cwe: "CWE-78", severity: "high", arg_positions: [0], languages: ["javascript", "typescript"] },
|
|
10711
|
+
{ method: "execFile", type: "command_injection", cwe: "CWE-78", severity: "high", arg_positions: [0], languages: ["javascript", "typescript"] },
|
|
10697
10712
|
// Node.js File System (path traversal)
|
|
10698
10713
|
{ method: "readFile", class: "fs", type: "path_traversal", cwe: "CWE-22", severity: "critical", arg_positions: [0] },
|
|
10699
10714
|
{ method: "readFileSync", class: "fs", type: "path_traversal", cwe: "CWE-22", severity: "critical", arg_positions: [0] },
|
|
@@ -10706,12 +10721,15 @@ var DEFAULT_SINKS = [
|
|
|
10706
10721
|
{ method: "createReadStream", class: "fs", type: "path_traversal", cwe: "CWE-22", severity: "critical", arg_positions: [0] },
|
|
10707
10722
|
{ method: "createWriteStream", class: "fs", type: "path_traversal", cwe: "CWE-22", severity: "critical", arg_positions: [0] },
|
|
10708
10723
|
// Node.js SQL (mysql, pg, sqlite, etc.)
|
|
10709
|
-
|
|
10710
|
-
|
|
10711
|
-
{ method: "query", class: "
|
|
10724
|
+
// Language-scoped: generic class names `Pool`/`Connection`/`Client` substring-match
|
|
10725
|
+
// unrelated Java identifiers like `cachedThreadPool`, `dbConnection`. See issue #14.
|
|
10726
|
+
{ method: "query", class: "Connection", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["javascript", "typescript"] },
|
|
10727
|
+
{ method: "query", class: "Pool", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["javascript", "typescript"] },
|
|
10728
|
+
{ method: "query", class: "Client", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["javascript", "typescript"] },
|
|
10712
10729
|
// Note: classless { method: 'query' } removed — too many FPs (UriComponentsBuilder.query(), etc.)
|
|
10713
10730
|
// SQL query calls are covered by class-specific patterns above (Connection, Pool, Client, JdbcTemplate)
|
|
10714
|
-
|
|
10731
|
+
// Note: `raw` is shared with Python (Django ORM) — scoped to JS+TS to avoid leaking.
|
|
10732
|
+
{ method: "raw", type: "sql_injection", cwe: "CWE-89", severity: "high", arg_positions: [0], languages: ["javascript", "typescript"] },
|
|
10715
10733
|
// Browser DOM XSS sinks
|
|
10716
10734
|
{ method: "setAttribute", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [1] },
|
|
10717
10735
|
// Express.js XSS (response methods)
|
|
@@ -10721,7 +10739,7 @@ var DEFAULT_SINKS = [
|
|
|
10721
10739
|
{ method: "html", class: "Response", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0] },
|
|
10722
10740
|
{ method: "render", class: "Response", type: "xss", cwe: "CWE-79", severity: "medium", arg_positions: [1] },
|
|
10723
10741
|
// Node.js Code Injection (eval, vm, etc.)
|
|
10724
|
-
{ method: "eval", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0] },
|
|
10742
|
+
{ method: "eval", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0], languages: ["javascript", "typescript"] },
|
|
10725
10743
|
{ method: "Function", class: "constructor", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0] },
|
|
10726
10744
|
{ method: "runInContext", class: "vm", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0] },
|
|
10727
10745
|
{ method: "runInNewContext", class: "vm", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0] },
|
|
@@ -10737,7 +10755,7 @@ var DEFAULT_SINKS = [
|
|
|
10737
10755
|
{ method: "get", class: "axios", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
|
|
10738
10756
|
{ method: "post", class: "axios", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
|
|
10739
10757
|
{ 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] },
|
|
10758
|
+
{ method: "fetch", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0], languages: ["javascript", "typescript"] },
|
|
10741
10759
|
{ method: "request", class: "http", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
|
|
10742
10760
|
{ method: "get", class: "http", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
|
|
10743
10761
|
{ method: "request", class: "https", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
|
|
@@ -10766,10 +10784,12 @@ var DEFAULT_SINKS = [
|
|
|
10766
10784
|
{ method: "check_call", class: "subprocess", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10767
10785
|
{ method: "Popen", class: "subprocess", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10768
10786
|
// Python Code Injection
|
|
10769
|
-
|
|
10770
|
-
|
|
10771
|
-
{ method: "
|
|
10772
|
-
{ method: "
|
|
10787
|
+
// Language-scoped: classless `exec`/`eval`/`compile` collide with Java/JS builtins
|
|
10788
|
+
// and Java util.concurrent (e.g. Executor.execute / future.compile).
|
|
10789
|
+
{ method: "eval", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0], languages: ["python"] },
|
|
10790
|
+
{ method: "exec", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0], languages: ["python"] },
|
|
10791
|
+
{ method: "compile", type: "code_injection", cwe: "CWE-94", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
10792
|
+
{ method: "__import__", type: "code_injection", cwe: "CWE-94", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
10773
10793
|
// Python Deserialization
|
|
10774
10794
|
{ method: "loads", class: "pickle", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0] },
|
|
10775
10795
|
{ method: "load", class: "pickle", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0] },
|
|
@@ -10777,36 +10797,39 @@ var DEFAULT_SINKS = [
|
|
|
10777
10797
|
{ method: "load", class: "yaml", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0] },
|
|
10778
10798
|
{ method: "loads", class: "yaml", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0] },
|
|
10779
10799
|
// Python SQL Injection
|
|
10780
|
-
|
|
10781
|
-
|
|
10782
|
-
{ method: "
|
|
10783
|
-
{ method: "
|
|
10800
|
+
// Language-scoped: classless `execute`/`raw` collide with Java util.concurrent
|
|
10801
|
+
// (Executor.execute, ThreadPool.execute) and other languages. See issue #14.
|
|
10802
|
+
{ method: "execute", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["python"] },
|
|
10803
|
+
{ method: "executemany", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["python"] },
|
|
10804
|
+
{ method: "raw", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["python"] },
|
|
10805
|
+
{ method: "extra", type: "sql_injection", cwe: "CWE-89", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
10784
10806
|
// Python Path Traversal
|
|
10785
|
-
|
|
10807
|
+
// Language-scoped: classless `open` collides with Java I/O / JS DOM.
|
|
10808
|
+
{ method: "open", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
10786
10809
|
{ method: "remove", class: "os", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10787
10810
|
{ method: "unlink", class: "os", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10788
10811
|
{ method: "rmdir", class: "os", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10789
10812
|
{ 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] },
|
|
10813
|
+
{ method: "send_file", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
10791
10814
|
// 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] },
|
|
10815
|
+
{ method: "render_template_string", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
10816
|
+
{ method: "Markup", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
10817
|
+
{ method: "mark_safe", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
10795
10818
|
// Python SSRF
|
|
10796
10819
|
{ method: "get", class: "requests", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
|
|
10797
10820
|
{ method: "post", class: "requests", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
|
|
10798
10821
|
{ method: "urlopen", class: "urllib.request", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
|
|
10799
10822
|
// Python Open Redirect
|
|
10800
|
-
{ method: "redirect", type: "open_redirect", cwe: "CWE-601", severity: "medium", arg_positions: [0] },
|
|
10823
|
+
{ method: "redirect", type: "open_redirect", cwe: "CWE-601", severity: "medium", arg_positions: [0], languages: ["python"] },
|
|
10801
10824
|
// Python XPath Injection
|
|
10802
|
-
{ method: "xpath", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0] },
|
|
10825
|
+
{ method: "xpath", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
10803
10826
|
{ method: "find", class: "etree", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0] },
|
|
10804
10827
|
{ method: "findall", class: "etree", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0] },
|
|
10805
10828
|
{ method: "iterfind", class: "etree", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0] },
|
|
10806
10829
|
{ method: "XPath", class: "lxml", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0] },
|
|
10807
10830
|
// elementpath library (XPath 2.0/3.0)
|
|
10808
10831
|
{ 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] },
|
|
10832
|
+
{ method: "select", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
10810
10833
|
{ method: "iter_select", class: "elementpath", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [1] },
|
|
10811
10834
|
{ method: "Selector", class: "elementpath", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0] },
|
|
10812
10835
|
// Python XXE
|
|
@@ -10898,36 +10921,42 @@ var DEFAULT_SINKS = [
|
|
|
10898
10921
|
{ method: "arg", class: "Command", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10899
10922
|
{ method: "args", class: "Command", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10900
10923
|
// 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: "
|
|
10924
|
+
// Language-scoped: generic class names `Pool`/`Connection`/`Client` substring-match
|
|
10925
|
+
// unrelated Java identifiers (cachedThreadPool, dbConnection). See issue #14.
|
|
10926
|
+
{ method: "query", class: "Client", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
10927
|
+
{ method: "execute", class: "Client", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
10928
|
+
{ method: "query", class: "Pool", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
10929
|
+
{ method: "execute", class: "Pool", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
10930
|
+
{ method: "sql_query", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
10931
|
+
{ method: "raw_sql", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
10932
|
+
{ method: "execute", class: "Connection", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
10933
|
+
{ method: "query_row", class: "Connection", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
10934
|
+
{ method: "prepare", class: "Connection", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
10910
10935
|
// sqlx::query macro — use class-specific pattern
|
|
10911
10936
|
{ method: "query", class: "sqlx", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
|
|
10912
10937
|
// rusqlite specific
|
|
10913
|
-
|
|
10914
|
-
|
|
10915
|
-
{ method: "
|
|
10938
|
+
// Language-scoped: classless `execute`/`prepare`/`query_map` collide with
|
|
10939
|
+
// Java util.concurrent (Executor.execute, ExecutorService) and other languages.
|
|
10940
|
+
{ method: "prepare", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
10941
|
+
{ method: "execute", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
10942
|
+
{ method: "query_map", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
10916
10943
|
// Rust Path Traversal
|
|
10917
10944
|
{ method: "open", class: "File", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10918
10945
|
{ 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: "
|
|
10946
|
+
// Language-scoped: classless std::fs helpers collide with Java/JS method names
|
|
10947
|
+
// (write, copy, rename, metadata, etc.) See issue #14.
|
|
10948
|
+
{ method: "read_dir", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["rust"] },
|
|
10949
|
+
{ method: "remove_file", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["rust"] },
|
|
10950
|
+
{ method: "remove_dir", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["rust"] },
|
|
10951
|
+
{ method: "remove_dir_all", type: "path_traversal", cwe: "CWE-22", severity: "critical", arg_positions: [0], languages: ["rust"] },
|
|
10952
|
+
{ method: "copy", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0, 1], languages: ["rust"] },
|
|
10953
|
+
{ method: "rename", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0, 1], languages: ["rust"] },
|
|
10954
|
+
{ method: "write", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["rust"] },
|
|
10955
|
+
{ method: "read_to_string", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["rust"] },
|
|
10956
|
+
{ method: "create_dir", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["rust"] },
|
|
10957
|
+
{ method: "create_dir_all", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["rust"] },
|
|
10958
|
+
{ method: "metadata", type: "path_traversal", cwe: "CWE-22", severity: "medium", arg_positions: [0], languages: ["rust"] },
|
|
10959
|
+
{ method: "symlink_metadata", type: "path_traversal", cwe: "CWE-22", severity: "medium", arg_positions: [0], languages: ["rust"] },
|
|
10931
10960
|
// Tokio async fs
|
|
10932
10961
|
{ method: "read_to_string", class: "fs", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10933
10962
|
{ method: "write", class: "fs", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
@@ -11292,9 +11321,9 @@ var PYTHON_TAINTED_PATTERNS = [
|
|
|
11292
11321
|
{ pattern: /\brequest\.query_params\b/, sourceType: "http_param" },
|
|
11293
11322
|
{ pattern: /\brequest\.path_params\b/, sourceType: "http_param" }
|
|
11294
11323
|
];
|
|
11295
|
-
function analyzeTaint(calls, types, config = getDefaultConfig(), typeHierarchy) {
|
|
11324
|
+
function analyzeTaint(calls, types, config = getDefaultConfig(), typeHierarchy, language) {
|
|
11296
11325
|
const sources = findSources(calls, types, config.sources);
|
|
11297
|
-
const sinks = findSinks(calls, config.sinks, typeHierarchy);
|
|
11326
|
+
const sinks = findSinks(calls, config.sinks, typeHierarchy, language);
|
|
11298
11327
|
const sanitizers = findSanitizers(calls, types, config.sanitizers);
|
|
11299
11328
|
return { sources, sinks, sanitizers };
|
|
11300
11329
|
}
|
|
@@ -11548,11 +11577,11 @@ function isParameterizedQueryCall(call, pattern) {
|
|
|
11548
11577
|
}
|
|
11549
11578
|
return false;
|
|
11550
11579
|
}
|
|
11551
|
-
function findSinks(calls, patterns, typeHierarchy) {
|
|
11580
|
+
function findSinks(calls, patterns, typeHierarchy, language) {
|
|
11552
11581
|
const sinkMap = /* @__PURE__ */ new Map();
|
|
11553
11582
|
for (const call of calls) {
|
|
11554
11583
|
for (const pattern of patterns) {
|
|
11555
|
-
if (matchesSinkPattern(call, pattern, typeHierarchy)) {
|
|
11584
|
+
if (matchesSinkPattern(call, pattern, typeHierarchy, language)) {
|
|
11556
11585
|
if (isParameterizedQueryCall(call, pattern)) {
|
|
11557
11586
|
continue;
|
|
11558
11587
|
}
|
|
@@ -11805,7 +11834,12 @@ function isKnownSafeReceiverForMethod(receiver, method, sinkType) {
|
|
|
11805
11834
|
}
|
|
11806
11835
|
return false;
|
|
11807
11836
|
}
|
|
11808
|
-
function matchesSinkPattern(call, pattern, typeHierarchy) {
|
|
11837
|
+
function matchesSinkPattern(call, pattern, typeHierarchy, language) {
|
|
11838
|
+
if (pattern.languages && pattern.languages.length > 0 && language !== void 0) {
|
|
11839
|
+
if (!pattern.languages.includes(language)) {
|
|
11840
|
+
return false;
|
|
11841
|
+
}
|
|
11842
|
+
}
|
|
11809
11843
|
const callMethodName = call.method_name;
|
|
11810
11844
|
const patternMethod = pattern.method;
|
|
11811
11845
|
let methodMatches = callMethodName === patternMethod;
|
|
@@ -11909,17 +11943,29 @@ function receiverMightBeClass(receiver, className) {
|
|
|
11909
11943
|
}
|
|
11910
11944
|
}
|
|
11911
11945
|
}
|
|
11912
|
-
|
|
11946
|
+
const ambiguousIdentifiers = /* @__PURE__ */ new Set([
|
|
11947
|
+
"executor",
|
|
11948
|
+
"pool",
|
|
11949
|
+
"connection",
|
|
11950
|
+
"manager",
|
|
11951
|
+
"handler",
|
|
11952
|
+
"controller",
|
|
11953
|
+
"task",
|
|
11954
|
+
"thread",
|
|
11955
|
+
"job"
|
|
11956
|
+
]);
|
|
11957
|
+
const isAmbiguous = ambiguousIdentifiers.has(lowerReceiver);
|
|
11958
|
+
if (!isAmbiguous && lowerReceiver.length >= 3 && lowerClass.includes(lowerReceiver)) {
|
|
11913
11959
|
if (lowerReceiver.length >= 5 || lowerReceiver.length / lowerClass.length >= 0.4) {
|
|
11914
11960
|
return true;
|
|
11915
11961
|
}
|
|
11916
11962
|
}
|
|
11917
|
-
if (lowerReceiver.length >= 2) {
|
|
11963
|
+
if (!isAmbiguous && lowerReceiver.length >= 2) {
|
|
11918
11964
|
if (lowerClass.startsWith(lowerReceiver) || lowerClass.endsWith(lowerReceiver)) {
|
|
11919
11965
|
return true;
|
|
11920
11966
|
}
|
|
11921
11967
|
}
|
|
11922
|
-
if (lowerReceiver.length >= 3) {
|
|
11968
|
+
if (!isAmbiguous && lowerReceiver.length >= 3) {
|
|
11923
11969
|
const words = className.replace(/([a-z])([A-Z])/g, "$1\0$2").toLowerCase().split("\0");
|
|
11924
11970
|
for (const word of words) {
|
|
11925
11971
|
if (word.startsWith(lowerReceiver) && lowerReceiver.length / word.length >= 0.4) {
|
|
@@ -14494,6 +14540,13 @@ var ANTI_SANITIZER_METHODS = /* @__PURE__ */ new Set([
|
|
|
14494
14540
|
"unescapeEcmaScript",
|
|
14495
14541
|
"unescapeJson",
|
|
14496
14542
|
"unescapeJava",
|
|
14543
|
+
// Apache Shiro WebUtils helpers (CVE-2023-34478, CVE-2023-46749 — issue #8).
|
|
14544
|
+
// These internally call URLDecoder.decode, so a value that passed a
|
|
14545
|
+
// string-level path sanitizer (e.g. Paths.normalize) becomes tainted again
|
|
14546
|
+
// after Shiro re-decodes %2e%2e → "..".
|
|
14547
|
+
"getPathWithinApplication",
|
|
14548
|
+
"getRequestUri",
|
|
14549
|
+
"decodeRequestString",
|
|
14497
14550
|
// General decoders
|
|
14498
14551
|
"unescape",
|
|
14499
14552
|
"decompress"
|
|
@@ -14529,8 +14582,15 @@ var PROPAGATOR_METHODS = /* @__PURE__ */ new Set([
|
|
|
14529
14582
|
"concat",
|
|
14530
14583
|
// String.concat(other)
|
|
14531
14584
|
// Object utilities
|
|
14532
|
-
"requireNonNull"
|
|
14585
|
+
"requireNonNull",
|
|
14533
14586
|
// Objects.requireNonNull(obj)
|
|
14587
|
+
// Apache Shiro WebUtils — propagate taint from string arg through the wrapper
|
|
14588
|
+
// back into the return value (e.g. `WebUtils.decodeRequestString(req, tainted)`).
|
|
14589
|
+
// Also covered by ANTI_SANITIZER_METHODS for sanitized-arg re-tainting and by
|
|
14590
|
+
// configs/sources/http_sources.yaml for the request-bound overloads. Issue #8.
|
|
14591
|
+
"getPathWithinApplication",
|
|
14592
|
+
"getRequestUri",
|
|
14593
|
+
"decodeRequestString"
|
|
14534
14594
|
]);
|
|
14535
14595
|
|
|
14536
14596
|
// src/analysis/constant-propagation/propagator.ts
|
|
@@ -20124,7 +20184,7 @@ var TaintMatcherPass = class {
|
|
|
20124
20184
|
}
|
|
20125
20185
|
const hierarchy = createWithJdkTypes();
|
|
20126
20186
|
hierarchy.addFromIR(graph.ir, graph.ir.meta.file);
|
|
20127
|
-
const taint = analyzeTaint(calls, types, mergedConfig, hierarchy);
|
|
20187
|
+
const taint = analyzeTaint(calls, types, mergedConfig, hierarchy, language);
|
|
20128
20188
|
const sanitizerMethods = [];
|
|
20129
20189
|
for (const type of types) {
|
|
20130
20190
|
for (const method of type.methods) {
|
|
@@ -26286,7 +26346,7 @@ async function analyzeForAPI(code, filePath, language, options = {}) {
|
|
|
26286
26346
|
const calls = extractCalls(tree, nodeCache, language);
|
|
26287
26347
|
const constPropResult = analyzeConstantPropagation(tree, code);
|
|
26288
26348
|
const config = options.taintConfig ?? getDefaultConfig();
|
|
26289
|
-
const taint = analyzeTaint(calls, types, config);
|
|
26349
|
+
const taint = analyzeTaint(calls, types, config, void 0, language);
|
|
26290
26350
|
let filteredSinks = taint.sinks.filter((sink) => !constPropResult.unreachableLines.has(sink.line));
|
|
26291
26351
|
filteredSinks = filterCleanVariableSinks(
|
|
26292
26352
|
filteredSinks,
|