cognium-dev 3.179.0 → 3.180.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 +91 -2
  2. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -32677,6 +32677,12 @@ function resolveFastjsonFromGradle(buildGradle) {
32677
32677
  const version2 = direct[1];
32678
32678
  return { version: version2, noneAutotype: /_noneautotype/i.test(version2) };
32679
32679
  }
32680
+ const constraintsBlockRe = /['"(]\s*com\.alibaba:fastjson\s*['")]\s*\)?\s*\{[\s\S]*?\bversion\s*\{[\s\S]*?\b(?:strictly|require|prefer)\s+['"]([^'"\s]+)['"]/;
32681
+ const constraintsBlock = buildGradle.match(constraintsBlockRe);
32682
+ if (constraintsBlock) {
32683
+ const version2 = constraintsBlock[1];
32684
+ return { version: version2, noneAutotype: /_noneautotype/i.test(version2) };
32685
+ }
32680
32686
  const propRefRe = /['"(]\s*com\.alibaba:fastjson:\$\{?([A-Za-z_][A-Za-z0-9_]*)\}?\s*['")]/;
32681
32687
  const propRef = buildGradle.match(propRefRe);
32682
32688
  if (!propRef)
@@ -32689,6 +32695,45 @@ function resolveFastjsonFromGradle(buildGradle) {
32689
32695
  const version = def[1];
32690
32696
  return { version, noneAutotype: /_noneautotype/i.test(version) };
32691
32697
  }
32698
+ function resolveFastjsonFromGradleCatalog(buildGradle, libsVersionsToml) {
32699
+ if (!buildGradle || !libsVersionsToml)
32700
+ return null;
32701
+ const librariesMatch = libsVersionsToml.match(/\[libraries\]([\s\S]*?)(?=\n\[|$)/);
32702
+ if (!librariesMatch)
32703
+ return null;
32704
+ const librariesBlock = librariesMatch[1];
32705
+ const moduleForm = librariesBlock.match(/^\s*([\w.-]+)\s*=\s*\{[^}]*\bmodule\s*=\s*"com\.alibaba:fastjson"[^}]*\}/m);
32706
+ const groupNameForm = librariesBlock.match(/^\s*([\w.-]+)\s*=\s*\{[^}]*\bgroup\s*=\s*"com\.alibaba"[^}]*\bname\s*=\s*"fastjson"[^}]*\}/m);
32707
+ const entry = moduleForm ?? groupNameForm;
32708
+ if (!entry)
32709
+ return null;
32710
+ const alias = entry[1];
32711
+ const entryBody = entry[0];
32712
+ const aliasEsc = alias.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
32713
+ const aliasRefRe = new RegExp(`\\blibs\\s*\\.\\s*${aliasEsc}\\b`);
32714
+ if (!aliasRefRe.test(buildGradle))
32715
+ return null;
32716
+ const inlineVersionM = entryBody.match(/\bversion\s*=\s*"([^"$][^"]*)"/);
32717
+ if (inlineVersionM) {
32718
+ const version2 = inlineVersionM[1];
32719
+ return { version: version2, noneAutotype: /_noneautotype/i.test(version2) };
32720
+ }
32721
+ const versionRefM = entryBody.match(/\bversion\.ref\s*=\s*"([^"]+)"/);
32722
+ if (!versionRefM)
32723
+ return null;
32724
+ const versionAlias = versionRefM[1];
32725
+ const versionsMatch = libsVersionsToml.match(/\[versions\]([\s\S]*?)(?=\n\[|$)/);
32726
+ if (!versionsMatch)
32727
+ return null;
32728
+ const versionsBlock = versionsMatch[1];
32729
+ const versionAliasEsc = versionAlias.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
32730
+ const versionLineRe = new RegExp(`^\\s*${versionAliasEsc}\\s*=\\s*"([^"]+)"`, "m");
32731
+ const versionLine = versionsBlock.match(versionLineRe);
32732
+ if (!versionLine)
32733
+ return null;
32734
+ const version = versionLine[1];
32735
+ return { version, noneAutotype: /_noneautotype/i.test(version) };
32736
+ }
32692
32737
  function resolvePyYamlFromRequirements(requirementsTxt) {
32693
32738
  if (!requirementsTxt)
32694
32739
  return null;
@@ -32798,7 +32843,8 @@ class DeserializationSafetyGatePass {
32798
32843
  const sinks = ctx.hasResult("sink-filter") ? ctx.getResult("sink-filter").sinks : graph.ir.taint.sinks;
32799
32844
  const pomXml = this.dependencyContext?.java?.pomXml;
32800
32845
  const buildGradle = this.dependencyContext?.java?.buildGradle;
32801
- const fastjson = (pomXml ? resolveFastjsonFromPom(pomXml) : null) ?? (buildGradle ? resolveFastjsonFromGradle(buildGradle) : null);
32846
+ const libsVersionsToml = this.dependencyContext?.java?.libsVersionsToml;
32847
+ const fastjson = (pomXml ? resolveFastjsonFromPom(pomXml) : null) ?? (buildGradle ? resolveFastjsonFromGradle(buildGradle) : null) ?? (buildGradle && libsVersionsToml ? resolveFastjsonFromGradleCatalog(buildGradle, libsVersionsToml) : null);
32802
32848
  const fastjsonHardened = fastjson?.noneAutotype === true && !fileReenablesFastjsonAutotype(code);
32803
32849
  const jacksonSafe = !fileEnablesJacksonPolymorphism(code);
32804
32850
  const snakeYamlSafe = fileConfiguresSnakeYamlSafely(code);
@@ -39735,6 +39781,47 @@ class ScanSecretsPass {
39735
39781
  }
39736
39782
  }
39737
39783
 
39784
+ // ../circle-ir/dist/analysis/passes/python-receiver-taint-format-pass.js
39785
+ class PythonReceiverTaintFormatPass {
39786
+ name = "python-receiver-taint-format";
39787
+ category = "security";
39788
+ run(ctx) {
39789
+ if (ctx.language !== "python") {
39790
+ return { findingsEmitted: 0 };
39791
+ }
39792
+ const { calls, meta } = ctx.graph.ir;
39793
+ const constProp = ctx.getResult("constant-propagation");
39794
+ const tainted = constProp.tainted;
39795
+ let count = 0;
39796
+ for (const call of calls) {
39797
+ if (call.method_name !== "format")
39798
+ continue;
39799
+ const receiver = call.receiver;
39800
+ if (!receiver)
39801
+ continue;
39802
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(receiver))
39803
+ continue;
39804
+ const scopedName = call.in_method ? `${call.in_method}:${receiver}` : receiver;
39805
+ if (!tainted.has(receiver) && !tainted.has(scopedName))
39806
+ continue;
39807
+ ctx.addFinding({
39808
+ id: `format_string-${meta.file}-${call.location.line}-${receiver}`,
39809
+ pass: this.name,
39810
+ category: "security",
39811
+ rule_id: "format_string",
39812
+ cwe: "CWE-134",
39813
+ severity: "medium",
39814
+ level: "warning",
39815
+ message: `Format-string vulnerability: the format template \`${receiver}\` ` + `is tainted (traces back to a taint source). Attacker can leak ` + `object attributes via \`{obj.__class__.__mro__[…]}\` chains or ` + `crash the process via unbounded specifiers. Use a literal ` + `format string and pass user input as an argument instead.`,
39816
+ file: meta.file,
39817
+ line: call.location.line
39818
+ });
39819
+ count++;
39820
+ }
39821
+ return { findingsEmitted: count };
39822
+ }
39823
+ }
39824
+
39738
39825
  // ../circle-ir/dist/analysis/passes/spring4shell-pass.js
