cognium-dev 3.52.0 → 3.53.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 +111 -10
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -10043,6 +10043,10 @@ var DEFAULT_SOURCES = [
|
|
|
10043
10043
|
{ method: "getFileName", class: "BodyPart", type: "file_input", severity: "high", return_tainted: true },
|
|
10044
10044
|
{ method: "getFileName", class: "MimeBodyPart", type: "file_input", severity: "high", return_tainted: true },
|
|
10045
10045
|
{ method: "getDisposition", class: "Part", type: "file_input", severity: "medium", return_tainted: true },
|
|
10046
|
+
{ method: "getName", class: "ZipEntry", type: "file_input", severity: "high", return_tainted: true },
|
|
10047
|
+
{ method: "getName", class: "ZipArchiveEntry", type: "file_input", severity: "high", return_tainted: true },
|
|
10048
|
+
{ method: "getName", class: "TarArchiveEntry", type: "file_input", severity: "high", return_tainted: true },
|
|
10049
|
+
{ method: "getName", class: "ArchiveEntry", type: "file_input", severity: "high", return_tainted: true },
|
|
10046
10050
|
{ method: "getArgs", type: "io_input", severity: "high", return_tainted: true },
|
|
10047
10051
|
{ method: "getOptionValue", class: "CommandLine", type: "io_input", severity: "high", return_tainted: true },
|
|
10048
10052
|
{ method: "url", class: "Request", type: "http_path", severity: "high", return_tainted: true },
|
|
@@ -10380,7 +10384,6 @@ var DEFAULT_SINKS = [
|
|
|
10380
10384
|
{ method: "externalStaticFileLocation", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10381
10385
|
{ method: "staticFileLocation", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10382
10386
|
{ method: "getEntry", class: "ZipFile", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10383
|
-
{ method: "getName", class: "ZipEntry", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [] },
|
|
10384
10387
|
{ method: "ClassPathResource", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10385
10388
|
{ method: "FileSystemResource", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10386
10389
|
{ method: "UrlResource", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
@@ -11716,10 +11719,9 @@ function matchesSourcePattern(call, pattern) {
|
|
|
11716
11719
|
return false;
|
|
11717
11720
|
}
|
|
11718
11721
|
if (pattern.class && pattern.class !== "constructor") {
|
|
11719
|
-
if (!call.receiver) {
|
|
11722
|
+
if (call.receiver_type && call.receiver_type === pattern.class) {} else if (call.receiver_type_fqn && call.receiver_type_fqn.endsWith("." + pattern.class)) {} else if (!call.receiver) {
|
|
11720
11723
|
return false;
|
|
11721
|
-
}
|
|
11722
|
-
if (!receiverMightBeClass(call.receiver, pattern.class)) {
|
|
11724
|
+
} else if (!receiverMightBeClass(call.receiver, pattern.class)) {
|
|
11723
11725
|
return false;
|
|
11724
11726
|
}
|
|
11725
11727
|
}
|
|
@@ -11969,13 +11971,12 @@ function matchesSinkPattern(call, pattern, typeHierarchy, language) {
|
|
|
11969
11971
|
if (pattern.class === "constructor") {
|
|
11970
11972
|
return true;
|
|
11971
11973
|
}
|
|
11972
|
-
if (call.receiver && !receiverMightBeClass(call.receiver, pattern.class)) {
|
|
11974
|
+
if (call.receiver_type && call.receiver_type === pattern.class) {} else if (call.receiver_type_fqn && call.receiver_type_fqn.endsWith("." + pattern.class)) {} else if (call.receiver && !receiverMightBeClass(call.receiver, pattern.class)) {
|
|
11973
11975
|
if (typeHierarchy && typeHierarchy.couldBeType(call.receiver, pattern.class)) {
|
|
11974
11976
|
return true;
|
|
11975
11977
|
}
|
|
11976
11978
|
return false;
|
|
11977
|
-
}
|
|
11978
|
-
if (!call.receiver) {
|
|
11979
|
+
} else if (!call.receiver && !call.receiver_type) {
|
|
11979
11980
|
return false;
|
|
11980
11981
|
}
|
|
11981
11982
|
}
|
|
@@ -27422,6 +27423,61 @@ function literalAlgo2(call, position) {
|
|
|
27422
27423
|
const cleaned = stripQuotes5(raw);
|
|
27423
27424
|
return cleaned || null;
|
|
27424
27425
|
}
|
|
27426
|
+
function detectStaticIvJava(call) {
|
|
27427
|
+
const arg = call.arguments.find((a) => a.position === 0);
|
|
27428
|
+
if (!arg)
|
|
27429
|
+
return null;
|
|
27430
|
+
const expr = (arg.literal ?? arg.expression ?? "").trim();
|
|
27431
|
+
if (!expr)
|
|
27432
|
+
return null;
|
|
27433
|
+
if (/^new\s+byte\s*\[[^\]]*\]\s*$/.test(expr)) {
|
|
27434
|
+
return `zero-filled ${expr}`;
|
|
27435
|
+
}
|
|
27436
|
+
if (/^new\s+byte\s*\[\s*\]\s*\{[^}]*\}\s*$/.test(expr)) {
|
|
27437
|
+
return `literal byte[] initializer`;
|
|
27438
|
+
}
|
|
27439
|
+
if (/^"[^"]*"\.getBytes\s*\(/.test(expr)) {
|
|
27440
|
+
return `literal string .getBytes()`;
|
|
27441
|
+
}
|
|
27442
|
+
if (/^"[^"]*"$/.test(expr)) {
|
|
27443
|
+
return `literal string`;
|
|
27444
|
+
}
|
|
27445
|
+
return null;
|
|
27446
|
+
}
|
|
27447
|
+
function isJavaCtor(call, className) {
|
|
27448
|
+
if (call.is_constructor === true)
|
|
27449
|
+
return true;
|
|
27450
|
+
if (call.receiver)
|
|
27451
|
+
return false;
|
|
27452
|
+
if (call.receiver_type === className)
|
|
27453
|
+
return true;
|
|
27454
|
+
if ((call.receiver_type_fqn ?? "").endsWith("." + className))
|
|
27455
|
+
return true;
|
|
27456
|
+
return false;
|
|
27457
|
+
}
|
|
27458
|
+
function detectHardcodedKeyJava(call) {
|
|
27459
|
+
const arg = call.arguments.find((a) => a.position === 0);
|
|
27460
|
+
if (!arg)
|
|
27461
|
+
return null;
|
|
27462
|
+
const expr = (arg.literal ?? arg.expression ?? "").trim();
|
|
27463
|
+
if (!expr)
|
|
27464
|
+
return null;
|
|
27465
|
+
if (/^"[^"]*"\.getBytes\s*\(/.test(expr))
|
|
27466
|
+
return `literal string .getBytes()`;
|
|
27467
|
+
if (/^new\s+byte\s*\[\s*\]\s*\{[^}]*\}\s*$/.test(expr))
|
|
27468
|
+
return `literal byte[] initializer`;
|
|
27469
|
+
if (/^"[^"]*"$/.test(expr))
|
|
27470
|
+
return `literal string`;
|
|
27471
|
+
return null;
|
|
27472
|
+
}
|
|
27473
|
+
var ISSUE_CWE = {
|
|
27474
|
+
"weak-cipher": "CWE-327",
|
|
27475
|
+
"ecb-mode": "CWE-327",
|
|
27476
|
+
"deprecated-api": "CWE-327",
|
|
27477
|
+
"static-iv": "CWE-329",
|
|
27478
|
+
"hardcoded-key": "CWE-321",
|
|
27479
|
+
"weak-rsa-key": "CWE-326"
|
|
27480
|
+
};
|
|
27425
27481
|
|
|
27426
27482
|
class WeakCryptoPass {
|
|
27427
27483
|
name = "weak-crypto";
|
|
@@ -27441,13 +27497,13 @@ class WeakCryptoPass {
|
|
|
27441
27497
|
pass: this.name,
|
|
27442
27498
|
category: this.category,
|
|
27443
27499
|
rule_id: this.name,
|
|
27444
|
-
cwe:
|
|
27500
|
+
cwe: ISSUE_CWE[det.issue],
|
|
27445
27501
|
severity: "high",
|
|
27446
27502
|
level: "error",
|
|
27447
27503
|
message,
|
|
27448
27504
|
file,
|
|
27449
27505
|
line,
|
|
27450
|
-
fix:
|
|
27506
|
+
fix: this.buildFix(det.issue),
|
|
27451
27507
|
evidence: { ...det, language }
|
|
27452
27508
|
});
|
|
27453
27509
|
}
|
|
@@ -27462,10 +27518,28 @@ class WeakCryptoPass {
|
|
|
27462
27518
|
return `ECB block-cipher mode used via \`${det.api}\` (\`${det.detail}\`). ` + "ECB leaks plaintext structure (identical blocks → identical ciphertext) " + "and is not semantically secure.";
|
|
27463
27519
|
case "deprecated-api":
|
|
27464
27520
|
return `Deprecated crypto API \`${det.api}\` used (no IV: \`${det.detail}\`). ` + "This API derives the key/IV from a password in an insecure way.";
|
|
27521
|
+
case "static-iv":
|
|
27522
|
+
return `Static or zero-valued IV passed to \`${det.api}\` (\`${det.detail}\`). ` + "Reusing a fixed IV with CBC/CTR/GCM breaks confidentiality and, for " + "GCM, can leak the authentication key.";
|
|
27523
|
+
case "hardcoded-key":
|
|
27524
|
+
return `Hardcoded symmetric key material passed to \`${det.api}\` (\`${det.detail}\`). ` + "Keys embedded in source code are trivially recoverable from binaries " + "and shared across deployments — they provide no confidentiality.";
|
|
27525
|
+
case "weak-rsa-key":
|
|
27526
|
+
return `Weak RSA key size \`${det.detail}\` requested via \`${det.api}\`. ` + "RSA keys below 2048 bits are factorable and not compliant with " + "NIST SP 800-57 / FIPS 186-5.";
|
|
27465
27527
|
default:
|
|
27466
27528
|
return `Weak cryptography: ${det.detail} (${det.api})`;
|
|
27467
27529
|
}
|
|
27468
27530
|
}
|
|
27531
|
+
buildFix(issue) {
|
|
27532
|
+
switch (issue) {
|
|
27533
|
+
case "static-iv":
|
|
27534
|
+
return "Generate a fresh random IV per message using SecureRandom: " + "`byte[] iv = new byte[12]; SecureRandom.getInstanceStrong().nextBytes(iv); " + "new IvParameterSpec(iv);` and prepend it to the ciphertext.";
|
|
27535
|
+
case "hardcoded-key":
|
|
27536
|
+
return "Load the key from a secure key management system (HSM, KMS, " + "Vault) or platform keystore. Never embed key material in source code.";
|
|
27537
|
+
case "weak-rsa-key":
|
|
27538
|
+
return "Initialize KeyPairGenerator with at least 2048 bits (preferably " + "3072 or 4096) for RSA, or switch to EC keys (P-256+).";
|
|
27539
|
+
default:
|
|
27540
|
+
return "Use AES-GCM (authenticated) or ChaCha20-Poly1305. Avoid DES, " + "3DES, RC2, RC4, Blowfish, and ECB mode. For asymmetric encryption " + "use RSA-OAEP with ≥2048-bit keys or modern curve-based schemes.";
|
|
27541
|
+
}
|
|
27542
|
+
}
|
|
27469
27543
|
detect(call, language) {
|
|
27470
27544
|
const method = call.method_name;
|
|
27471
27545
|
const receiver = call.receiver ?? "";
|
|
@@ -27483,6 +27557,33 @@ class WeakCryptoPass {
|
|
|
27483
27557
|
out2.push({ issue: "ecb-mode", detail: spec, api });
|
|
27484
27558
|
}
|
|
27485
27559
|
}
|
|
27560
|
+
if (method === "IvParameterSpec" && isJavaCtor(call, "IvParameterSpec")) {
|
|
27561
|
+
const ivDetail = detectStaticIvJava(call);
|
|
27562
|
+
if (ivDetail) {
|
|
27563
|
+
out2.push({ issue: "static-iv", detail: ivDetail, api: "new IvParameterSpec" });
|
|
27564
|
+
}
|
|
27565
|
+
}
|
|
27566
|
+
if (method === "SecretKeySpec" && isJavaCtor(call, "SecretKeySpec")) {
|
|
27567
|
+
const keyDetail = detectHardcodedKeyJava(call);
|
|
27568
|
+
if (keyDetail) {
|
|
27569
|
+
out2.push({ issue: "hardcoded-key", detail: keyDetail, api: "new SecretKeySpec" });
|
|
27570
|
+
}
|
|
27571
|
+
}
|
|
27572
|
+
if (method === "initialize") {
|
|
27573
|
+
const isKpg = call.receiver_type === "KeyPairGenerator" || (call.receiver_type_fqn ?? "").endsWith(".KeyPairGenerator");
|
|
27574
|
+
if (isKpg) {
|
|
27575
|
+
const sizeArg = call.arguments.find((a) => a.position === 0);
|
|
27576
|
+
const expr = (sizeArg?.literal ?? sizeArg?.expression ?? "").trim();
|
|
27577
|
+
const n = parseInt(expr, 10);
|
|
27578
|
+
if (Number.isFinite(n) && n > 0 && n < 2048) {
|
|
27579
|
+
out2.push({
|
|
27580
|
+
issue: "weak-rsa-key",
|
|
27581
|
+
detail: String(n),
|
|
27582
|
+
api: "KeyPairGenerator.initialize"
|
|
27583
|
+
});
|
|
27584
|
+
}
|
|
27585
|
+
}
|
|
27586
|
+
}
|
|
27486
27587
|
return out2;
|
|
27487
27588
|
}
|
|
27488
27589
|
if (language === "python") {
|
|
@@ -29226,7 +29327,7 @@ var colors = {
|
|
|
29226
29327
|
};
|
|
29227
29328
|
|
|
29228
29329
|
// src/version.ts
|
|
29229
|
-
var version = "3.
|
|
29330
|
+
var version = "3.53.0";
|
|
29230
29331
|
|
|
29231
29332
|
// src/formatters.ts
|
|
29232
29333
|
var SINK_SEVERITY = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cognium-dev",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.53.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.53.0"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
71
|
"@types/node": "^25.5.0",
|