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.
- package/dist/cli.js +211 -1
- 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.
|
|
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.
|
|
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.
|
|
68
|
+
"circle-ir": "^3.47.0"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
71
|
"@types/node": "^25.5.0",
|