cognium-dev 3.52.0 → 3.54.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 +255 -12
- 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] },
|
|
@@ -11131,7 +11134,36 @@ var DEFAULT_SINKS = [
|
|
|
11131
11134
|
{ method: "from_str", class: "serde_yaml", type: "deserialization", cwe: "CWE-502", severity: "high", arg_positions: [0] },
|
|
11132
11135
|
{ method: "from_reader", class: "serde_yaml", type: "deserialization", cwe: "CWE-502", severity: "high", arg_positions: [0] },
|
|
11133
11136
|
{ method: "from_str", class: "serde_json", type: "deserialization", cwe: "CWE-502", severity: "medium", arg_positions: [0] },
|
|
11134
|
-
{ method: "from_slice", class: "serde_json", type: "deserialization", cwe: "CWE-502", severity: "medium", arg_positions: [0] }
|
|
11137
|
+
{ method: "from_slice", class: "serde_json", type: "deserialization", cwe: "CWE-502", severity: "medium", arg_positions: [0] },
|
|
11138
|
+
{ method: "match", class: "re", type: "redos", cwe: "CWE-1333", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
11139
|
+
{ method: "search", class: "re", type: "redos", cwe: "CWE-1333", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
11140
|
+
{ method: "fullmatch", class: "re", type: "redos", cwe: "CWE-1333", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
11141
|
+
{ method: "compile", class: "re", type: "redos", cwe: "CWE-1333", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
11142
|
+
{ method: "findall", class: "re", type: "redos", cwe: "CWE-1333", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
11143
|
+
{ method: "finditer", class: "re", type: "redos", cwe: "CWE-1333", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
11144
|
+
{ method: "sub", class: "re", type: "redos", cwe: "CWE-1333", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
11145
|
+
{ method: "subn", class: "re", type: "redos", cwe: "CWE-1333", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
11146
|
+
{ method: "split", class: "re", type: "redos", cwe: "CWE-1333", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
11147
|
+
{ method: "compile", class: "Pattern", type: "redos", cwe: "CWE-1333", severity: "high", arg_positions: [0], languages: ["java"] },
|
|
11148
|
+
{ method: "matches", class: "Pattern", type: "redos", cwe: "CWE-1333", severity: "high", arg_positions: [0], languages: ["java"] },
|
|
11149
|
+
{ method: "matches", class: "String", type: "redos", cwe: "CWE-1333", severity: "high", arg_positions: [0], languages: ["java"] },
|
|
11150
|
+
{ method: "replaceAll", class: "String", type: "redos", cwe: "CWE-1333", severity: "high", arg_positions: [0], languages: ["java"] },
|
|
11151
|
+
{ method: "replaceFirst", class: "String", type: "redos", cwe: "CWE-1333", severity: "high", arg_positions: [0], languages: ["java"] },
|
|
11152
|
+
{ method: "split", class: "String", type: "redos", cwe: "CWE-1333", severity: "high", arg_positions: [0], languages: ["java"] },
|
|
11153
|
+
{ method: "RegExp", class: "constructor", type: "redos", cwe: "CWE-1333", severity: "high", arg_positions: [0], languages: ["javascript", "typescript"] },
|
|
11154
|
+
{ method: "Compile", class: "regexp", type: "redos", cwe: "CWE-1333", severity: "medium", arg_positions: [0], languages: ["go"] },
|
|
11155
|
+
{ method: "MustCompile", class: "regexp", type: "redos", cwe: "CWE-1333", severity: "medium", arg_positions: [0], languages: ["go"] },
|
|
11156
|
+
{ method: "Match", class: "regexp", type: "redos", cwe: "CWE-1333", severity: "medium", arg_positions: [0], languages: ["go"] },
|
|
11157
|
+
{ method: "MatchString", class: "regexp", type: "redos", cwe: "CWE-1333", severity: "medium", arg_positions: [0], languages: ["go"] },
|
|
11158
|
+
{ method: "format", class: "String", type: "format_string", cwe: "CWE-134", severity: "high", arg_positions: [0], languages: ["java"] },
|
|
11159
|
+
{ method: "format", class: "Formatter", type: "format_string", cwe: "CWE-134", severity: "high", arg_positions: [0], languages: ["java"] },
|
|
11160
|
+
{ method: "printf", class: "System.out", type: "format_string", cwe: "CWE-134", severity: "high", arg_positions: [0], languages: ["java"] },
|
|
11161
|
+
{ method: "printf", type: "format_string", cwe: "CWE-134", severity: "high", arg_positions: [0], languages: ["python"] },
|
|
11162
|
+
{ method: "fprintf", type: "format_string", cwe: "CWE-134", severity: "high", arg_positions: [1], languages: ["python"] },
|
|
11163
|
+
{ method: "Sprintf", class: "fmt", type: "format_string", cwe: "CWE-134", severity: "medium", arg_positions: [0], languages: ["go"] },
|
|
11164
|
+
{ method: "Printf", class: "fmt", type: "format_string", cwe: "CWE-134", severity: "medium", arg_positions: [0], languages: ["go"] },
|
|
11165
|
+
{ method: "Errorf", class: "fmt", type: "format_string", cwe: "CWE-134", severity: "medium", arg_positions: [0], languages: ["go"] },
|
|
11166
|
+
{ method: "Fprintf", class: "fmt", type: "format_string", cwe: "CWE-134", severity: "medium", arg_positions: [1], languages: ["go"] }
|
|
11135
11167
|
];
|
|
11136
11168
|
var DEFAULT_SANITIZERS = [
|
|
11137
11169
|
{ method: "setString", class: "PreparedStatement", removes: ["sql_injection"] },
|
|
@@ -11716,10 +11748,9 @@ function matchesSourcePattern(call, pattern) {
|
|
|
11716
11748
|
return false;
|
|
11717
11749
|
}
|
|
11718
11750
|
if (pattern.class && pattern.class !== "constructor") {
|
|
11719
|
-
if (!call.receiver) {
|
|
11751
|
+
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
11752
|
return false;
|
|
11721
|
-
}
|
|
11722
|
-
if (!receiverMightBeClass(call.receiver, pattern.class)) {
|
|
11753
|
+
} else if (!receiverMightBeClass(call.receiver, pattern.class)) {
|
|
11723
11754
|
return false;
|
|
11724
11755
|
}
|
|
11725
11756
|
}
|
|
@@ -11969,13 +12000,12 @@ function matchesSinkPattern(call, pattern, typeHierarchy, language) {
|
|
|
11969
12000
|
if (pattern.class === "constructor") {
|
|
11970
12001
|
return true;
|
|
11971
12002
|
}
|
|
11972
|
-
if (call.receiver && !receiverMightBeClass(call.receiver, pattern.class)) {
|
|
12003
|
+
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
12004
|
if (typeHierarchy && typeHierarchy.couldBeType(call.receiver, pattern.class)) {
|
|
11974
12005
|
return true;
|
|
11975
12006
|
}
|
|
11976
12007
|
return false;
|
|
11977
|
-
}
|
|
11978
|
-
if (!call.receiver) {
|
|
12008
|
+
} else if (!call.receiver && !call.receiver_type) {
|
|
11979
12009
|
return false;
|
|
11980
12010
|
}
|
|
11981
12011
|
}
|
|
@@ -21471,7 +21501,9 @@ var KNOWN_SINK_TYPES = new Set([
|
|
|
21471
21501
|
"xxe",
|
|
21472
21502
|
"deserialization",
|
|
21473
21503
|
"code_injection",
|
|
21474
|
-
"mybatis_mapper_call"
|
|
21504
|
+
"mybatis_mapper_call",
|
|
21505
|
+
"redos",
|
|
21506
|
+
"format_string"
|
|
21475
21507
|
]);
|
|
21476
21508
|
function checkSanitized(_fromLine, toLine, sinkType, sanitizersByLine) {
|
|
21477
21509
|
const sanitizersAtTarget = sanitizersByLine.get(toLine);
|
|
@@ -27422,6 +27454,61 @@ function literalAlgo2(call, position) {
|
|
|
27422
27454
|
const cleaned = stripQuotes5(raw);
|
|
27423
27455
|
return cleaned || null;
|
|
27424
27456
|
}
|
|
27457
|
+
function detectStaticIvJava(call) {
|
|
27458
|
+
const arg = call.arguments.find((a) => a.position === 0);
|
|
27459
|
+
if (!arg)
|
|
27460
|
+
return null;
|
|
27461
|
+
const expr = (arg.literal ?? arg.expression ?? "").trim();
|
|
27462
|
+
if (!expr)
|
|
27463
|
+
return null;
|
|
27464
|
+
if (/^new\s+byte\s*\[[^\]]*\]\s*$/.test(expr)) {
|
|
27465
|
+
return `zero-filled ${expr}`;
|
|
27466
|
+
}
|
|
27467
|
+
if (/^new\s+byte\s*\[\s*\]\s*\{[^}]*\}\s*$/.test(expr)) {
|
|
27468
|
+
return `literal byte[] initializer`;
|
|
27469
|
+
}
|
|
27470
|
+
if (/^"[^"]*"\.getBytes\s*\(/.test(expr)) {
|
|
27471
|
+
return `literal string .getBytes()`;
|
|
27472
|
+
}
|
|
27473
|
+
if (/^"[^"]*"$/.test(expr)) {
|
|
27474
|
+
return `literal string`;
|
|
27475
|
+
}
|
|
27476
|
+
return null;
|
|
27477
|
+
}
|
|
27478
|
+
function isJavaCtor(call, className) {
|
|
27479
|
+
if (call.is_constructor === true)
|
|
27480
|
+
return true;
|
|
27481
|
+
if (call.receiver)
|
|
27482
|
+
return false;
|
|
27483
|
+
if (call.receiver_type === className)
|
|
27484
|
+
return true;
|
|
27485
|
+
if ((call.receiver_type_fqn ?? "").endsWith("." + className))
|
|
27486
|
+
return true;
|
|
27487
|
+
return false;
|
|
27488
|
+
}
|
|
27489
|
+
function detectHardcodedKeyJava(call) {
|
|
27490
|
+
const arg = call.arguments.find((a) => a.position === 0);
|
|
27491
|
+
if (!arg)
|
|
27492
|
+
return null;
|
|
27493
|
+
const expr = (arg.literal ?? arg.expression ?? "").trim();
|
|
27494
|
+
if (!expr)
|
|
27495
|
+
return null;
|
|
27496
|
+
if (/^"[^"]*"\.getBytes\s*\(/.test(expr))
|
|
27497
|
+
return `literal string .getBytes()`;
|
|
27498
|
+
if (/^new\s+byte\s*\[\s*\]\s*\{[^}]*\}\s*$/.test(expr))
|
|
27499
|
+
return `literal byte[] initializer`;
|
|
27500
|
+
if (/^"[^"]*"$/.test(expr))
|
|
27501
|
+
return `literal string`;
|
|
27502
|
+
return null;
|
|
27503
|
+
}
|
|
27504
|
+
var ISSUE_CWE = {
|
|
27505
|
+
"weak-cipher": "CWE-327",
|
|
27506
|
+
"ecb-mode": "CWE-327",
|
|
27507
|
+
"deprecated-api": "CWE-327",
|
|
27508
|
+
"static-iv": "CWE-329",
|
|
27509
|
+
"hardcoded-key": "CWE-321",
|
|
27510
|
+
"weak-rsa-key": "CWE-326"
|
|
27511
|
+
};
|
|
27425
27512
|
|
|
27426
27513
|
class WeakCryptoPass {
|
|
27427
27514
|
name = "weak-crypto";
|
|
@@ -27441,13 +27528,13 @@ class WeakCryptoPass {
|
|
|
27441
27528
|
pass: this.name,
|
|
27442
27529
|
category: this.category,
|
|
27443
27530
|
rule_id: this.name,
|
|
27444
|
-
cwe:
|
|
27531
|
+
cwe: ISSUE_CWE[det.issue],
|
|
27445
27532
|
severity: "high",
|
|
27446
27533
|
level: "error",
|
|
27447
27534
|
message,
|
|
27448
27535
|
file,
|
|
27449
27536
|
line,
|
|
27450
|
-
fix:
|
|
27537
|
+
fix: this.buildFix(det.issue),
|
|
27451
27538
|
evidence: { ...det, language }
|
|
27452
27539
|
});
|
|
27453
27540
|
}
|
|
@@ -27462,10 +27549,28 @@ class WeakCryptoPass {
|
|
|
27462
27549
|
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
27550
|
case "deprecated-api":
|
|
27464
27551
|
return `Deprecated crypto API \`${det.api}\` used (no IV: \`${det.detail}\`). ` + "This API derives the key/IV from a password in an insecure way.";
|
|
27552
|
+
case "static-iv":
|
|
27553
|
+
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.";
|
|
27554
|
+
case "hardcoded-key":
|
|
27555
|
+
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.";
|
|
27556
|
+
case "weak-rsa-key":
|
|
27557
|
+
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
27558
|
default:
|
|
27466
27559
|
return `Weak cryptography: ${det.detail} (${det.api})`;
|
|
27467
27560
|
}
|
|
27468
27561
|
}
|
|
27562
|
+
buildFix(issue) {
|
|
27563
|
+
switch (issue) {
|
|
27564
|
+
case "static-iv":
|
|
27565
|
+
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.";
|
|
27566
|
+
case "hardcoded-key":
|
|
27567
|
+
return "Load the key from a secure key management system (HSM, KMS, " + "Vault) or platform keystore. Never embed key material in source code.";
|
|
27568
|
+
case "weak-rsa-key":
|
|
27569
|
+
return "Initialize KeyPairGenerator with at least 2048 bits (preferably " + "3072 or 4096) for RSA, or switch to EC keys (P-256+).";
|
|
27570
|
+
default:
|
|
27571
|
+
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.";
|
|
27572
|
+
}
|
|
27573
|
+
}
|
|
27469
27574
|
detect(call, language) {
|
|
27470
27575
|
const method = call.method_name;
|
|
27471
27576
|
const receiver = call.receiver ?? "";
|
|
@@ -27483,6 +27588,33 @@ class WeakCryptoPass {
|
|
|
27483
27588
|
out2.push({ issue: "ecb-mode", detail: spec, api });
|
|
27484
27589
|
}
|
|
27485
27590
|
}
|
|
27591
|
+
if (method === "IvParameterSpec" && isJavaCtor(call, "IvParameterSpec")) {
|
|
27592
|
+
const ivDetail = detectStaticIvJava(call);
|
|
27593
|
+
if (ivDetail) {
|
|
27594
|
+
out2.push({ issue: "static-iv", detail: ivDetail, api: "new IvParameterSpec" });
|
|
27595
|
+
}
|
|
27596
|
+
}
|
|
27597
|
+
if (method === "SecretKeySpec" && isJavaCtor(call, "SecretKeySpec")) {
|
|
27598
|
+
const keyDetail = detectHardcodedKeyJava(call);
|
|
27599
|
+
if (keyDetail) {
|
|
27600
|
+
out2.push({ issue: "hardcoded-key", detail: keyDetail, api: "new SecretKeySpec" });
|
|
27601
|
+
}
|
|
27602
|
+
}
|
|
27603
|
+
if (method === "initialize") {
|
|
27604
|
+
const isKpg = call.receiver_type === "KeyPairGenerator" || (call.receiver_type_fqn ?? "").endsWith(".KeyPairGenerator");
|
|
27605
|
+
if (isKpg) {
|
|
27606
|
+
const sizeArg = call.arguments.find((a) => a.position === 0);
|
|
27607
|
+
const expr = (sizeArg?.literal ?? sizeArg?.expression ?? "").trim();
|
|
27608
|
+
const n = parseInt(expr, 10);
|
|
27609
|
+
if (Number.isFinite(n) && n > 0 && n < 2048) {
|
|
27610
|
+
out2.push({
|
|
27611
|
+
issue: "weak-rsa-key",
|
|
27612
|
+
detail: String(n),
|
|
27613
|
+
api: "KeyPairGenerator.initialize"
|
|
27614
|
+
});
|
|
27615
|
+
}
|
|
27616
|
+
}
|
|
27617
|
+
}
|
|
27486
27618
|
return out2;
|
|
27487
27619
|
}
|
|
27488
27620
|
if (language === "python") {
|
|
@@ -27913,6 +28045,115 @@ class TlsVerifyDisabledPass {
|
|
|
27913
28045
|
}
|
|
27914
28046
|
}
|
|
27915
28047
|
|
|
28048
|
+
// ../circle-ir/dist/analysis/passes/jwt-verify-disabled-pass.js
|
|
28049
|
+
var PY_VERIFY_SIGNATURE_FALSE_RE = /["']verify_signature["']\s*:\s*False\b/;
|
|
28050
|
+
var PY_VERIFY_KW_FALSE_RE = /\bverify\s*=\s*False\b/;
|
|
28051
|
+
var PY_ALG_NONE_RE = /\balgorithms\s*=\s*[\[\(]\s*["']none["']/i;
|
|
28052
|
+
var JS_ALG_NONE_RE = /\balgorithms\s*:\s*\[\s*["']none["']/i;
|
|
28053
|
+
|
|
28054
|
+
class JwtVerifyDisabledPass {
|
|
28055
|
+
name = "jwt-verify-disabled";
|
|
28056
|
+
category = "security";
|
|
28057
|
+
run(ctx) {
|
|
28058
|
+
const { graph, language } = ctx;
|
|
28059
|
+
const file = graph.ir.meta.file;
|
|
28060
|
+
const findings = [];
|
|
28061
|
+
for (const call of graph.ir.calls) {
|
|
28062
|
+
const detections = this.detect(call, language);
|
|
28063
|
+
for (const det of detections) {
|
|
28064
|
+
const line = call.location.line;
|
|
28065
|
+
findings.push({ line, language, ...det });
|
|
28066
|
+
ctx.addFinding({
|
|
28067
|
+
id: `${this.name}-${file}-${line}-${det.pattern}`,
|
|
28068
|
+
pass: this.name,
|
|
28069
|
+
category: this.category,
|
|
28070
|
+
rule_id: this.name,
|
|
28071
|
+
cwe: "CWE-347",
|
|
28072
|
+
severity: "critical",
|
|
28073
|
+
level: "error",
|
|
28074
|
+
message: `JWT signature verification disabled via \`${det.pattern}\` in ` + `\`${det.api}\`. Any attacker can forge a token with arbitrary ` + "claims (user id, roles, expiry) since the signature is not " + "checked.",
|
|
28075
|
+
file,
|
|
28076
|
+
line,
|
|
28077
|
+
fix: this.fixFor(language),
|
|
28078
|
+
evidence: { ...det, language }
|
|
28079
|
+
});
|
|
28080
|
+
}
|
|
28081
|
+
}
|
|
28082
|
+
return { findings };
|
|
28083
|
+
}
|
|
28084
|
+
detect(call, language) {
|
|
28085
|
+
const method = call.method_name;
|
|
28086
|
+
const receiver = call.receiver ?? "";
|
|
28087
|
+
const out2 = [];
|
|
28088
|
+
if (language === "python") {
|
|
28089
|
+
if (receiver === "jwt" && method === "decode") {
|
|
28090
|
+
for (const arg of call.arguments) {
|
|
28091
|
+
const expr = (arg.expression ?? "").trim();
|
|
28092
|
+
if (!expr)
|
|
28093
|
+
continue;
|
|
28094
|
+
if (PY_VERIFY_SIGNATURE_FALSE_RE.test(expr)) {
|
|
28095
|
+
out2.push({ pattern: "verify_signature: False", api: "jwt.decode" });
|
|
28096
|
+
}
|
|
28097
|
+
if (PY_VERIFY_KW_FALSE_RE.test(expr)) {
|
|
28098
|
+
out2.push({ pattern: "verify=False", api: "jwt.decode" });
|
|
28099
|
+
}
|
|
28100
|
+
if (PY_ALG_NONE_RE.test(expr)) {
|
|
28101
|
+
out2.push({ pattern: "algorithms=['none']", api: "jwt.decode" });
|
|
28102
|
+
}
|
|
28103
|
+
}
|
|
28104
|
+
}
|
|
28105
|
+
return out2;
|
|
28106
|
+
}
|
|
28107
|
+
if (language === "javascript" || language === "typescript") {
|
|
28108
|
+
if (receiver === "jwt" && method === "verify") {
|
|
28109
|
+
for (const arg of call.arguments) {
|
|
28110
|
+
const expr = (arg.expression ?? "").trim();
|
|
28111
|
+
if (!expr)
|
|
28112
|
+
continue;
|
|
28113
|
+
if (JS_ALG_NONE_RE.test(expr)) {
|
|
28114
|
+
out2.push({ pattern: "algorithms: ['none']", api: "jwt.verify" });
|
|
28115
|
+
}
|
|
28116
|
+
if (/\bverify\s*:\s*false\b/i.test(expr)) {
|
|
28117
|
+
out2.push({ pattern: "verify: false", api: "jwt.verify" });
|
|
28118
|
+
}
|
|
28119
|
+
}
|
|
28120
|
+
const keyArg = call.arguments.find((a) => a.position === 1);
|
|
28121
|
+
const keyExpr = (keyArg?.expression ?? keyArg?.literal ?? "").trim();
|
|
28122
|
+
if (keyExpr === "null" || keyExpr === "undefined" || keyExpr === '""' || keyExpr === "''" || keyExpr === "``") {
|
|
28123
|
+
out2.push({ pattern: `empty key (${keyExpr || "missing"})`, api: "jwt.verify" });
|
|
28124
|
+
}
|
|
28125
|
+
}
|
|
28126
|
+
return out2;
|
|
28127
|
+
}
|
|
28128
|
+
if (language === "java") {
|
|
28129
|
+
if (method === "require" && (receiver === "JWT" || receiver.endsWith(".JWT"))) {
|
|
28130
|
+
const arg = call.arguments.find((a) => a.position === 0);
|
|
28131
|
+
const expr = (arg?.expression ?? "").trim();
|
|
28132
|
+
if (/\bAlgorithm\s*\.\s*none\s*\(/.test(expr)) {
|
|
28133
|
+
out2.push({ pattern: "Algorithm.none()", api: "JWT.require" });
|
|
28134
|
+
}
|
|
28135
|
+
}
|
|
28136
|
+
if (method === "parse" && receiver.includes("parser")) {
|
|
28137
|
+
out2.push({ pattern: "parse() instead of parseClaimsJws()", api: "Jwts.parser().parse" });
|
|
28138
|
+
}
|
|
28139
|
+
return out2;
|
|
28140
|
+
}
|
|
28141
|
+
return out2;
|
|
28142
|
+
}
|
|
28143
|
+
fixFor(language) {
|
|
28144
|
+
if (language === "python") {
|
|
28145
|
+
return 'Always pass `options={"verify_signature": True}` (the default in ' + 'PyJWT 2.0+) and a concrete `algorithms=["HS256"|"RS256"]` list. ' + "Never accept `none`.";
|
|
28146
|
+
}
|
|
28147
|
+
if (language === "javascript" || language === "typescript") {
|
|
28148
|
+
return 'Call `jwt.verify(token, secret, { algorithms: ["HS256" | "RS256"] })` ' + 'with a non-empty key. Never use `algorithms: ["none"]` or pass ' + "null/empty as the secret.";
|
|
28149
|
+
}
|
|
28150
|
+
if (language === "java") {
|
|
28151
|
+
return "For auth0/java-jwt: use `JWT.require(Algorithm.HMAC256(secret))` or " + "an RSA algorithm. For jjwt: call `parseClaimsJws(token)` (signature " + "enforced) rather than `parse(token)` (signature ignored).";
|
|
28152
|
+
}
|
|
28153
|
+
return "Enforce JWT signature verification with a concrete algorithm " + "(HS256/RS256/ES256). Never accept `alg: none`.";
|
|
28154
|
+
}
|
|
28155
|
+
}
|
|
28156
|
+
|
|
27916
28157
|
// ../circle-ir/dist/graph/import-graph.js
|
|
27917
28158
|
function dirname(filePath) {
|
|
27918
28159
|
const idx = filePath.lastIndexOf("/");
|
|
@@ -29033,6 +29274,8 @@ async function analyze(code, filePath, language, options = {}) {
|
|
|
29033
29274
|
pipeline.add(new WeakRandomPass);
|
|
29034
29275
|
if (!disabledPasses.has("tls-verify-disabled"))
|
|
29035
29276
|
pipeline.add(new TlsVerifyDisabledPass);
|
|
29277
|
+
if (!disabledPasses.has("jwt-verify-disabled"))
|
|
29278
|
+
pipeline.add(new JwtVerifyDisabledPass);
|
|
29036
29279
|
const { results, findings } = pipeline.run(graph, code, language, config);
|
|
29037
29280
|
const sinkFilter = results.get("sink-filter");
|
|
29038
29281
|
const interProc = results.get("interprocedural");
|
|
@@ -29226,7 +29469,7 @@ var colors = {
|
|
|
29226
29469
|
};
|
|
29227
29470
|
|
|
29228
29471
|
// src/version.ts
|
|
29229
|
-
var version = "3.
|
|
29472
|
+
var version = "3.54.0";
|
|
29230
29473
|
|
|
29231
29474
|
// src/formatters.ts
|
|
29232
29475
|
var SINK_SEVERITY = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cognium-dev",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.54.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.54.0"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
71
|
"@types/node": "^25.5.0",
|