cognium-dev 3.70.0 → 3.71.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 +105 -2
  2. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -21228,6 +21228,13 @@ function findOopFieldReadSources(types, sourceCode, language) {
21228
21228
  let returnedField = null;
21229
21229
  let returnStatementCount = 0;
21230
21230
  const returnRe = new RegExp(`\\breturn\\s+${SELF}\\.([A-Za-z_]\\w*)\\s*[;}]?`);
21231
+ const guardRePy = /\bif\s+[\w.]+\s+(?:not\s+)?in\s+(?:self\.)?[A-Z_][A-Z0-9_]*\s*:/;
21232
+ const guardThrowRePy = /^\s*(?:raise\b|abort\b|return\s+(?:None\b|''|""|\)?$))/;
21233
+ const guardReJv = /\bif\s*\(\s*!\s*(?:this\.)?[A-Z_][A-Z0-9_]*\s*\.\s*(?:contains|includes|has|matches)\s*\(/;
21234
+ const guardThrowReJv = /^\s*(?:throw\b|return\s+null\b)/;
21235
+ const guardRe = isPython ? guardRePy : guardReJv;
21236
+ const guardThrowRe = isPython ? guardThrowRePy : guardThrowReJv;
21237
+ let hasAllowlistGuard = false;
21231
21238
  for (let i2 = mStart - 1;i2 < Math.min(mEnd, lines.length); i2++) {
21232
21239
  const raw = lines[i2] ?? "";
21233
21240
  const trimmed = raw.trim();
@@ -21243,8 +21250,17 @@ function findOopFieldReadSources(types, sourceCode, language) {
21243
21250
  returnStatementCount = 99;
21244
21251
  break;
21245
21252
  }
21253
+ if (guardRe.test(trimmed)) {
21254
+ for (let j = i2 + 1;j < Math.min(i2 + 4, mEnd, lines.length); j++) {
21255
+ const next = lines[j] ?? "";
21256
+ if (guardThrowRe.test(next)) {
21257
+ hasAllowlistGuard = true;
21258
+ break;
21259
+ }
21260
+ }
21261
+ }
21246
21262
  }
21247
- if (returnStatementCount === 1 && returnedField && fieldTaint.has(returnedField)) {
21263
+ if (returnStatementCount === 1 && returnedField && fieldTaint.has(returnedField) && !hasAllowlistGuard) {
21248
21264
  const fieldInfo = fieldTaint.get(returnedField);
21249
21265
  const getterVar = isPython ? `${SELF}.${m.name}` : m.name;
21250
21266
  sources.push({
@@ -22835,6 +22851,23 @@ class TaintPropagationPass {
22835
22851
  return false;
22836
22852
  });
22837
22853
  }
22854
+ if (typeof ctx.code === "string") {
22855
+ const sinkByLine = new Map;
22856
+ for (const s of sinks) {
22857
+ if (s.type === "nosql_injection")
22858
+ sinkByLine.set(s.line, s);
22859
+ }
22860
+ if (sinkByLine.size > 0) {
22861
+ finalFlows = finalFlows.filter((f) => {
22862
+ if (f.sink_type !== "nosql_injection")
22863
+ return true;
22864
+ const sink = sinkByLine.get(f.sink_line);
22865
+ if (!sink || !sink.code || !sink.method)
22866
+ return true;
22867
+ return !isMongoValueBoundFilter(sink.code, sink.method);
22868
+ });
22869
+ }
22870
+ }
22838
22871
  if (finalFlows.length > 1) {
22839
22872
  const bestByKey = new Map;
22840
22873
  for (const f of finalFlows) {
@@ -22852,6 +22885,76 @@ class TaintPropagationPass {
22852
22885
  return { flows: finalFlows };
22853
22886
  }
22854
22887
  }
22888
+ function isMongoValueBoundFilter(sinkCode, sinkMethod) {
22889
+ if (!sinkCode || !sinkMethod)
22890
+ return false;
22891
+ const callIdx = sinkCode.indexOf(`${sinkMethod}(`);
22892
+ if (callIdx < 0)
22893
+ return false;
22894
+ const openIdx = callIdx + sinkMethod.length;
22895
+ let depth = 0;
22896
+ let braceDepth = 0;
22897
+ let bracketDepth = 0;
22898
+ let inString = null;
22899
+ let firstArgEnd = -1;
22900
+ let firstArgComma = -1;
22901
+ const limit = Math.min(sinkCode.length, openIdx + 4096);
22902
+ for (let i2 = openIdx;i2 < limit; i2++) {
22903
+ const ch = sinkCode[i2];
22904
+ if (inString) {
22905
+ if (ch === "\\" && i2 + 1 < limit) {
22906
+ i2++;
22907
+ continue;
22908
+ }
22909
+ if (ch === inString)
22910
+ inString = null;
22911
+ continue;
22912
+ }
22913
+ if (ch === '"' || ch === "'" || ch === "`") {
22914
+ inString = ch;
22915
+ continue;
22916
+ }
22917
+ if (ch === "(")
22918
+ depth++;
22919
+ else if (ch === ")") {
22920
+ depth--;
22921
+ if (depth === 0) {
22922
+ firstArgEnd = i2;
22923
+ break;
22924
+ }
22925
+ } else if (ch === "{")
22926
+ braceDepth++;
22927
+ else if (ch === "}")
22928
+ braceDepth--;
22929
+ else if (ch === "[")
22930
+ bracketDepth++;
22931
+ else if (ch === "]")
22932
+ bracketDepth--;
22933
+ else if (ch === "," && depth === 1 && braceDepth === 0 && bracketDepth === 0) {
22934
+ if (firstArgComma < 0)
22935
+ firstArgComma = i2;
22936
+ }
22937
+ }
22938
+ if (firstArgEnd < 0)
22939
+ return false;
22940
+ const argEnd = firstArgComma >= 0 ? firstArgComma : firstArgEnd;
22941
+ const firstArg = sinkCode.slice(openIdx + 1, argEnd).trim();
22942
+ if (!firstArg)
22943
+ return false;
22944
+ if (firstArg[0] !== "{" || firstArg[firstArg.length - 1] !== "}")
22945
+ return false;
22946
+ const body2 = firstArg.slice(1, -1).trim();
22947
+ if (!body2)
22948
+ return false;
22949
+ const stripped = body2.replace(/(['"`])(?:\\.|(?!\1).)*\1/g, '""');
22950
+ if (/\.\.\./.test(stripped))
22951
+ return false;
22952
+ if (/(^|[,{\s])\$[A-Za-z_]\w*\s*:/.test(stripped))
22953
+ return false;
22954
+ if (/(['"])\$[A-Za-z_]\w*\1\s*:/.test(body2))
22955
+ return false;
22956
+ return true;
22957
+ }
22855
22958
  function isInJavaSanitizedMethod(code, types, sinkLine, sinkType) {
22856
22959
  if (!types || types.length === 0)
22857
22960
  return false;
@@ -31898,7 +32001,7 @@ var colors = {
31898
32001
  };
31899
32002
 
31900
32003
  // src/version.ts
31901
- var version = "3.70.0";
32004
+ var version = "3.71.0";
31902
32005
 
31903
32006
  // src/formatters.ts
31904
32007
  var SINK_SEVERITY = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cognium-dev",
3
- "version": "3.70.0",
3
+ "version": "3.71.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.70.0"
68
+ "circle-ir": "^3.71.0"
69
69
  },
70
70
  "devDependencies": {
71
71
  "@types/node": "^25.5.0",