cognium-dev 3.77.0 → 3.79.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 +82 -7
  2. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -29334,6 +29334,17 @@ var COMMONS_DIGEST_METHODS = new Set([
29334
29334
  "sha",
29335
29335
  "shaHex"
29336
29336
  ]);
29337
+ var COMMONS_DIGEST_GETTERS = {
29338
+ getMd2Digest: "md2",
29339
+ getMd5Digest: "md5",
29340
+ getSha1Digest: "sha1",
29341
+ getShaDigest: "sha1"
29342
+ };
29343
+ var COMMONS_ALGO_CONSTANTS = {
29344
+ "MessageDigestAlgorithms.MD2": "md2",
29345
+ "MessageDigestAlgorithms.MD5": "md5",
29346
+ "MessageDigestAlgorithms.SHA_1": "sha1"
29347
+ };
29337
29348
  var PY_HASHLIB_WEAK = new Set(["md5", "sha1", "md4", "md2", "new"]);
29338
29349
  function stripQuotes4(s) {
29339
29350
  const trimmed = s.trim();
@@ -29350,16 +29361,68 @@ function literalAlgo(call, position) {
29350
29361
  const cleaned = stripQuotes4(raw).toLowerCase();
29351
29362
  return cleaned || null;
29352
29363
  }
29364
+ function resolveJavaAlgo(call, position, constProp, javaBindings) {
29365
+ const arg = call.arguments.find((a) => a.position === position);
29366
+ if (!arg)
29367
+ return null;
29368
+ if (arg.literal) {
29369
+ const cleaned = stripQuotes4(arg.literal).toLowerCase();
29370
+ if (cleaned)
29371
+ return cleaned;
29372
+ }
29373
+ const expr = (arg.expression ?? "").trim();
29374
+ if (expr.startsWith('"') || expr.startsWith("`") || expr.startsWith("'")) {
29375
+ const cleaned = stripQuotes4(expr).toLowerCase();
29376
+ if (cleaned)
29377
+ return cleaned;
29378
+ }
29379
+ if (COMMONS_ALGO_CONSTANTS[expr])
29380
+ return COMMONS_ALGO_CONSTANTS[expr];
29381
+ const tail = expr.split(".").slice(-2).join(".");
29382
+ if (COMMONS_ALGO_CONSTANTS[tail])
29383
+ return COMMONS_ALGO_CONSTANTS[tail];
29384
+ if (arg.variable && constProp) {
29385
+ const sym = constProp.symbols?.get(arg.variable);
29386
+ if (sym && sym.type === "string" && typeof sym.value === "string") {
29387
+ const cleaned = stripQuotes4(sym.value).toLowerCase();
29388
+ if (cleaned)
29389
+ return cleaned;
29390
+ }
29391
+ }
29392
+ if (arg.variable) {
29393
+ const bound = javaBindings.get(arg.variable);
29394
+ if (bound) {
29395
+ const cleaned = stripQuotes4(bound).toLowerCase();
29396
+ if (cleaned)
29397
+ return cleaned;
29398
+ }
29399
+ }
29400
+ return null;
29401
+ }
29402
+ function scanJavaStringBindings(code) {
29403
+ const out2 = new Map;
29404
+ if (!code)
29405
+ return out2;
29406
+ const re = /^[ \t]*(?:(?:public|private|protected|static|final|volatile)\s+){0,5}String\s+([A-Za-z_][A-Za-z0-9_]*)\s*=\s*("[^"]*")\s*;/gm;
29407
+ let m;
29408
+ while ((m = re.exec(code)) !== null) {
29409
+ if (m[1] && m[2])
29410
+ out2.set(m[1], m[2]);
29411
+ }
29412
+ return out2;
29413
+ }
29353
29414
 
29354
29415
  class WeakHashPass {
29355
29416
  name = "weak-hash";
29356
29417
  category = "security";
29357
29418
  run(ctx) {
29358
- const { graph, language } = ctx;
29419
+ const { graph, language, code } = ctx;
29359
29420
  const file = graph.ir.meta.file;
29360
29421
  const findings = [];
29422
+ const constProp = ctx.hasResult("constant-propagation") ? ctx.getResult("constant-propagation") : null;
29423
+ const javaBindings = language === "java" ? scanJavaStringBindings(code) : new Map;
29361
29424
  for (const call of graph.ir.calls) {
29362
- const detection = this.detect(call, language);
29425
+ const detection = this.detect(call, language, constProp, javaBindings);
29363
29426
  if (!detection)
29364
29427
  continue;
29365
29428
  const { algorithm, api } = detection;
@@ -29382,12 +29445,12 @@ class WeakHashPass {
29382
29445
  }
29383
29446
  return { findings };
29384
29447
  }
29385
- detect(call, language) {
29448
+ detect(call, language, constProp, javaBindings) {
29386
29449
  const method = call.method_name;
29387
29450
  const receiver = call.receiver ?? "";
29388
29451
  if (language === "java") {
29389
29452
  if (method === "getInstance" && (receiver === "MessageDigest" || receiver.endsWith(".MessageDigest"))) {
29390
- const algo = literalAlgo(call, 0);
29453
+ const algo = resolveJavaAlgo(call, 0, constProp, javaBindings);
29391
29454
  if (algo && WEAK_HASH_NAMES.has(algo)) {
29392
29455
  return { algorithm: algo, api: "MessageDigest.getInstance" };
29393
29456
  }
@@ -29397,6 +29460,9 @@ class WeakHashPass {
29397
29460
  const normalized = algoFromMethod === "sha" ? "sha1" : algoFromMethod;
29398
29461
  return { algorithm: normalized, api: `DigestUtils.${method}` };
29399
29462
  }
29463
+ if (COMMONS_DIGEST_GETTERS[method] && (receiver === "DigestUtils" || receiver.endsWith(".DigestUtils"))) {
29464
+ return { algorithm: COMMONS_DIGEST_GETTERS[method], api: `DigestUtils.${method}` };
29465
+ }
29400
29466
  return null;
29401
29467
  }
29402
29468
  if (language === "python") {
@@ -29706,8 +29772,9 @@ class WeakCryptoPass {
29706
29772
  const receiver = call.receiver ?? "";
29707
29773
  const out2 = [];
29708
29774
  if (language === "java") {
29709
- const isCipherFactory = method === "getInstance" && (receiver === "Cipher" || receiver.endsWith(".Cipher") || receiver === "KeyGenerator" || receiver.endsWith(".KeyGenerator"));
29710
- if (isCipherFactory) {
29775
+ const isCipherInstance = method === "getInstance" && (receiver === "Cipher" || receiver.endsWith(".Cipher"));
29776
+ const isKeyGenInstance = method === "getInstance" && (receiver === "KeyGenerator" || receiver.endsWith(".KeyGenerator"));
29777
+ if (isCipherInstance) {
29711
29778
  const spec = literalAlgo2(call, 0);
29712
29779
  if (spec) {
29713
29780
  const { weakBase, ecb } = classifyJavaCipherSpec(spec);
@@ -29717,6 +29784,14 @@ class WeakCryptoPass {
29717
29784
  if (ecb)
29718
29785
  out2.push({ issue: "ecb-mode", detail: spec, api });
29719
29786
  }
29787
+ } else if (isKeyGenInstance) {
29788
+ const spec = literalAlgo2(call, 0);
29789
+ if (spec) {
29790
+ const { weakBase } = classifyJavaCipherSpec(spec);
29791
+ const api = `${receiver}.getInstance`;
29792
+ if (weakBase)
29793
+ out2.push({ issue: "weak-cipher", detail: weakBase, api });
29794
+ }
29720
29795
  }
29721
29796
  if (method === "IvParameterSpec" && isJavaCtor(call, "IvParameterSpec")) {
29722
29797
  const ivDetail = detectStaticIvJava(call);
@@ -32540,7 +32615,7 @@ var colors = {
32540
32615
  };
32541
32616
 
32542
32617
  // src/version.ts
32543
- var version = "3.77.0";
32618
+ var version = "3.79.0";
32544
32619
 
32545
32620
  // src/formatters.ts
32546
32621
  var SINK_SEVERITY = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cognium-dev",
3
- "version": "3.77.0",
3
+ "version": "3.79.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.77.0"
68
+ "circle-ir": "^3.79.0"
69
69
  },
70
70
  "devDependencies": {
71
71
  "@types/node": "^25.5.0",