circle-ir 3.216.0 → 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -1
- package/dist/analysis/config-loader.d.ts.map +1 -1
- package/dist/analysis/config-loader.js +68 -0
- package/dist/analysis/config-loader.js.map +1 -1
- package/dist/analysis/findings.d.ts.map +1 -1
- package/dist/analysis/findings.js +15 -9
- package/dist/analysis/findings.js.map +1 -1
- package/dist/analysis/note-coalescer.d.ts +0 -4
- package/dist/analysis/note-coalescer.d.ts.map +1 -1
- package/dist/analysis/note-coalescer.js +36 -1
- package/dist/analysis/note-coalescer.js.map +1 -1
- package/dist/analysis/passes/language-sources-pass.d.ts.map +1 -1
- package/dist/analysis/passes/language-sources-pass.js +54 -1
- package/dist/analysis/passes/language-sources-pass.js.map +1 -1
- package/dist/analysis/passes/sink-filter-pass.d.ts.map +1 -1
- package/dist/analysis/passes/sink-filter-pass.js +178 -0
- package/dist/analysis/passes/sink-filter-pass.js.map +1 -1
- package/dist/analysis/passes/taint-propagation-pass.js +1 -1
- package/dist/analysis/passes/taint-propagation-pass.js.map +1 -1
- package/dist/analysis/taint-matcher.d.ts.map +1 -1
- package/dist/analysis/taint-matcher.js +18 -3
- package/dist/analysis/taint-matcher.js.map +1 -1
- package/dist/browser/circle-ir.js +573 -17
- package/dist/core/circle-ir-core.cjs +338 -4
- package/dist/core/circle-ir-core.js +338 -4
- package/dist/core/extractors/calls.d.ts.map +1 -1
- package/dist/core/extractors/calls.js +133 -0
- package/dist/core/extractors/calls.js.map +1 -1
- package/dist/core/extractors/dfg.d.ts.map +1 -1
- package/dist/core/extractors/dfg.js +86 -1
- package/dist/core/extractors/dfg.js.map +1 -1
- package/dist/core/extractors/types.d.ts.map +1 -1
- package/dist/core/extractors/types.js +89 -0
- package/dist/core/extractors/types.js.map +1 -1
- package/dist/languages/plugins/csharp.d.ts +35 -0
- package/dist/languages/plugins/csharp.d.ts.map +1 -0
- package/dist/languages/plugins/csharp.js +72 -0
- package/dist/languages/plugins/csharp.js.map +1 -0
- package/dist/languages/plugins/index.d.ts +1 -0
- package/dist/languages/plugins/index.d.ts.map +1 -1
- package/dist/languages/plugins/index.js +3 -0
- package/dist/languages/plugins/index.js.map +1 -1
- package/dist/languages/types.d.ts +1 -1
- package/dist/languages/types.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/wasm/tree-sitter-csharp.wasm +0 -0
- package/docs/SPEC.md +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ A high-performance Static Application Security Testing (SAST) library for detect
|
|
|
8
8
|
## Features
|
|
9
9
|
|
|
10
10
|
- **Taint Analysis**: Track data flow from sources (user input) to sinks (dangerous operations)
|
|
11
|
-
- **Multi-language Support**: Java, JavaScript/TypeScript, Python, Go, Rust, Bash/Shell, HTML
|
|
11
|
+
- **Multi-language Support**: Java, JavaScript/TypeScript, Python, Go, Rust, Bash/Shell, HTML, and **C#/.NET (experimental)**
|
|
12
12
|
- **High Accuracy**: 100% on OWASP Benchmark, 100% on Juliet Test Suite, 97.7% TPR on SecuriBench Micro
|
|
13
13
|
- **36-Pass Pipeline**: 19 security taint passes + 17 reliability/performance/maintainability/architecture quality passes
|
|
14
14
|
- **Metrics Engine**: 24 software quality metrics (cyclomatic complexity, Halstead, CBO, RFC, LCOM, DIT, and 4 composite scores)
|
|
@@ -209,6 +209,17 @@ const response = await analyzeForAPI(code, 'File.java', 'java');
|
|
|
209
209
|
| **Rust** | tree-sitter-rust | Actix-web, Rocket, Axum |
|
|
210
210
|
| **Bash/Shell** | tree-sitter-bash | Shell scripts (.sh, .bash, .zsh, .ksh) |
|
|
211
211
|
| **HTML** | tree-sitter-html | Web extraction preprocessor (.html, .htm, .xhtml) |
|
|
212
|
+
| **C#/.NET** _(experimental)_ | tree-sitter-c-sharp | ASP.NET Core, ADO.NET, EF Core |
|
|
213
|
+
|
|
214
|
+
**C#/.NET support is experimental / preview** (since 4.0.0). It performs
|
|
215
|
+
straight-line taint analysis across 10 CWE families — SQL injection, command
|
|
216
|
+
injection, path traversal, SSRF, code injection, XSS, insecure deserialization,
|
|
217
|
+
LDAP, XPath, XXE — on ASP.NET Core / ADO.NET / EF Core / BCL, handling string
|
|
218
|
+
concatenation and `$"…{tainted}…"` interpolation, with sink-type-aware
|
|
219
|
+
sanitizer recognition (`HtmlEncode`, `Path.GetFileName`). It is **not yet
|
|
220
|
+
benchmark-verified** (no published TPR/FPR); expect gaps in branch/alias
|
|
221
|
+
precision and detector breadth. See `docs/PASSES.md` and the CHANGELOG for
|
|
222
|
+
scope.
|
|
212
223
|
|
|
213
224
|
HTML is handled as a preprocessor: `<script>` blocks are extracted and analyzed as JavaScript, inline event handlers are analyzed as JS snippets, and 8 attribute-level security checks (missing noopener, javascript: URIs, missing sandbox/SRI, mixed content, etc.) run directly on the HTML AST.
|
|
214
225
|
|
|
@@ -227,6 +238,9 @@ const goResult = await analyze(goCode, 'main.go', 'go');
|
|
|
227
238
|
// Analyze Rust
|
|
228
239
|
const rsResult = await analyze(rsCode, 'main.rs', 'rust');
|
|
229
240
|
|
|
241
|
+
// Analyze C#/.NET (experimental)
|
|
242
|
+
const csResult = await analyze(csCode, 'Controller.cs', 'csharp');
|
|
243
|
+
|
|
230
244
|
// Analyze HTML (extracts scripts, checks attributes)
|
|
231
245
|
const htmlResult = await analyze(htmlCode, 'index.html', 'html');
|
|
232
246
|
```
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../src/analysis/config-loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EACV,mBAAmB,EACnB,kBAAkB,EAClB,WAAW,EACX,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,UAAU,EACX,MAAM,oBAAoB,CAAC;AAE5B;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,CAAC,CAEjD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,aAAa,EAAE,CAiB1E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG;IACtD,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,UAAU,EAAE,gBAAgB,EAAE,CAAC;CAChC,CAcA;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,mBAAmB,EAAE,GAC7B,kBAAkB,EAAE,CAQtB;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,cAAc,EAAE,MAAM,EAAE,EACxB,YAAY,EAAE,MAAM,EAAE,EACtB,qBAAqB,GAAE,MAAM,EAAO,GACnC,WAAW,CAYb;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,aAAa,EAuwB1C,CAAC;AA+KF,eAAO,MAAM,aAAa,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../src/analysis/config-loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EACV,mBAAmB,EACnB,kBAAkB,EAClB,WAAW,EACX,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,UAAU,EACX,MAAM,oBAAoB,CAAC;AAE5B;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,CAAC,CAEjD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,aAAa,EAAE,CAiB1E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG;IACtD,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,UAAU,EAAE,gBAAgB,EAAE,CAAC;CAChC,CAcA;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,mBAAmB,EAAE,GAC7B,kBAAkB,EAAE,CAQtB;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,cAAc,EAAE,MAAM,EAAE,EACxB,YAAY,EAAE,MAAM,EAAE,EACtB,qBAAqB,GAAE,MAAM,EAAO,GACnC,WAAW,CAYb;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,aAAa,EAuwB1C,CAAC;AA+KF,eAAO,MAAM,aAAa,EAAE,WAAW,EAq6DtC,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,gBAAgB,EAuiBhD,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,sBAAsB,EAAE,kBAAkB,EAiDtD,CAAC;AAEF;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,WAAW,CAO9C;AAMD;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,EAAE,UAAU,EA8F5C,CAAC"}
|
|
@@ -2599,6 +2599,67 @@ export const DEFAULT_SINKS = [
|
|
|
2599
2599
|
{ method: 'put', class: 'httpx', type: 'ssrf', cwe: 'CWE-918', severity: 'high', arg_positions: [0] },
|
|
2600
2600
|
{ method: 'patch', class: 'httpx', type: 'ssrf', cwe: 'CWE-918', severity: 'high', arg_positions: [0] },
|
|
2601
2601
|
{ method: 'head', class: 'httpx', type: 'ssrf', cwe: 'CWE-918', severity: 'high', arg_positions: [0] },
|
|
2602
|
+
// C# SQLi (Phase-0 spike — ADO.NET). `new SqlCommand(sql, conn)` builds the
|
|
2603
|
+
// command from a raw string; the tainted SQL is arg[0] of the constructor.
|
|
2604
|
+
{ method: 'SqlCommand', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0], languages: ['csharp'] },
|
|
2605
|
+
{ method: 'NpgsqlCommand', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0], languages: ['csharp'] },
|
|
2606
|
+
{ method: 'MySqlCommand', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0], languages: ['csharp'] },
|
|
2607
|
+
{ method: 'SqliteCommand', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0], languages: ['csharp'] },
|
|
2608
|
+
{ method: 'OracleCommand', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0], languages: ['csharp'] },
|
|
2609
|
+
{ method: 'ExecuteSqlRaw', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0], languages: ['csharp'] },
|
|
2610
|
+
{ method: 'ExecuteSqlRawAsync', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0], languages: ['csharp'] },
|
|
2611
|
+
{ method: 'FromSqlRaw', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0], languages: ['csharp'] },
|
|
2612
|
+
{ method: 'FromSqlRawAsync', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0], languages: ['csharp'] },
|
|
2613
|
+
// C# command injection — Process.Start / ProcessStartInfo (CWE-78).
|
|
2614
|
+
{ method: 'Start', class: 'Process', type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0], languages: ['csharp'] },
|
|
2615
|
+
{ method: 'ProcessStartInfo', type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0, 1], languages: ['csharp'] },
|
|
2616
|
+
// C# path traversal — System.IO file APIs (CWE-22). Distinctive method names.
|
|
2617
|
+
{ method: 'ReadAllText', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0], languages: ['csharp'] },
|
|
2618
|
+
{ method: 'ReadAllBytes', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0], languages: ['csharp'] },
|
|
2619
|
+
{ method: 'ReadAllLines', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0], languages: ['csharp'] },
|
|
2620
|
+
{ method: 'WriteAllText', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0], languages: ['csharp'] },
|
|
2621
|
+
{ method: 'WriteAllBytes', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0], languages: ['csharp'] },
|
|
2622
|
+
{ method: 'AppendAllText', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0], languages: ['csharp'] },
|
|
2623
|
+
{ method: 'OpenRead', class: 'File', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0], languages: ['csharp'] },
|
|
2624
|
+
{ method: 'OpenWrite', class: 'File', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0], languages: ['csharp'] },
|
|
2625
|
+
{ method: 'FileStream', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0], languages: ['csharp'] },
|
|
2626
|
+
{ method: 'StreamReader', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0], languages: ['csharp'] },
|
|
2627
|
+
{ method: 'StreamWriter', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0], languages: ['csharp'] },
|
|
2628
|
+
// C# SSRF — HttpClient / WebClient / WebRequest (CWE-918).
|
|
2629
|
+
{ method: 'GetAsync', type: 'ssrf', cwe: 'CWE-918', severity: 'high', arg_positions: [0], languages: ['csharp'] },
|
|
2630
|
+
{ method: 'PostAsync', type: 'ssrf', cwe: 'CWE-918', severity: 'high', arg_positions: [0], languages: ['csharp'] },
|
|
2631
|
+
{ method: 'PutAsync', type: 'ssrf', cwe: 'CWE-918', severity: 'high', arg_positions: [0], languages: ['csharp'] },
|
|
2632
|
+
{ method: 'DeleteAsync', type: 'ssrf', cwe: 'CWE-918', severity: 'high', arg_positions: [0], languages: ['csharp'] },
|
|
2633
|
+
{ method: 'GetStringAsync', type: 'ssrf', cwe: 'CWE-918', severity: 'high', arg_positions: [0], languages: ['csharp'] },
|
|
2634
|
+
{ method: 'GetByteArrayAsync', type: 'ssrf', cwe: 'CWE-918', severity: 'high', arg_positions: [0], languages: ['csharp'] },
|
|
2635
|
+
{ method: 'GetStreamAsync', type: 'ssrf', cwe: 'CWE-918', severity: 'high', arg_positions: [0], languages: ['csharp'] },
|
|
2636
|
+
{ method: 'SendAsync', type: 'ssrf', cwe: 'CWE-918', severity: 'high', arg_positions: [0], languages: ['csharp'] },
|
|
2637
|
+
{ method: 'DownloadString', type: 'ssrf', cwe: 'CWE-918', severity: 'high', arg_positions: [0], languages: ['csharp'] },
|
|
2638
|
+
{ method: 'DownloadData', type: 'ssrf', cwe: 'CWE-918', severity: 'high', arg_positions: [0], languages: ['csharp'] },
|
|
2639
|
+
{ method: 'DownloadFile', type: 'ssrf', cwe: 'CWE-918', severity: 'high', arg_positions: [1], languages: ['csharp'] },
|
|
2640
|
+
{ method: 'Create', class: 'WebRequest', type: 'ssrf', cwe: 'CWE-918', severity: 'high', arg_positions: [0], languages: ['csharp'] },
|
|
2641
|
+
// C# code injection — dynamic script/assembly loading (CWE-94).
|
|
2642
|
+
{ method: 'EvaluateAsync', type: 'code_injection', cwe: 'CWE-94', severity: 'critical', arg_positions: [0], languages: ['csharp'] },
|
|
2643
|
+
{ method: 'RunAsync', class: 'CSharpScript', type: 'code_injection', cwe: 'CWE-94', severity: 'critical', arg_positions: [0], languages: ['csharp'] },
|
|
2644
|
+
// C# insecure deserialization — BinaryFormatter et al. (CWE-502).
|
|
2645
|
+
{ method: 'Deserialize', class: 'BinaryFormatter', type: 'deserialization', cwe: 'CWE-502', severity: 'critical', arg_positions: [0], languages: ['csharp'] },
|
|
2646
|
+
{ method: 'Deserialize', class: 'NetDataContractSerializer', type: 'deserialization', cwe: 'CWE-502', severity: 'critical', arg_positions: [0], languages: ['csharp'] },
|
|
2647
|
+
// C# XSS — raw HTML output (CWE-79).
|
|
2648
|
+
{ method: 'Raw', class: 'Html', type: 'xss', cwe: 'CWE-79', severity: 'high', arg_positions: [0], languages: ['csharp'] },
|
|
2649
|
+
{ method: 'Write', class: 'Response', type: 'xss', cwe: 'CWE-79', severity: 'high', arg_positions: [0], languages: ['csharp'] },
|
|
2650
|
+
{ method: 'HtmlString', type: 'xss', cwe: 'CWE-79', severity: 'high', arg_positions: [0], languages: ['csharp'] },
|
|
2651
|
+
// C# LDAP injection — System.DirectoryServices (CWE-90). The user-built
|
|
2652
|
+
// filter is the constructor argument.
|
|
2653
|
+
{ method: 'DirectorySearcher', type: 'ldap_injection', cwe: 'CWE-90', severity: 'high', arg_positions: [0], languages: ['csharp'] },
|
|
2654
|
+
{ method: 'DirectoryEntry', type: 'ldap_injection', cwe: 'CWE-90', severity: 'high', arg_positions: [0], languages: ['csharp'] },
|
|
2655
|
+
// C# XPath injection — System.Xml.XPath (CWE-643). Distinctive selector methods.
|
|
2656
|
+
{ method: 'SelectSingleNode', type: 'xpath_injection', cwe: 'CWE-643', severity: 'high', arg_positions: [0], languages: ['csharp'] },
|
|
2657
|
+
{ method: 'SelectNodes', type: 'xpath_injection', cwe: 'CWE-643', severity: 'high', arg_positions: [0], languages: ['csharp'] },
|
|
2658
|
+
{ method: 'Compile', class: 'XPathExpression', type: 'xpath_injection', cwe: 'CWE-643', severity: 'high', arg_positions: [0], languages: ['csharp'] },
|
|
2659
|
+
// C# XXE — untrusted XML into a parser without DTD hardening (CWE-611).
|
|
2660
|
+
{ method: 'LoadXml', type: 'xxe', cwe: 'CWE-611', severity: 'high', arg_positions: [0], languages: ['csharp'] },
|
|
2661
|
+
{ method: 'Load', class: 'XmlDocument', type: 'xxe', cwe: 'CWE-611', severity: 'high', arg_positions: [0], languages: ['csharp'] },
|
|
2662
|
+
{ method: 'Load', class: 'XDocument', type: 'xxe', cwe: 'CWE-611', severity: 'high', arg_positions: [0], languages: ['csharp'] },
|
|
2602
2663
|
// Python SQLi — asyncpg Connection.*
|
|
2603
2664
|
{ method: 'execute', class: 'Connection', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0] },
|
|
2604
2665
|
{ method: 'fetch', class: 'Connection', type: 'sql_injection', cwe: 'CWE-89', severity: 'critical', arg_positions: [0] },
|
|
@@ -2798,6 +2859,13 @@ export const DEFAULT_SANITIZERS = [
|
|
|
2798
2859
|
{ method: 'escapeCsv', removes: ['xss'] },
|
|
2799
2860
|
// OWASP HTML sanitizer (`com.googlecode.owasp-java-html-sanitizer`).
|
|
2800
2861
|
{ method: 'sanitize', class: 'PolicyFactory', removes: ['xss'] },
|
|
2862
|
+
// C# sanitizers (Phase-1). HTML encoders neutralise XSS; Path.GetFileName
|
|
2863
|
+
// strips any directory component (basename) so a traversal payload cannot
|
|
2864
|
+
// escape the target directory. Method names are C#-distinctive.
|
|
2865
|
+
{ method: 'HtmlEncode', removes: ['xss'] }, // HttpUtility / WebUtility
|
|
2866
|
+
{ method: 'JavaScriptStringEncode', removes: ['xss'] }, // HttpUtility
|
|
2867
|
+
{ method: 'Encode', class: 'HtmlEncoder', removes: ['xss'] },
|
|
2868
|
+
{ method: 'GetFileName', class: 'Path', removes: ['path_traversal'] },
|
|
2801
2869
|
// Java Base64 / Hex / MessageDigest — encoded output is binary-safe
|
|
2802
2870
|
// (cognium-dev #213 seventh slice). None of these carry attacker
|
|
2803
2871
|
// shell/SQL/HTML metacharacters through the encoding — Base64 emits
|