39739
39826
  var CONTROLLER_ANNOTATIONS = new Set([
39740
39827
  "Controller",
@@ -44406,6 +44493,8 @@ async function analyze(code, filePath, language, options = {}) {
44406
44493
  pipeline.add(new LibraryProfileCwe22PathGatePass);
44407
44494
  if (!disabledPasses.has("scan-secrets"))
44408
44495
  pipeline.add(new ScanSecretsPass);
44496
+ if (!disabledPasses.has("python-receiver-taint-format"))
44497
+ pipeline.add(new PythonReceiverTaintFormatPass);
44409
44498
  if (!disabledPasses.has("dead-code"))
44410
44499
  pipeline.add(new DeadCodePass);
44411
44500
  if (!disabledPasses.has("missing-await"))
@@ -45335,7 +45424,7 @@ var colors = {
45335
45424
  };
45336
45425
 
45337
45426
  // src/version.ts
45338
- var version = "3.179.0";
45427
+ var version = "3.180.0";
45339
45428
 
45340
45429
  // src/formatters.ts
45341
45430
  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.179.0",
3
+ "version": "3.180.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.179.0"
69
+ "circle-ir": "^3.180.0"
70
70
  },
71
71
  "devDependencies": {
72
72
  "@types/node": "^25.5.0",