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.
Files changed (2) hide show
  1. package/dist/cli.js +151 -9
  2. 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
- imports: new Set
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
- const parts2 = match[1].split(".");
5377
- context.imports.add(parts2[parts2.length - 1]);
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 resolveReceiverType = (rcv) => {
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 = resolveReceiverType(receiver);
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 = resolveReceiverType(rcvUse.variable);
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.42.0";
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.42.0",
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.42.0"
68
+ "circle-ir": "^3.44.0"
69
69
  },
70
70
  "devDependencies": {
71
71
  "@types/node": "^25.5.0",