cognium-dev 3.46.0 → 3.47.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 (2) hide show
  1. package/dist/cli.js +211 -1
  2. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -26547,6 +26547,214 @@ class ScanSecretsPass {
26547
26547
  }
26548
26548
  }
26549
26549
 
26550
+ // ../circle-ir/dist/analysis/passes/spring4shell-pass.js
26551
+ var CONTROLLER_ANNOTATIONS = new Set([
26552
+ "Controller",
26553
+ "RestController",
26554
+ "ControllerAdvice",
26555
+ "RestControllerAdvice"
26556
+ ]);
26557
+ var ROUTE_ANNOTATIONS = new Set([
26558
+ "RequestMapping",
26559
+ "GetMapping",
26560
+ "PostMapping",
26561
+ "PutMapping",
26562
+ "DeleteMapping",
26563
+ "PatchMapping"
26564
+ ]);
26565
+ var BINDING_ANNOTATIONS = new Set([
26566
+ "RequestBody",
26567
+ "RequestParam",
26568
+ "PathVariable",
26569
+ "RequestHeader",
26570
+ "CookieValue",
26571
+ "MatrixVariable",
26572
+ "ModelAttribute",
26573
+ "Valid",
26574
+ "Validated",
26575
+ "RequestPart",
26576
+ "SessionAttribute",
26577
+ "RequestAttribute"
26578
+ ]);
26579
+ var FRAMEWORK_PARAM_TYPES = new Set([
26580
+ "HttpServletRequest",
26581
+ "HttpServletResponse",
26582
+ "ServletRequest",
26583
+ "ServletResponse",
26584
+ "HttpSession",
26585
+ "ServletContext",
26586
+ "Cookie",
26587
+ "Model",
26588
+ "ModelMap",
26589
+ "ModelAndView",
26590
+ "Map",
26591
+ "BindingResult",
26592
+ "Errors",
26593
+ "RedirectAttributes",
26594
+ "SessionStatus",
26595
+ "WebRequest",
26596
+ "NativeWebRequest",
26597
+ "ServletWebRequest",
26598
+ "UriComponentsBuilder",
26599
+ "UriBuilder",
26600
+ "HttpEntity",
26601
+ "RequestEntity",
26602
+ "ResponseEntity",
26603
+ "HttpHeaders",
26604
+ "InputStream",
26605
+ "OutputStream",
26606
+ "Reader",
26607
+ "Writer",
26608
+ "ServerHttpRequest",
26609
+ "ServerHttpResponse",
26610
+ "ServerWebExchange",
26611
+ "Principal",
26612
+ "Authentication",
26613
+ "Locale",
26614
+ "TimeZone",
26615
+ "ZoneId",
26616
+ "MultipartFile",
26617
+ "Part",
26618
+ "TimeZone"
26619
+ ]);
26620
+ var SIMPLE_JAVA_TYPES = new Set([
26621
+ "boolean",
26622
+ "byte",
26623
+ "char",
26624
+ "short",
26625
+ "int",
26626
+ "long",
26627
+ "float",
26628
+ "double",
26629
+ "void",
26630
+ "Boolean",
26631
+ "Byte",
26632
+ "Character",
26633
+ "Short",
26634
+ "Integer",
26635
+ "Long",
26636
+ "Float",
26637
+ "Double",
26638
+ "String",
26639
+ "CharSequence",
26640
+ "BigInteger",
26641
+ "BigDecimal",
26642
+ "UUID",
26643
+ "Date",
26644
+ "Calendar",
26645
+ "Instant",
26646
+ "LocalDate",
26647
+ "LocalTime",
26648
+ "LocalDateTime",
26649
+ "OffsetDateTime",
26650
+ "OffsetTime",
26651
+ "ZonedDateTime",
26652
+ "Duration",
26653
+ "Period",
26654
+ "List",
26655
+ "Set",
26656
+ "Collection",
26657
+ "Iterable",
26658
+ "Optional"
26659
+ ]);
26660
+
26661
+ class Spring4ShellPass {
26662
+ name = "spring4shell";
26663
+ category = "security";
26664
+ run(ctx) {
26665
+ const { graph, language } = ctx;
26666
+ if (language !== "java") {
26667
+ return { controllerMethodsScanned: 0, findingsEmitted: 0 };
26668
+ }
26669
+ const file = graph.ir.meta.file;
26670
+ let scanned = 0;
26671
+ let emitted = 0;
26672
+ for (const type of graph.ir.types) {
26673
+ if (!isController(type))
26674
+ continue;
26675
+ for (const method of type.methods) {
26676
+ if (!isRouteHandler(method))
26677
+ continue;
26678
+ scanned++;
26679
+ for (const param of method.parameters) {
26680
+ if (!isVulnerableParameter(param))
26681
+ continue;
26682
+ ctx.addFinding({
26683
+ id: `${this.name}-${file}-${method.start_line}-${param.name}`,
26684
+ pass: this.name,
26685
+ category: this.category,
26686
+ rule_id: this.name,
26687
+ cwe: "CWE-94",
26688
+ severity: "high",
26689
+ level: "error",
26690
+ message: `Spring MVC controller method '${type.name}.${method.name}' binds parameter '${param.name}' of type '${param.type ?? "?"}' via implicit form-data binding (no @RequestBody / @RequestParam / @ModelAttribute) — vulnerable to Spring4Shell (CVE-2022-22965) class-graph RCE on Spring < 5.3.18 / 5.2.20`,
26691
+ file,
26692
+ line: param.line ?? method.start_line,
26693
+ fix: "Annotate the parameter with @RequestBody (JSON) or @ModelAttribute + @InitBinder/setAllowedFields whitelisting, upgrade Spring to ≥ 5.3.18 / 5.2.20, and ensure JDK is patched.",
26694
+ evidence: {
26695
+ controller_class: type.name,
26696
+ controller_annotations: type.annotations,
26697
+ method: method.name,
26698
+ method_annotations: method.annotations,
26699
+ parameter_name: param.name,
26700
+ parameter_type: param.type
26701
+ }
26702
+ });
26703
+ emitted++;
26704
+ }
26705
+ }
26706
+ }
26707
+ return { controllerMethodsScanned: scanned, findingsEmitted: emitted };
26708
+ }
26709
+ }
26710
+ function annotationHead(annotation) {
26711
+ const parenIdx = annotation.indexOf("(");
26712
+ return parenIdx >= 0 ? annotation.slice(0, parenIdx) : annotation;
26713
+ }
26714
+ function hasAnnotation(annotations, names) {
26715
+ for (const a of annotations) {
26716
+ if (names.has(annotationHead(a)))
26717
+ return true;
26718
+ }
26719
+ return false;
26720
+ }
26721
+ function isController(type) {
26722
+ return hasAnnotation(type.annotations, CONTROLLER_ANNOTATIONS);
26723
+ }
26724
+ function isRouteHandler(method) {
26725
+ return hasAnnotation(method.annotations, ROUTE_ANNOTATIONS);
26726
+ }
26727
+ function isVulnerableParameter(param) {
26728
+ if (hasAnnotation(param.annotations, BINDING_ANNOTATIONS))
26729
+ return false;
26730
+ if (!param.type)
26731
+ return false;
26732
+ const type = stripGenerics2(param.type).trim();
26733
+ if (!type)
26734
+ return false;
26735
+ if (type.endsWith("[]")) {
26736
+ const elem = type.slice(0, -2).trim();
26737
+ return !SIMPLE_JAVA_TYPES.has(elem) && isPotentialPojo(elem);
26738
+ }
26739
+ if (SIMPLE_JAVA_TYPES.has(type))
26740
+ return false;
26741
+ if (FRAMEWORK_PARAM_TYPES.has(type))
26742
+ return false;
26743
+ if (!isPotentialPojo(type))
26744
+ return false;
26745
+ return true;
26746
+ }
26747
+ function stripGenerics2(type) {
26748
+ const ltIdx = type.indexOf("<");
26749
+ return ltIdx >= 0 ? type.slice(0, ltIdx) : type;
26750
+ }
26751
+ function isPotentialPojo(type) {
26752
+ if (type.length === 0)
26753
+ return false;
26754
+ const first = type.charCodeAt(0);
26755
+ return first >= 65 && first <= 90;
26756
+ }
26757
+
26550
26758
  // ../circle-ir/dist/graph/import-graph.js
