cognium-dev 3.53.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 +145 -3
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -11134,7 +11134,36 @@ var DEFAULT_SINKS = [
|
|
|
11134
11134
|
{ method: "from_str", class: "serde_yaml", type: "deserialization", cwe: "CWE-502", severity: "high", arg_positions: [0] },
|
|
11135
11135
|
{ method: "from_reader", class: "serde_yaml", type: "deserialization", cwe: "CWE-502", severity: "high", arg_positions: [0] },
|
|
11136
11136
|
{ method: "from_str", 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] }
|
|
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"] }
|
|
11138
11167
|
];
|
|
11139
11168
|
var DEFAULT_SANITIZERS = [
|
|
11140
11169
|
{ method: "setString", class: "PreparedStatement", removes: ["sql_injection"] },
|
|
@@ -21472,7 +21501,9 @@ var KNOWN_SINK_TYPES = new Set([
|
|
|
21472
21501
|
"xxe",
|
|
21473
21502
|
"deserialization",
|
|
21474
21503
|
"code_injection",
|
|
21475
|
-
"mybatis_mapper_call"
|
|
21504
|
+
"mybatis_mapper_call",
|
|
21505
|
+
"redos",
|
|
21506
|
+
"format_string"
|
|
21476
21507
|
]);
|
|
21477
21508
|
function checkSanitized(_fromLine, toLine, sinkType, sanitizersByLine) {
|
|
21478
21509
|
const sanitizersAtTarget = sanitizersByLine.get(toLine);
|
|
@@ -28014,6 +28045,115 @@ class TlsVerifyDisabledPass {
|
|
|
28014
28045
|
}
|
|
28015
28046
|
}
|
|
28016
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
|
+
|
|
28017
28157
|
// ../circle-ir/dist/graph/import-graph.js
|
|
28018
28158
|
function dirname(filePath) {
|
|
28019
28159
|
const idx = filePath.lastIndexOf("/");
|
|
@@ -29134,6 +29274,8 @@ async function analyze(code, filePath, language, options = {}) {
|
|
|
29134
29274
|
pipeline.add(new WeakRandomPass);
|
|
29135
29275
|
if (!disabledPasses.has("tls-verify-disabled"))
|
|
29136
29276
|
pipeline.add(new TlsVerifyDisabledPass);
|
|
29277
|
+
if (!disabledPasses.has("jwt-verify-disabled"))
|
|
29278
|
+
pipeline.add(new JwtVerifyDisabledPass);
|
|
29137
29279
|
const { results, findings } = pipeline.run(graph, code, language, config);
|
|
29138
29280
|
const sinkFilter = results.get("sink-filter");
|
|
29139
29281
|
const interProc = results.get("interprocedural");
|
|
@@ -29327,7 +29469,7 @@ var colors = {
|
|
|
29327
29469
|
};
|
|
29328
29470
|
|
|
29329
29471
|
// src/version.ts
|
|
29330
|
-
var version = "3.
|
|
29472
|
+
var version = "3.54.0";
|
|
29331
29473
|
|
|
29332
29474
|
// src/formatters.ts
|
|
29333
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",
|