cognium-dev 3.99.0 → 3.101.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 +172 -1
  2. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -23490,6 +23490,106 @@ var JS_XSS_SANITIZERS = [
23490
23490
  /\btrustAsHtml\s*\(/,
23491
23491
  /\bbypassSecurityTrust/
23492
23492
  ];
23493
+ var DATA_PARSER_TYPES = new Set([
23494
+ "Parser",
23495
+ "CommandLine",
23496
+ "JCommander",
23497
+ "DateParser",
23498
+ "FastDateFormat",
23499
+ "FastDatePrinter",
23500
+ "ResultParser",
23501
+ "DateFormat",
23502
+ "SimpleDateFormat",
23503
+ "NumberFormat",
23504
+ "DecimalFormat",
23505
+ "OptionParser",
23506
+ "CmdLineParser"
23507
+ ]);
23508
+ var COMPILED_TEMPLATE_TYPES = new Set([
23509
+ "Template",
23510
+ "JetTemplate",
23511
+ "ITemplate",
23512
+ "VelocityTemplate",
23513
+ "BeetlTemplate"
23514
+ ]);
23515
+ var REFLECTION_LITERAL_METHODS = new Set([
23516
+ "forName",
23517
+ "loadClass",
23518
+ "getMethod",
23519
+ "getDeclaredMethod",
23520
+ "getConstructor",
23521
+ "getDeclaredConstructor",
23522
+ "parseExpression",
23523
+ "invoke"
23524
+ ]);
23525
+ var JAVA_DECL_RE_TEMPLATE = "(?:\\b(?:final|public|private|protected|static)\\s+)*" + "([A-Z]\\w*(?:\\.[A-Z]\\w*)?(?:<[^>]*>)?)\\s+RECV\\b\\s*[=;,)]";
23526
+ var PROTOCOL_WIRE_METHODS = new Set([
23527
+ "executeCommand",
23528
+ "execute",
23529
+ "dispatch",
23530
+ "send",
23531
+ "publish",
23532
+ "command",
23533
+ "run"
23534
+ ]);
23535
+ var PROTOCOL_CLIENT_PACKAGES = [
23536
+ "redis.clients.jedis",
23537
+ "io.lettuce",
23538
+ "org.springframework.data.redis",
23539
+ "org.springframework.data.mongodb",
23540
+ "org.springframework.amqp",
23541
+ "com.rabbitmq",
23542
+ "org.apache.kafka",
23543
+ "org.eclipse.paho"
23544
+ ];
23545
+ var OS_EXEC_RECEIVER_RE = /\b(?:Runtime|ProcessBuilder|DefaultExecutor|Executor|Exec|Launcher|ProcStarter|ProcessExecutor|RuntimeUtil)\s*[.(]/;
23546
+ function resolveJavaReceiverType(receiver, sinkLine, sourceLines) {
23547
+ if (!receiver || !/^[A-Za-z_]\w*$/.test(receiver))
23548
+ return null;
23549
+ const start2 = Math.max(0, sinkLine - 31);
23550
+ const declRe = new RegExp(JAVA_DECL_RE_TEMPLATE.replace("RECV", receiver));
23551
+ for (let i2 = sinkLine - 2;i2 >= start2; i2--) {
23552
+ const ln = sourceLines[i2] ?? "";
23553
+ const m = ln.match(declRe);
23554
+ if (m) {
23555
+ const raw = m[1].replace(/<[^>]*>/g, "").trim();
23556
+ const parts2 = raw.split(".");
23557
+ return parts2[parts2.length - 1] ?? null;
23558
+ }
23559
+ }
23560
+ return null;
23561
+ }
23562
+ function isJavaLiteralOrAnnotationAccessor(expr) {
23563
+ const e = expr.trim();
23564
+ if (e === "")
23565
+ return true;
23566
+ if (/^"(?:[^"\\]|\\.)*"$/.test(e))
23567
+ return true;
23568
+ if (/^[A-Za-z_]\w*\s*\.\s*(?:value|name|key)\s*\(\s*\)$/.test(e))
23569
+ return true;
23570
+ return false;
23571
+ }
23572
+ function extractJavaCallArgs(method, line) {
23573
+ const re = new RegExp(`\\b${method}\\s*\\(([^()]*(?:\\([^()]*\\)[^()]*)*)\\)`);
23574
+ const m = line.match(re);
23575
+ if (!m)
23576
+ return null;
23577
+ const argsText = m[1].trim();
23578
+ if (argsText === "")
23579
+ return [];
23580
+ return argsText.split(",").map((s) => s.trim());
23581
+ }
23582
+ function hasJavaImportFromPackage(packagePrefix, sourceLines) {
23583
+ if (!/^[A-Za-z_][\w.]*$/.test(packagePrefix))
23584
+ return false;
23585
+ const limit = Math.min(sourceLines.length, 80);
23586
+ const re = new RegExp(`^\\s*import\\s+(?:static\\s+)?${packagePrefix.replace(/\./g, "\\.")}\\b`);
23587
+ for (let i2 = 0;i2 < limit; i2++) {
23588
+ if (re.test(sourceLines[i2] ?? ""))
23589
+ return true;
23590
+ }
23591
+ return false;
23592
+ }
23493
23593
 
23494
23594
  class SinkFilterPass {
23495
23595
  name = "sink-filter";
@@ -23653,6 +23753,67 @@ class SinkFilterPass {
23653
23753
  return true;
23654
23754
  });
23655
23755
  }
