cognium-dev 4.3.1 → 4.5.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 +81 -4
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -5268,6 +5268,14 @@ function findFirstDescendant(node, type) {
|
|
|
5268
5268
|
}
|
|
5269
5269
|
return null;
|
|
5270
5270
|
}
|
|
5271
|
+
var CSHARP_COMMAND_EXECUTE_METHODS = new Set([
|
|
5272
|
+
"ExecuteScalar",
|
|
5273
|
+
"ExecuteReader",
|
|
5274
|
+
"ExecuteNonQuery",
|
|
5275
|
+
"ExecuteScalarAsync",
|
|
5276
|
+
"ExecuteReaderAsync",
|
|
5277
|
+
"ExecuteNonQueryAsync"
|
|
5278
|
+
]);
|
|
5271
5279
|
function extractCSharpCalls(tree, cache) {
|
|
5272
5280
|
const calls = [];
|
|
5273
5281
|
const typeMap = buildCSharpReceiverTypeMap(tree, cache);
|
|
@@ -5285,12 +5293,16 @@ function extractCSharpCalls(tree, cache) {
|
|
|
5285
5293
|
methodName = getNodeText(fn);
|
|
5286
5294
|
}
|
|
5287
5295
|
const argsNode = inv.childForFieldName("arguments");
|
|
5296
|
+
let args2 = argsNode ? extractCSharpArguments(argsNode) : [];
|
|
5297
|
+
if (receiver && CSHARP_COMMAND_EXECUTE_METHODS.has(methodName)) {
|
|
5298
|
+
args2 = [{ position: 0, expression: receiver, variable: receiver, literal: null, value: null }, ...args2];
|
|
5299
|
+
}
|
|
5288
5300
|
calls.push({
|
|
5289
5301
|
method_name: methodName,
|
|
5290
5302
|
receiver,
|
|
5291
5303
|
receiver_type: receiver ? typeMap.get(receiver) ?? null : null,
|
|
5292
5304
|
receiver_type_fqn: null,
|
|
5293
|
-
arguments:
|
|
5305
|
+
arguments: args2,
|
|
5294
5306
|
location: { line: inv.startPosition.row + 1, column: inv.startPosition.column },
|
|
5295
5307
|
in_method: findEnclosingMethod(inv)
|
|
5296
5308
|
});
|
|
@@ -5310,6 +5322,35 @@ function extractCSharpCalls(tree, cache) {
|
|
|
5310
5322
|
is_constructor: true
|
|
5311
5323
|
});
|
|
5312
5324
|
}
|
|
5325
|
+
const assignments = getNodesFromCache(tree.rootNode, "assignment_expression", cache);
|
|
5326
|
+
for (const asn of assignments) {
|
|
5327
|
+
const left = asn.childForFieldName("left");
|
|
5328
|
+
if (left?.type !== "member_access_expression")
|
|
5329
|
+
continue;
|
|
5330
|
+
const nameNode = left.childForFieldName("name");
|
|
5331
|
+
if (!nameNode || getNodeText(nameNode) !== "CommandText")
|
|
5332
|
+
continue;
|
|
5333
|
+
const right = asn.childForFieldName("right");
|
|
5334
|
+
if (!right)
|
|
5335
|
+
continue;
|
|
5336
|
+
const rhsText = getNodeText(right);
|
|
5337
|
+
const exprNode = left.childForFieldName("expression");
|
|
5338
|
+
calls.push({
|
|
5339
|
+
method_name: "CommandText",
|
|
5340
|
+
receiver: exprNode ? getNodeText(exprNode) : null,
|
|
5341
|
+
receiver_type: null,
|
|
5342
|
+
receiver_type_fqn: null,
|
|
5343
|
+
arguments: [{
|
|
5344
|
+
position: 0,
|
|
5345
|
+
expression: rhsText,
|
|
5346
|
+
variable: right.type === "identifier" ? rhsText : null,
|
|
5347
|
+
literal: right.type === "string_literal" ? rhsText : null,
|
|
5348
|
+
value: null
|
|
5349
|
+
}],
|
|
5350
|
+
location: { line: asn.startPosition.row + 1, column: asn.startPosition.column },
|
|
5351
|
+
in_method: findEnclosingMethod(asn)
|
|
5352
|
+
});
|
|
5353
|
+
}
|
|
5313
5354
|
return calls;
|
|
5314
5355
|
}
|
|
5315
5356
|
function extractCSharpArguments(argsNode) {
|
|
@@ -12284,6 +12325,13 @@ var DEFAULT_SINKS = [
|
|
|
12284
12325
|
{ method: "ExecuteSqlRawAsync", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
|
|
12285
12326
|
{ method: "FromSqlRaw", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
|
|
12286
12327
|
{ method: "FromSqlRawAsync", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
|
|
12328
|
+
{ method: "CommandText", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
|
|
12329
|
+
{ method: "ExecuteScalar", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
|
|
12330
|
+
{ method: "ExecuteReader", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
|
|
12331
|
+
{ method: "ExecuteNonQuery", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
|
|
12332
|
+
{ method: "ExecuteScalarAsync", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
|
|
12333
|
+
{ method: "ExecuteReaderAsync", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
|
|
12334
|
+
{ method: "ExecuteNonQueryAsync", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
|
|
12287
12335
|
{ method: "Start", class: "Process", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0], languages: ["csharp"] },
|
|
12288
12336
|
{ method: "ProcessStartInfo", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0, 1], languages: ["csharp"] },
|
|
12289
12337
|
{ method: "ReadAllText", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
@@ -25589,18 +25637,20 @@ function findCSharpRequestSources(sourceCode, language) {
|
|
|
25589
25637
|
`);
|
|
25590
25638
|
const assignRe = /^\s*(?:var\s+|[A-Za-z_][\w.<>\[\]]*\s+)?([A-Za-z_]\w*)\s*=\s*(.+?);?\s*$/;
|
|
25591
25639
|
const requestReadRe = /\bRequest\s*\.\s*(?:Query|Form|Headers|Cookies|QueryString|RouteValues|Body|Files|Params)\b/;
|
|
25640
|
+
const consoleReadRe = /\bConsole\s*\.\s*ReadLine\s*\(/;
|
|
25592
25641
|
for (let i2 = 0;i2 < lines.length; i2++) {
|
|
25593
25642
|
const m = assignRe.exec(lines[i2]);
|
|
25594
25643
|
if (!m)
|
|
25595
25644
|
continue;
|
|
25596
25645
|
const [, varName, rhs] = m;
|
|
25597
|
-
|
|
25646
|
+
const type = requestReadRe.test(rhs) ? "http_param" : consoleReadRe.test(rhs) ? "io_input" : null;
|
|
25647
|
+
if (!type)
|
|
25598
25648
|
continue;
|
|
25599
25649
|
const lineNumber = i2 + 1;
|
|
25600
25650
|
if (sources.some((s) => s.line === lineNumber && s.variable === varName))
|
|
25601
25651
|
continue;
|
|
25602
25652
|
sources.push({
|
|
25603
|
-
type
|
|
25653
|
+
type,
|
|
25604
25654
|
location: `${varName} = ${rhs.trim().substring(0, 50)}${rhs.length > 50 ? "..." : ""}`,
|
|
25605
25655
|
severity: "high",
|
|
25606
25656
|
line: lineNumber,
|
|
@@ -35990,6 +36040,33 @@ function detectExpressionScanFlows(calls, sources, sinks, sanitizers, unreachabl
|
|
|
35990
36040
|
}
|
|
35991
36041
|
}
|
|
35992
36042
|
}
|
|
36043
|
+
if (language === "csharp" && typeof code === "string" && sourcesWithVar.length > 0) {
|
|
36044
|
+
const lines = code.split(`
|
|
36045
|
+
`);
|
|
36046
|
+
const ctRe = /(\w+)\s*\.\s*CommandText\s*\+?=\s*(.+)/;
|
|
36047
|
+
const anchor = sourcesWithVar.reduce((a, s) => s.line < a.line ? s : a, sourcesWithVar[0]);
|
|
36048
|
+
let added = true;
|
|
36049
|
+
let guard = 0;
|
|
36050
|
+
while (added && guard < lines.length + 2) {
|
|
36051
|
+
added = false;
|
|
36052
|
+
guard++;
|
|
36053
|
+
const known = new Set(sourcesWithVar.map((s) => s.variable));
|
|
36054
|
+
for (let i2 = 0;i2 < lines.length; i2++) {
|
|
36055
|
+
const m = ctRe.exec(lines[i2]);
|
|
36056
|
+
if (!m)
|
|
36057
|
+
continue;
|
|
36058
|
+
const [, obj, rhs] = m;
|
|
36059
|
+
if (known.has(obj))
|
|
36060
|
+
continue;
|
|
36061
|
+
const codePart = rhs.replace(/\$@?"(?:[^"\\]|\\.)*"/g, (lit) => " " + [...lit.matchAll(/\{([^}]*)\}/g)].map((x) => x[1]).join(" ") + " ").replace(/@?"(?:[^"\\]|\\.)*"/g, " ");
|
|
36062
|
+
const rhsTainted = sourcesWithVar.some((s) => new RegExp(`(?<![\\p{L}\\p{N}_])${s.variable.replace(/[.*+?^${}()|[\\]\\\\]/g, "\\$&")}(?![\\p{L}\\p{N}_])`, "u").test(codePart));
|
|
36063
|
+
if (!rhsTainted)
|
|
36064
|
+
continue;
|
|
36065
|
+
sourcesWithVar.push({ ...anchor, variable: obj, line: i2 + 1 });
|
|
36066
|
+
added = true;
|
|
36067
|
+
}
|
|
36068
|
+
}
|
|
36069
|
+
}
|
|
35993
36070
|
const reCache = new Map;
|
|
35994
36071
|
for (const s of sourcesWithVar) {
|
|
35995
36072
|
if (reCache.has(s.variable))
|
|
@@ -47778,7 +47855,7 @@ var colors = {
|
|
|
47778
47855
|
};
|
|
47779
47856
|
|
|
47780
47857
|
// src/version.ts
|
|
47781
|
-
var version = "4.
|
|
47858
|
+
var version = "4.5.0";
|
|
47782
47859
|
|
|
47783
47860
|
// src/formatters.ts
|
|
47784
47861
|
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.5.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.5.0"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@types/node": "^25.5.0",
|