cognium-dev 3.102.0 → 3.104.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 +99 -2
  2. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -23544,6 +23544,7 @@ var PROTOCOL_CLIENT_PACKAGES = [
23544
23544
  ];
23545
23545
  var OS_EXEC_RECEIVER_RE = /\b(?:Runtime|ProcessBuilder|DefaultExecutor|Executor|Exec|Launcher|ProcStarter|ProcessExecutor|RuntimeUtil)\s*[.(]/;
23546
23546
  var PROCESS_BUILDER_ARGV_FORM_RE = /\bnew\s+ProcessBuilder\s*\(\s*(?:Arrays\.asList\b|List\.of\b|Collections\.singletonList\b|new\s+ArrayList\b|new\s+String\s*\[\s*\]\s*\{|"[^"]*"\s*,)/;
23547
+ var JAVA_THROW_STATEMENT_RE = /^\s*throw\s+new\s+\w+(?:Exception|Error)\b/;
23547
23548
  function resolveJavaReceiverType(receiver, sinkLine, sourceLines) {
23548
23549
  if (!receiver || !/^[A-Za-z_]\w*$/.test(receiver))
23549
23550
  return null;
@@ -23831,6 +23832,16 @@ class SinkFilterPass {
23831
23832
  return true;
23832
23833
  });
23833
23834
  }
23835
+ if (language === "java") {
23836
+ const sourceLines = ctx.code.split(`
23837
+ `);
23838
+ filtered = filtered.filter((sink) => {
23839
+ const sinkLineText = sourceLines[sink.line - 1] ?? "";
23840
+ if (JAVA_THROW_STATEMENT_RE.test(sinkLineText))
23841
+ return false;
23842
+ return true;
23843
+ });
23844
+ }
23834
23845
  return { sources, sinks: filtered, sanitizers };
23835
23846
  }
23836
23847
  }
@@ -26463,6 +26474,10 @@ class NullDerefPass {
26463
26474
  }
26464
26475
 
26465
26476
  // ../circle-ir/dist/analysis/passes/resource-leak-pass.js
26477
+ function escapeRegex(s) {
26478
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
26479
+ }
26480
+ var FACTORY_METHOD_NAME_RE = /^(?:open|create|new|get|make|build)[A-Z]/;
26466
26481
  var RESOURCE_CTORS = new Set([
26467
26482
  "FileInputStream",
26468
26483
  "FileOutputStream",
@@ -26537,7 +26552,18 @@ class ResourceLeakPass {
26537
26552
  const methodInfo = graph.methodAtLine(openLine);
26538
26553
  if (!methodInfo)
26539
26554
  continue;
26555
+ const methodStart = methodInfo.method.start_line;
26540
26556
  const methodEnd = methodInfo.method.end_line;
26557
+ if (this.isReturnedToCaller(codeLines, resourceVar, methodStart, methodEnd)) {
26558
+ continue;
26559
+ }
26560
+ const fieldName = this.fieldStoredName(codeLines, resourceVar, openLine, methodEnd);
26561
+ if (fieldName && this.classHasCloseMethodFor(graph, fieldName, methodInfo.type)) {
26562
+ continue;
26563
+ }
26564
+ if (this.isFactoryMethod(methodInfo.method)) {
26565
+ continue;
26566
+ }
26541
26567
  const closeCall = graph.ir.calls.find((c) => CLOSE_METHODS.has(c.method_name) && c.receiver === resourceVar && c.location.line > openLine && c.location.line <= methodEnd);
26542
26568
  const snippet = (codeLines[openLine - 1] ?? "").trim();
26543
26569
  if (!closeCall) {
@@ -26601,6 +26627,39 @@ class ResourceLeakPass {
26601
26627
  }
26602
26628
  return false;
26603
26629
  }
26630
+ isReturnedToCaller(lines, variable, fromLine, toLine) {
26631
+ const varRe = new RegExp(`\\breturn\\b[^;]*\\b${escapeRegex(variable)}\\b`);
26632
+ for (let l = fromLine;l <= toLine && l <= lines.length; l++) {
26633
+ if (varRe.test(lines[l - 1] ?? ""))
26634
+ return true;
26635
+ }
26636
+ return false;
26637
+ }
26638
+ fieldStoredName(lines, variable, openLine, toLine) {
26639
+ const thisAssignRe = new RegExp(`\\bthis\\s*\\.\\s*(\\w+)\\s*=\\s*${escapeRegex(variable)}\\b`);
26640
+ for (let l = openLine;l <= toLine && l <= lines.length; l++) {
26641
+ const m = thisAssignRe.exec(lines[l - 1] ?? "");
26642
+ if (m)
26643
+ return m[1];
26644
+ }
26645
+ return null;
26646
+ }
26647
+ classHasCloseMethodFor(graph, fieldName, type) {
26648
+ for (const c of graph.ir.calls) {
26649
+ if (c.location.line < type.start_line || c.location.line > type.end_line)
26650
+ continue;
26651
+ if (c.receiver !== fieldName)
26652
+ continue;
26653
+ if (CLOSE_METHODS.has(c.method_name))
26654
+ return true;
26655
+ }
26656
+ return false;
26657
+ }
26658
+ isFactoryMethod(method) {
26659
+ if (!method.return_type || method.return_type === "void")
26660
+ return false;
26661
+ return FACTORY_METHOD_NAME_RE.test(method.name);
26662
+ }
26604
26663
  }
26605
26664
 
26606
26665
  // ../circle-ir/dist/graph/scope-graph.js
@@ -29844,6 +29903,33 @@ function mapReturnValueToCorsRule(returnValue) {
29844
29903
  };
29845
29904
  }
29846
29905
 
29906
+ // ../circle-ir/dist/analysis/passes/_fp-allowlists.js
29907
+ var PEM_BODY_RE = /[A-Za-z0-9+/]{30,}/;
29908
+ function pemHasInlineBody(lines, hitLineIdx) {
29909
+ const end = Math.min(hitLineIdx + 5, lines.length);
29910
+ for (let l = hitLineIdx;l < end; l++) {
29911
+ if (PEM_BODY_RE.test(lines[l] ?? ""))
29912
+ return true;
29913
+ }
29914
+ return false;
29915
+ }
29916
+ var CLI_OPTION_KEY_RE = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)+$/;
29917
+ function isCliOptionKeyValue(value) {
29918
+ return value.length <= 48 && CLI_OPTION_KEY_RE.test(value);
29919
+ }
29920
+ var PROTOCOL_MANDATED_PATH_RE = /(?:^|[\\/])(?:ntlm|kerberos|krb5|smb1?|sasl[\\/]cram-md5?|digest)(?:[\\/]|$)/i;
29921
+ var PROTOCOL_MANDATED_CLASS_RE = /\b(?:N[Tt][Ll][Mm](?:Scheme|Engine|AuthHandler|AuthScheme)|Krb5\w+|KerberosClient|Smb\w*Signing|CramMd5\w*|DigestScheme)\b/;
29922
+ var PROTOCOL_MANDATED_CITATION_RE = /\b(?:MS-NLMP|RFC\s*4757|RFC\s*3961|RFC\s*2617|RFC\s*2195|CRAM-MD5)\b/i;
29923
+ function isProtocolMandatedCryptoFile(file, code) {
29924
+ if (PROTOCOL_MANDATED_PATH_RE.test(file))
29925
+ return true;
29926
+ if (PROTOCOL_MANDATED_CLASS_RE.test(code))
29927
+ return true;
29928
+ if (PROTOCOL_MANDATED_CITATION_RE.test(code))
29929
+ return true;
29930
+ return false;
29931
+ }
29932
+
29847
29933
  // ../circle-ir/dist/analysis/passes/scan-secrets-pass.js
