circle-ir 3.47.0 → 3.49.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 (53) hide show
  1. package/dist/analysis/config-loader.d.ts.map +1 -1
  2. package/dist/analysis/config-loader.js +86 -2
  3. package/dist/analysis/config-loader.js.map +1 -1
  4. package/dist/analysis/constant-propagation/index.d.ts.map +1 -1
  5. package/dist/analysis/constant-propagation/index.js +16 -6
  6. package/dist/analysis/constant-propagation/index.js.map +1 -1
  7. package/dist/analysis/constant-propagation/propagator.d.ts +7 -0
  8. package/dist/analysis/constant-propagation/propagator.d.ts.map +1 -1
  9. package/dist/analysis/constant-propagation/propagator.js +81 -41
  10. package/dist/analysis/constant-propagation/propagator.js.map +1 -1
  11. package/dist/analysis/html/html-attribute-security-pass.js +14 -9
  12. package/dist/analysis/html/html-attribute-security-pass.js.map +1 -1
  13. package/dist/analysis/html/html-extractor.d.ts.map +1 -1
  14. package/dist/analysis/html/html-extractor.js +16 -11
  15. package/dist/analysis/html/html-extractor.js.map +1 -1
  16. package/dist/analysis/passes/insecure-cookie-pass.d.ts +53 -0
  17. package/dist/analysis/passes/insecure-cookie-pass.d.ts.map +1 -0
  18. package/dist/analysis/passes/insecure-cookie-pass.js +109 -0
  19. package/dist/analysis/passes/insecure-cookie-pass.js.map +1 -0
  20. package/dist/analysis/passes/interprocedural-pass.d.ts.map +1 -1
  21. package/dist/analysis/passes/interprocedural-pass.js +7 -0
  22. package/dist/analysis/passes/interprocedural-pass.js.map +1 -1
  23. package/dist/analysis/passes/language-sources-pass.d.ts +14 -0
  24. package/dist/analysis/passes/language-sources-pass.d.ts.map +1 -1
  25. package/dist/analysis/passes/language-sources-pass.js +50 -0
  26. package/dist/analysis/passes/language-sources-pass.js.map +1 -1
  27. package/dist/analysis/passes/sink-filter-pass.d.ts.map +1 -1
  28. package/dist/analysis/passes/sink-filter-pass.js +21 -2
  29. package/dist/analysis/passes/sink-filter-pass.js.map +1 -1
  30. package/dist/analysis/passes/taint-propagation-pass.js +94 -3
  31. package/dist/analysis/passes/taint-propagation-pass.js.map +1 -1
  32. package/dist/analysis/taint-matcher.d.ts.map +1 -1
  33. package/dist/analysis/taint-matcher.js +117 -20
  34. package/dist/analysis/taint-matcher.js.map +1 -1
  35. package/dist/analyzer.d.ts.map +1 -1
  36. package/dist/analyzer.js +3 -0
  37. package/dist/analyzer.js.map +1 -1
  38. package/dist/browser/circle-ir.js +453 -99
  39. package/dist/core/circle-ir-core.cjs +251 -64
  40. package/dist/core/circle-ir-core.js +251 -64
  41. package/dist/core/extractors/types.js +85 -2
  42. package/dist/core/extractors/types.js.map +1 -1
  43. package/dist/core/parser.d.ts +10 -0
  44. package/dist/core/parser.d.ts.map +1 -1
  45. package/dist/core/parser.js +20 -5
  46. package/dist/core/parser.js.map +1 -1
  47. package/dist/languages/plugins/base.d.ts.map +1 -1
  48. package/dist/languages/plugins/base.js +15 -11
  49. package/dist/languages/plugins/base.js.map +1 -1
  50. package/dist/languages/plugins/java.d.ts.map +1 -1
  51. package/dist/languages/plugins/java.js +8 -4
  52. package/dist/languages/plugins/java.js.map +1 -1
  53. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/analysis/constant-propagation/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,KAAK,EAAE,wBAAwB,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAC;AAIvF,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,wBAAwB,EAAE,0BAA0B,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGtI,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAGlG,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAG3G,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErD;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,IAAI,EACV,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,0BAA+B,GACvC,wBAAwB,CAS1B;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,wBAAwB,EAChC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB;IAAE,eAAe,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAsBrD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,wBAAwB,EAChC,IAAI,EAAE;IAAE,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAAC,IAAI,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,GAC1G,OAAO,CA2CT"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/analysis/constant-propagation/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,KAAK,EAAE,wBAAwB,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAC;AAIvF,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,wBAAwB,EAAE,0BAA0B,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGtI,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAGlG,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAG3G,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErD;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,IAAI,EACV,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,0BAA+B,GACvC,wBAAwB,CAS1B;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,wBAAwB,EAChC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB;IAAE,eAAe,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAgCrD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,wBAAwB,EAChC,IAAI,EAAE;IAAE,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAAC,IAAI,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,GAC1G,OAAO,CA2CT"}