23756
+ if (language === "java") {
23757
+ const sourceLines = ctx.code.split(`
23758
+ `);
23759
+ filtered = filtered.filter((sink) => {
23760
+ if (sink.type !== "code_injection")
23761
+ return true;
23762
+ const sinkLineText = sourceLines[sink.line - 1] ?? "";
23763
+ const receiverMatch = sinkLineText.match(/\b(\w+)\s*\.\s*(\w+)\s*\(/);
23764
+ const receiver = receiverMatch?.[1];
23765
+ const method = sink.method ?? receiverMatch?.[2];
23766
+ if (method === "parse" && receiver) {
23767
+ const recvType = resolveJavaReceiverType(receiver, sink.line, sourceLines);
23768
+ if (recvType && DATA_PARSER_TYPES.has(recvType))
23769
+ return false;
23770
+ }
23771
+ if ((method === "render" || method === "process" || method === "merge" || method === "renderTo") && receiver) {
23772
+ const recvType = resolveJavaReceiverType(receiver, sink.line, sourceLines);
23773
+ if (recvType && COMPILED_TEMPLATE_TYPES.has(recvType))
23774
+ return false;
23775
+ }
23776
+ if (method && REFLECTION_LITERAL_METHODS.has(method)) {
23777
+ const args2 = extractJavaCallArgs(method, sinkLineText);
23778
+ if (args2 !== null) {
23779
+ if (method === "invoke") {
23780
+ if (args2.length <= 1)
23781
+ return false;
23782
+ } else {
23783
+ const firstArg = args2[0] ?? "";
23784
+ if (isJavaLiteralOrAnnotationAccessor(firstArg))
23785
+ return false;
23786
+ }
23787
+ }
23788
+ }
23789
+ if (method === "newInstance" && /\.\s*newInstance\s*\(\s*\)/.test(sinkLineText)) {
23790
+ return false;
23791
+ }
23792
+ return true;
23793
+ });
23794
+ }
23795
+ if (language === "java") {
23796
+ const sourceLines = ctx.code.split(`
23797
+ `);
23798
+ filtered = filtered.filter((sink) => {
23799
+ if (sink.type !== "command_injection")
23800
+ return true;
23801
+ const sinkLineText = sourceLines[sink.line - 1] ?? "";
23802
+ if (sink.method === "CommandLine" && /\bnew\s+CommandLine\s*\(/.test(sinkLineText) && hasJavaImportFromPackage("picocli", sourceLines)) {
23803
+ return false;
23804
+ }
23805
+ if (sink.method && PROTOCOL_WIRE_METHODS.has(sink.method)) {
23806
+ for (const pkg of PROTOCOL_CLIENT_PACKAGES) {
23807
+ if (hasJavaImportFromPackage(pkg, sourceLines)) {
23808
+ if (!OS_EXEC_RECEIVER_RE.test(sinkLineText)) {
23809
+ return false;
23810
+ }
23811
+ }
23812
+ }
23813
+ }
23814
+ return true;
23815
+ });
23816
+ }
23656
23817
  return { sources, sinks: filtered, sanitizers };
23657
23818
  }
23658
23819
  }
