cognium-dev 3.215.0 → 4.0.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 +612 -7
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -3627,8 +3627,87 @@ function extractTypes(tree, cache, language) {
|
|
|
3627
3627
|
if (isJavaScript) {
|
|
3628
3628
|
return extractJavaScriptTypes(tree, cache);
|
|
3629
3629
|
}
|
|
3630
|
+
if (effectiveLanguage === "csharp") {
|
|
3631
|
+
return extractCSharpTypes(tree, cache);
|
|
3632
|
+
}
|
|
3630
3633
|
return extractJavaTypes(tree, cache);
|
|
3631
3634
|
}
|
|
3635
|
+
function extractCSharpTypes(tree, cache) {
|
|
3636
|
+
const types = [];
|
|
3637
|
+
const KINDS = {
|
|
3638
|
+
class_declaration: "class",
|
|
3639
|
+
record_declaration: "class",
|
|
3640
|
+
struct_declaration: "class",
|
|
3641
|
+
interface_declaration: "interface",
|
|
3642
|
+
enum_declaration: "enum"
|
|
3643
|
+
};
|
|
3644
|
+
for (const kindNode of Object.keys(KINDS)) {
|
|
3645
|
+
for (const node of getNodesFromCache(tree.rootNode, kindNode, cache)) {
|
|
3646
|
+
const nameNode = node.childForFieldName("name");
|
|
3647
|
+
const body2 = node.childForFieldName("body");
|
|
3648
|
+
const methods = [];
|
|
3649
|
+
if (body2) {
|
|
3650
|
+
for (let i2 = 0;i2 < body2.childCount; i2++) {
|
|
3651
|
+
const m = body2.child(i2);
|
|
3652
|
+
if (!m || m.type !== "method_declaration")
|
|
3653
|
+
continue;
|
|
3654
|
+
const mName = m.childForFieldName("name");
|
|
3655
|
+
const paramList = m.childForFieldName("parameters");
|
|
3656
|
+
const parameters = [];
|
|
3657
|
+
if (paramList) {
|
|
3658
|
+
for (let j = 0;j < paramList.childCount; j++) {
|
|
3659
|
+
const pnode = paramList.child(j);
|
|
3660
|
+
if (!pnode || pnode.type !== "parameter")
|
|
3661
|
+
continue;
|
|
3662
|
+
const pName = pnode.childForFieldName("name");
|
|
3663
|
+
const pType = pnode.childForFieldName("type");
|
|
3664
|
+
if (pName) {
|
|
3665
|
+
parameters.push({
|
|
3666
|
+
name: getNodeText(pName),
|
|
3667
|
+
type: pType ? getNodeText(pType) : null,
|
|
3668
|
+
annotations: [],
|
|
3669
|
+
line: pnode.startPosition.row + 1
|
|
3670
|
+
});
|
|
3671
|
+
}
|
|
3672
|
+
}
|
|
3673
|
+
}
|
|
3674
|
+
const returns = m.childForFieldName("returns");
|
|
3675
|
+
methods.push({
|
|
3676
|
+
name: mName ? getNodeText(mName) : "unknown",
|
|
3677
|
+
return_type: returns ? getNodeText(returns) : null,
|
|
3678
|
+
parameters,
|
|
3679
|
+
annotations: [],
|
|
3680
|
+
modifiers: extractCSharpModifiers(m),
|
|
3681
|
+
start_line: m.startPosition.row + 1,
|
|
3682
|
+
end_line: m.endPosition.row + 1
|
|
3683
|
+
});
|
|
3684
|
+
}
|
|
3685
|
+
}
|
|
3686
|
+
types.push({
|
|
3687
|
+
name: nameNode ? getNodeText(nameNode) : "anonymous",
|
|
3688
|
+
kind: KINDS[kindNode],
|
|
3689
|
+
package: null,
|
|
3690
|
+
extends: null,
|
|
3691
|
+
implements: [],
|
|
3692
|
+
annotations: [],
|
|
3693
|
+
methods,
|
|
3694
|
+
fields: [],
|
|
3695
|
+
start_line: node.startPosition.row + 1,
|
|
3696
|
+
end_line: node.endPosition.row + 1
|
|
3697
|
+
});
|
|
3698
|
+
}
|
|
3699
|
+
}
|
|
3700
|
+
return types;
|
|
3701
|
+
}
|
|
3702
|
+
function extractCSharpModifiers(node) {
|
|
3703
|
+
const mods = [];
|
|
3704
|
+
for (let i2 = 0;i2 < node.childCount; i2++) {
|
|
3705
|
+
const c = node.child(i2);
|
|
3706
|
+
if (c && c.type === "modifier")
|
|
3707
|
+
mods.push(getNodeText(c));
|
|
3708
|
+
}
|
|
3709
|
+
return mods;
|
|
3710
|
+
}
|
|
3632
3711
|
function extractJavaTypes(tree, cache) {
|
|
3633
3712
|
const types = [];
|
|
3634
3713
|
const classes = getNodesFromCache(tree.rootNode, "class_declaration", cache);
|
|
@@ -5133,6 +5212,9 @@ function extractCalls(tree, cache, language) {
|
|
|
5133
5212
|
if (isJavaScript) {
|
|
5134
5213
|
return extractJavaScriptCalls(tree, cache);
|
|
5135
5214
|
}
|
|
5215
|
+
if (detectedLanguage === "csharp") {
|
|
5216
|
+
return extractCSharpCalls(tree, cache);
|
|
5217
|
+
}
|
|
5136
5218
|
const context = buildResolutionContext(tree, cache);
|
|
5137
5219
|
const invocations = getNodesFromCache(tree.rootNode, "method_invocation", cache);
|
|
5138
5220
|
for (const inv of invocations) {
|
|
@@ -5147,6 +5229,115 @@ function extractCalls(tree, cache, language) {
|
|
|
5147
5229
|
}
|
|
5148
5230
|
return calls;
|
|
5149
5231
|
}
|
|
5232
|
+
function buildCSharpReceiverTypeMap(tree, cache) {
|
|
5233
|
+
const map = new Map;
|
|
5234
|
+
const simple = (t) => t.replace(/<[^>]*>/g, "").split(".").pop()?.trim() ?? t;
|
|
5235
|
+
for (const vd of getNodesFromCache(tree.rootNode, "variable_declaration", cache)) {
|
|
5236
|
+
const typeNode = vd.childForFieldName("type");
|
|
5237
|
+
const declaredType = typeNode ? getNodeText(typeNode) : null;
|
|
5238
|
+
for (let i2 = 0;i2 < vd.childCount; i2++) {
|
|
5239
|
+
const decl = vd.child(i2);
|
|
5240
|
+
if (!decl || decl.type !== "variable_declarator")
|
|
5241
|
+
continue;
|
|
5242
|
+
const nameNode = decl.childForFieldName("name");
|
|
5243
|
+
if (nameNode?.type !== "identifier")
|
|
5244
|
+
continue;
|
|
5245
|
+
let t = declaredType && declaredType !== "var" ? declaredType : null;
|
|
5246
|
+
if (!t) {
|
|
5247
|
+
const oce = findFirstDescendant(decl, "object_creation_expression");
|
|
5248
|
+
const oceType = oce?.childForFieldName("type");
|
|
5249
|
+
if (oceType)
|
|
5250
|
+
t = getNodeText(oceType);
|
|
5251
|
+
}
|
|
5252
|
+
if (t && t !== "var")
|
|
5253
|
+
map.set(getNodeText(nameNode), simple(t));
|
|
5254
|
+
}
|
|
5255
|
+
}
|
|
5256
|
+
return map;
|
|
5257
|
+
}
|
|
5258
|
+
function findFirstDescendant(node, type) {
|
|
5259
|
+
for (let i2 = 0;i2 < node.childCount; i2++) {
|
|
5260
|
+
const c = node.child(i2);
|
|
5261
|
+
if (!c)
|
|
5262
|
+
continue;
|
|
5263
|
+
if (c.type === type)
|
|
5264
|
+
return c;
|
|
5265
|
+
const found = findFirstDescendant(c, type);
|
|
5266
|
+
if (found)
|
|
5267
|
+
return found;
|
|
5268
|
+
}
|
|
5269
|
+
return null;
|
|
5270
|
+
}
|
|
5271
|
+
function extractCSharpCalls(tree, cache) {
|
|
5272
|
+
const calls = [];
|
|
5273
|
+
const typeMap = buildCSharpReceiverTypeMap(tree, cache);
|
|
5274
|
+
const invocations = getNodesFromCache(tree.rootNode, "invocation_expression", cache);
|
|
5275
|
+
for (const inv of invocations) {
|
|
5276
|
+
const fn = inv.childForFieldName("function");
|
|
5277
|
+
let methodName = "unknown";
|
|
5278
|
+
let receiver = null;
|
|
5279
|
+
if (fn?.type === "member_access_expression") {
|
|
5280
|
+
const nameNode = fn.childForFieldName("name");
|
|
5281
|
+
const exprNode = fn.childForFieldName("expression");
|
|
5282
|
+
methodName = nameNode ? getNodeText(nameNode) : "unknown";
|
|
5283
|
+
receiver = exprNode ? getNodeText(exprNode) : null;
|
|
5284
|
+
} else if (fn) {
|
|
5285
|
+
methodName = getNodeText(fn);
|
|
5286
|
+
}
|
|
5287
|
+
const argsNode = inv.childForFieldName("arguments");
|
|
5288
|
+
calls.push({
|
|
5289
|
+
method_name: methodName,
|
|
5290
|
+
receiver,
|
|
5291
|
+
receiver_type: receiver ? typeMap.get(receiver) ?? null : null,
|
|
5292
|
+
receiver_type_fqn: null,
|
|
5293
|
+
arguments: argsNode ? extractCSharpArguments(argsNode) : [],
|
|
5294
|
+
location: { line: inv.startPosition.row + 1, column: inv.startPosition.column },
|
|
5295
|
+
in_method: findEnclosingMethod(inv)
|
|
5296
|
+
});
|
|
5297
|
+
}
|
|
5298
|
+
const objectCreations = getNodesFromCache(tree.rootNode, "object_creation_expression", cache);
|
|
5299
|
+
for (const creation of objectCreations) {
|
|
5300
|
+
const typeNode = creation.childForFieldName("type");
|
|
5301
|
+
const argsNode = creation.childForFieldName("arguments");
|
|
5302
|
+
calls.push({
|
|
5303
|
+
method_name: typeNode ? getNodeText(typeNode) : "unknown",
|
|
5304
|
+
receiver: null,
|
|
5305
|
+
receiver_type: null,
|
|
5306
|
+
receiver_type_fqn: null,
|
|
5307
|
+
arguments: argsNode ? extractCSharpArguments(argsNode) : [],
|
|
5308
|
+
location: { line: creation.startPosition.row + 1, column: creation.startPosition.column },
|
|
5309
|
+
in_method: findEnclosingMethod(creation),
|
|
5310
|
+
is_constructor: true
|
|
5311
|
+
});
|
|
5312
|
+
}
|
|
5313
|
+
return calls;
|
|
5314
|
+
}
|
|
5315
|
+
function extractCSharpArguments(argsNode) {
|
|
5316
|
+
const args2 = [];
|
|
5317
|
+
let position = 0;
|
|
5318
|
+
for (let i2 = 0;i2 < argsNode.childCount; i2++) {
|
|
5319
|
+
const child = argsNode.child(i2);
|
|
5320
|
+
if (!child || child.type !== "argument")
|
|
5321
|
+
continue;
|
|
5322
|
+
let expr = null;
|
|
5323
|
+
for (let j = child.childCount - 1;j >= 0; j--) {
|
|
5324
|
+
const c = child.child(j);
|
|
5325
|
+
if (c && c.isNamed) {
|
|
5326
|
+
expr = c;
|
|
5327
|
+
break;
|
|
5328
|
+
}
|
|
5329
|
+
}
|
|
5330
|
+
const text = expr ? getNodeText(expr) : getNodeText(child);
|
|
5331
|
+
args2.push({
|
|
5332
|
+
position: position++,
|
|
5333
|
+
expression: text,
|
|
5334
|
+
variable: expr?.type === "identifier" ? text : null,
|
|
5335
|
+
literal: expr?.type === "string_literal" ? text : null,
|
|
5336
|
+
value: null
|
|
5337
|
+
});
|
|
5338
|
+
}
|
|
5339
|
+
return args2;
|
|
5340
|
+
}
|
|
5150
5341
|
function extractJavaScriptCalls(tree, cache) {
|
|
5151
5342
|
const calls = [];
|
|
5152
5343
|
const context = buildJSResolutionContext(tree, cache);
|
|
@@ -8337,8 +8528,72 @@ function buildDFG(tree, cache, language) {
|
|
|
8337
8528
|
if (effectiveLanguage === "go") {
|
|
8338
8529
|
return buildGoDFG(tree);
|
|
8339
8530
|
}
|
|
8531
|
+
if (effectiveLanguage === "csharp") {
|
|
8532
|
+
return buildCSharpDFG(tree, cache);
|
|
8533
|
+
}
|
|
8340
8534
|
return buildJavaDFG(tree, cache);
|
|
8341
8535
|
}
|
|
8536
|
+
function buildCSharpDFG(tree, cache) {
|
|
8537
|
+
const defs = [];
|
|
8538
|
+
const uses = [];
|
|
8539
|
+
let defIdCounter = 1;
|
|
8540
|
+
let useIdCounter = 1;
|
|
8541
|
+
const scopeStack = [new Map];
|
|
8542
|
+
const methods = [
|
|
8543
|
+
...getNodesFromCache(tree.rootNode, "method_declaration", cache),
|
|
8544
|
+
...getNodesFromCache(tree.rootNode, "constructor_declaration", cache),
|
|
8545
|
+
...getNodesFromCache(tree.rootNode, "local_function_statement", cache)
|
|
8546
|
+
];
|
|
8547
|
+
for (const method of methods) {
|
|
8548
|
+
scopeStack.push(new Map);
|
|
8549
|
+
const params = method.childForFieldName("parameters");
|
|
8550
|
+
if (params) {
|
|
8551
|
+
for (const def of extractParameterDefs(params, defIdCounter)) {
|
|
8552
|
+
defs.push(def);
|
|
8553
|
+
currentScope(scopeStack).set(def.variable, def.id);
|
|
8554
|
+
defIdCounter++;
|
|
8555
|
+
}
|
|
8556
|
+
}
|
|
8557
|
+
const body2 = method.childForFieldName("body");
|
|
8558
|
+
if (body2) {
|
|
8559
|
+
for (const decl of findNodes(body2, "variable_declarator")) {
|
|
8560
|
+
const nameNode = decl.childForFieldName("name");
|
|
8561
|
+
if (nameNode?.type === "identifier") {
|
|
8562
|
+
const name2 = getNodeText(nameNode);
|
|
8563
|
+
const def = { id: defIdCounter++, variable: name2, line: decl.startPosition.row + 1, kind: "local" };
|
|
8564
|
+
defs.push(def);
|
|
8565
|
+
currentScope(scopeStack).set(name2, def.id);
|
|
8566
|
+
}
|
|
8567
|
+
}
|
|
8568
|
+
for (const asn of findNodes(body2, "assignment_expression")) {
|
|
8569
|
+
const left = asn.childForFieldName("left");
|
|
8570
|
+
if (left?.type === "identifier") {
|
|
8571
|
+
const name2 = getNodeText(left);
|
|
8572
|
+
const def = { id: defIdCounter++, variable: name2, line: asn.startPosition.row + 1, kind: "local" };
|
|
8573
|
+
defs.push(def);
|
|
8574
|
+
currentScope(scopeStack).set(name2, def.id);
|
|
8575
|
+
}
|
|
8576
|
+
}
|
|
8577
|
+
const bodyUses = extractUses(body2, useIdCounter, scopeStack, false);
|
|
8578
|
+
uses.push(...bodyUses.uses);
|
|
8579
|
+
useIdCounter = bodyUses.nextId;
|
|
8580
|
+
}
|
|
8581
|
+
scopeStack.pop();
|
|
8582
|
+
}
|
|
8583
|
+
const classes = getNodesFromCache(tree.rootNode, "class_declaration", cache);
|
|
8584
|
+
for (const cls of classes) {
|
|
8585
|
+
const body2 = cls.childForFieldName("body");
|
|
8586
|
+
if (body2) {
|
|
8587
|
+
for (const def of extractFieldDefs(body2, defIdCounter)) {
|
|
8588
|
+
defs.push(def);
|
|
8589
|
+
currentScope(scopeStack).set(def.variable, def.id);
|
|
8590
|
+
defIdCounter++;
|
|
8591
|
+
}
|
|
8592
|
+
}
|
|
8593
|
+
}
|
|
8594
|
+
const chains = computeChains(defs, uses);
|
|
8595
|
+
return { defs, uses, chains };
|
|
8596
|
+
}
|
|
8342
8597
|
function buildJavaDFG(tree, cache) {
|
|
8343
8598
|
const defs = [];
|
|
8344
8599
|
const uses = [];
|
|
@@ -8808,7 +9063,7 @@ function extractParameterDefs(params, startId) {
|
|
|
8808
9063
|
const param = params.child(i2);
|
|
8809
9064
|
if (!param)
|
|
8810
9065
|
continue;
|
|
8811
|
-
if (param.type === "formal_parameter" || param.type === "spread_parameter") {
|
|
9066
|
+
if (param.type === "formal_parameter" || param.type === "spread_parameter" || param.type === "parameter") {
|
|
8812
9067
|
const nameNode = param.childForFieldName("name");
|
|
8813
9068
|
if (nameNode) {
|
|
8814
9069
|
defs.push({
|
|
@@ -12020,6 +12275,55 @@ var DEFAULT_SINKS = [
|
|
|
12020
12275
|
{ method: "put", class: "httpx", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
|
|
12021
12276
|
{ method: "patch", class: "httpx", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
|
|
12022
12277
|
{ method: "head", class: "httpx", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0] },
|
|
12278
|
+
{ method: "SqlCommand", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
|
|
12279
|
+
{ method: "NpgsqlCommand", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
|
|
12280
|
+
{ method: "MySqlCommand", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
|
|
12281
|
+
{ method: "SqliteCommand", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
|
|
12282
|
+
{ method: "OracleCommand", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
|
|
12283
|
+
{ method: "ExecuteSqlRaw", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
|
|
12284
|
+
{ method: "ExecuteSqlRawAsync", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
|
|
12285
|
+
{ method: "FromSqlRaw", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
|
|
12286
|
+
{ method: "FromSqlRawAsync", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
|
|
12287
|
+
{ method: "Start", class: "Process", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0], languages: ["csharp"] },
|
|
12288
|
+
{ method: "ProcessStartInfo", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0, 1], languages: ["csharp"] },
|
|
12289
|
+
{ method: "ReadAllText", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12290
|
+
{ method: "ReadAllBytes", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12291
|
+
{ method: "ReadAllLines", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12292
|
+
{ method: "WriteAllText", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12293
|
+
{ method: "WriteAllBytes", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12294
|
+
{ method: "AppendAllText", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12295
|
+
{ method: "OpenRead", class: "File", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12296
|
+
{ method: "OpenWrite", class: "File", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12297
|
+
{ method: "FileStream", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12298
|
+
{ method: "StreamReader", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12299
|
+
{ method: "StreamWriter", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12300
|
+
{ method: "GetAsync", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12301
|
+
{ method: "PostAsync", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12302
|
+
{ method: "PutAsync", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12303
|
+
{ method: "DeleteAsync", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12304
|
+
{ method: "GetStringAsync", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12305
|
+
{ method: "GetByteArrayAsync", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12306
|
+
{ method: "GetStreamAsync", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12307
|
+
{ method: "SendAsync", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12308
|
+
{ method: "DownloadString", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12309
|
+
{ method: "DownloadData", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12310
|
+
{ method: "DownloadFile", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [1], languages: ["csharp"] },
|
|
12311
|
+
{ method: "Create", class: "WebRequest", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12312
|
+
{ method: "EvaluateAsync", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0], languages: ["csharp"] },
|
|
12313
|
+
{ method: "RunAsync", class: "CSharpScript", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0], languages: ["csharp"] },
|
|
12314
|
+
{ method: "Deserialize", class: "BinaryFormatter", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0], languages: ["csharp"] },
|
|
12315
|
+
{ method: "Deserialize", class: "NetDataContractSerializer", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0], languages: ["csharp"] },
|
|
12316
|
+
{ method: "Raw", class: "Html", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12317
|
+
{ method: "Write", class: "Response", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12318
|
+
{ method: "HtmlString", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12319
|
+
{ method: "DirectorySearcher", type: "ldap_injection", cwe: "CWE-90", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12320
|
+
{ method: "DirectoryEntry", type: "ldap_injection", cwe: "CWE-90", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12321
|
+
{ method: "SelectSingleNode", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12322
|
+
{ method: "SelectNodes", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12323
|
+
{ method: "Compile", class: "XPathExpression", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12324
|
+
{ method: "LoadXml", type: "xxe", cwe: "CWE-611", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12325
|
+
{ method: "Load", class: "XmlDocument", type: "xxe", cwe: "CWE-611", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12326
|
+
{ method: "Load", class: "XDocument", type: "xxe", cwe: "CWE-611", severity: "high", arg_positions: [0], languages: ["csharp"] },
|
|
12023
12327
|
{ method: "execute", class: "Connection", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
|
|
12024
12328
|
{ method: "fetch", class: "Connection", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
|
|
12025
12329
|
{ method: "fetchrow", class: "Connection", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0] },
|
|
@@ -12138,6 +12442,10 @@ var DEFAULT_SANITIZERS = [
|
|
|
12138
12442
|
{ method: "escapeEcmaScript", removes: ["xss"] },
|
|
12139
12443
|
{ method: "escapeCsv", removes: ["xss"] },
|
|
12140
12444
|
{ method: "sanitize", class: "PolicyFactory", removes: ["xss"] },
|
|
12445
|
+
{ method: "HtmlEncode", removes: ["xss"] },
|
|
12446
|
+
{ method: "JavaScriptStringEncode", removes: ["xss"] },
|
|
12447
|
+
{ method: "Encode", class: "HtmlEncoder", removes: ["xss"] },
|
|
12448
|
+
{ method: "GetFileName", class: "Path", removes: ["path_traversal"] },
|
|
12141
12449
|
{ method: "encodeToString", class: "Encoder", removes: ["sql_injection", "command_injection", "xss", "path_traversal", "code_injection"] },
|
|
12142
12450
|
{ method: "encode", class: "Encoder", removes: ["sql_injection", "command_injection", "xss", "path_traversal", "code_injection"] },
|
|
12143
12451
|
{ method: "encodeHexString", class: "Hex", removes: ["sql_injection", "command_injection", "xss", "path_traversal", "code_injection"] },
|
|
@@ -12790,7 +13098,7 @@ function findSources(calls, types, patterns, sourceLines, language) {
|
|
|
12790
13098
|
if (skipMethods.includes(method.name))
|
|
12791
13099
|
continue;
|
|
12792
13100
|
for (const param of method.parameters) {
|
|
12793
|
-
const isTaintable = param.type ? isInterproceduralTaintableType(param.type) : true;
|
|
13101
|
+
const isTaintable = param.type ? isInterproceduralTaintableType(param.type, language) : true;
|
|
12794
13102
|
if (isTaintable) {
|
|
12795
13103
|
const paramLine = param.line ?? method.start_line;
|
|
12796
13104
|
sources.push({
|
|
@@ -12800,7 +13108,7 @@ function findSources(calls, types, patterns, sourceLines, language) {
|
|
|
12800
13108
|
line: paramLine,
|
|
12801
13109
|
confidence: param.type ? 0.7 : 0.5,
|
|
12802
13110
|
in_method: method.name,
|
|
12803
|
-
...language === "java" ? { variable: param.name } : {}
|
|
13111
|
+
...language === "java" || language === "csharp" ? { variable: param.name } : {}
|
|
12804
13112
|
});
|
|
12805
13113
|
}
|
|
12806
13114
|
}
|
|
@@ -12903,7 +13211,7 @@ function findSources(calls, types, patterns, sourceLines, language) {
|
|
|
12903
13211
|
}
|
|
12904
13212
|
return result;
|
|
12905
13213
|
}
|
|
12906
|
-
function isInterproceduralTaintableType(typeName) {
|
|
13214
|
+
function isInterproceduralTaintableType(typeName, language) {
|
|
12907
13215
|
const baseType = typeName.split("<")[0].trim();
|
|
12908
13216
|
const excludedTypes = [
|
|
12909
13217
|
"HttpServletRequest",
|
|
@@ -12966,6 +13274,26 @@ function isInterproceduralTaintableType(typeName) {
|
|
|
12966
13274
|
if (taintableTypes.includes(baseType)) {
|
|
12967
13275
|
return true;
|
|
12968
13276
|
}
|
|
13277
|
+
if (language === "csharp") {
|
|
13278
|
+
const csharpTaintable = [
|
|
13279
|
+
"string",
|
|
13280
|
+
"object",
|
|
13281
|
+
"IEnumerable",
|
|
13282
|
+
"ICollection",
|
|
13283
|
+
"IList",
|
|
13284
|
+
"Dictionary",
|
|
13285
|
+
"IDictionary",
|
|
13286
|
+
"IReadOnlyList",
|
|
13287
|
+
"IReadOnlyCollection",
|
|
13288
|
+
"Stream",
|
|
13289
|
+
"byte[]",
|
|
13290
|
+
"Byte[]",
|
|
13291
|
+
"MemoryStream"
|
|
13292
|
+
];
|
|
13293
|
+
const leaf = baseType.split(".").pop() ?? baseType;
|
|
13294
|
+
if (csharpTaintable.includes(baseType) || csharpTaintable.includes(leaf))
|
|
13295
|
+
return true;
|
|
13296
|
+
}
|
|
12969
13297
|
if (typeName.endsWith("[]")) {
|
|
12970
13298
|
const elementType = typeName.slice(0, -2);
|
|
12971
13299
|
if (elementType === "String" || elementType === "Object" || elementType === "byte") {
|
|
@@ -23377,6 +23705,65 @@ class GoPlugin extends BaseLanguagePlugin {
|
|
|
23377
23705
|
}
|
|
23378
23706
|
}
|
|
23379
23707
|
|
|
23708
|
+
// ../circle-ir/dist/languages/plugins/csharp.js
|
|
23709
|
+
class CSharpPlugin extends BaseLanguagePlugin {
|
|
23710
|
+
id = "csharp";
|
|
23711
|
+
name = "C#";
|
|
23712
|
+
extensions = [".cs"];
|
|
23713
|
+
wasmPath = "tree-sitter-csharp.wasm";
|
|
23714
|
+
nodeTypes = {
|
|
23715
|
+
classDeclaration: ["class_declaration", "record_declaration", "struct_declaration"],
|
|
23716
|
+
interfaceDeclaration: ["interface_declaration"],
|
|
23717
|
+
enumDeclaration: ["enum_declaration"],
|
|
23718
|
+
functionDeclaration: [],
|
|
23719
|
+
methodDeclaration: ["method_declaration", "constructor_declaration", "local_function_statement"],
|
|
23720
|
+
methodCall: ["invocation_expression"],
|
|
23721
|
+
functionCall: [],
|
|
23722
|
+
assignment: ["assignment_expression"],
|
|
23723
|
+
variableDeclaration: ["local_declaration_statement", "field_declaration", "variable_declaration"],
|
|
23724
|
+
parameter: ["parameter"],
|
|
23725
|
+
argument: ["argument_list"],
|
|
23726
|
+
annotation: ["attribute", "attribute_list"],
|
|
23727
|
+
decorator: [],
|
|
23728
|
+
importStatement: ["using_directive"],
|
|
23729
|
+
ifStatement: ["if_statement"],
|
|
23730
|
+
forStatement: ["for_statement", "for_each_statement"],
|
|
23731
|
+
whileStatement: ["while_statement"],
|
|
23732
|
+
tryStatement: ["try_statement"],
|
|
23733
|
+
returnStatement: ["return_statement"]
|
|
23734
|
+
};
|
|
23735
|
+
detectFramework(context) {
|
|
23736
|
+
for (const imp of context.imports) {
|
|
23737
|
+
const path = imp.from_package || imp.imported_name;
|
|
23738
|
+
if (path.startsWith("Microsoft.AspNetCore") || path.startsWith("Microsoft.Extensions")) {
|
|
23739
|
+
return { name: "aspnetcore", confidence: 0.9, indicators: [`using: ${path}`] };
|
|
23740
|
+
}
|
|
23741
|
+
if (path.startsWith("Microsoft.EntityFrameworkCore")) {
|
|
23742
|
+
return { name: "efcore", confidence: 0.9, indicators: [`using: ${path}`] };
|
|
23743
|
+
}
|
|
23744
|
+
}
|
|
23745
|
+
return;
|
|
23746
|
+
}
|
|
23747
|
+
extractTypes(_context) {
|
|
23748
|
+
return [];
|
|
23749
|
+
}
|
|
23750
|
+
extractCalls(_context) {
|
|
23751
|
+
return [];
|
|
23752
|
+
}
|
|
23753
|
+
extractImports(_context) {
|
|
23754
|
+
return [];
|
|
23755
|
+
}
|
|
23756
|
+
extractPackage(_context) {
|
|
23757
|
+
return;
|
|
23758
|
+
}
|
|
23759
|
+
getBuiltinSources() {
|
|
23760
|
+
return [];
|
|
23761
|
+
}
|
|
23762
|
+
getBuiltinSinks() {
|
|
23763
|
+
return [];
|
|
23764
|
+
}
|
|
23765
|
+
}
|
|
23766
|
+
|
|
23380
23767
|
// ../circle-ir/dist/languages/plugins/index.js
|
|
23381
23768
|
function registerBuiltinPlugins() {
|
|
23382
23769
|
registerLanguage(new JavaPlugin);
|
|
@@ -23387,6 +23774,7 @@ function registerBuiltinPlugins() {
|
|
|
23387
23774
|
registerLanguage(new HtmlPlugin);
|
|
23388
23775
|
registerLanguage(new VuePlugin);
|
|
23389
23776
|
registerLanguage(new GoPlugin);
|
|
23777
|
+
registerLanguage(new CSharpPlugin);
|
|
23390
23778
|
}
|
|
23391
23779
|
// ../circle-ir/dist/analysis/passes/cross-file-pass.js
|
|
23392
23780
|
class CrossFilePass {
|
|
@@ -24570,6 +24958,7 @@ class LanguageSourcesPass {
|
|
|
24570
24958
|
additionalSources.push(...findStaticFieldSources(types, code, language));
|
|
24571
24959
|
additionalSources.push(...findSetterChainSources(types, code, language));
|
|
24572
24960
|
additionalSources.push(...findJavaScriptAssignmentSources(code, language));
|
|
24961
|
+
additionalSources.push(...findCSharpRequestSources(code, language));
|
|
24573
24962
|
const jsDOMSinks = findJavaScriptDOMSinks(code, language);
|
|
24574
24963
|
for (const s of jsDOMSinks) {
|
|
24575
24964
|
const alreadyExists = additionalSinks.some((x) => x.line === s.line && x.cwe === s.cwe);
|
|
@@ -25172,6 +25561,35 @@ function findSetterChainSources(types, sourceCode, language) {
|
|
|
25172
25561
|
}
|
|
25173
25562
|
return sources;
|
|
25174
25563
|
}
|
|
25564
|
+
function findCSharpRequestSources(sourceCode, language) {
|
|
25565
|
+
if (language !== "csharp")
|
|
25566
|
+
return [];
|
|
25567
|
+
const sources = [];
|
|
25568
|
+
const lines = sourceCode.split(`
|
|
25569
|
+
`);
|
|
25570
|
+
const assignRe = /^\s*(?:var\s+|[A-Za-z_][\w.<>\[\]]*\s+)?([A-Za-z_]\w*)\s*=\s*(.+?);?\s*$/;
|
|
25571
|
+
const requestReadRe = /\bRequest\s*\.\s*(?:Query|Form|Headers|Cookies|QueryString|RouteValues|Body|Files|Params)\b/;
|
|
25572
|
+
for (let i2 = 0;i2 < lines.length; i2++) {
|
|
25573
|
+
const m = assignRe.exec(lines[i2]);
|
|
25574
|
+
if (!m)
|
|
25575
|
+
continue;
|
|
25576
|
+
const [, varName, rhs] = m;
|
|
25577
|
+
if (!requestReadRe.test(rhs))
|
|
25578
|
+
continue;
|
|
25579
|
+
const lineNumber = i2 + 1;
|
|
25580
|
+
if (sources.some((s) => s.line === lineNumber && s.variable === varName))
|
|
25581
|
+
continue;
|
|
25582
|
+
sources.push({
|
|
25583
|
+
type: "http_param",
|
|
25584
|
+
location: `${varName} = ${rhs.trim().substring(0, 50)}${rhs.length > 50 ? "..." : ""}`,
|
|
25585
|
+
severity: "high",
|
|
25586
|
+
line: lineNumber,
|
|
25587
|
+
confidence: 1,
|
|
25588
|
+
variable: varName
|
|
25589
|
+
});
|
|
25590
|
+
}
|
|
25591
|
+
return sources;
|
|
25592
|
+
}
|
|
25175
25593
|
function findJavaScriptAssignmentSources(sourceCode, language) {
|
|
25176
25594
|
if (!["javascript", "typescript"].includes(language))
|
|
25177
25595
|
return [];
|
|
@@ -31857,6 +32275,13 @@ var REPLACE_ALL_TO_PLACEHOLDER_RE = /\.replaceAll\s*\([\s\S]*?,\s*"[\s,?]*\?[\s,
|
|
|
31857
32275
|
var HTML_CONTENT_TYPE_RE = /text\/html|TEXT_HTML/;
|
|
31858
32276
|
var FETCH_GLOBAL_RECEIVER_RE = /(?:^|[^.\w])(?:window|globalThis|self|global)\s*\.\s*fetch\s*\(/;
|
|
31859
32277
|
var FETCH_MEMBER_RECEIVER_RE = /[\w$)\]]\s*\.\s*fetch\s*\(/;
|
|
32278
|
+
var NOSQL_ARRAY_METHODS = new Set(["find", "filter", "some", "every", "findIndex", "findLast"]);
|
|
32279
|
+
var FUNCTION_FIRST_ARG_RE = /\.\s*(?:find|filter|some|every|findIndex|findLast)\s*\(\s*(?:async\s+)?(?:function\b|(?:\([^()]*\)|[A-Za-z_$][\w$]*)\s*=>)/;
|
|
32280
|
+
var ORM_BUILDER_KEY_RE = /[{,]\s*(?:where|select|populate|include|orderBy|relations|attributes)\s*:/;
|
|
32281
|
+
var BROWSER_COMPONENT_EXT_RE = /\.(?:jsx|tsx|vue|svelte)$/;
|
|
32282
|
+
var CLIENT_SIGNAL_RE = /["']use client["']|\buse(?:State|Effect|Ref|Callback|Memo|Context|Reducer|LayoutEffect)\s*\(|\b(?:window|document|localStorage|sessionStorage|navigator)\s*\.|\son(?:Click|Change|Submit|Input|KeyDown|KeyUp|MouseOver|Focus|Blur)\s*=/;
|
|
32283
|
+
var SERVER_SIGNAL_RE = /["']use server["']|\b(?:getServerSideProps|getStaticProps|getStaticPaths)\b|from\s+["']next\/server["']|\bNext(?:Api)?(?:Request|Response)\b|from\s+["'](?:node:)?(?:fs|child_process|http|https|net|dns|dgram)["']|\bexport\s+(?:default\s+)?(?:async\s+)?function\s+handler\s*\(/;
|
|
32284
|
+
var FIXED_HOST_TEMPLATE_RE = /`https?:\/\/[^/${}\s`]+[/`]/;
|
|
31860
32285
|
function javaTraversalRejectGuardedLines(code) {
|
|
31861
32286
|
const covered = new Set;
|
|
31862
32287
|
const lines = code.split(`
|
|
@@ -31903,6 +32328,121 @@ function javaTraversalRejectGuardedLines(code) {
|
|
|
31903
32328
|
}
|
|
31904
32329
|
return covered;
|
|
31905
32330
|
}
|
|
32331
|
+
function isAnchoredHostAllowlistRegex(src) {
|
|
32332
|
+
if (!src.startsWith("^"))
|
|
32333
|
+
return false;
|
|
32334
|
+
if (!/https?/i.test(src))
|
|
32335
|
+
return false;
|
|
32336
|
+
return /[A-Za-z][A-Za-z0-9-]+\\?\./.test(src);
|
|
32337
|
+
}
|
|
32338
|
+
function isSchemeHostPrefix(prefix) {
|
|
32339
|
+
if (!/^https?:\/\//i.test(prefix))
|
|
32340
|
+
return false;
|
|
32341
|
+
const afterScheme = prefix.replace(/^https?:\/\//i, "");
|
|
32342
|
+
return /[A-Za-z][A-Za-z0-9-]*\./.test(afterScheme);
|
|
32343
|
+
}
|
|
32344
|
+
function jsSsrfHostGuardedLines(code) {
|
|
32345
|
+
const covered = new Set;
|
|
32346
|
+
const lines = code.split(`
|
|
32347
|
+
`);
|
|
32348
|
+
const rejectRegexTest = /\bif\s*\(\s*!\s*\/((?:[^/\\]|\\.)*)\/[a-z]*\s*\.\s*test\s*\(\s*([A-Za-z_]\w*)\s*\)/;
|
|
32349
|
+
const rejectStartsWith = /\bif\s*\(\s*!\s*([A-Za-z_]\w*)\s*\.\s*startsWith\s*\(\s*["'`]([^"'`]+)["'`]/;
|
|
32350
|
+
const terminatorRe = /\b(throw|return)\b/;
|
|
32351
|
+
const assignRe = /^\s*(?:const|let|var\s+)?\s*([A-Za-z_]\w*)\s*=(?!=)\s*(.*)$/;
|
|
32352
|
+
for (let i2 = 0;i2 < lines.length; i2++) {
|
|
32353
|
+
let guardedVar = null;
|
|
32354
|
+
const rm = rejectRegexTest.exec(lines[i2]);
|
|
32355
|
+
if (rm && isAnchoredHostAllowlistRegex(rm[1]))
|
|
32356
|
+
guardedVar = rm[2];
|
|
32357
|
+
if (!guardedVar) {
|
|
32358
|
+
const sm = rejectStartsWith.exec(lines[i2]);
|
|
32359
|
+
if (sm && isSchemeHostPrefix(sm[2]))
|
|
32360
|
+
guardedVar = sm[1];
|
|
32361
|
+
}
|
|
32362
|
+
if (!guardedVar)
|
|
32363
|
+
continue;
|
|
32364
|
+
let hasTerminator = terminatorRe.test(lines[i2]);
|
|
32365
|
+
if (!hasTerminator) {
|
|
32366
|
+
for (let j = i2 + 1;j < Math.min(lines.length, i2 + 6); j++) {
|
|
32367
|
+
if (terminatorRe.test(lines[j])) {
|
|
32368
|
+
hasTerminator = true;
|
|
32369
|
+
break;
|
|
32370
|
+
}
|
|
32371
|
+
if (lines[j].includes("}"))
|
|
32372
|
+
break;
|
|
32373
|
+
}
|
|
32374
|
+
}
|
|
32375
|
+
if (!hasTerminator)
|
|
32376
|
+
continue;
|
|
32377
|
+
const guarded = new Set([guardedVar]);
|
|
32378
|
+
const mentionsGuarded = (text) => {
|
|
32379
|
+
for (const name2 of guarded)
|
|
32380
|
+
if (new RegExp(`\\b${name2}\\b`).test(text))
|
|
32381
|
+
return true;
|
|
32382
|
+
return false;
|
|
32383
|
+
};
|
|
32384
|
+
for (let l = i2 + 1;l < lines.length; l++) {
|
|
32385
|
+
const lineText = lines[l];
|
|
32386
|
+
const assign = assignRe.exec(lineText);
|
|
32387
|
+
if (assign) {
|
|
32388
|
+
if (mentionsGuarded(assign[2]))
|
|
32389
|
+
guarded.add(assign[1]);
|
|
32390
|
+
else if (assign[1] !== guardedVar)
|
|
32391
|
+
guarded.delete(assign[1]);
|
|
32392
|
+
}
|
|
32393
|
+
if (mentionsGuarded(lineText))
|
|
32394
|
+
covered.add(l + 1);
|
|
32395
|
+
}
|
|
32396
|
+
}
|
|
32397
|
+
return covered;
|
|
32398
|
+
}
|
|
32399
|
+
var CSHARP_SANITIZER_RES = [
|
|
32400
|
+
{ re: /\b(?:HtmlEncode|JavaScriptStringEncode)\s*\(/, type: "xss" },
|
|
32401
|
+
{ re: /\bHtmlEncoder\s*\.\s*Encode\s*\(/, type: "xss" },
|
|
32402
|
+
{ re: /\bPath\s*\.\s*GetFileName\s*\(/, type: "path_traversal" }
|
|
32403
|
+
];
|
|
32404
|
+
function csharpSanitizedVarsByType(code) {
|
|
32405
|
+
const lines = code.split(`
|
|
32406
|
+
`);
|
|
32407
|
+
const byType = new Map;
|
|
32408
|
+
const assignRe = /^\s*(?:var\s+|[A-Za-z_][\w.<>\[\]]*\s+)?([A-Za-z_]\w*)\s*=\s*(.+?);?\s*$/;
|
|
32409
|
+
for (const { type } of CSHARP_SANITIZER_RES) {
|
|
32410
|
+
if (!byType.has(type))
|
|
32411
|
+
byType.set(type, new Set);
|
|
32412
|
+
}
|
|
32413
|
+
for (const line of lines) {
|
|
32414
|
+
const m = assignRe.exec(line);
|
|
32415
|
+
if (!m)
|
|
32416
|
+
continue;
|
|
32417
|
+
const [, lhs, rhs] = m;
|
|
32418
|
+
for (const { re, type } of CSHARP_SANITIZER_RES) {
|
|
32419
|
+
if (re.test(rhs))
|
|
32420
|
+
byType.get(type).add(lhs);
|
|
32421
|
+
}
|
|
32422
|
+
}
|
|
32423
|
+
let changed = true;
|
|
32424
|
+
let guard = 0;
|
|
32425
|
+
while (changed && guard < lines.length + 2) {
|
|
32426
|
+
changed = false;
|
|
32427
|
+
guard++;
|
|
32428
|
+
for (const line of lines) {
|
|
32429
|
+
const m = assignRe.exec(line);
|
|
32430
|
+
if (!m)
|
|
32431
|
+
continue;
|
|
32432
|
+
const [, lhs, rhs] = m;
|
|
32433
|
+
for (const [type, set] of byType) {
|
|
32434
|
+
if (set.has(lhs))
|
|
32435
|
+
continue;
|
|
32436
|
+
const refsSanitized = [...set].some((v) => new RegExp(`(?<![\\w])${escapeRegex(v)}(?![\\w])`).test(rhs));
|
|
32437
|
+
if (refsSanitized) {
|
|
32438
|
+
set.add(lhs);
|
|
32439
|
+
changed = true;
|
|
32440
|
+
}
|
|
32441
|
+
}
|
|
32442
|
+
}
|
|
32443
|
+
}
|
|
32444
|
+
return byType;
|
|
32445
|
+
}
|
|
31906
32446
|
var JAVA_INLINE_MATCHES_RE = /\.\s*matches\s*\(\s*"((?:[^"\\]|\\.)*)"\s*\)/g;
|
|
31907
32447
|
function resolveJavaReceiverType(receiver, sinkLine, sourceLines) {
|
|
31908
32448
|
if (!receiver || !/^[A-Za-z_]\w*$/.test(receiver))
|
|
@@ -32702,6 +33242,70 @@ class SinkFilterPass {
|
|
|
32702
33242
|
}
|
|
32703
33243
|
if (["javascript", "typescript"].includes(language)) {
|
|
32704
33244
|
const sourceLines = ctx.code.split(`
|
|
33245
|
+
`);
|
|
33246
|
+
filtered = filtered.filter((sink) => {
|
|
33247
|
+
if (sink.type !== "nosql_injection")
|
|
33248
|
+
return true;
|
|
33249
|
+
if (!NOSQL_ARRAY_METHODS.has(sink.method ?? ""))
|
|
33250
|
+
return true;
|
|
33251
|
+
const sinkLineText = sourceLines[sink.line - 1] ?? "";
|
|
33252
|
+
return !FUNCTION_FIRST_ARG_RE.test(sinkLineText);
|
|
33253
|
+
});
|
|
33254
|
+
}
|
|
33255
|
+
if (["javascript", "typescript"].includes(language)) {
|
|
33256
|
+
const sourceLines = ctx.code.split(`
|
|
33257
|
+
`);
|
|
33258
|
+
filtered = filtered.filter((sink) => {
|
|
33259
|
+
if (sink.type !== "sql_injection" && sink.type !== "nosql_injection")
|
|
33260
|
+
return true;
|
|
33261
|
+
const sinkLineText = sourceLines[sink.line - 1] ?? "";
|
|
33262
|
+
return !ORM_BUILDER_KEY_RE.test(sinkLineText);
|
|
33263
|
+
});
|
|
33264
|
+
}
|
|
33265
|
+
if (["javascript", "typescript", "tsx"].includes(language)) {
|
|
33266
|
+
const file = ctx.graph?.ir?.meta?.file ?? "";
|
|
33267
|
+
if (BROWSER_COMPONENT_EXT_RE.test(file) && CLIENT_SIGNAL_RE.test(ctx.code) && !SERVER_SIGNAL_RE.test(ctx.code)) {
|
|
33268
|
+
filtered = filtered.filter((sink) => sink.type !== "ssrf");
|
|
33269
|
+
}
|
|
33270
|
+
}
|
|
33271
|
+
if (["javascript", "typescript"].includes(language)) {
|
|
33272
|
+
const sourceLines = ctx.code.split(`
|
|
33273
|
+
`);
|
|
33274
|
+
filtered = filtered.filter((sink) => {
|
|
33275
|
+
if (sink.type !== "ssrf")
|
|
33276
|
+
return true;
|
|
33277
|
+
const sinkLineText = sourceLines[sink.line - 1] ?? "";
|
|
33278
|
+
return !FIXED_HOST_TEMPLATE_RE.test(sinkLineText);
|
|
33279
|
+
});
|
|
33280
|
+
}
|
|
33281
|
+
if (["javascript", "typescript"].includes(language)) {
|
|
33282
|
+
const guardedLines = jsSsrfHostGuardedLines(ctx.code);
|
|
33283
|
+
if (guardedLines.size > 0) {
|
|
33284
|
+
filtered = filtered.filter((sink) => !(sink.type === "ssrf" && guardedLines.has(sink.line)));
|
|
33285
|
+
}
|
|
33286
|
+
}
|
|
33287
|
+
if (language === "csharp") {
|
|
33288
|
+
const sourceLines = ctx.code.split(`
|
|
33289
|
+
`);
|
|
33290
|
+
const sanitizedByType = csharpSanitizedVarsByType(ctx.code);
|
|
33291
|
+
filtered = filtered.filter((sink) => {
|
|
33292
|
+
const sinkLineText = sourceLines[sink.line - 1] ?? "";
|
|
33293
|
+
for (const { re, type } of CSHARP_SANITIZER_RES) {
|
|
33294
|
+
if (type === sink.type && re.test(sinkLineText))
|
|
33295
|
+
return false;
|
|
33296
|
+
}
|
|
33297
|
+
const sanitizedVars = sanitizedByType.get(sink.type);
|
|
33298
|
+
if (sanitizedVars && sanitizedVars.size > 0) {
|
|
33299
|
+
for (const v of sanitizedVars) {
|
|
33300
|
+
if (new RegExp(`(?<![\\w])${escapeRegex(v)}(?![\\w])`).test(sinkLineText))
|
|
33301
|
+
return false;
|
|
33302
|
+
}
|
|
33303
|
+
}
|
|
33304
|
+
return true;
|
|
33305
|
+
});
|
|
33306
|
+
}
|
|
33307
|
+
if (["javascript", "typescript"].includes(language)) {
|
|
33308
|
+
const sourceLines = ctx.code.split(`
|
|
32705
33309
|
`);
|
|
32706
33310
|
filtered = filtered.filter((sink) => {
|
|
32707
33311
|
if (sink.type !== "log_injection")
|
|
@@ -35343,7 +35947,7 @@ function detectExpressionScanFlows(calls, sources, sinks, sanitizers, unreachabl
|
|
|
35343
35947
|
}
|
|
35344
35948
|
}
|
|
35345
35949
|
}
|
|
35346
|
-
if (language === "java" && typeof code === "string" && sourcesWithVar.length > 0) {
|
|
35950
|
+
if ((language === "java" || language === "csharp") && typeof code === "string" && sourcesWithVar.length > 0) {
|
|
35347
35951
|
const seedVars = new Set(sourcesWithVar.map((s) => s.variable));
|
|
35348
35952
|
const derived = buildJavaTaintedVars(code, seedVars);
|
|
35349
35953
|
if (derived.size > 0) {
|
|
@@ -47152,7 +47756,7 @@ var colors = {
|
|
|
47152
47756
|
};
|
|
47153
47757
|
|
|
47154
47758
|
// src/version.ts
|
|
47155
|
-
var version = "
|
|
47759
|
+
var version = "4.0.0";
|
|
47156
47760
|
|
|
47157
47761
|
// src/formatters.ts
|
|
47158
47762
|
var LIBRARY_API_SURFACE_TAG2 = "library-api-surface:caller-responsibility";
|
|
@@ -48034,6 +48638,7 @@ var LANG_MAP = {
|
|
|
48034
48638
|
".tsx": "typescript",
|
|
48035
48639
|
".py": "python",
|
|
48036
48640
|
".go": "go",
|
|
48641
|
+
".cs": "csharp",
|
|
48037
48642
|
".rs": "rust",
|
|
48038
48643
|
".sh": "bash",
|
|
48039
48644
|
".bash": "bash",
|
|
@@ -48792,7 +49397,7 @@ async function handleInit() {
|
|
|
48792
49397
|
}
|
|
48793
49398
|
const config = {
|
|
48794
49399
|
version: "1.0",
|
|
48795
|
-
include: ["src/**/*.java", "src/**/*.ts", "src/**/*.js", "src/**/*.py", "src/**/*.go"],
|
|
49400
|
+
include: ["src/**/*.java", "src/**/*.ts", "src/**/*.js", "src/**/*.py", "src/**/*.go", "src/**/*.cs"],
|
|
48796
49401
|
exclude: ["**/test/**", "**/tests/**", "**/node_modules/**", "**/dist/**"],
|
|
48797
49402
|
passes: {
|
|
48798
49403
|
"naming-convention": false,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cognium-dev",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.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": "^
|
|
69
|
+
"circle-ir": "^4.0.0"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@types/node": "^25.5.0",
|