circle-ir 3.59.0 → 3.64.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.
Files changed (66) hide show
  1. package/dist/analysis/config-loader.d.ts.map +1 -1
  2. package/dist/analysis/config-loader.js +58 -17
  3. package/dist/analysis/config-loader.js.map +1 -1
  4. package/dist/analysis/html/html-merge.d.ts.map +1 -1
  5. package/dist/analysis/html/html-merge.js +10 -0
  6. package/dist/analysis/html/html-merge.js.map +1 -1
  7. package/dist/analysis/interprocedural.d.ts.map +1 -1
  8. package/dist/analysis/interprocedural.js +44 -11
  9. package/dist/analysis/interprocedural.js.map +1 -1
  10. package/dist/analysis/passes/language-sources-pass.d.ts +7 -1
  11. package/dist/analysis/passes/language-sources-pass.d.ts.map +1 -1
  12. package/dist/analysis/passes/language-sources-pass.js +112 -15
  13. package/dist/analysis/passes/language-sources-pass.js.map +1 -1
  14. package/dist/analysis/passes/missing-public-doc-pass.d.ts.map +1 -1
  15. package/dist/analysis/passes/missing-public-doc-pass.js +2 -1
  16. package/dist/analysis/passes/missing-public-doc-pass.js.map +1 -1
  17. package/dist/analysis/passes/sink-filter-pass.d.ts.map +1 -1
  18. package/dist/analysis/passes/sink-filter-pass.js +4 -1
  19. package/dist/analysis/passes/sink-filter-pass.js.map +1 -1
  20. package/dist/analysis/passes/taint-propagation-pass.d.ts.map +1 -1
  21. package/dist/analysis/passes/taint-propagation-pass.js +222 -10
  22. package/dist/analysis/passes/taint-propagation-pass.js.map +1 -1
  23. package/dist/analysis/passes/weak-random-pass.d.ts.map +1 -1
  24. package/dist/analysis/passes/weak-random-pass.js +2 -1
  25. package/dist/analysis/passes/weak-random-pass.js.map +1 -1
  26. package/dist/analysis/taint-matcher.d.ts.map +1 -1
  27. package/dist/analysis/taint-matcher.js +83 -7
  28. package/dist/analysis/taint-matcher.js.map +1 -1
  29. package/dist/analysis/taint-propagation.d.ts.map +1 -1
  30. package/dist/analysis/taint-propagation.js +32 -0
  31. package/dist/analysis/taint-propagation.js.map +1 -1
  32. package/dist/analyzer.d.ts.map +1 -1
  33. package/dist/analyzer.js +19 -2
  34. package/dist/analyzer.js.map +1 -1
  35. package/dist/browser/circle-ir.js +526 -67
  36. package/dist/core/circle-ir-core.cjs +270 -33
  37. package/dist/core/circle-ir-core.js +270 -33
  38. package/dist/core/extractors/calls.js +181 -1
  39. package/dist/core/extractors/calls.js.map +1 -1
  40. package/dist/core/extractors/cfg.js +1 -1
  41. package/dist/core/extractors/cfg.js.map +1 -1
  42. package/dist/core/extractors/dfg.js +29 -3
  43. package/dist/core/extractors/dfg.js.map +1 -1
  44. package/dist/core/extractors/imports.js +1 -1
  45. package/dist/core/extractors/imports.js.map +1 -1
  46. package/dist/core/extractors/runtime-registrations.js +1 -1
  47. package/dist/core/extractors/runtime-registrations.js.map +1 -1
  48. package/dist/core/extractors/types.js +1 -1
  49. package/dist/core/extractors/types.js.map +1 -1
  50. package/dist/core/parser.d.ts +1 -1
  51. package/dist/core/parser.d.ts.map +1 -1
  52. package/dist/graph/scope-graph.d.ts.map +1 -1
  53. package/dist/graph/scope-graph.js +1 -0
  54. package/dist/graph/scope-graph.js.map +1 -1
  55. package/dist/languages/plugins/bash.d.ts.map +1 -1
  56. package/dist/languages/plugins/bash.js +17 -0
  57. package/dist/languages/plugins/bash.js.map +1 -1
  58. package/dist/languages/registry.d.ts.map +1 -1
  59. package/dist/languages/registry.js +6 -0
  60. package/dist/languages/registry.js.map +1 -1
  61. package/dist/languages/types.d.ts +1 -1
  62. package/dist/languages/types.d.ts.map +1 -1
  63. package/dist/types/index.d.ts +9 -1
  64. package/dist/types/index.d.ts.map +1 -1
  65. package/dist/wasm/tree-sitter-tsx.wasm +0 -0
  66. package/package.json +2 -1
