cognium-dev 3.90.0 → 3.91.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 (3) hide show
  1. package/README.md +27 -0
  2. package/dist/cli.js +51 -3
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -213,6 +213,33 @@ Found 2 vulnerability(ies) in 1 file(s)
213
213
 
214
214
  Use `-v` flag to see all scanned files including clean ones.
215
215
 
216
+ ### Output streams (stdout vs stderr)
217
+
218
+ `cognium-dev` follows the standard CLI convention: machine-readable payload on **stdout**, diagnostics on **stderr**.
219
+
220
+ | Output | Stream | Notes |
221
+ |--------|--------|-------|
222
+ | `--format json` document | **stdout** | Pure JSON starting at character 1. No banner, no preamble. Safe to pipe directly to `jq`, `json_pp`, etc. |
223
+ | `--format sarif` document | **stdout** | Pure SARIF 2.1.0 JSON. Same contract as `--format json`. |
224
+ | `--format text` report | **stdout** | The human-readable report (default). |
225
+ | Status lines (`Loaded config: …`, `Suppressed N finding(s) …`, `Results written to …`) | **stderr** | |
226
+ | Spinner animation and final status (`✔ Scanned N file(s)`) | **stderr** | |
227
+ | Error messages and usage hints | **stderr** | |
228
+ | Library log output (cross-file phase markers, budget warnings, etc.) | **stderr** | Silent by default; enable with `--log-level <level>` or `COGNIUM_LOG_LEVEL`. |
229
+ | Findings instrumentation (`CIRCLE_IR_INSTRUMENT_FINDINGS=1`) | **stderr** | JSONL `[finding] …` / `[findings-summary] …` lines. |
230
+
231
+ The stdout contract for `--format json` and `--format sarif` is **stable**: pure parseable payload, version included inside the JSON object (not as a stdout preamble). Consumers can safely pipe stdout to a parser without skip-the-first-line idioms.
232
+
233
+ ```bash
234
+ # Safe — stdout is pure JSON
235
+ cognium-dev scan ./src --format json | jq '.summary'
236
+
237
+ # Status lines and warnings on stderr, JSON on stdout
238
+ cognium-dev scan ./src --format json > results.json 2> scan.log
239
+ ```
240
+
241
+ If you previously relied on a `tail -n +2` or `split("\n",1)[1]` idiom against pre-3.89.2 builds, drop it — there is no longer a stdout banner to skip.
242
+
216
243
  ## Detected Vulnerabilities
217
244
 
218
245
  | Type | CWE | Severity | Description |
package/dist/cli.js CHANGED
@@ -15075,8 +15075,17 @@ class AnalysisPipeline {
15075
15075
  return findings;
15076
15076
  }
15077
15077
  };
15078
+ const timingEnabled = globalThis.__circleIrPassTiming === true;
15078
15079
  for (const pass of this.passes) {
15080
+ if (timingEnabled) {
15081
+ console.error(`[pass-start] ${pass.name} file=${graph.ir.meta.file}`);
15082
+ }
15083
+ const t0 = timingEnabled ? Date.now() : 0;
15079
15084
  const result = pass.run(context);
15085
+ if (timingEnabled) {
15086
+ const dt = Date.now() - t0;
15087
+ console.error(`[pass-timing] ${pass.name} ${dt}ms file=${graph.ir.meta.file}`);
15088
+ }
15080
15089
  results.set(pass.name, result);
15081
15090
  }
15082
15091
  return { results, findings };
@@ -15857,6 +15866,7 @@ class ConstantPropagator {
15857
15866
  inConstructor = false;
15858
15867
  constructorParamPositions = new Map;
15859
15868
  safePatternFieldsCache = null;
15869
+ isTaintedExpressionCache = null;
15860
15870
  analyze(tree, sourceCode, additionalTaintPatterns = [], sanitizerMethods = [], taintedParameters = []) {
15861
15871
  this.source = sourceCode;
15862
15872
  this.additionalTaintPatterns = additionalTaintPatterns;
@@ -15888,6 +15898,7 @@ class ConstantPropagator {
15888
15898
  this.inConstructor = false;
15889
15899
  this.constructorParamPositions.clear();
15890
15900
  this.safePatternFieldsCache = null;
15901
+ this.isTaintedExpressionCache = null;
15891
15902
  this.collectClassFields(tree.rootNode);
15892
15903
  for (const methodName of sanitizerMethods) {
15893
15904
  this.methodReturnsSanitized.add(methodName);
@@ -17237,18 +17248,52 @@ class ConstantPropagator {
17237
17248
  return null;
17238
17249
  }
17239
17250
  isTaintedExpression(node) {
17251
+ const isTopLevel = this.isTaintedExpressionCache === null;
17252
+ if (isTopLevel) {
17253
+ this.isTaintedExpressionCache = new Map;
17254
+ }
17255
+ try {
17256
+ return this.isTaintedExpressionImpl(node);
17257
+ } finally {
17258
+ if (isTopLevel) {
17259
+ this.isTaintedExpressionCache = null;
17260
+ }
17261
+ }
17262
+ }
17263
+ isTaintedExpressionImpl(node) {
17264
+ const cache = this.isTaintedExpressionCache;
17265
+ const rootId = node.id;
17266
+ const cachedRoot = cache.get(rootId);
17267
+ if (cachedRoot !== undefined) {
17268
+ return cachedRoot;
17269
+ }
17240
17270
  const stack = [node];
17241
17271
  while (stack.length > 0) {
17242
17272
  const current = stack.pop();
17273
+ const currentId = current.id;
17274
+ const cached = cache.get(currentId);
17275
+ if (cached !== undefined) {
17276
+ if (cached) {
17277
+ cache.set(rootId, true);
17278
+ return true;
17279
+ }
17280
+ continue;
17281
+ }
17243
17282
  const result = this.isTaintedExpressionStep(current);
17244
- if (result === true)
17283
+ if (result === true) {
17284
+ cache.set(currentId, true);
17285
+ cache.set(rootId, true);
17245
17286
  return true;
17246
- if (result === false)
17287
+ }
17288
+ if (result === false) {
17289
+ cache.set(currentId, false);
17247
17290
  continue;
17291
+ }
17248
17292
  for (let i2 = current.children.length - 1;i2 >= 0; i2--) {
17249
17293
  stack.push(current.children[i2]);
17250
17294
  }
17251
17295
  }
17296
+ cache.set(rootId, false);
17252
17297
  return false;
17253
17298
  }
17254
17299
  isTaintedExpressionStep(node) {
@@ -24956,6 +25001,9 @@ var TIER_1_METHOD_ANNOTATIONS = new Set([
24956
25001
  var TIER_1_CLASS_ANNOTATIONS = new Set([
24957
25002
  "RestController",
24958
25003
  "Controller",
25004
+ "Service",
25005
+ "Repository",
25006
+ "Component",
24959
25007
  "Path",
24960
25008
  "WebServlet",
24961
25009
  "ServerEndpoint",
@@ -34472,7 +34520,7 @@ var colors = {
34472
34520
  };
34473
34521
 
34474
34522
  // src/version.ts
34475
- var version = "3.90.0";
34523
+ var version = "3.91.0";
34476
34524
 
34477
34525
  // src/formatters.ts
34478
34526
  var SINK_SEVERITY = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cognium-dev",
3
- "version": "3.90.0",
3
+ "version": "3.91.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.90.0"
68
+ "circle-ir": "^3.91.0"
69
69
  },
70
70
  "devDependencies": {
71
71
  "@types/node": "^25.5.0",