26551
26759
  function dirname(filePath) {
26552
26760
  const idx = filePath.lastIndexOf("/");
@@ -27655,6 +27863,8 @@ async function analyze(code, filePath, language, options = {}) {
27655
27863
  pipeline.add(new NamingConventionPass(passOpts.namingConvention));
27656
27864
  if (!disabledPasses.has("security-headers"))
27657
27865
  pipeline.add(new SecurityHeadersPass(passOpts.securityHeaders));
27866
+ if (!disabledPasses.has("spring4shell"))
27867
+ pipeline.add(new Spring4ShellPass);
27658
27868
  const { results, findings } = pipeline.run(graph, code, language, config);
27659
27869
  const sinkFilter = results.get("sink-filter");
27660
27870
  const interProc = results.get("interprocedural");
@@ -27848,7 +28058,7 @@ var colors = {
27848
28058
  };
27849
28059
 
27850
28060
  // src/version.ts
27851
- var version = "3.46.0";
28061
+ var version = "3.47.0";
27852
28062
 
27853
28063
  // src/formatters.ts
27854
28064
  var SINK_SEVERITY = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cognium-dev",
3
- "version": "3.46.0",
3
+ "version": "3.47.0",
4
4
  "description": "Static Application Security Testing CLI for detecting security vulnerabilities via taint tracking",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -65,7 +65,7 @@
65
65
  "registry": "https://registry.npmjs.org/"
66
66
  },
67
67
  "dependencies": {
68
- "circle-ir": "^3.46.0"
68
+ "circle-ir": "^3.47.0"
69
69
  },
70
70
  "devDependencies": {
71
71
  "@types/node": "^25.5.0",