@@ -44,12 +44,22 @@ export function isFalsePositive(result, sinkLine, taintedVar) {
44
44
  if (varValue && varValue.type !== 'unknown' && !result.tainted.has(taintedVar)) {
45
45
  return { isFalsePositive: true, reason: `variable_is_constant: ${varValue.value}` };
46
46
  }
47
- // Reason 3: Variable not tainted
48
- // Only apply this check when constant propagation actually tracked symbols.
49
- // When the symbols map is empty (e.g. JavaScript code where the constant propagation
50
- // engine doesn't process variable declarations), we can't conclude anything about
51
- // taint status return false to avoid suppressing real flows.
52
- if (result.symbols.size > 0 && !result.tainted.has(taintedVar)) {
47
+ // Reason 3: Variable not tainted.
48
+ //
49
+ // Only fire when const-prop *specifically* tracked this variable (it's in
50
+ // the symbols map) AND didn't mark it tainted. Using `symbols.size > 0` as
51
+ // a proxy for "const-prop ran" is brittle: in JavaScript, the engine
52
+ // doesn't process arrow-function-scoped `const c = ...` declarations, so
53
+ // request-handler locals never appear in symbols — but a single unrelated
54
+ // top-level assignment like `module.exports = app` adds `module.exports`
55
+ // to symbols, flips size from 0 to 1, and then incorrectly flags every
56
+ // flow path variable as `variable_not_tainted`. This silently zeroed JS
57
+ // taint analysis on any realistic multi-handler Express file
58
+ // (cognium-dev#77).
59
+ //
60
+ // Switching to `symbols.has(taintedVar)` is strictly tighter: we only
61
+ // suppress when we actually tracked the var and concluded it's clean.
62
+ if (result.symbols.has(taintedVar) && !result.tainted.has(taintedVar)) {
53
63
  return { isFalsePositive: true, reason: 'variable_not_tainted' };
54
64
  }
55
65
  return { isFalsePositive: false, reason: null };
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/analysis/constant-propagation/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/analysis/constant-propagation/index.ts"],"names":[],"mappings":"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"}
@@ -84,6 +84,12 @@ export declare class ConstantPropagator {
84
84
  private getMethodName;
85
85
  private refineTaintFromConstants;
86
86
  private visit;
87
+ /**
88
+ * Visit a single node. Returns true if the handler already descended into
89
+ * children (and the caller should NOT push them), false to fall through to
90
+ * the default pre-order descent.
91
+ */
92
+ private visitOne;
87
93
  /**
88
94
  * Handle method declarations - scope local variables to this method.
89
95
  * This prevents local variables from one method bleeding into another.
@@ -176,6 +182,7 @@ export declare class ConstantPropagator {
176
182
  */
177
183
  private getTaintTypeForVariable;
178
184
  isTaintedExpression(node: Node): boolean;
185
+ private isTaintedExpressionStep;
179
186
  private checkCollectionTaint;
180
187
  }
181
188
  //# sourceMappingURL=propagator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"propagator.d.ts","sourceRoot":"","sources":["../../../src/analysis/constant-propagation/propagator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"propagator.d.ts","sourceRoot":"","sources":["../../../src/analysis/constant-propagation/propagator.ts"],"names":[],"mappings":"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"}
@@ -473,15 +473,19 @@ export class ConstantPropagator {
473
473
  * These are variables declared directly in the class body, not inside methods.
474
474
  */
475
475
  collectClassFields(root) {
476
- const traverse = (n, inClass, inMethod) => {
476
+ // Iterative DFS guards against stack overflow on deeply nested AST
477
+ // shapes such as `"a" + "b" + "c" + ...` chains in generated Java
478
+ // sources (cognium-ai#88). Only class_body direct children qualify
479
+ // as class fields; nested classes are still walked because their
480
+ // bodies are pushed onto the stack.
481
+ const stack = [root];
482
+ while (stack.length > 0) {
483
+ const n = stack.pop();
477
484
  if (!n)
478
- return;
479
- // Track when we enter a class body
485
+ continue;
480
486
  if (n.type === 'class_body') {
481
487
  for (const child of n.children) {
482
- // Field declarations are direct children of class_body
483
488
  if (child.type === 'field_declaration') {
484
- // Find the variable declarator(s) in this field declaration
485
489
  for (const declarator of child.children) {
486
490
  if (declarator.type === 'variable_declarator') {
487
491
  const nameNode = declarator.childForFieldName('name');
@@ -492,36 +496,32 @@ export class ConstantPropagator {
492
496
  }
493
497
  }
494
498
  }
495
- // Recurse into methods without marking them as fields
496
- if (child.type === 'method_declaration' || child.type === 'constructor_declaration') {
497
- traverse(child, true, true);
498
- }
499
- else {
500
- traverse(child, true, false);
501
- }
499
+ stack.push(child);
502
500
  }
503
- return;
501
+ continue;
504
502
  }
505
503
  for (const child of n.children) {
506
- traverse(child, inClass, inMethod);
504
+ stack.push(child);
507
505
  }
508
- };
509
- traverse(root, false, false);
506
+ }
510
507
  }
511
508
  findAllMethods(node) {
509
+ // Iterative DFS — guards against stack overflow on deeply nested AST
510
+ // shapes (cognium-ai#88).
512
511
  const methods = [];
513
- const traverse = (n) => {
512
+ const stack = [node];
513
+ while (stack.length > 0) {
514
+ const n = stack.pop();
514
515
  if (!n)
515
- return;
516
+ continue;
516
517
  if (n.type === 'method_declaration' || n.type === 'function_declaration') {
517
518
  methods.push(n);
518
519
  }
519
520
  for (const child of n.children) {
520
521
  if (child)
521
- traverse(child);
522
+ stack.push(child);
522
523
  }
523
- };
524
- traverse(node);
524
+ }
525
525
  return methods;
526
526
  }
527
527
  getMethodName(method) {
@@ -575,9 +575,33 @@ export class ConstantPropagator {
575
575
  // AST Visitor
576
576
  // ===========================================================================
577
577
  visit(node) {
578
+ // Iterative pre-order DFS with explicit stack — guards against stack
579
+ // overflow on pathological ASTs (e.g. 4500+ segment string concatenation
580
+ // chains in generated Java sources, cognium-ai#88).
581
+ //
582
+ // The structured handlers (method/if/switch/loop/synchronized) keep
583
+ // managing their own descent because their semantics depend on scope
584
+ // and control-flow ordering. For unhandled node types we push children
585
+ // onto our own stack instead of recursing.
586
+ const stack = [node];
587
+ while (stack.length > 0) {
588
+ const current = stack.pop();
589
+ if (this.visitOne(current))
590
+ continue; // handler took care of descent
591
+ for (let i = current.children.length - 1; i >= 0; i--) {
592
+ stack.push(current.children[i]);
593
+ }
594
+ }
595
+ }
596
+ /**
597
+ * Visit a single node. Returns true if the handler already descended into
598
+ * children (and the caller should NOT push them), false to fall through to
599
+ * the default pre-order descent.
600
+ */
601
+ visitOne(node) {
578
602
  const line = getNodeLine(node);
579
603
  if (this.unreachableLines.has(line)) {
580
- return;
604
+ return true; // skip subtree
581
605
  }
582
606
  // Track which condition this line is under for correlated predicate analysis
583
607
  if (this.conditionStack.length > 0 && !this.lineConditions.has(line)) {
@@ -588,42 +612,40 @@ export class ConstantPropagator {
588
612
  case 'method_declaration':
589
613
  case 'constructor_declaration':
590
614
  this.handleMethodDeclaration(node);
591
- return; // Don't visit children directly, handleMethodDeclaration does it
615
+ return true; // Don't visit children directly, handleMethodDeclaration does it
592
616
  case 'local_variable_declaration':
593
617
  this.handleVariableDeclaration(node);
594
- break;
618
+ return false;
595
619
  case 'assignment_expression':
596
620
  this.handleAssignment(node);
597
- break;
621
+ return false;
598
622
  case 'update_expression':
599
623
  this.handleUpdateExpression(node);
600
- break;
624
+ return false;
601
625
  case 'if_statement':
602
626
  this.handleIfStatement(node);
603
- return;
627
+ return true;
604
628
  case 'switch_expression':
605
629
  case 'switch_statement':
606
630
  this.handleSwitch(node);
607
- return;
631
+ return true;
608
632
  case 'ternary_expression':
609
633
  this.handleTernary(node);
610
- break;
634
+ return false;
611
635
  case 'expression_statement':
612
636
  this.handleExpressionStatement(node);
613
- break;
637
+ return false;
614
638
  case 'for_statement':
615
639
  case 'enhanced_for_statement':
616
640
  case 'while_statement':
617
641
  case 'do_statement':
618
642
  this.handleLoopStatement(node);
619
- return;
643
+ return true;
620
644
  case 'synchronized_statement':
621
645
  this.handleSynchronizedStatement(node);
622
- return;
646
+ return true;
623
647
  default:
624
- for (const child of node.children) {
625
- this.visit(child);
626
- }
648
+ return false;
627
649
  }
628
650
  }
629
651
  /**
@@ -1505,6 +1527,28 @@ export class ConstantPropagator {
1505
1527
  return null;
1506
1528
  }
1507
1529
  isTaintedExpression(node) {
1530
+ // Iterative wrapper that calls isTaintedExpressionStep per node.
1531
+ // The step returns true/false to short-circuit, or undefined to indicate
1532
+ // "descend into children". This guards against stack overflow on
1533
+ // pathological ASTs (cognium-ai#88). Internal recursive calls inside the
1534
+ // step method route back through this wrapper, so each one starts a fresh
1535
+ // explicit stack rather than blowing the JS call stack.
1536
+ const stack = [node];
1537
+ while (stack.length > 0) {
1538
+ const current = stack.pop();
1539
+ const result = this.isTaintedExpressionStep(current);
1540
+ if (result === true)
1541
+ return true;
1542
+ if (result === false)
1543
+ continue;
1544
+ // undefined → descend pre-order (children pushed right-to-left)
1545
+ for (let i = current.children.length - 1; i >= 0; i--) {
1546
+ stack.push(current.children[i]);
1547
+ }
1548
+ }
1549
+ return false;
1550
+ }
1551
+ isTaintedExpressionStep(node) {
1508
1552
  const text = getNodeText(node, this.source);
1509
1553
  if (node.type === 'method_invocation') {
1510
1554
  const nameNode = node.childForFieldName('name');
@@ -1813,12 +1857,8 @@ export class ConstantPropagator {
1813
1857
  }
1814
1858
  return isTainted;
1815
1859
  }
1816
- for (const child of node.children) {
1817
- if (this.isTaintedExpression(child)) {
1818
- return true;
1819
- }
1820
- }
1821
- return false;
1860
+ // No verdict at this node — let the wrapper descend into children.
1861
+ return undefined;
1822
1862
  }
1823
1863
  checkCollectionTaint(node) {
1824
1864
  const objectNode = node.childForFieldName('object');