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.
@@ -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
- { method: "execute", class: "Executor", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
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
- { method: "execute", class: "Executor", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
10070
- { method: "setCommandline", class: "Executor", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
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
- { method: "File", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
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
- { method: "execSync", type: "command_injection", cwe: "CWE-78", severity: "high", arg_positions: [0] },
10694
- { method: "spawn", type: "command_injection", cwe: "CWE-78", severity: "high", arg_positions: [0] },
10695
- { method: "spawnSync", type: "command_injection", cwe: "CWE-78", severity: "high", arg_positions: [0] },
10696
- { method: "execFile", type: "command_injection", cwe: "CWE-78", severity: "high", arg_positions: [0] },
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
- { method: "query", class: "Connection", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
10710
- { method: "query", class: "Pool", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
10711
- { method: "query", class: "Client", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
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
- { method: "raw", type: "sql_injection", cwe: "CWE-89", severity: "high", arg_positions: [0] },
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
- { method: "eval", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0] },
10770
- { method: "exec", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0] },
10771
- { method: "compile", type: "code_injection", cwe: "CWE-94", severity: "high", arg_positions: [0] },
10772
- { method: "__import__", type: "code_injection", cwe: "CWE-94", severity: "high", arg_positions: [0] },
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
- { method: "execute", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
10781
- { method: "executemany", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
10782
- { method: "raw", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
10783
- { method: "extra", type: "sql_injection", cwe: "CWE-89", severity: "high", arg_positions: [0] },
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
- { method: "open", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
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
- { method: "query", class: "Client", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
10902
- { method: "execute", class: "Client", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
10903
- { method: "query", class: "Pool", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
10904
- { method: "execute", class: "Pool", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
10905
- { method: "sql_query", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
10906
- { method: "raw_sql", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
10907
- { method: "execute", class: "Connection", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
10908
- { method: "query_row", class: "Connection", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
10909
- { method: "prepare", class: "Connection", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
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
- { method: "prepare", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
10914
- { method: "execute", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
10915
- { method: "query_map", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
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
- { method: "read_dir", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10920
- { method: "remove_file", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10921
- { method: "remove_dir", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10922
- { method: "remove_dir_all", type: "path_traversal", cwe: "CWE-22", severity: "critical", arg_positions: [0] },
10923
- { method: "copy", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0, 1] },
10924
- { method: "rename", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0, 1] },
10925
- { method: "write", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10926
- { method: "read_to_string", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10927
- { method: "create_dir", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10928
- { method: "create_dir_all", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10929
- { method: "metadata", type: "path_traversal", cwe: "CWE-22", severity: "medium", arg_positions: [0] },
10930
- { method: "symlink_metadata", type: "path_traversal", cwe: "CWE-22", severity: "medium", arg_positions: [0] },
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
- if (lowerReceiver.length >= 3 && lowerClass.includes(lowerReceiver)) {
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,