@@ -33203,6 +33364,10 @@ var JAVA_FACTORIES = new Set([
33203
33364
  "TransformerFactory"
33204
33365
  ]);
33205
33366
  var JAVA_SAFE_EVIDENCE_RE = /(disallow-doctype-decl|external-general-entities|external-parameter-entities|SUPPORT_DTD|ACCESS_EXTERNAL_DTD|ACCESS_EXTERNAL_SCHEMA|setXIncludeAware\s*\(\s*false\s*\)|setExpandEntityReferences\s*\(\s*false\s*\))/;
33367
+ var JAVA_XML_OUTPUT_ONLY_RE = /\bnew\s+(?:DOMSource|StreamResult)\s*\(/;
33368
+ var JAVA_XML_PARSE_INPUT_RE = /\bnew\s+(?:StreamSource|SAXSource|InputSource)\s*\(/;
33369
+ var JAVA_DOC_BUILDER_NEW_DOCUMENT_RE = /\.\s*newDocument\s*\(\s*\)/;
33370
+ var JAVA_DOC_BUILDER_PARSE_RE = /(?:DocumentBuilder|builder)\s*\.\s*parse\s*\(/;
33206
33371
  var PY_LXML_PARSER_INSECURE_DEFAULT_RE = /\bresolve_entities\s*=\s*False\b/;
33207
33372
 
33208
33373
  class XmlEntityExpansionPass {
@@ -33217,10 +33382,16 @@ class XmlEntityExpansionPass {
33217
33382
  const safeInFile = JAVA_SAFE_EVIDENCE_RE.test(code);
33218
33383
  if (safeInFile)
33219
33384
  return { findings };
33385
+ const isXmlOutputOnly = JAVA_XML_OUTPUT_ONLY_RE.test(code) && !JAVA_XML_PARSE_INPUT_RE.test(code);
33386
+ const isDocumentBuilderEmptyOnly = JAVA_DOC_BUILDER_NEW_DOCUMENT_RE.test(code) && !JAVA_DOC_BUILDER_PARSE_RE.test(code);
33220
33387
  for (const call of graph.ir.calls) {
33221
33388
  const det = this.detectJavaCall(call);
33222
33389
  if (!det)
33223
33390
  continue;
33391
+ if (det.api === "TransformerFactory" && isXmlOutputOnly)
33392
+ continue;
33393
+ if (det.api === "DocumentBuilderFactory" && isDocumentBuilderEmptyOnly)
33394
+ continue;
33224
33395
  const line = call.location.line;
33225
33396
  findings.push({ line, language, ...det });
33226
33397
  ctx.addFinding({
@@ -34768,7 +34939,7 @@ var colors = {
34768
34939
  };
34769
34940
 
34770
34941
  // src/version.ts
34771
- var version = "3.99.0";
34942
+ var version = "3.101.0";
34772
34943
 
34773
34944
  // src/formatters.ts
34774
34945
  var SINK_SEVERITY = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cognium-dev",
3
- "version": "3.99.0",
3
+ "version": "3.101.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.99.0"
68
+ "circle-ir": "^3.101.0"
69
69
  },
70
70
  "devDependencies": {
71
71
  "@types/node": "^25.5.0",