cognium-dev 3.42.0 → 3.44.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 +151 -9
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -5321,11 +5321,22 @@ function inferJSTypeFromReceiver(receiver) {
|
|
|
5321
5321
|
function buildResolutionContext(tree, cache) {
|
|
5322
5322
|
const context = {
|
|
5323
5323
|
className: null,
|
|
5324
|
+
packageName: null,
|
|
5324
5325
|
methodNames: new Set,
|
|
5325
5326
|
fieldTypes: new Map,
|
|
5326
5327
|
localVarTypes: new Map,
|
|
5327
|
-
|
|
5328
|
+
paramTypes: new Map,
|
|
5329
|
+
imports: new Map,
|
|
5330
|
+
wildcardImports: []
|
|
5328
5331
|
};
|
|
5332
|
+
const packages = getNodesFromCache(tree.rootNode, "package_declaration", cache);
|
|
5333
|
+
if (packages.length > 0) {
|
|
5334
|
+
const text = getNodeText(packages[0]);
|
|
5335
|
+
const match = text.match(/package\s+([a-zA-Z0-9_.]+)/);
|
|
5336
|
+
if (match) {
|
|
5337
|
+
context.packageName = match[1];
|
|
5338
|
+
}
|
|
5339
|
+
}
|
|
5329
5340
|
const classes = getNodesFromCache(tree.rootNode, "class_declaration", cache);
|
|
5330
5341
|
if (classes.length > 0) {
|
|
5331
5342
|
const nameNode = classes[0].childForFieldName("name");
|
|
@@ -5339,6 +5350,17 @@ function buildResolutionContext(tree, cache) {
|
|
|
5339
5350
|
if (nameNode) {
|
|
5340
5351
|
context.methodNames.add(getNodeText(nameNode));
|
|
5341
5352
|
}
|
|
5353
|
+
const paramsNode = method.childForFieldName("parameters");
|
|
5354
|
+
if (paramsNode) {
|
|
5355
|
+
collectParameterTypes(paramsNode, context.paramTypes);
|
|
5356
|
+
}
|
|
5357
|
+
}
|
|
5358
|
+
const constructors = getNodesFromCache(tree.rootNode, "constructor_declaration", cache);
|
|
5359
|
+
for (const ctor of constructors) {
|
|
5360
|
+
const paramsNode = ctor.childForFieldName("parameters");
|
|
5361
|
+
if (paramsNode) {
|
|
5362
|
+
collectParameterTypes(paramsNode, context.paramTypes);
|
|
5363
|
+
}
|
|
5342
5364
|
}
|
|
5343
5365
|
const fields = getNodesFromCache(tree.rootNode, "field_declaration", cache);
|
|
5344
5366
|
for (const field of fields) {
|
|
@@ -5371,14 +5393,112 @@ function buildResolutionContext(tree, cache) {
|
|
|
5371
5393
|
const imports = getNodesFromCache(tree.rootNode, "import_declaration", cache);
|
|
5372
5394
|
for (const imp of imports) {
|
|
5373
5395
|
const text = getNodeText(imp);
|
|
5374
|
-
const match = text.match(/import\s+(?:static\s+)?([a-zA-Z0-9_.]+)
|
|
5375
|
-
if (match)
|
|
5376
|
-
|
|
5377
|
-
|
|
5396
|
+
const match = text.match(/import\s+(?:static\s+)?([a-zA-Z0-9_.]+)(\.\*)?/);
|
|
5397
|
+
if (!match)
|
|
5398
|
+
continue;
|
|
5399
|
+
const fqn = match[1];
|
|
5400
|
+
const isWildcard = match[2] === ".*";
|
|
5401
|
+
if (isWildcard) {
|
|
5402
|
+
context.wildcardImports.push(fqn);
|
|
5403
|
+
} else {
|
|
5404
|
+
const parts2 = fqn.split(".");
|
|
5405
|
+
const simple = parts2[parts2.length - 1];
|
|
5406
|
+
context.imports.set(simple, fqn);
|
|
5378
5407
|
}
|
|
5379
5408
|
}
|
|
5380
5409
|
return context;
|
|
5381
5410
|
}
|
|
5411
|
+
function collectParameterTypes(paramsNode, out2) {
|
|
5412
|
+
for (let i2 = 0;i2 < paramsNode.childCount; i2++) {
|
|
5413
|
+
const child = paramsNode.child(i2);
|
|
5414
|
+
if (!child)
|
|
5415
|
+
continue;
|
|
5416
|
+
if (child.type !== "formal_parameter" && child.type !== "spread_parameter") {
|
|
5417
|
+
continue;
|
|
5418
|
+
}
|
|
5419
|
+
const typeNode = child.childForFieldName("type");
|
|
5420
|
+
const nameNode = child.childForFieldName("name");
|
|
5421
|
+
if (typeNode && nameNode) {
|
|
5422
|
+
out2.set(getNodeText(nameNode), getNodeText(typeNode));
|
|
5423
|
+
}
|
|
5424
|
+
}
|
|
5425
|
+
}
|
|
5426
|
+
function stripGenerics(type) {
|
|
5427
|
+
const ltIdx = type.indexOf("<");
|
|
5428
|
+
return ltIdx === -1 ? type : type.substring(0, ltIdx);
|
|
5429
|
+
}
|
|
5430
|
+
function resolveReceiverType(receiver, context) {
|
|
5431
|
+
if (!receiver)
|
|
5432
|
+
return { simpleName: null, fqn: null };
|
|
5433
|
+
if (receiver === "this") {
|
|
5434
|
+
return resolveFqn(context.className, context);
|
|
5435
|
+
}
|
|
5436
|
+
if (receiver.startsWith("this.")) {
|
|
5437
|
+
const fieldName = receiver.substring("this.".length);
|
|
5438
|
+
const fieldType = context.fieldTypes.get(fieldName);
|
|
5439
|
+
if (fieldType)
|
|
5440
|
+
return resolveFqn(stripGenerics(fieldType), context);
|
|
5441
|
+
return { simpleName: null, fqn: null };
|
|
5442
|
+
}
|
|
5443
|
+
if (receiver === "super")
|
|
5444
|
+
return { simpleName: null, fqn: null };
|
|
5445
|
+
const declaredType = context.localVarTypes.get(receiver) ?? context.paramTypes.get(receiver) ?? context.fieldTypes.get(receiver);
|
|
5446
|
+
if (declaredType) {
|
|
5447
|
+
return resolveFqn(stripGenerics(declaredType), context);
|
|
5448
|
+
}
|
|
5449
|
+
if (/^[A-Z]/.test(receiver)) {
|
|
5450
|
+
const simple = receiver.includes(".") ? receiver.substring(receiver.lastIndexOf(".") + 1) : receiver;
|
|
5451
|
+
if (/^[A-Z][A-Za-z0-9_]*$/.test(simple)) {
|
|
5452
|
+
return resolveFqn(simple, context);
|
|
5453
|
+
}
|
|
5454
|
+
}
|
|
5455
|
+
return { simpleName: null, fqn: null };
|
|
5456
|
+
}
|
|
5457
|
+
function resolveFqn(simpleName, context) {
|
|
5458
|
+
if (!simpleName)
|
|
5459
|
+
return { simpleName: null, fqn: null };
|
|
5460
|
+
const importedFqn = context.imports.get(simpleName);
|
|
5461
|
+
if (importedFqn) {
|
|
5462
|
+
return { simpleName, fqn: importedFqn };
|
|
5463
|
+
}
|
|
5464
|
+
if (context.className === simpleName && context.packageName) {
|
|
5465
|
+
return { simpleName, fqn: `${context.packageName}.${simpleName}` };
|
|
5466
|
+
}
|
|
5467
|
+
if (JAVA_LANG_TYPES.has(simpleName)) {
|
|
5468
|
+
return { simpleName, fqn: `java.lang.${simpleName}` };
|
|
5469
|
+
}
|
|
5470
|
+
return { simpleName, fqn: null };
|
|
5471
|
+
}
|
|
5472
|
+
var JAVA_LANG_TYPES = new Set([
|
|
5473
|
+
"String",
|
|
5474
|
+
"StringBuilder",
|
|
5475
|
+
"StringBuffer",
|
|
5476
|
+
"Object",
|
|
5477
|
+
"Class",
|
|
5478
|
+
"Integer",
|
|
5479
|
+
"Long",
|
|
5480
|
+
"Double",
|
|
5481
|
+
"Float",
|
|
5482
|
+
"Boolean",
|
|
5483
|
+
"Character",
|
|
5484
|
+
"Byte",
|
|
5485
|
+
"Short",
|
|
5486
|
+
"Number",
|
|
5487
|
+
"Math",
|
|
5488
|
+
"System",
|
|
5489
|
+
"Thread",
|
|
5490
|
+
"Runnable",
|
|
5491
|
+
"Throwable",
|
|
5492
|
+
"Exception",
|
|
5493
|
+
"RuntimeException",
|
|
5494
|
+
"Error",
|
|
5495
|
+
"Process",
|
|
5496
|
+
"ProcessBuilder",
|
|
5497
|
+
"Iterable",
|
|
5498
|
+
"Comparable",
|
|
5499
|
+
"CharSequence",
|
|
5500
|
+
"Enum"
|
|
5501
|
+
]);
|
|
5382
5502
|
function extractCallInfo(node, context) {
|
|
5383
5503
|
const nameNode = node.childForFieldName("name");
|
|
5384
5504
|
const methodName = nameNode ? getNodeText(nameNode) : "unknown";
|
|
@@ -5388,9 +5508,12 @@ function extractCallInfo(node, context) {
|
|
|
5388
5508
|
const args2 = argsNode ? extractArguments(argsNode) : [];
|
|
5389
5509
|
const enclosingMethod = findEnclosingMethod(node);
|
|
5390
5510
|
const { resolved, resolution } = resolveMethodCall(methodName, receiver, context);
|
|
5511
|
+
const { simpleName, fqn } = resolveReceiverType(receiver, context);
|
|
5391
5512
|
return {
|
|
5392
5513
|
method_name: methodName,
|
|
5393
5514
|
receiver,
|
|
5515
|
+
receiver_type: simpleName,
|
|
5516
|
+
receiver_type_fqn: fqn,
|
|
5394
5517
|
arguments: args2,
|
|
5395
5518
|
location: {
|
|
5396
5519
|
line: node.startPosition.row + 1,
|
|
@@ -5413,9 +5536,13 @@ function extractObjectCreation(node, context) {
|
|
|
5413
5536
|
status: "resolved",
|
|
5414
5537
|
target: `${typeName}.<init>`
|
|
5415
5538
|
};
|
|
5539
|
+
const simpleType = stripGenerics(typeName);
|
|
5540
|
+
const { simpleName, fqn } = resolveFqn(simpleType, context);
|
|
5416
5541
|
return {
|
|
5417
5542
|
method_name: typeName,
|
|
5418
5543
|
receiver: null,
|
|
5544
|
+
receiver_type: simpleName,
|
|
5545
|
+
receiver_type_fqn: fqn,
|
|
5419
5546
|
arguments: args2,
|
|
5420
5547
|
location: {
|
|
5421
5548
|
line: node.startPosition.row + 1,
|
|
@@ -11645,6 +11772,11 @@ function isKnownSafeReceiverForMethod(receiver, method, sinkType) {
|
|
|
11645
11772
|
}
|
|
11646
11773
|
return false;
|
|
11647
11774
|
}
|
|
11775
|
+
var SINK_FQN_EXCLUSIONS = {
|
|
11776
|
+
sql_injection: [
|
|
11777
|
+
"net.sf.jsqlparser."
|
|
11778
|
+
]
|
|
11779
|
+
};
|
|
11648
11780
|
function matchesSinkPattern(call, pattern, typeHierarchy, language) {
|
|
11649
11781
|
if (pattern.languages && pattern.languages.length > 0 && language !== undefined) {
|
|
11650
11782
|
if (!pattern.languages.includes(language)) {
|
|
@@ -11661,6 +11793,16 @@ function matchesSinkPattern(call, pattern, typeHierarchy, language) {
|
|
|
11661
11793
|
if (!methodMatches) {
|
|
11662
11794
|
return false;
|
|
11663
11795
|
}
|
|
11796
|
+
if (call.receiver_type_fqn) {
|
|
11797
|
+
const exclusions = SINK_FQN_EXCLUSIONS[pattern.type];
|
|
11798
|
+
if (exclusions) {
|
|
11799
|
+
for (const prefix of exclusions) {
|
|
11800
|
+
if (call.receiver_type_fqn.startsWith(prefix)) {
|
|
11801
|
+
return false;
|
|
11802
|
+
}
|
|
11803
|
+
}
|
|
11804
|
+
}
|
|
11805
|
+
}
|
|
11664
11806
|
if (pattern.class) {
|
|
11665
11807
|
if (pattern.class === "constructor") {
|
|
11666
11808
|
return true;
|
|
@@ -18744,7 +18886,7 @@ class CrossFileResolver {
|
|
|
18744
18886
|
fieldName = exprMatch[2];
|
|
18745
18887
|
}
|
|
18746
18888
|
}
|
|
18747
|
-
const
|
|
18889
|
+
const resolveReceiverType2 = (rcv) => {
|
|
18748
18890
|
const param = method.parameters.find((p) => p.name === rcv);
|
|
18749
18891
|
if (param?.type)
|
|
18750
18892
|
return param.type;
|
|
@@ -18755,13 +18897,13 @@ class CrossFileResolver {
|
|
|
18755
18897
|
};
|
|
18756
18898
|
let receiverType = null;
|
|
18757
18899
|
if (receiver && fieldName) {
|
|
18758
|
-
receiverType =
|
|
18900
|
+
receiverType = resolveReceiverType2(receiver);
|
|
18759
18901
|
}
|
|
18760
18902
|
if (!receiverType) {
|
|
18761
18903
|
for (const rcvUse of usesAtLine) {
|
|
18762
18904
|
if (!rcvUse.variable || rcvUse.variable === def.variable)
|
|
18763
18905
|
continue;
|
|
18764
|
-
const rt =
|
|
18906
|
+
const rt = resolveReceiverType2(rcvUse.variable);
|
|
18765
18907
|
if (!rt)
|
|
18766
18908
|
continue;
|
|
18767
18909
|
const fieldUse = usesAtLine.find((u) => u !== rcvUse && !!u.variable && u.variable !== def.variable && u.variable !== rcvUse.variable && this.typeHasField(rt, u.variable));
|
|
@@ -27652,7 +27794,7 @@ var colors = {
|
|
|
27652
27794
|
};
|
|
27653
27795
|
|
|
27654
27796
|
// src/version.ts
|
|
27655
|
-
var version = "3.
|
|
27797
|
+
var version = "3.44.0";
|
|
27656
27798
|
|
|
27657
27799
|
// src/formatters.ts
|
|
27658
27800
|
var SINK_SEVERITY = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cognium-dev",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.44.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.44.0"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
71
|
"@types/node": "^25.5.0",
|