cognium-dev 3.90.1 → 3.93.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.
- package/README.md +27 -0
- package/dist/cli.js +120 -75
- 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
|
@@ -17789,6 +17789,114 @@ function normalizeCondition(cond) {
|
|
|
17789
17789
|
}
|
|
17790
17790
|
return normalized;
|
|
17791
17791
|
}
|
|
17792
|
+
// ../circle-ir/dist/utils/logger.js
|
|
17793
|
+
var LOG_LEVELS = {
|
|
17794
|
+
trace: 0,
|
|
17795
|
+
debug: 1,
|
|
17796
|
+
info: 2,
|
|
17797
|
+
warn: 3,
|
|
17798
|
+
error: 4,
|
|
17799
|
+
fatal: 5,
|
|
17800
|
+
silent: 6
|
|
17801
|
+
};
|
|
17802
|
+
var currentLevel = "silent";
|
|
17803
|
+
var customLogger = null;
|
|
17804
|
+
function shouldLog(level) {
|
|
17805
|
+
return LOG_LEVELS[level] >= LOG_LEVELS[currentLevel];
|
|
17806
|
+
}
|
|
17807
|
+
function setLogLevel(level) {
|
|
17808
|
+
currentLevel = level;
|
|
17809
|
+
}
|
|
17810
|
+
var logger = {
|
|
17811
|
+
trace: (msg, obj) => {
|
|
17812
|
+
if (customLogger) {
|
|
17813
|
+
customLogger.trace(msg, obj);
|
|
17814
|
+
return;
|
|
17815
|
+
}
|
|
17816
|
+
if (shouldLog("trace"))
|
|
17817
|
+
console.debug(obj ? `[TRACE] ${msg} ${JSON.stringify(obj)}` : `[TRACE] ${msg}`);
|
|
17818
|
+
},
|
|
17819
|
+
debug: (msg, obj) => {
|
|
17820
|
+
if (customLogger) {
|
|
17821
|
+
customLogger.debug(msg, obj);
|
|
17822
|
+
return;
|
|
17823
|
+
}
|
|
17824
|
+
if (shouldLog("debug"))
|
|
17825
|
+
console.debug(obj ? `[DEBUG] ${msg} ${JSON.stringify(obj)}` : `[DEBUG] ${msg}`);
|
|
17826
|
+
},
|
|
17827
|
+
info: (msg, obj) => {
|
|
17828
|
+
if (customLogger) {
|
|
17829
|
+
customLogger.info(msg, obj);
|
|
17830
|
+
return;
|
|
17831
|
+
}
|
|
17832
|
+
if (shouldLog("info"))
|
|
17833
|
+
console.error(obj ? `[INFO] ${msg} ${JSON.stringify(obj)}` : `[INFO] ${msg}`);
|
|
17834
|
+
},
|
|
17835
|
+
warn: (msg, obj) => {
|
|
17836
|
+
if (customLogger) {
|
|
17837
|
+
customLogger.warn(msg, obj);
|
|
17838
|
+
return;
|
|
17839
|
+
}
|
|
17840
|
+
if (shouldLog("warn"))
|
|
17841
|
+
console.warn(obj ? `[WARN] ${msg} ${JSON.stringify(obj)}` : `[WARN] ${msg}`);
|
|
17842
|
+
},
|
|
17843
|
+
error: (msg, obj) => {
|
|
17844
|
+
if (customLogger) {
|
|
17845
|
+
customLogger.error(msg, obj);
|
|
17846
|
+
return;
|
|
17847
|
+
}
|
|
17848
|
+
if (shouldLog("error"))
|
|
17849
|
+
console.error(obj ? `[ERROR] ${msg} ${JSON.stringify(obj)}` : `[ERROR] ${msg}`);
|
|
17850
|
+
},
|
|
17851
|
+
fatal: (msg, obj) => {
|
|
17852
|
+
if (customLogger) {
|
|
17853
|
+
customLogger.fatal(msg, obj);
|
|
17854
|
+
return;
|
|
17855
|
+
}
|
|
17856
|
+
if (shouldLog("fatal"))
|
|
17857
|
+
console.error(obj ? `[FATAL] ${msg} ${JSON.stringify(obj)}` : `[FATAL] ${msg}`);
|
|
17858
|
+
},
|
|
17859
|
+
isLevelEnabled: (level) => {
|
|
17860
|
+
return shouldLog(level);
|
|
17861
|
+
}
|
|
17862
|
+
};
|
|
17863
|
+
|
|
17864
|
+
// ../circle-ir/dist/analysis/per-file-finding-cap.js
|
|
17865
|
+
var DEFAULT_PER_FILE_FINDING_CAP = 1000;
|
|
17866
|
+
var SATURATED_FILE_RULE_ID = "saturated-file";
|
|
17867
|
+
function applyPerFileFindingCap(filePath, findings, cap) {
|
|
17868
|
+
if (cap <= 0)
|
|
17869
|
+
return findings;
|
|
17870
|
+
if (findings.length <= cap)
|
|
17871
|
+
return findings;
|
|
17872
|
+
const suppressedCount = findings.length;
|
|
17873
|
+
const byRule = {};
|
|
17874
|
+
const bySeverity = {};
|
|
17875
|
+
for (const f of findings) {
|
|
17876
|
+
byRule[f.rule_id] = (byRule[f.rule_id] ?? 0) + 1;
|
|
17877
|
+
bySeverity[f.severity] = (bySeverity[f.severity] ?? 0) + 1;
|
|
17878
|
+
}
|
|
17879
|
+
logger.warn(`File ${filePath} produced ${suppressedCount} findings (cap=${cap}); ` + "suppressing individual findings and emitting saturated-file advisory.", { file: filePath, suppressedCount, cap, byRule, bySeverity });
|
|
17880
|
+
const advisory = {
|
|
17881
|
+
id: `${SATURATED_FILE_RULE_ID}-${filePath}-1`,
|
|
17882
|
+
pass: SATURATED_FILE_RULE_ID,
|
|
17883
|
+
category: "maintainability",
|
|
17884
|
+
rule_id: SATURATED_FILE_RULE_ID,
|
|
17885
|
+
severity: "low",
|
|
17886
|
+
level: "note",
|
|
17887
|
+
message: `File suppressed: produced ${suppressedCount} findings, exceeding the ` + `per-file cap of ${cap}. This typically indicates cross-product noise, ` + "mislabelled sink class, or pathological generated code rather than a " + "legitimate detection burst. Individual findings dropped; re-run with " + "`perFileFindingCap: 0` to bypass the cap if the volume is intentional.",
|
|
17888
|
+
file: filePath,
|
|
17889
|
+
line: 1,
|
|
17890
|
+
evidence: {
|
|
17891
|
+
suppressed_count: suppressedCount,
|
|
17892
|
+
cap,
|
|
17893
|
+
by_rule: byRule,
|
|
17894
|
+
by_severity: bySeverity
|
|
17895
|
+
}
|
|
17896
|
+
};
|
|
17897
|
+
return [advisory];
|
|
17898
|
+
}
|
|
17899
|
+
|
|
17792
17900
|
// ../circle-ir/dist/languages/registry.js
|
|
17793
17901
|
class DefaultLanguageRegistry {
|
|
17794
17902
|
plugins = new Map;
|
|
@@ -20800,78 +20908,6 @@ function registerBuiltinPlugins() {
|
|
|
20800
20908
|
registerLanguage(new HtmlPlugin);
|
|
20801
20909
|
registerLanguage(new GoPlugin);
|
|
20802
20910
|
}
|
|
20803
|
-
// ../circle-ir/dist/utils/logger.js
|
|
20804
|
-
var LOG_LEVELS = {
|
|
20805
|
-
trace: 0,
|
|
20806
|
-
debug: 1,
|
|
20807
|
-
info: 2,
|
|
20808
|
-
warn: 3,
|
|
20809
|
-
error: 4,
|
|
20810
|
-
fatal: 5,
|
|
20811
|
-
silent: 6
|
|
20812
|
-
};
|
|
20813
|
-
var currentLevel = "silent";
|
|
20814
|
-
var customLogger = null;
|
|
20815
|
-
function shouldLog(level) {
|
|
20816
|
-
return LOG_LEVELS[level] >= LOG_LEVELS[currentLevel];
|
|
20817
|
-
}
|
|
20818
|
-
function setLogLevel(level) {
|
|
20819
|
-
currentLevel = level;
|
|
20820
|
-
}
|
|
20821
|
-
var logger = {
|
|
20822
|
-
trace: (msg, obj) => {
|
|
20823
|
-
if (customLogger) {
|
|
20824
|
-
customLogger.trace(msg, obj);
|
|
20825
|
-
return;
|
|
20826
|
-
}
|
|
20827
|
-
if (shouldLog("trace"))
|
|
20828
|
-
console.debug(obj ? `[TRACE] ${msg} ${JSON.stringify(obj)}` : `[TRACE] ${msg}`);
|
|
20829
|
-
},
|
|
20830
|
-
debug: (msg, obj) => {
|
|
20831
|
-
if (customLogger) {
|
|
20832
|
-
customLogger.debug(msg, obj);
|
|
20833
|
-
return;
|
|
20834
|
-
}
|
|
20835
|
-
if (shouldLog("debug"))
|
|
20836
|
-
console.debug(obj ? `[DEBUG] ${msg} ${JSON.stringify(obj)}` : `[DEBUG] ${msg}`);
|
|
20837
|
-
},
|
|
20838
|
-
info: (msg, obj) => {
|
|
20839
|
-
if (customLogger) {
|
|
20840
|
-
customLogger.info(msg, obj);
|
|
20841
|
-
return;
|
|
20842
|
-
}
|
|
20843
|
-
if (shouldLog("info"))
|
|
20844
|
-
console.error(obj ? `[INFO] ${msg} ${JSON.stringify(obj)}` : `[INFO] ${msg}`);
|
|
20845
|
-
},
|
|
20846
|
-
warn: (msg, obj) => {
|
|
20847
|
-
if (customLogger) {
|
|
20848
|
-
customLogger.warn(msg, obj);
|
|
20849
|
-
return;
|
|
20850
|
-
}
|
|
20851
|
-
if (shouldLog("warn"))
|
|
20852
|
-
console.warn(obj ? `[WARN] ${msg} ${JSON.stringify(obj)}` : `[WARN] ${msg}`);
|
|
20853
|
-
},
|
|
20854
|
-
error: (msg, obj) => {
|
|
20855
|
-
if (customLogger) {
|
|
20856
|
-
customLogger.error(msg, obj);
|
|
20857
|
-
return;
|
|
20858
|
-
}
|
|
20859
|
-
if (shouldLog("error"))
|
|
20860
|
-
console.error(obj ? `[ERROR] ${msg} ${JSON.stringify(obj)}` : `[ERROR] ${msg}`);
|
|
20861
|
-
},
|
|
20862
|
-
fatal: (msg, obj) => {
|
|
20863
|
-
if (customLogger) {
|
|
20864
|
-
customLogger.fatal(msg, obj);
|
|
20865
|
-
return;
|
|
20866
|
-
}
|
|
20867
|
-
if (shouldLog("fatal"))
|
|
20868
|
-
console.error(obj ? `[FATAL] ${msg} ${JSON.stringify(obj)}` : `[FATAL] ${msg}`);
|
|
20869
|
-
},
|
|
20870
|
-
isLevelEnabled: (level) => {
|
|
20871
|
-
return shouldLog(level);
|
|
20872
|
-
}
|
|
20873
|
-
};
|
|
20874
|
-
|
|
20875
20911
|
// ../circle-ir/dist/analysis/passes/cross-file-pass.js
|
|
20876
20912
|
class CrossFilePass {
|
|
20877
20913
|
run(projectGraph, sourceLines, options = {}) {
|
|
@@ -25001,6 +25037,9 @@ var TIER_1_METHOD_ANNOTATIONS = new Set([
|
|
|
25001
25037
|
var TIER_1_CLASS_ANNOTATIONS = new Set([
|
|
25002
25038
|
"RestController",
|
|
25003
25039
|
"Controller",
|
|
25040
|
+
"Service",
|
|
25041
|
+
"Repository",
|
|
25042
|
+
"Component",
|
|
25004
25043
|
"Path",
|
|
25005
25044
|
"WebServlet",
|
|
25006
25045
|
"ServerEndpoint",
|
|
@@ -25013,7 +25052,12 @@ var TIER_1_BY_SUPERTYPE = new Map([
|
|
|
25013
25052
|
["HandlerInterceptor", new Set(["preHandle", "postHandle", "afterCompletion"])],
|
|
25014
25053
|
["AsyncHandlerInterceptor", new Set(["preHandle", "postHandle", "afterCompletion", "afterConcurrentHandlingStarted"])],
|
|
25015
25054
|
["CommandLineRunner", new Set(["run"])],
|
|
25016
|
-
["ApplicationRunner", new Set(["run"])]
|
|
25055
|
+
["ApplicationRunner", new Set(["run"])],
|
|
25056
|
+
["SimpleChannelInboundHandler", new Set(["channelRead0", "messageReceived"])],
|
|
25057
|
+
["ChannelInboundHandler", new Set(["channelRead", "channelReadComplete"])],
|
|
25058
|
+
["ChannelInboundHandlerAdapter", new Set(["channelRead", "channelReadComplete"])],
|
|
25059
|
+
["ChannelDuplexHandler", new Set(["channelRead", "channelReadComplete"])],
|
|
25060
|
+
["NettyRequestProcessor", new Set(["process"])]
|
|
25017
25061
|
]);
|
|
25018
25062
|
var TIER_3_CLASS_SUFFIXES = [
|
|
25019
25063
|
"Util",
|
|
@@ -34339,6 +34383,7 @@ async function analyze(code, filePath, language, options = {}) {
|
|
|
34339
34383
|
unresolvedItems: unresolved.length
|
|
34340
34384
|
});
|
|
34341
34385
|
emitFindingsInstrumentation(filePath, findings, taint);
|
|
34386
|
+
const cappedFindings = applyPerFileFindingCap(filePath, findings, options.perFileFindingCap ?? DEFAULT_PER_FILE_FINDING_CAP);
|
|
34342
34387
|
return {
|
|
34343
34388
|
meta,
|
|
34344
34389
|
types,
|
|
@@ -34350,7 +34395,7 @@ async function analyze(code, filePath, language, options = {}) {
|
|
|
34350
34395
|
exports,
|
|
34351
34396
|
unresolved,
|
|
34352
34397
|
enriched,
|
|
34353
|
-
findings:
|
|
34398
|
+
findings: cappedFindings.length > 0 ? cappedFindings : undefined,
|
|
34354
34399
|
metrics: { file: filePath, metrics: metricValues },
|
|
34355
34400
|
runtime_registrations: runtimeRegistrations.length > 0 ? runtimeRegistrations : undefined,
|
|
34356
34401
|
parse_status: parseStatus
|
|
@@ -34517,7 +34562,7 @@ var colors = {
|
|
|
34517
34562
|
};
|
|
34518
34563
|
|
|
34519
34564
|
// src/version.ts
|
|
34520
|
-
var version = "3.
|
|
34565
|
+
var version = "3.93.0";
|
|
34521
34566
|
|
|
34522
34567
|
// src/formatters.ts
|
|
34523
34568
|
var SINK_SEVERITY = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cognium-dev",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.93.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.
|
|
68
|
+
"circle-ir": "^3.93.0"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
71
|
"@types/node": "^25.5.0",
|