cognium-dev 3.178.0 → 3.179.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 +117 -6
  2. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -11683,12 +11683,20 @@ var DEFAULT_SINKS = [
11683
11683
  { method: "format", class: "String", type: "format_string", cwe: "CWE-134", severity: "high", arg_positions: [0], languages: ["java"] },
11684
11684
  { method: "format", class: "Formatter", type: "format_string", cwe: "CWE-134", severity: "high", arg_positions: [0], languages: ["java"] },
11685
11685
  { method: "printf", class: "System.out", type: "format_string", cwe: "CWE-134", severity: "high", arg_positions: [0], languages: ["java"] },
11686
+ { method: "format", class: "MessageFormat", type: "format_string", cwe: "CWE-134", severity: "high", arg_positions: [0], languages: ["java"] },
11687
+ { method: "printf", class: "PrintStream", type: "format_string", cwe: "CWE-134", severity: "high", arg_positions: [0], languages: ["java"] },
11688
+ { method: "format", class: "PrintStream", type: "format_string", cwe: "CWE-134", severity: "high", arg_positions: [0], languages: ["java"] },
11689
+ { method: "printf", class: "PrintWriter", type: "format_string", cwe: "CWE-134", severity: "high", arg_positions: [0], languages: ["java"] },
11690
+ { method: "format", class: "PrintWriter", type: "format_string", cwe: "CWE-134", severity: "high", arg_positions: [0], languages: ["java"] },
11686
11691
  { method: "printf", type: "format_string", cwe: "CWE-134", severity: "high", arg_positions: [0], languages: ["python"] },
11687
11692
  { method: "fprintf", type: "format_string", cwe: "CWE-134", severity: "high", arg_positions: [1], languages: ["python"] },
11688
11693
  { method: "Sprintf", class: "fmt", type: "format_string", cwe: "CWE-134", severity: "medium", arg_positions: [0], languages: ["go"] },
11689
11694
  { method: "Printf", class: "fmt", type: "format_string", cwe: "CWE-134", severity: "medium", arg_positions: [0], languages: ["go"] },
11690
11695
  { method: "Errorf", class: "fmt", type: "format_string", cwe: "CWE-134", severity: "medium", arg_positions: [0], languages: ["go"] },
11691
11696
  { method: "Fprintf", class: "fmt", type: "format_string", cwe: "CWE-134", severity: "medium", arg_positions: [1], languages: ["go"] },
11697
+ { method: "Printf", class: "log", type: "format_string", cwe: "CWE-134", severity: "medium", arg_positions: [0], languages: ["go"] },
11698
+ { method: "Fatalf", class: "log", type: "format_string", cwe: "CWE-134", severity: "medium", arg_positions: [0], languages: ["go"] },
11699
+ { method: "Panicf", class: "log", type: "format_string", cwe: "CWE-134", severity: "medium", arg_positions: [0], languages: ["go"] },
11692
11700
  { method: "setHeader", type: "crlf", cwe: "CWE-113", severity: "medium", arg_positions: [1], languages: ["javascript", "typescript"] },
11693
11701
  { method: "writeHead", type: "crlf", cwe: "CWE-113", severity: "medium", arg_positions: [2], languages: ["javascript", "typescript"] },
11694
11702
  { method: "cookie", type: "crlf", cwe: "CWE-113", severity: "medium", arg_positions: [1], languages: ["javascript", "typescript"] },
@@ -13680,6 +13688,11 @@ function calculateSinkConfidence(call, pattern) {
13680
13688
  if (pattern.class && call.receiver) {
13681
13689
  if (receiverMightBeClass(call.receiver, pattern.class)) {
13682
13690
  confidence += 0.1;
13691
+ const receiverLc = call.receiver.toLowerCase();
13692
+ const classLc = pattern.class.toLowerCase();
13693
+ if (call.receiver === pattern.class || receiverLc === classLc) {
13694
+ confidence += 0.05;
13695
+ }
13683
13696
  }
13684
13697
  }
13685
13698
  if (pattern.severity === "critical") {
@@ -32655,6 +32668,85 @@ function resolveFastjsonFromPom(pomXml) {
32655
32668
  }
32656
32669
  return null;
32657
32670
  }
32671
+ function resolveFastjsonFromGradle(buildGradle) {
32672
+ if (!buildGradle)
32673
+ return null;
32674
+ const directRe = /['"(]\s*com\.alibaba:fastjson:([^'"$\s)]+)\s*['")]/;
32675
+ const direct = buildGradle.match(directRe);
32676
+ if (direct) {
32677
+ const version2 = direct[1];
32678
+ return { version: version2, noneAutotype: /_noneautotype/i.test(version2) };
32679
+ }
32680
+ const propRefRe = /['"(]\s*com\.alibaba:fastjson:\$\{?([A-Za-z_][A-Za-z0-9_]*)\}?\s*['")]/;
32681
+ const propRef = buildGradle.match(propRefRe);
32682
+ if (!propRef)
32683
+ return null;
32684
+ const propName = propRef[1];
32685
+ const defRe = new RegExp(`\\b${propName}\\s*[=:]\\s*['"]([^'"\\s]+)['"]`);
32686
+ const def = buildGradle.match(defRe);
32687
+ if (!def)
32688
+ return null;
32689
+ const version = def[1];
32690
+ return { version, noneAutotype: /_noneautotype/i.test(version) };
32691
+ }
32692
+ function resolvePyYamlFromRequirements(requirementsTxt) {
32693
+ if (!requirementsTxt)
32694
+ return null;
32695
+ for (const rawLine of requirementsTxt.split(/\r?\n/)) {
32696
+ const line = rawLine.replace(/#.*$/, "").trim();
32697
+ if (!line)
32698
+ continue;
32699
+ if (line.startsWith("-"))
32700
+ continue;
32701
+ const m = line.match(/^(pyyaml)\s*(==|>=|~=|>|===)\s*(\d+(?:\.\d+)*)/i);
32702
+ if (!m)
32703
+ continue;
32704
+ const version = m[3];
32705
+ return { version, safeByDefault: isPyYamlVersionSafeByDefault(version) };
32706
+ }
32707
+ return null;
32708
+ }
32709
+ function resolvePyYamlFromPyproject(pyprojectToml) {
32710
+ if (!pyprojectToml)
32711
+ return null;
32712
+ const poetryLine = pyprojectToml.match(/^\s*(pyyaml)\s*=\s*"([\^~=<>]*)(\d+(?:\.\d+)*)"/im);
32713
+ if (poetryLine) {
32714
+ const version = poetryLine[3];
32715
+ return { version, safeByDefault: isPyYamlVersionSafeByDefault(version) };
32716
+ }
32717
+ const poetryTable = pyprojectToml.match(/^\s*(pyyaml)\s*=\s*\{[^}]*\bversion\s*=\s*"([\^~=<>]*)(\d+(?:\.\d+)*)"/im);
32718
+ if (poetryTable) {
32719
+ const version = poetryTable[3];
32720
+ return { version, safeByDefault: isPyYamlVersionSafeByDefault(version) };
32721
+ }
32722
+ const pep621 = pyprojectToml.match(/"(pyyaml)\s*(==|>=|~=|>|===)\s*(\d+(?:\.\d+)*)/i);
32723
+ if (pep621) {
32724
+ const version = pep621[3];
32725
+ return { version, safeByDefault: isPyYamlVersionSafeByDefault(version) };
32726
+ }
32727
+ return null;
32728
+ }
32729
+ function isPyYamlVersionSafeByDefault(version) {
32730
+ const parts2 = version.split(".").map((s) => Number.parseInt(s, 10));
32731
+ if (parts2.length === 0 || !Number.isFinite(parts2[0]))
32732
+ return false;
32733
+ return parts2[0] >= 6;
32734
+ }
32735
+ function fileHasUnsafePyYamlLoader(sourceLines, sinkLine) {
32736
+ const start2 = Math.max(0, sinkLine - 1);
32737
+ const end = Math.min(sourceLines.length, start2 + 10);
32738
+ const unsafeRe = /\bLoader\s*=\s*(?:yaml\s*\.\s*)?(?:Loader|UnsafeLoader|FullLoader)\b/;
32739
+ for (let i2 = start2;i2 < end; i2++) {
32740
+ const ln = sourceLines[i2] ?? "";
32741
+ if (unsafeRe.test(ln))
32742
+ return true;
32743
+ const stripped = ln.trim();
32744
+ if (i2 > start2 && (stripped === ")" || stripped.endsWith(")"))) {
32745
+ return false;
32746
+ }
32747
+ }
32748
+ return false;
32749
+ }
32658
32750
  function fileReenablesFastjsonAutotype(source) {
32659
32751
  if (!source)
32660
32752
  return false;
@@ -32688,6 +32780,8 @@ var JACKSON_METHODS = new Set(["readValue", "convertValue", "treeToValue"]);
32688
32780
  var JACKSON_CLASSES = new Set(["ObjectMapper", "ObjectReader"]);
32689
32781
  var SNAKEYAML_METHODS = new Set(["load", "loadAs", "loadAll"]);
32690
32782
  var SNAKEYAML_CLASSES = new Set(["Yaml"]);
32783
+ var PYYAML_METHODS = new Set(["load"]);
32784
+ var PYYAML_CLASSES = new Set(["yaml"]);
32691
32785
 
32692
32786
  class DeserializationSafetyGatePass {
32693
32787
  dependencyContext;
@@ -32698,18 +32792,31 @@ class DeserializationSafetyGatePass {
32698
32792
  }
32699
32793
  run(ctx) {
32700
32794
  const { graph, language, code } = ctx;
32701
- if (language !== "java") {
32702
- return { droppedFastjson: 0, droppedJackson: 0, droppedSnakeYaml: 0 };
32795
+ if (language !== "java" && language !== "python") {
32796
+ return { droppedFastjson: 0, droppedJackson: 0, droppedSnakeYaml: 0, droppedPyYaml: 0 };
32703
32797
  }
32704
32798
  const sinks = ctx.hasResult("sink-filter") ? ctx.getResult("sink-filter").sinks : graph.ir.taint.sinks;
32705
32799
  const pomXml = this.dependencyContext?.java?.pomXml;
32706
- const fastjson = pomXml ? resolveFastjsonFromPom(pomXml) : null;
32800
+ const buildGradle = this.dependencyContext?.java?.buildGradle;
32801
+ const fastjson = (pomXml ? resolveFastjsonFromPom(pomXml) : null) ?? (buildGradle ? resolveFastjsonFromGradle(buildGradle) : null);
32707
32802
  const fastjsonHardened = fastjson?.noneAutotype === true && !fileReenablesFastjsonAutotype(code);
32708
32803
  const jacksonSafe = !fileEnablesJacksonPolymorphism(code);
32709
32804
  const snakeYamlSafe = fileConfiguresSnakeYamlSafely(code);
32805
+ const requirementsTxt = this.dependencyContext?.python?.requirementsTxt;
32806
+ const pyprojectToml = this.dependencyContext?.python?.pyprojectToml;
32807
+ const pyYaml = (requirementsTxt ? resolvePyYamlFromRequirements(requirementsTxt) : null) ?? (pyprojectToml ? resolvePyYamlFromPyproject(pyprojectToml) : null);
32808
+ const pyYamlSafeByDefault = pyYaml?.safeByDefault === true;
32809
+ let sourceLines = null;
32810
+ const getSourceLines = () => {
32811
+ if (sourceLines === null)
32812
+ sourceLines = code.split(`
32813
+ `);
32814
+ return sourceLines;
32815
+ };
32710
32816
  let droppedFastjson = 0;
32711
32817
  let droppedJackson = 0;
32712
32818
  let droppedSnakeYaml = 0;
32819
+ let droppedPyYaml = 0;
32713
32820
  const kept = sinks.filter((sink) => {
32714
32821
  if (sink.type !== "deserialization")
32715
32822
  return true;
@@ -32727,14 +32834,18 @@ class DeserializationSafetyGatePass {
32727
32834
  droppedSnakeYaml++;
32728
32835
  return false;
32729
32836
  }
32837
+ if (language === "python" && pyYamlSafeByDefault && PYYAML_METHODS.has(sink.method) && (sink.class === undefined || PYYAML_CLASSES.has(sink.class)) && !fileHasUnsafePyYamlLoader(getSourceLines(), sink.line)) {
32838
+ droppedPyYaml++;
32839
+ return false;
32840
+ }
32730
32841
  return true;
32731
32842
  });
32732
- const totalDropped = droppedFastjson + droppedJackson + droppedSnakeYaml;
32843
+ const totalDropped = droppedFastjson + droppedJackson + droppedSnakeYaml + droppedPyYaml;
32733
32844
  if (totalDropped > 0) {
32734
32845
  sinks.length = 0;
32735
32846
  sinks.push(...kept);
32736
32847
  }
32737
- return { droppedFastjson, droppedJackson, droppedSnakeYaml };
32848
+ return { droppedFastjson, droppedJackson, droppedSnakeYaml, droppedPyYaml };
32738
32849
  }
32739
32850
  }
32740
32851
 
@@ -45224,7 +45335,7 @@ var colors = {
45224
45335
  };
45225
45336
 
45226
45337
  // src/version.ts
45227
- var version = "3.178.0";
45338
+ var version = "3.179.0";
45228
45339
 
45229
45340
  // src/formatters.ts
45230
45341
  var LIBRARY_API_SURFACE_TAG2 = "library-api-surface:caller-responsibility";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cognium-dev",
3
- "version": "3.178.0",
3
+ "version": "3.179.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",
@@ -66,7 +66,7 @@
66
66
  },
67
67
  "dependencies": {
68
68
  "@cognium/project-profile-detect": "^1.1.0",
69
- "circle-ir": "^3.178.0"
69
+ "circle-ir": "^3.179.0"
70
70
  },
71
71
  "devDependencies": {
72
72
  "@types/node": "^25.5.0",