29848
29934
  var TEST_PATH_RE3 = /(?:^|[\\/])(?:test|tests|spec|specs|__tests?__|__mocks?__|fixtures?|testdata)(?:[\\/]|$)/i;
29849
29935
  var TEST_FILENAME_RE = /(?:\.(?:test|spec)\.[cm]?[jt]sx?|_test\.go|_test\.py|Test\.java|Tests\.java)$/i;
@@ -30010,6 +30096,8 @@ function isLikelyCredentialAssignment(line) {
30010
30096
  return null;
30011
30097
  if (/^[0-9]+$/.test(value) && value.length < 16)
30012
30098
  return null;
30099
+ if (isCliOptionKeyValue(value))
30100
+ return null;
30013
30101
  return { name: name2, value };
30014
30102
  }
30015
30103
  var STRING_LITERAL_RE = /(["'`])((?:\\.|(?!\1).){8,200})\1/g;
@@ -30216,6 +30304,9 @@ class ScanSecretsPass {
30216
30304
  const m = pattern.regex.exec(lineText);
30217
30305
  if (!m)
30218
30306
  continue;
30307
+ if (pattern.name === "PEM private key" && !pemHasInlineBody(lines, i2)) {
30308
+ continue;
30309
+ }
30219
30310
  const key = `${lineNum}:hardcoded-credential`;
30220
30311
  if (seen.has(key))
30221
30312
  continue;
@@ -31090,6 +31181,9 @@ class WeakCryptoPass {
31090
31181
  run(ctx) {
31091
31182
  const { graph, language, code } = ctx;
31092
31183
  const file = graph.ir.meta.file;
31184
+ if (isProtocolMandatedCryptoFile(file, code)) {
31185
+ return { findings: [] };
31186
+ }
31093
31187
  const findings = [];
31094
31188
  const constProp = ctx.hasResult("constant-propagation") ? ctx.getResult("constant-propagation") : null;
31095
31189
  const literalBindings = scanLiteralBindings(code, language);
@@ -31620,8 +31714,11 @@ class WeakPasswordHashPass {
31620
31714
  name = "weak-password-hash";
31621
31715
  category = "security";
31622
31716
  run(ctx) {
31623
- const { graph, language } = ctx;
31717
+ const { graph, language, code } = ctx;
31624
31718
  const file = graph.ir.meta.file;
31719
+ if (isProtocolMandatedCryptoFile(file, code)) {
31720
+ return { findings: [] };
31721
+ }
31625
31722
  const findings = [];
31626
31723
  for (const call of graph.ir.calls) {
31627
31724
  const detection = this.detect(call, language);
@@ -34956,7 +35053,7 @@ var colors = {
34956
35053
  };
34957
35054
 
34958
35055
  // src/version.ts
34959
- var version = "3.102.0";
35056
+ var version = "3.104.0";
34960
35057
 
34961
35058
  // src/formatters.ts
34962
35059
  var SINK_SEVERITY = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cognium-dev",
3
- "version": "3.102.0",
3
+ "version": "3.104.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.102.0"
68
+ "circle-ir": "^3.104.0"
69
69
  },
70
70
  "devDependencies": {
71
71
  "@types/node": "^25.5.0",