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.
@@ -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
- { method: "execute", class: "Executor", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
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
- { 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] },
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
- { method: "File", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
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
- { 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] },
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
- { 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] },
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
- { method: "raw", type: "sql_injection", cwe: "CWE-89", severity: "high", arg_positions: [0] },
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
- { 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] },
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
- { 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] },
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
- { method: "open", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
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
- { 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] },
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
- { 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] },
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
- { 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] },
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
- if (lowerReceiver.length >= 3 && lowerClass.includes(lowerReceiver)) {
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,