@@ -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,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;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,cAAc,EAAE,MAAM,EAAE,EACxB,YAAY,EAAE,MAAM,EAAE,GACrB,WAAW,CAQb;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,aAAa,EAub1C,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,WAAW,EA22CtC,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,gBAAgB,EAiPhD,CAAC;AAEF;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,WAAW,CAM9C;AAMD;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,EAAE,UAAU,EA8F5C,CAAC"}
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,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;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,cAAc,EAAE,MAAM,EAAE,EACxB,YAAY,EAAE,MAAM,EAAE,GACrB,WAAW,CAQb;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,aAAa,EA2b1C,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,WAAW,EAk5CtC,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,gBAAgB,EAiPhD,CAAC;AAEF;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,WAAW,CAM9C;AAMD;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,EAAE,UAAU,EA8F5C,CAAC"}
@@ -341,8 +341,12 @@ export const DEFAULT_SOURCES = [
341
341
  { method: 'get', class: 'cookies', type: 'http_cookie', severity: 'high', return_tainted: true },
342
342
  { property: 'json', object: 'request', type: 'http_body', severity: 'high', property_tainted: true },
343
343
  { property: 'data', object: 'request', type: 'http_body', severity: 'high', property_tainted: true },
344
+ { property: 'stream', object: 'request', type: 'http_body', severity: 'high', property_tainted: true },
344
345
  { property: 'path', object: 'request', type: 'http_path', severity: 'medium', property_tainted: true },
345
346
  { property: 'query_string', object: 'request', type: 'http_query', severity: 'high', property_tainted: true },
347
+ // Flask request.get_data() — raw request bytes (method form, parallel to request.data property)
348
+ { method: 'get_data', class: 'request', type: 'http_body', severity: 'high', return_tainted: true },
349
+ { method: 'get_json', class: 'request', type: 'http_body', severity: 'high', return_tainted: true },
346
350
  // Django request object
347
351
  { method: 'get', class: 'GET', type: 'http_param', severity: 'high', return_tainted: true },
348
352
  { method: 'get', class: 'POST', type: 'http_param', severity: 'high', return_tainted: true },
@@ -554,14 +558,19 @@ export const DEFAULT_SINKS = [
554
558
  { method: 'setExecutable', class: 'ExecTask', type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
555
559
  { method: 'setCommand', class: 'ExecTask', type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
556
560
  { method: 'execute', class: 'Java', type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
557
- // Shell/Bash utilities
558
- { method: 'bash', type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
559
- { method: 'shell', type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
560
- { method: 'sh', type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
561
- { method: 'spawn', type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
562
- { method: 'fork', type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
563
- { method: 'popen', type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
564
- { method: 'system', type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
561
+ // Shell/Bash utilities — these are method-call sinks in host languages
562
+ // (Java Runtime/ProcessBuilder, JS child_process spawn/exec, Python subprocess, etc.).
563
+ // When the analyzed file IS a bash/shell script, the bash plugin's per-flag entries
564
+ // (argPositions: [1] for `bash -c <cmd>`) MUST win. Restrict these generic entries
565
+ // to non-shell languages so they don't collide on the dedup key
566
+ // `${location}:${call.location.line}:${pattern.cwe}`.
567
+ { method: 'bash', languages: ['java', 'javascript', 'typescript', 'python', 'go', 'rust'], type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
568
+ { method: 'shell', languages: ['java', 'javascript', 'typescript', 'python', 'go', 'rust'], type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
569
+ { method: 'sh', languages: ['java', 'javascript', 'typescript', 'python', 'go', 'rust'], type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
570
+ { method: 'spawn', languages: ['java', 'javascript', 'typescript', 'python', 'go', 'rust'], type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
571
+ { method: 'fork', languages: ['java', 'javascript', 'typescript', 'python', 'go', 'rust'], type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
572
+ { method: 'popen', languages: ['java', 'javascript', 'typescript', 'python', 'go', 'rust'], type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
573
+ { method: 'system', languages: ['java', 'javascript', 'typescript', 'python', 'go', 'rust'], type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
565
574
  // Apache Commons Exec
566
575
  // Note: bare class 'Executor' removed (see comment above) — DefaultExecutor matched explicitly.
567
576
  { method: 'setCommandline', class: 'DefaultExecutor', type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
@@ -651,6 +660,12 @@ export const DEFAULT_SINKS = [
651
660
  { method: 'unzip', type: 'path_traversal', cwe: 'CWE-22', severity: 'critical', arg_positions: [0, 1] },
652
661
  { method: 'extract', type: 'path_traversal', cwe: 'CWE-22', severity: 'critical', arg_positions: [0, 1] },
653
662
  { method: 'extractAll', type: 'path_traversal', cwe: 'CWE-22', severity: 'critical', arg_positions: [0, 1] },
663
+ // Python zipfile/tarfile use lowercase extractall (PEP 8 naming)
664
+ { method: 'extractall', type: 'path_traversal', cwe: 'CWE-22', severity: 'critical', arg_positions: [0], languages: ['python'] },
665
+ // Python zipfile.ZipFile(path) — tainted archive path enables Zip-Slip via malicious archive
666
+ { method: 'ZipFile', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0], languages: ['python'] },
667
+ // Flask send_from_directory: untrusted filename can escape directory via ../
668
+ { method: 'send_from_directory', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [1], languages: ['python'] },
654
669
  { method: 'unjar', type: 'path_traversal', cwe: 'CWE-22', severity: 'critical', arg_positions: [0, 1] },
655
670
  // Additional file constructors — BufferedReader(Reader) is NOT a path traversal sink; it wraps a Reader, not a file path
656
671
  { method: 'PrintWriter', class: 'constructor', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0] },
@@ -1734,16 +1749,42 @@ export const DEFAULT_SINKS = [
1734
1749
  // value position so a tainted variable is detected.
1735
1750
  { method: 'Set', class: 'Header', type: 'crlf', cwe: 'CWE-113', severity: 'medium', arg_positions: [1], languages: ['go'] },
1736
1751
  { method: 'Add', class: 'Header', type: 'crlf', cwe: 'CWE-113', severity: 'medium', arg_positions: [1], languages: ['go'] },
1737
- // Mass-assignment (CWE-915) — Sprint 6, #86.
1738
- // JS Object.assign(target, ...sources) — sources are arg 1..N, and if any
1739
- // source is request-tainted, every key gets written onto the target. We
1740
- // flag the source positions; the analyzer only needs one tainted to fire.
1741
- { method: 'assign', class: 'Object', type: 'mass_assignment', cwe: 'CWE-915', severity: 'high', arg_positions: [1, 2, 3], languages: ['javascript', 'typescript'] },
1742
- // Lodash bulk-merge helpers behave identically.
1743
- { method: 'merge', class: '_', type: 'mass_assignment', cwe: 'CWE-915', severity: 'high', arg_positions: [1, 2, 3], languages: ['javascript', 'typescript'] },
1744
- { method: 'extend', class: '_', type: 'mass_assignment', cwe: 'CWE-915', severity: 'high', arg_positions: [1, 2, 3], languages: ['javascript', 'typescript'] },
1752
+ // Mass-assignment (CWE-915 / CWE-1321) — Sprint 6, #86; cognium-dev #68 Sprint 10.
1753
+ // JS Object.assign(target, ...sources), `_.merge`, `_.extend`, `$.extend`,
1754
+ // `Object.defineProperty` when fed an attacker-controlled bag, they write
1755
+ // arbitrary keys onto the target (or, for `__proto__`/`constructor.prototype`,
1756
+ // pollute the prototype chain). The CWE is CWE-1321 (Prototype Pollution),
1757
+ // which subsumes mass assignment for JS sinks operating on plain Objects.
1758
+ // We keep the existing `mass_assignment` SinkType so consumers route the
1759
+ // findings the same way; only the CWE shifts to flag prototype-pollution.
1760
+ { method: 'assign', class: 'Object', type: 'mass_assignment', cwe: 'CWE-1321', severity: 'high', arg_positions: [1, 2, 3], languages: ['javascript', 'typescript'] },
1761
+ { method: 'defineProperty', class: 'Object', type: 'mass_assignment', cwe: 'CWE-1321', severity: 'high', arg_positions: [1, 2], languages: ['javascript', 'typescript'] },
1762
+ { method: 'defineProperties', class: 'Object', type: 'mass_assignment', cwe: 'CWE-1321', severity: 'high', arg_positions: [1], languages: ['javascript', 'typescript'] },
1763
+ // Lodash bulk-merge helpers behave identically. `_.merge` and `lodash.merge`
1764
+ // are aliases — match both receivers.
1765
+ { method: 'merge', class: '_', type: 'mass_assignment', cwe: 'CWE-1321', severity: 'high', arg_positions: [1, 2, 3], languages: ['javascript', 'typescript'] },
1766
+ { method: 'merge', class: 'lodash', type: 'mass_assignment', cwe: 'CWE-1321', severity: 'high', arg_positions: [1, 2, 3], languages: ['javascript', 'typescript'] },
1767
+ { method: 'extend', class: '_', type: 'mass_assignment', cwe: 'CWE-1321', severity: 'high', arg_positions: [1, 2, 3], languages: ['javascript', 'typescript'] },
1768
+ { method: 'extend', class: 'lodash', type: 'mass_assignment', cwe: 'CWE-1321', severity: 'high', arg_positions: [1, 2, 3], languages: ['javascript', 'typescript'] },
1769
+ { method: 'defaultsDeep', class: '_', type: 'mass_assignment', cwe: 'CWE-1321', severity: 'high', arg_positions: [1, 2, 3], languages: ['javascript', 'typescript'] },
1770
+ { method: 'defaultsDeep', class: 'lodash', type: 'mass_assignment', cwe: 'CWE-1321', severity: 'high', arg_positions: [1, 2, 3], languages: ['javascript', 'typescript'] },
1745
1771
  // jQuery $.extend(target, source) (legacy).
1746
- { method: 'extend', class: '$', type: 'mass_assignment', cwe: 'CWE-915', severity: 'high', arg_positions: [1, 2, 3], languages: ['javascript', 'typescript'] },
1772
+ { method: 'extend', class: '$', type: 'mass_assignment', cwe: 'CWE-1321', severity: 'high', arg_positions: [1, 2, 3], languages: ['javascript', 'typescript'] },
1773
+ { method: 'extend', class: 'jQuery', type: 'mass_assignment', cwe: 'CWE-1321', severity: 'high', arg_positions: [1, 2, 3], languages: ['javascript', 'typescript'] },
1774
+ // DOM-XSS via property assignment (CWE-79) — cognium-dev #68 Sprint 10.
1775
+ // `el.innerHTML = tainted` / `el.outerHTML = tainted`. The JS call extractor
1776
+ // emits a synthetic CallInfo with method=`innerHTML`/`outerHTML` for each
1777
+ // matching assignment_expression. These classless entries catch them.
1778
+ { method: 'innerHTML', type: 'xss', cwe: 'CWE-79', severity: 'critical', arg_positions: [0], languages: ['javascript', 'typescript'] },
1779
+ { method: 'outerHTML', type: 'xss', cwe: 'CWE-79', severity: 'critical', arg_positions: [0], languages: ['javascript', 'typescript'] },
1780
+ // node-serialize.unserialize (CWE-502) — cognium-dev #68 Sprint 10.
1781
+ // The node-serialize package evaluates `_$$ND_FUNC$$_` IIFE payloads on
1782
+ // decode, turning untrusted input into RCE. Match both receiver-bound
1783
+ // calls (`serialize.unserialize(x)`) and destructured imports
1784
+ // (`const { unserialize } = require('node-serialize')`).
1785
+ { method: 'unserialize', class: 'serialize', type: 'deserialization', cwe: 'CWE-502', severity: 'critical', arg_positions: [0], languages: ['javascript', 'typescript'] },
1786
+ { method: 'unserialize', class: 'node-serialize', type: 'deserialization', cwe: 'CWE-502', severity: 'critical', arg_positions: [0], languages: ['javascript', 'typescript'] },
1787
+ { method: 'unserialize', type: 'deserialization', cwe: 'CWE-502', severity: 'critical', arg_positions: [0], languages: ['javascript', 'typescript'] },
1747
1788
  ];
1748
1789
  export const DEFAULT_SANITIZERS = [
1749
1790
  // SQL Injection - proper parameter binding sanitizes input