cognium-dev 4.6.0 → 4.7.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 +106 -4
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -12332,7 +12332,7 @@ var DEFAULT_SINKS = [
|
|
|
12332
12332
|
{ method: "ExecuteScalarAsync", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
|
|
12333
12333
|
{ method: "ExecuteReaderAsync", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
|
|
12334
12334
|
{ method: "ExecuteNonQueryAsync", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
|
|
12335
|
-
{ method: "Start", class: "Process", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0], languages: ["csharp"] },
|
|
12335
|
+
{ method: "Start", class: "Process", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0, 1], languages: ["csharp"] },
|
|
12336
12336
|
{ method: "ProcessStartInfo", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0, 1], languages: ["csharp"] },
|
|
12337
12337
|
{ method: "ReadAllText", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12338
12338
|
{ method: "ReadAllBytes", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
@@ -12366,6 +12366,11 @@ var DEFAULT_SINKS = [
|
|
|
12366
12366
|
{ method: "HtmlString", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12367
12367
|
{ method: "DirectorySearcher", type: "ldap_injection", cwe: "CWE-90", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12368
12368
|
{ method: "DirectoryEntry", type: "ldap_injection", cwe: "CWE-90", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12369
|
+
{ method: "Redirect", type: "open_redirect", cwe: "CWE-601", severity: "medium", arg_positions: [0], languages: ["csharp"] },
|
|
12370
|
+
{ method: "RedirectPermanent", type: "open_redirect", cwe: "CWE-601", severity: "medium", arg_positions: [0], languages: ["csharp"] },
|
|
12371
|
+
{ method: "AddHeader", type: "crlf", cwe: "CWE-113", severity: "medium", arg_positions: [1], languages: ["csharp"] },
|
|
12372
|
+
{ method: "AppendHeader", type: "crlf", cwe: "CWE-113", severity: "medium", arg_positions: [1], languages: ["csharp"] },
|
|
12373
|
+
{ method: "Parse", class: "BsonDocument", type: "nosql_injection", cwe: "CWE-943", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12369
12374
|
{ method: "SelectSingleNode", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12370
12375
|
{ method: "SelectNodes", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12371
12376
|
{ method: "Compile", class: "XPathExpression", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
@@ -25638,12 +25643,13 @@ function findCSharpRequestSources(sourceCode, language) {
|
|
|
25638
25643
|
const assignRe = /^\s*(?:var\s+|[A-Za-z_][\w.<>\[\]]*\s+)?([A-Za-z_]\w*)\s*=\s*(.+?);?\s*$/;
|
|
25639
25644
|
const requestReadRe = /\bRequest\s*\.\s*(?:Query|Form|Headers|Cookies|QueryString|RouteValues|Body|Files|Params)\b/;
|
|
25640
25645
|
const consoleReadRe = /\bConsole\s*\.\s*ReadLine\s*\(/;
|
|
25646
|
+
const envReadRe = /\bEnvironment\s*\.\s*GetEnvironmentVariables?\s*(?:\(|\[)/;
|
|
25641
25647
|
for (let i2 = 0;i2 < lines.length; i2++) {
|
|
25642
25648
|
const m = assignRe.exec(lines[i2]);
|
|
25643
25649
|
if (!m)
|
|
25644
25650
|
continue;
|
|
25645
25651
|
const [, varName, rhs] = m;
|
|
25646
|
-
const type = requestReadRe.test(rhs) ? "http_param" : consoleReadRe.test(rhs) ? "io_input" : null;
|
|
25652
|
+
const type = requestReadRe.test(rhs) ? "http_param" : consoleReadRe.test(rhs) ? "io_input" : envReadRe.test(rhs) ? "env_input" : null;
|
|
25647
25653
|
if (!type)
|
|
25648
25654
|
continue;
|
|
25649
25655
|
const lineNumber = i2 + 1;
|
|
@@ -33360,7 +33366,10 @@ class SinkFilterPass {
|
|
|
33360
33366
|
const sourceLines = ctx.code.split(`
|
|
33361
33367
|
`);
|
|
33362
33368
|
const sanitizedByType = csharpSanitizedVarsByType(ctx.code);
|
|
33369
|
+
const xxeHardened = /\bXmlResolver\s*=\s*null\b/.test(ctx.code) || /\bDtdProcessing\s*=\s*(?:DtdProcessing\s*\.\s*)?(?:Prohibit|Ignore)\b/.test(ctx.code);
|
|
33363
33370
|
filtered = filtered.filter((sink) => {
|
|
33371
|
+
if (sink.type === "xxe" && xxeHardened)
|
|
33372
|
+
return false;
|
|
33364
33373
|
const sinkLineText = sourceLines[sink.line - 1] ?? "";
|
|
33365
33374
|
for (const { re, type } of CSHARP_SANITIZER_RES) {
|
|
33366
33375
|
if (type === sink.type && re.test(sinkLineText))
|
|
@@ -37234,6 +37243,8 @@ function isPublicMethod(method, language) {
|
|
|
37234
37243
|
switch (language) {
|
|
37235
37244
|
case "java":
|
|
37236
37245
|
return method.modifiers.includes("public");
|
|
37246
|
+
case "csharp":
|
|
37247
|
+
return method.modifiers.includes("public");
|
|
37237
37248
|
case "javascript":
|
|
37238
37249
|
case "typescript":
|
|
37239
37250
|
case "tsx":
|
|
@@ -37256,7 +37267,7 @@ class MissingPublicDocPass {
|
|
|
37256
37267
|
if (UTIL_DIR_RE.test(graph.ir.meta.file)) {
|
|
37257
37268
|
return { missingDocMethods: [], missingDocTypes: [] };
|
|
37258
37269
|
}
|
|
37259
|
-
if (!["java", "javascript", "typescript", "tsx", "python"].includes(language)) {
|
|
37270
|
+
if (!["java", "javascript", "typescript", "tsx", "python", "csharp"].includes(language)) {
|
|
37260
37271
|
return { missingDocMethods: [], missingDocTypes: [] };
|
|
37261
37272
|
}
|
|
37262
37273
|
const lines = code.split(`
|
|
@@ -42231,6 +42242,30 @@ var WEAK_HASH_NAMES = new Set([
|
|
|
42231
42242
|
"sha-1",
|
|
42232
42243
|
"sha1"
|
|
42233
42244
|
]);
|
|
42245
|
+
var CSHARP_WEAK_HASH_CLASSES = new Set(["MD5", "SHA1"]);
|
|
42246
|
+
var CSHARP_HASH_FACTORY_RECEIVERS = new Set([
|
|
42247
|
+
"HashAlgorithm",
|
|
42248
|
+
"KeyedHashAlgorithm",
|
|
42249
|
+
"HMAC",
|
|
42250
|
+
"CryptoConfig"
|
|
42251
|
+
]);
|
|
42252
|
+
var CSHARP_WEAK_HASH_CTORS = {
|
|
42253
|
+
MD5CryptoServiceProvider: "md5",
|
|
42254
|
+
MD5Cng: "md5",
|
|
42255
|
+
SHA1CryptoServiceProvider: "sha1",
|
|
42256
|
+
SHA1Managed: "sha1",
|
|
42257
|
+
SHA1Cng: "sha1",
|
|
42258
|
+
HMACMD5: "md5",
|
|
42259
|
+
HMACSHA1: "sha1"
|
|
42260
|
+
};
|
|
42261
|
+
function csharpWeakHashAlgo(cleaned) {
|
|
42262
|
+
if (!cleaned)
|
|
42263
|
+
return null;
|
|
42264
|
+
const base = (cleaned.split(".").pop() ?? cleaned).replace(/^hmac/, "");
|
|
42265
|
+
if (base === "sha")
|
|
42266
|
+
return "sha1";
|
|
42267
|
+
return WEAK_HASH_NAMES.has(base) ? base : null;
|
|
42268
|
+
}
|
|
42234
42269
|
var COMMONS_DIGEST_METHODS = new Set([
|
|
42235
42270
|
"md2",
|
|
42236
42271
|
"md2Hex",
|
|
@@ -42401,6 +42436,20 @@ class WeakHashPass {
|
|
|
42401
42436
|
}
|
|
42402
42437
|
return null;
|
|
42403
42438
|
}
|
|
42439
|
+
if (language === "csharp") {
|
|
42440
|
+
if ((method === "Create" || method === "HashData") && CSHARP_WEAK_HASH_CLASSES.has(receiver)) {
|
|
42441
|
+
return { algorithm: receiver.toLowerCase(), api: `${receiver}.${method}` };
|
|
42442
|
+
}
|
|
42443
|
+
if ((method === "Create" || method === "CreateFromName") && CSHARP_HASH_FACTORY_RECEIVERS.has(receiver)) {
|
|
42444
|
+
const algo = csharpWeakHashAlgo(literalAlgo(call, 0));
|
|
42445
|
+
if (algo)
|
|
42446
|
+
return { algorithm: algo, api: `${receiver}.${method}` };
|
|
42447
|
+
}
|
|
42448
|
+
if (call.is_constructor && CSHARP_WEAK_HASH_CTORS[method]) {
|
|
42449
|
+
return { algorithm: CSHARP_WEAK_HASH_CTORS[method], api: `new ${method}()` };
|
|
42450
|
+
}
|
|
42451
|
+
return null;
|
|
42452
|
+
}
|
|
42404
42453
|
return null;
|
|
42405
42454
|
}
|
|
42406
42455
|
}
|
|
@@ -42457,6 +42506,30 @@ var WEAK_CIPHER_BASES = new Set([
|
|
|
42457
42506
|
"seed",
|
|
42458
42507
|
"cast5"
|
|
42459
42508
|
]);
|
|
42509
|
+
var CSHARP_WEAK_CIPHER_CLASSES = new Set(["DES", "TripleDES", "RC2", "RC4"]);
|
|
42510
|
+
var CSHARP_CIPHER_FACTORY_RECEIVERS = new Set(["SymmetricAlgorithm", "CryptoConfig"]);
|
|
42511
|
+
var CSHARP_WEAK_CIPHER_CTORS = {
|
|
42512
|
+
DESCryptoServiceProvider: "des",
|
|
42513
|
+
TripleDESCryptoServiceProvider: "3des",
|
|
42514
|
+
RC2CryptoServiceProvider: "rc2"
|
|
42515
|
+
};
|
|
42516
|
+
var CSHARP_RSA_FACTORY_CLASSES = new Set(["RSA", "DSA"]);
|
|
42517
|
+
var CSHARP_RSA_CTORS = new Set([
|
|
42518
|
+
"RSACryptoServiceProvider",
|
|
42519
|
+
"DSACryptoServiceProvider",
|
|
42520
|
+
"RSACng",
|
|
42521
|
+
"DSACng"
|
|
42522
|
+
]);
|
|
42523
|
+
function csharpWeakCipher(cleaned) {
|
|
42524
|
+
if (!cleaned)
|
|
42525
|
+
return null;
|
|
42526
|
+
const base = (cleaned.split(".").pop() ?? cleaned).toLowerCase();
|
|
42527
|
+
if (base === "tripledes" || base === "desede")
|
|
42528
|
+
return "3des";
|
|
42529
|
+
if (base === "arc4")
|
|
42530
|
+
return "rc4";
|
|
42531
|
+
return WEAK_CIPHER_BASES.has(base) ? base : null;
|
|
42532
|
+
}
|
|
42460
42533
|
function classifyJavaCipherSpec(spec) {
|
|
42461
42534
|
const parts2 = spec.split("/").map((p) => p.trim().toLowerCase());
|
|
42462
42535
|
const base = parts2[0] ?? "";
|
|
@@ -42880,6 +42953,35 @@ class WeakCryptoPass {
|
|
|
42880
42953
|
}
|
|
42881
42954
|
return out2;
|
|
42882
42955
|
}
|
|
42956
|
+
if (language === "csharp") {
|
|
42957
|
+
if (method === "Create" && CSHARP_WEAK_CIPHER_CLASSES.has(receiver)) {
|
|
42958
|
+
const base = receiver === "TripleDES" ? "3des" : receiver.toLowerCase();
|
|
42959
|
+
out2.push({ issue: "weak-cipher", detail: base, api: `${receiver}.Create` });
|
|
42960
|
+
}
|
|
42961
|
+
if ((method === "Create" || method === "CreateFromName") && CSHARP_CIPHER_FACTORY_RECEIVERS.has(receiver)) {
|
|
42962
|
+
const base = csharpWeakCipher(literalAlgo2(call, 0));
|
|
42963
|
+
if (base)
|
|
42964
|
+
out2.push({ issue: "weak-cipher", detail: base, api: `${receiver}.${method}` });
|
|
42965
|
+
}
|
|
42966
|
+
if (call.is_constructor && CSHARP_WEAK_CIPHER_CTORS[method]) {
|
|
42967
|
+
out2.push({ issue: "weak-cipher", detail: CSHARP_WEAK_CIPHER_CTORS[method], api: `new ${method}()` });
|
|
42968
|
+
}
|
|
42969
|
+
const rsaFactory = method === "Create" && CSHARP_RSA_FACTORY_CLASSES.has(receiver);
|
|
42970
|
+
const rsaCtor = call.is_constructor && CSHARP_RSA_CTORS.has(method);
|
|
42971
|
+
if (rsaFactory || rsaCtor) {
|
|
42972
|
+
const sizeArg = call.arguments.find((a) => a.position === 0);
|
|
42973
|
+
const expr = (sizeArg?.literal ?? sizeArg?.expression ?? "").trim();
|
|
42974
|
+
const n = parseInt(expr, 10);
|
|
42975
|
+
if (Number.isFinite(n) && n > 0 && n < 2048) {
|
|
42976
|
+
out2.push({
|
|
42977
|
+
issue: "weak-rsa-key",
|
|
42978
|
+
detail: String(n),
|
|
42979
|
+
api: rsaCtor ? `new ${method}()` : `${receiver}.Create`
|
|
42980
|
+
});
|
|
42981
|
+
}
|
|
42982
|
+
}
|
|
42983
|
+
return out2;
|
|
42984
|
+
}
|
|
42883
42985
|
return out2;
|
|
42884
42986
|
}
|
|
42885
42987
|
}
|
|
@@ -47900,7 +48002,7 @@ var colors = {
|
|
|
47900
48002
|
};
|
|
47901
48003
|
|
|
47902
48004
|
// src/version.ts
|
|
47903
|
-
var version = "4.
|
|
48005
|
+
var version = "4.7.0";
|
|
47904
48006
|
|
|
47905
48007
|
// src/formatters.ts
|
|
47906
48008
|
var LIBRARY_API_SURFACE_TAG2 = "library-api-surface:caller-responsibility";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cognium-dev",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.7.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",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
},
|
|
67
67
|
"dependencies": {
|
|
68
68
|
"@cognium/project-profile-detect": "^1.1.0",
|
|
69
|
-
"circle-ir": "^4.
|
|
69
|
+
"circle-ir": "^4.7.0"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@types/node": "^25.5.0",
|