cognium-dev 4.4.0 → 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.
Files changed (2) hide show
  1. package/dist/cli.js +51 -4
  2. 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: argsNode ? extractCSharpArguments(argsNode) : [],
5305
+ arguments: args2,
5294
5306
  location: { line: inv.startPosition.row + 1, column: inv.startPosition.column },
5295
5307
  in_method: findEnclosingMethod(inv)
5296
5308
  });
@@ -12314,6 +12326,12 @@ var DEFAULT_SINKS = [
12314
12326
  { method: "FromSqlRaw", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
12315
12327
  { method: "FromSqlRawAsync", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
12316
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"] },
12317
12335
  { method: "Start", class: "Process", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0], languages: ["csharp"] },
12318
12336
  { method: "ProcessStartInfo", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0, 1], languages: ["csharp"] },
12319
12337
  { method: "ReadAllText", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["csharp"] },
@@ -25619,18 +25637,20 @@ function findCSharpRequestSources(sourceCode, language) {
25619
25637
  `);
25620
25638
  const assignRe = /^\s*(?:var\s+|[A-Za-z_][\w.<>\[\]]*\s+)?([A-Za-z_]\w*)\s*=\s*(.+?);?\s*$/;
25621
25639
  const requestReadRe = /\bRequest\s*\.\s*(?:Query|Form|Headers|Cookies|QueryString|RouteValues|Body|Files|Params)\b/;
25640
+ const consoleReadRe = /\bConsole\s*\.\s*ReadLine\s*\(/;
25622
25641
  for (let i2 = 0;i2 < lines.length; i2++) {
25623
25642
  const m = assignRe.exec(lines[i2]);
25624
25643
  if (!m)
25625
25644
  continue;
25626
25645
  const [, varName, rhs] = m;
25627
- if (!requestReadRe.test(rhs))
25646
+ const type = requestReadRe.test(rhs) ? "http_param" : consoleReadRe.test(rhs) ? "io_input" : null;
25647
+ if (!type)
25628
25648
  continue;
25629
25649
  const lineNumber = i2 + 1;
25630
25650
  if (sources.some((s) => s.line === lineNumber && s.variable === varName))
25631
25651
  continue;
25632
25652
  sources.push({
25633
- type: "http_param",
25653
+ type,
25634
25654
  location: `${varName} = ${rhs.trim().substring(0, 50)}${rhs.length > 50 ? "..." : ""}`,
25635
25655
  severity: "high",
25636
25656
  line: lineNumber,
@@ -36020,6 +36040,33 @@ function detectExpressionScanFlows(calls, sources, sinks, sanitizers, unreachabl
36020
36040
  }
36021
36041
  }
36022
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
+ }
36023
36070
  const reCache = new Map;
36024
36071
  for (const s of sourcesWithVar) {
36025
36072
  if (reCache.has(s.variable))
@@ -47808,7 +47855,7 @@ var colors = {
47808
47855
  };
47809
47856
 
47810
47857
  // src/version.ts
47811
- var version = "4.4.0";
47858
+ var version = "4.5.0";
47812
47859
 
47813
47860
  // src/formatters.ts
47814
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.4.0",
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.4.0"
69
+ "circle-ir": "^4.5.0"
70
70
  },
71
71
  "devDependencies": {
72
72
  "@types/node": "^25.5.0",