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.
@@ -10049,7 +10049,9 @@ var DEFAULT_SINKS = [
10049
10049
  { method: "ProcessBuilder", class: "constructor", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
10050
10050
  { method: "command", class: "ProcessBuilder", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
10051
10051
  // Commons Exec
10052
- { method: "execute", class: "Executor", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
10052
+ // Note: bare class 'Executor' removed it collided with java.util.concurrent.Executor
10053
+ // (Executor.execute(Runnable) is not command injection). Apache Commons Exec users
10054
+ // typically declare DefaultExecutor explicitly, so we match that instead. See issue #14.
10053
10055
  { method: "execute", class: "DefaultExecutor", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
10054
10056
  { method: "CommandLine", class: "constructor", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
10055
10057
  { method: "parse", class: "CommandLine", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
@@ -10117,8 +10119,8 @@ var DEFAULT_SINKS = [
10117
10119
  { method: "popen", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
10118
10120
  { method: "system", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
10119
10121
  // Apache Commons Exec
10120
- { method: "execute", class: "Executor", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
10121
- { method: "setCommandline", class: "Executor", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
10122
+ // Note: bare class 'Executor' removed (see comment above) DefaultExecutor matched explicitly.
10123
+ { method: "setCommandline", class: "DefaultExecutor", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
10122
10124
  { method: "parse", class: "CommandLine", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
10123
10125
  { method: "addArgument", class: "CommandLine", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
10124
10126
  // Process-related utilities
@@ -10127,7 +10129,10 @@ var DEFAULT_SINKS = [
10127
10129
  { method: "redirectOutput", class: "ProcessBuilder", type: "command_injection", cwe: "CWE-78", severity: "medium", arg_positions: [0] },
10128
10130
  { method: "redirectInput", class: "ProcessBuilder", type: "command_injection", cwe: "CWE-78", severity: "medium", arg_positions: [0] },
10129
10131
  // Path Traversal (CWE-22)
10130
- { method: "File", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10132
+ // File: covers both File(String pathname) and File(parent, child). The 2-arg
10133
+ // overload's child argument carries CVE-2018-8041 (Camel mail Content-Disposition
10134
+ // filename written to disk).
10135
+ { method: "File", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0, 1] },
10131
10136
  { method: "FileInputStream", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10132
10137
  { method: "FileOutputStream", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10133
10138
  { method: "FileReader", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
@@ -10740,11 +10745,14 @@ var DEFAULT_SINKS = [
10740
10745
  { method: "spawn", class: "child_process", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
10741
10746
  { method: "spawnSync", class: "child_process", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
10742
10747
  // Also match without receiver (destructured imports: const { exec } = require('child_process'))
10748
+ // `exec` is intentionally classless: catches Node.js child_process.exec AND
10749
+ // Java Runtime.exec (via `r.exec()` where heuristic can't resolve r → Runtime).
10743
10750
  { method: "exec", type: "command_injection", cwe: "CWE-78", severity: "high", arg_positions: [0] },
10744
- { method: "execSync", type: "command_injection", cwe: "CWE-78", severity: "high", arg_positions: [0] },
10745
- { method: "spawn", type: "command_injection", cwe: "CWE-78", severity: "high", arg_positions: [0] },
10746
- { method: "spawnSync", type: "command_injection", cwe: "CWE-78", severity: "high", arg_positions: [0] },
10747
- { method: "execFile", type: "command_injection", cwe: "CWE-78", severity: "high", arg_positions: [0] },
10751
+ // `execSync`/`spawn`/`spawnSync`/`execFile` are Node-specific language-scope them.
10752
+ { method: "execSync", type: "command_injection", cwe: "CWE-78", severity: "high", arg_positions: [0], languages: ["javascript", "typescript"] },
10753
+ { method: "spawn", type: "command_injection", cwe: "CWE-78", severity: "high", arg_positions: [0], languages: ["javascript", "typescript"] },
10754
+ { method: "spawnSync", type: "command_injection", cwe: "CWE-78", severity: "high", arg_positions: [0], languages: ["javascript", "typescript"] },
10755
+ { method: "execFile", type: "command_injection", cwe: "CWE-78", severity: "high", arg_positions: [0], languages: ["javascript", "typescript"] },
10748
10756
  // Node.js File System (path traversal)
10749
10757
  { method: "readFile", class: "fs", type: "path_traversal", cwe: "CWE-22", severity: "critical", arg_positions: [0] },
10750
10758
  { method: "readFileSync", class: "fs", type: "path_traversal", cwe: "CWE-22", severity: "critical", arg_positions: [0] },
@@ -10757,12 +10765,15 @@ var DEFAULT_SINKS = [
10757
10765
  { method: "createReadStream", class: "fs", type: "path_traversal", cwe: "CWE-22", severity: "critical", arg_positions: [0] },
10758
10766
  { method: "createWriteStream", class: "fs", type: "path_traversal", cwe: "CWE-22", severity: "critical", arg_positions: [0] },
10759
10767
  // Node.js SQL (mysql, pg, sqlite, etc.)
10760
- { method: "query", class: "Connection", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
10761
- { method: "query", class: "Pool", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
10762
- { method: "query", class: "Client", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
10768
+ // Language-scoped: generic class names `Pool`/`Connection`/`Client` substring-match
10769
+ // unrelated Java identifiers like `cachedThreadPool`, `dbConnection`. See issue #14.
10770
+ { method: "query", class: "Connection", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["javascript", "typescript"] },
10771
+ { method: "query", class: "Pool", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["javascript", "typescript"] },
10772
+ { method: "query", class: "Client", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["javascript", "typescript"] },
10763
10773
  // Note: classless { method: 'query' } removed — too many FPs (UriComponentsBuilder.query(), etc.)
10764
10774
  // SQL query calls are covered by class-specific patterns above (Connection, Pool, Client, JdbcTemplate)
10765
- { method: "raw", type: "sql_injection", cwe: "CWE-89", severity: "high", arg_positions: [0] },
10775
+ // Note: `raw` is shared with Python (Django ORM) scoped to JS+TS to avoid leaking.
10776
+ { method: "raw", type: "sql_injection", cwe: "CWE-89", severity: "high", arg_positions: [0], languages: ["javascript", "typescript"] },
10766
10777
  // Browser DOM XSS sinks
10767
10778
  { method: "setAttribute", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [1] },
10768
10779
  // Express.js XSS (response methods)
@@ -10772,7 +10783,7 @@ var DEFAULT_SINKS = [
10772
10783
  { method: "html", class: "Response", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0] },
10773
10784
  { method: "render", class: "Response", type: "xss", cwe: "CWE-79", severity: "medium", arg_positions: [1] },
10774
10785
  // Node.js Code Injection (eval, vm, etc.)
10775
- { method: "eval", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0] },
10786
+ { method: "eval", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0], languages: ["javascript", "typescript"] },
10776
10787
  { method: "Function", class: "constructor", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0] },
10777
10788
  { method: "runInContext", class: "vm", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0] },
10778
10789
  { method: "runInNewContext", class: "vm", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0] },
@@ -10788,7 +10799,7 @@ var DEFAULT_SINKS = [
10788
10799
  { method: "get", class: "axios", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
10789
10800
  { method: "post", class: "axios", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
10790
10801
  { method: "request", class: "axios", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
10791
- { method: "fetch", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
10802
+ { method: "fetch", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0], languages: ["javascript", "typescript"] },
10792
10803
  { method: "request", class: "http", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
10793
10804
  { method: "get", class: "http", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
10794
10805
  { method: "request", class: "https", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
@@ -10817,10 +10828,12 @@ var DEFAULT_SINKS = [
10817
10828
  { method: "check_call", class: "subprocess", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
10818
10829
  { method: "Popen", class: "subprocess", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
10819
10830
  // Python Code Injection
10820
- { method: "eval", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0] },
10821
- { method: "exec", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0] },
10822
- { method: "compile", type: "code_injection", cwe: "CWE-94", severity: "high", arg_positions: [0] },
10823
- { method: "__import__", type: "code_injection", cwe: "CWE-94", severity: "high", arg_positions: [0] },
10831
+ // Language-scoped: classless `exec`/`eval`/`compile` collide with Java/JS builtins
10832
+ // and Java util.concurrent (e.g. Executor.execute / future.compile).
10833
+ { method: "eval", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0], languages: ["python"] },
10834
+ { method: "exec", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0], languages: ["python"] },
10835
+ { method: "compile", type: "code_injection", cwe: "CWE-94", severity: "high", arg_positions: [0], languages: ["python"] },
10836
+ { method: "__import__", type: "code_injection", cwe: "CWE-94", severity: "high", arg_positions: [0], languages: ["python"] },
10824
10837
  // Python Deserialization
10825
10838
  { method: "loads", class: "pickle", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0] },
10826
10839
  { method: "load", class: "pickle", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0] },
@@ -10828,36 +10841,39 @@ var DEFAULT_SINKS = [
10828
10841
  { method: "load", class: "yaml", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0] },
10829
10842
  { method: "loads", class: "yaml", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0] },
10830
10843
  // Python SQL Injection
10831
- { method: "execute", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
10832
- { method: "executemany", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
10833
- { method: "raw", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
10834
- { method: "extra", type: "sql_injection", cwe: "CWE-89", severity: "high", arg_positions: [0] },
10844
+ // Language-scoped: classless `execute`/`raw` collide with Java util.concurrent
10845
+ // (Executor.execute, ThreadPool.execute) and other languages. See issue #14.
10846
+ { method: "execute", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["python"] },
10847
+ { method: "executemany", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["python"] },
10848
+ { method: "raw", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["python"] },
10849
+ { method: "extra", type: "sql_injection", cwe: "CWE-89", severity: "high", arg_positions: [0], languages: ["python"] },
10835
10850
  // Python Path Traversal
10836
- { method: "open", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10851
+ // Language-scoped: classless `open` collides with Java I/O / JS DOM.
10852
+ { method: "open", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["python"] },
10837
10853
  { method: "remove", class: "os", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10838
10854
  { method: "unlink", class: "os", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10839
10855
  { method: "rmdir", class: "os", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10840
10856
  { method: "rmtree", class: "shutil", type: "path_traversal", cwe: "CWE-22", severity: "critical", arg_positions: [0] },
10841
- { method: "send_file", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10857
+ { method: "send_file", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["python"] },
10842
10858
  // Python XSS / SSTI
10843
- { method: "render_template_string", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0] },
10844
- { method: "Markup", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0] },
10845
- { method: "mark_safe", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0] },
10859
+ { method: "render_template_string", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0], languages: ["python"] },
10860
+ { method: "Markup", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0], languages: ["python"] },
10861
+ { method: "mark_safe", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0], languages: ["python"] },
10846
10862
  // Python SSRF
10847
10863
  { method: "get", class: "requests", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
10848
10864
  { method: "post", class: "requests", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
10849
10865
  { method: "urlopen", class: "urllib.request", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
10850
10866
  // Python Open Redirect
10851
- { method: "redirect", type: "open_redirect", cwe: "CWE-601", severity: "medium", arg_positions: [0] },
10867
+ { method: "redirect", type: "open_redirect", cwe: "CWE-601", severity: "medium", arg_positions: [0], languages: ["python"] },
10852
10868
  // Python XPath Injection
10853
- { method: "xpath", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0] },
10869
+ { method: "xpath", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0], languages: ["python"] },
10854
10870
  { method: "find", class: "etree", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0] },
10855
10871
  { method: "findall", class: "etree", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0] },
10856
10872
  { method: "iterfind", class: "etree", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0] },
10857
10873
  { method: "XPath", class: "lxml", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0] },
10858
10874
  // elementpath library (XPath 2.0/3.0)
10859
10875
  { method: "select", class: "elementpath", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [1] },
10860
- { method: "select", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0] },
10876
+ { method: "select", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0], languages: ["python"] },
10861
10877
  { method: "iter_select", class: "elementpath", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [1] },
10862
10878
  { method: "Selector", class: "elementpath", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0] },
10863
10879
  // Python XXE
@@ -10949,36 +10965,42 @@ var DEFAULT_SINKS = [
10949
10965
  { method: "arg", class: "Command", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
10950
10966
  { method: "args", class: "Command", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
10951
10967
  // Rust SQL Injection (sqlx, diesel, rusqlite, tokio-postgres)
10952
- { method: "query", class: "Client", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
10953
- { method: "execute", class: "Client", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
10954
- { method: "query", class: "Pool", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
10955
- { method: "execute", class: "Pool", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
10956
- { method: "sql_query", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
10957
- { method: "raw_sql", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
10958
- { method: "execute", class: "Connection", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
10959
- { method: "query_row", class: "Connection", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
10960
- { method: "prepare", class: "Connection", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
10968
+ // Language-scoped: generic class names `Pool`/`Connection`/`Client` substring-match
10969
+ // unrelated Java identifiers (cachedThreadPool, dbConnection). See issue #14.
10970
+ { method: "query", class: "Client", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
10971
+ { method: "execute", class: "Client", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
10972
+ { method: "query", class: "Pool", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
10973
+ { method: "execute", class: "Pool", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
10974
+ { method: "sql_query", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
10975
+ { method: "raw_sql", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
10976
+ { method: "execute", class: "Connection", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
10977
+ { method: "query_row", class: "Connection", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
10978
+ { method: "prepare", class: "Connection", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
10961
10979
  // sqlx::query macro — use class-specific pattern
10962
10980
  { method: "query", class: "sqlx", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
10963
10981
  // rusqlite specific
10964
- { method: "prepare", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
10965
- { method: "execute", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
10966
- { method: "query_map", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
10982
+ // Language-scoped: classless `execute`/`prepare`/`query_map` collide with
10983
+ // Java util.concurrent (Executor.execute, ExecutorService) and other languages.
10984
+ { method: "prepare", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
10985
+ { method: "execute", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
10986
+ { method: "query_map", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["rust"] },
10967
10987
  // Rust Path Traversal
10968
10988
  { method: "open", class: "File", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10969
10989
  { method: "create", class: "File", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10970
- { method: "read_dir", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10971
- { method: "remove_file", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10972
- { method: "remove_dir", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10973
- { method: "remove_dir_all", type: "path_traversal", cwe: "CWE-22", severity: "critical", arg_positions: [0] },
10974
- { method: "copy", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0, 1] },
10975
- { method: "rename", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0, 1] },
10976
- { method: "write", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10977
- { method: "read_to_string", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10978
- { method: "create_dir", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10979
- { method: "create_dir_all", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10980
- { method: "metadata", type: "path_traversal", cwe: "CWE-22", severity: "medium", arg_positions: [0] },
10981
- { method: "symlink_metadata", type: "path_traversal", cwe: "CWE-22", severity: "medium", arg_positions: [0] },
10990
+ // Language-scoped: classless std::fs helpers collide with Java/JS method names
10991
+ // (write, copy, rename, metadata, etc.) See issue #14.
10992
+ { method: "read_dir", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["rust"] },
10993
+ { method: "remove_file", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["rust"] },
10994
+ { method: "remove_dir", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["rust"] },
10995
+ { method: "remove_dir_all", type: "path_traversal", cwe: "CWE-22", severity: "critical", arg_positions: [0], languages: ["rust"] },
10996
+ { method: "copy", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0, 1], languages: ["rust"] },
10997
+ { method: "rename", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0, 1], languages: ["rust"] },
10998
+ { method: "write", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["rust"] },
10999
+ { method: "read_to_string", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["rust"] },
11000
+ { method: "create_dir", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["rust"] },
11001
+ { method: "create_dir_all", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["rust"] },
11002
+ { method: "metadata", type: "path_traversal", cwe: "CWE-22", severity: "medium", arg_positions: [0], languages: ["rust"] },
11003
+ { method: "symlink_metadata", type: "path_traversal", cwe: "CWE-22", severity: "medium", arg_positions: [0], languages: ["rust"] },
10982
11004
  // Tokio async fs
10983
11005
  { method: "read_to_string", class: "fs", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10984
11006
  { method: "write", class: "fs", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
@@ -11256,9 +11278,9 @@ var PYTHON_TAINTED_PATTERNS = [
11256
11278
  { pattern: /\brequest\.query_params\b/, sourceType: "http_param" },
11257
11279
  { pattern: /\brequest\.path_params\b/, sourceType: "http_param" }
11258
11280
  ];
11259
- function analyzeTaint(calls, types, config = getDefaultConfig(), typeHierarchy) {
11281
+ function analyzeTaint(calls, types, config = getDefaultConfig(), typeHierarchy, language) {
11260
11282
  const sources = findSources(calls, types, config.sources);
11261
- const sinks = findSinks(calls, config.sinks, typeHierarchy);
11283
+ const sinks = findSinks(calls, config.sinks, typeHierarchy, language);
11262
11284
  const sanitizers = findSanitizers(calls, types, config.sanitizers);
11263
11285
  return { sources, sinks, sanitizers };
11264
11286
  }
@@ -11512,11 +11534,11 @@ function isParameterizedQueryCall(call, pattern) {
11512
11534
  }
11513
11535
  return false;
11514
11536
  }
11515
- function findSinks(calls, patterns, typeHierarchy) {
11537
+ function findSinks(calls, patterns, typeHierarchy, language) {
11516
11538
  const sinkMap = /* @__PURE__ */ new Map();
11517
11539
  for (const call of calls) {
11518
11540
  for (const pattern of patterns) {
11519
- if (matchesSinkPattern(call, pattern, typeHierarchy)) {
11541
+ if (matchesSinkPattern(call, pattern, typeHierarchy, language)) {
11520
11542
  if (isParameterizedQueryCall(call, pattern)) {
11521
11543
  continue;
11522
11544
  }
@@ -11769,7 +11791,12 @@ function isKnownSafeReceiverForMethod(receiver, method, sinkType) {
11769
11791
  }
11770
11792
  return false;
11771
11793
  }
11772
- function matchesSinkPattern(call, pattern, typeHierarchy) {
11794
+ function matchesSinkPattern(call, pattern, typeHierarchy, language) {
11795
+ if (pattern.languages && pattern.languages.length > 0 && language !== void 0) {
11796
+ if (!pattern.languages.includes(language)) {
11797
+ return false;
11798
+ }
11799
+ }
11773
11800
  const callMethodName = call.method_name;
11774
11801
  const patternMethod = pattern.method;
11775
11802
  let methodMatches = callMethodName === patternMethod;
@@ -11873,17 +11900,29 @@ function receiverMightBeClass(receiver, className) {
11873
11900
  }
11874
11901
  }
11875
11902
  }
11876
- if (lowerReceiver.length >= 3 && lowerClass.includes(lowerReceiver)) {
11903
+ const ambiguousIdentifiers = /* @__PURE__ */ new Set([
11904
+ "executor",
11905
+ "pool",
11906
+ "connection",
11907
+ "manager",
11908
+ "handler",
11909
+ "controller",
11910
+ "task",
11911
+ "thread",
11912
+ "job"
11913
+ ]);
11914
+ const isAmbiguous = ambiguousIdentifiers.has(lowerReceiver);
11915
+ if (!isAmbiguous && lowerReceiver.length >= 3 && lowerClass.includes(lowerReceiver)) {
11877
11916
  if (lowerReceiver.length >= 5 || lowerReceiver.length / lowerClass.length >= 0.4) {
11878
11917
  return true;
11879
11918
  }
11880
11919
  }
11881
- if (lowerReceiver.length >= 2) {
11920
+ if (!isAmbiguous && lowerReceiver.length >= 2) {
11882
11921
  if (lowerClass.startsWith(lowerReceiver) || lowerClass.endsWith(lowerReceiver)) {
11883
11922
  return true;
11884
11923
  }
11885
11924
  }
11886
- if (lowerReceiver.length >= 3) {
11925
+ if (!isAmbiguous && lowerReceiver.length >= 3) {
11887
11926
  const words = className.replace(/([a-z])([A-Z])/g, "$1\0$2").toLowerCase().split("\0");
11888
11927
  for (const word of words) {
11889
11928
  if (word.startsWith(lowerReceiver) && lowerReceiver.length / word.length >= 0.4) {
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Types for YAML configuration files (configs/sources/, configs/sinks/)
3
3
  */
4
- import type { SarifLevel, Severity, SinkType, SourceType } from './index.js';
4
+ import type { SarifLevel, Severity, SinkType, SourceType, SupportedLanguage } from './index.js';
5
5
  export interface SourceConfig {
6
6
  sources: SourcePattern[];
7
7
  }
@@ -30,6 +30,13 @@ export interface SinkPattern {
30
30
  cwe: string;
31
31
  severity: Severity;
32
32
  arg_positions: number[];
33
+ /**
34
+ * Restrict the pattern to specific source languages. When omitted, the
35
+ * pattern matches calls regardless of language. Use this for sinks whose
36
+ * method name collides across language ecosystems (e.g. Python/Rust
37
+ * `cursor.execute()` vs Java `Executor.execute()`).
38
+ */
39
+ languages?: SupportedLanguage[];
33
40
  note?: string;
34
41
  }
35
42
  export interface SanitizerPattern {
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAM7E,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,aAAa,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAE5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IAGf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAIhB,UAAU,CAAC,EAAE,MAAM,CAAC;IAIpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,QAAQ,CAAC;IAGnB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAMD,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,UAAU,CAAC,EAAE,gBAAgB,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,QAAQ,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,QAAQ,CAAC;IACnB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,QAAQ,EAAE,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAMD,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,UAAU,EAAE,gBAAgB,EAAE,CAAC;CAChC;AAMD;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAC;IAChB,8DAA8D;IAC9D,GAAG,EAAE,MAAM,CAAC;IACZ,0DAA0D;IAC1D,KAAK,EAAE,UAAU,CAAC;IAClB,+DAA+D;IAC/D,QAAQ,EAAE,QAAQ,CAAC;IACnB,oEAAoE;IACpE,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;OAMG;IACH,IAAI,EAAE,SAAS,GAAG,YAAY,GAAG,cAAc,CAAC;IAChD;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAC;IAChB,mDAAmD;IACnD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAC;CACf"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAMhG,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,aAAa,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAE5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IAGf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAIhB,UAAU,CAAC,EAAE,MAAM,CAAC;IAIpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,QAAQ,CAAC;IAGnB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAMD,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,UAAU,CAAC,EAAE,gBAAgB,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,QAAQ,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,QAAQ,CAAC;IACnB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,QAAQ,EAAE,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAMD,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,UAAU,EAAE,gBAAgB,EAAE,CAAC;CAChC;AAMD;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAC;IAChB,8DAA8D;IAC9D,GAAG,EAAE,MAAM,CAAC;IACZ,0DAA0D;IAC1D,KAAK,EAAE,UAAU,CAAC;IAClB,+DAA+D;IAC/D,QAAQ,EAAE,QAAQ,CAAC;IACnB,oEAAoE;IACpE,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;OAMG;IACH,IAAI,EAAE,SAAS,GAAG,YAAY,GAAG,cAAc,CAAC;IAChD;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAC;IAChB,mDAAmD;IACnD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAC;CACf"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "circle-ir",
3
- "version": "3.28.0",
3
+ "version": "3.29.0",
4
4
  "description": "High-performance Static Application Security Testing (SAST) library for detecting security vulnerabilities through taint analysis",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",