cognium-dev 4.10.0 → 4.11.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/dist/cli.js +141 -4
- package/package.json +3 -3
package/dist/cli.js
CHANGED
|
@@ -27299,6 +27299,27 @@ function findPythonAssignmentSources(sourceCode, language) {
|
|
|
27299
27299
|
const lineNumber = lineNum + 1;
|
|
27300
27300
|
if (line.trimStart().startsWith("#"))
|
|
27301
27301
|
continue;
|
|
27302
|
+
const forTargetMatch = line.match(/^\s*for\s+([\p{L}\p{N}_]+)\s+in\s+(.+?)\s*:\s*$/u);
|
|
27303
|
+
if (forTargetMatch) {
|
|
27304
|
+
const [, iterVar, iterExpr] = forTargetMatch;
|
|
27305
|
+
for (const { pattern, type } of PYTHON_TAINTED_PATTERNS2) {
|
|
27306
|
+
if (!pattern.test(iterExpr))
|
|
27307
|
+
continue;
|
|
27308
|
+
const alreadyExists = sources.some((s2) => s2.line === lineNumber && s2.type === type);
|
|
27309
|
+
if (!alreadyExists) {
|
|
27310
|
+
sources.push({
|
|
27311
|
+
type,
|
|
27312
|
+
location: `for ${iterVar} in ${iterExpr.trim().substring(0, 50)}${iterExpr.length > 50 ? "..." : ""}`,
|
|
27313
|
+
severity: "high",
|
|
27314
|
+
line: lineNumber,
|
|
27315
|
+
confidence: 0.95,
|
|
27316
|
+
variable: iterVar
|
|
27317
|
+
});
|
|
27318
|
+
}
|
|
27319
|
+
break;
|
|
27320
|
+
}
|
|
27321
|
+
continue;
|
|
27322
|
+
}
|
|
27302
27323
|
const assignmentMatch = line.match(/^(\s*\w[\w.]*)\s*(?::\s*\w[\w\[\], .]*)?\s*=\s*(.+)/);
|
|
27303
27324
|
if (!assignmentMatch)
|
|
27304
27325
|
continue;
|
|
@@ -36572,6 +36593,103 @@ class SpeculativePromptParamSourcePass {
|
|
|
36572
36593
|
}
|
|
36573
36594
|
}
|
|
36574
36595
|
|
|
36596
|
+
// ../circle-ir/dist/analysis/passes/param-source-flow-gate-pass.js
|
|
36597
|
+
var EXEMPT_LANGUAGES = new Set(["java", "csharp"]);
|
|
36598
|
+
var ROUTE_ANNOTATION = /(?:^|[.\s@])(?:route|api_route|get|post|put|patch|delete|head|options|websocket|api_view|view_config|RequestMapping|GetMapping|PostMapping|PutMapping|DeleteMapping|PatchMapping|All)\s*(?:\(|$)/i;
|
|
36599
|
+
var RUST_ROUTE_ATTR = /^\s*#\[\s*(?:[A-Za-z_][\w]*::)*(?:get|post|put|patch|delete|head|options|route|handler)\s*[(\]]/;
|
|
36600
|
+
var RUST_HANDLER_RETURN = /\b(?:HttpResponse|Responder|Reply|IntoResponse|Response(?:<[^>]*>)?)\b/;
|
|
36601
|
+
function enclosingMethod(methods, line) {
|
|
36602
|
+
let best;
|
|
36603
|
+
for (const m of methods) {
|
|
36604
|
+
if (m.start_line <= line && line <= m.end_line) {
|
|
36605
|
+
if (!best || m.end_line - m.start_line < best.end_line - best.start_line)
|
|
36606
|
+
best = m;
|
|
36607
|
+
}
|
|
36608
|
+
}
|
|
36609
|
+
return best;
|
|
36610
|
+
}
|
|
36611
|
+
function rustAttributesAbove(lines, startLine) {
|
|
36612
|
+
const out2 = [];
|
|
36613
|
+
for (let i2 = startLine - 2;i2 >= 0; i2--) {
|
|
36614
|
+
const t = (lines[i2] ?? "").trim();
|
|
36615
|
+
if (t.startsWith("#[")) {
|
|
36616
|
+
out2.push(t);
|
|
36617
|
+
continue;
|
|
36618
|
+
}
|
|
36619
|
+
if (t === "" || t.startsWith("//"))
|
|
36620
|
+
continue;
|
|
36621
|
+
break;
|
|
36622
|
+
}
|
|
36623
|
+
return out2;
|
|
36624
|
+
}
|
|
36625
|
+
function isFrameworkHandler(method, language, lines) {
|
|
36626
|
+
if (method.annotations.some((a) => ROUTE_ANNOTATION.test(a)))
|
|
36627
|
+
return true;
|
|
36628
|
+
if (language === "rust") {
|
|
36629
|
+
if (rustAttributesAbove(lines, method.start_line).some((a) => RUST_ROUTE_ATTR.test(a)))
|
|
36630
|
+
return true;
|
|
36631
|
+
if (method.return_type && RUST_HANDLER_RETURN.test(method.return_type))
|
|
36632
|
+
return true;
|
|
36633
|
+
}
|
|
36634
|
+
return false;
|
|
36635
|
+
}
|
|
36636
|
+
|
|
36637
|
+
class ParamSourceFlowGatePass {
|
|
36638
|
+
keepParamSourcedFlows;
|
|
36639
|
+
name = "param-source-flow-gate";
|
|
36640
|
+
category = "security";
|
|
36641
|
+
constructor(keepParamSourcedFlows) {
|
|
36642
|
+
this.keepParamSourcedFlows = keepParamSourcedFlows;
|
|
36643
|
+
}
|
|
36644
|
+
run(ctx) {
|
|
36645
|
+
const result = { applied: false, dropped: 0, droppedBySinkType: {} };
|
|
36646
|
+
if (this.keepParamSourcedFlows || EXEMPT_LANGUAGES.has(ctx.language))
|
|
36647
|
+
return result;
|
|
36648
|
+
if (!ctx.hasResult("interprocedural"))
|
|
36649
|
+
return result;
|
|
36650
|
+
const flows = ctx.getResult("interprocedural").additionalFlows;
|
|
36651
|
+
result.applied = true;
|
|
36652
|
+
if (flows.length === 0)
|
|
36653
|
+
return result;
|
|
36654
|
+
const methods = ctx.graph.ir.types.flatMap((t) => t.methods);
|
|
36655
|
+
const lines = ctx.code.split(`
|
|
36656
|
+
`);
|
|
36657
|
+
const handlerCache = new Map;
|
|
36658
|
+
const isHandler = (m) => {
|
|
36659
|
+
let v = handlerCache.get(m);
|
|
36660
|
+
if (v === undefined) {
|
|
36661
|
+
v = isFrameworkHandler(m, ctx.language, lines);
|
|
36662
|
+
handlerCache.set(m, v);
|
|
36663
|
+
}
|
|
36664
|
+
return v;
|
|
36665
|
+
};
|
|
36666
|
+
const realSourceLines = new Set;
|
|
36667
|
+
if (ctx.hasResult("sink-filter")) {
|
|
36668
|
+
const sources = ctx.getResult("sink-filter").sources;
|
|
36669
|
+
for (const s of sources) {
|
|
36670
|
+
if (s.type !== "interprocedural_param")
|
|
36671
|
+
realSourceLines.add(s.line);
|
|
36672
|
+
}
|
|
36673
|
+
}
|
|
36674
|
+
let w = 0;
|
|
36675
|
+
for (const f of flows) {
|
|
36676
|
+
let keep = true;
|
|
36677
|
+
if (f.source_type === "interprocedural_param" && !realSourceLines.has(f.source_line)) {
|
|
36678
|
+
const m = enclosingMethod(methods, f.source_line);
|
|
36679
|
+
keep = m !== undefined && isHandler(m);
|
|
36680
|
+
}
|
|
36681
|
+
if (keep)
|
|
36682
|
+
flows[w++] = f;
|
|
36683
|
+
else {
|
|
36684
|
+
result.dropped++;
|
|
36685
|
+
result.droppedBySinkType[f.sink_type] = (result.droppedBySinkType[f.sink_type] ?? 0) + 1;
|
|
36686
|
+
}
|
|
36687
|
+
}
|
|
36688
|
+
flows.length = w;
|
|
36689
|
+
return result;
|
|
36690
|
+
}
|
|
36691
|
+
}
|
|
36692
|
+
|
|
36575
36693
|
// ../circle-ir/dist/analysis/passes/cli-main-reflection-suppress-pass.js
|
|
36576
36694
|
var REFLECTION_SINK_METHODS = new Set([
|
|
36577
36695
|
"forName",
|
|
@@ -43827,6 +43945,13 @@ var PROVIDER_PATTERNS = [
|
|
|
43827
43945
|
level: "error",
|
|
43828
43946
|
fix: "Revoke the GitHub refresh token and store secrets outside source control."
|
|
43829
43947
|
},
|
|
43948
|
+
{
|
|
43949
|
+
name: "GitLab personal access token",
|
|
43950
|
+
regex: /\bglpat-[A-Za-z0-9_-]{20,}\b/,
|
|
43951
|
+
severity: "critical",
|
|
43952
|
+
level: "error",
|
|
43953
|
+
fix: "Revoke the GitLab personal access token and store it outside source control."
|
|
43954
|
+
},
|
|
43830
43955
|
{
|
|
43831
43956
|
name: "Stripe live secret key",
|
|
43832
43957
|
regex: /\bsk_live_[A-Za-z0-9]{24,}\b/,
|
|
@@ -43834,6 +43959,13 @@ var PROVIDER_PATTERNS = [
|
|
|
43834
43959
|
level: "error",
|
|
43835
43960
|
fix: "Rotate the Stripe secret key in the Stripe Dashboard and load it from a secrets manager."
|
|
43836
43961
|
},
|
|
43962
|
+
{
|
|
43963
|
+
name: "Stripe live restricted key",
|
|
43964
|
+
regex: /\brk_live_[A-Za-z0-9]{24,}\b/,
|
|
43965
|
+
severity: "critical",
|
|
43966
|
+
level: "error",
|
|
43967
|
+
fix: "Rotate the Stripe restricted key in the Stripe Dashboard and load it from a secrets manager."
|
|
43968
|
+
},
|
|
43837
43969
|
{
|
|
43838
43970
|
name: "Stripe live publishable key",
|
|
43839
43971
|
regex: /\bpk_live_[A-Za-z0-9]{24,}\b/,
|
|
@@ -44185,6 +44317,9 @@ class ScanSecretsPass {
|
|
|
44185
44317
|
const m = pattern.regex.exec(lineText);
|
|
44186
44318
|
if (!m)
|
|
44187
44319
|
continue;
|
|
44320
|
+
if ((pattern.name === "Stripe live restricted key" || pattern.name === "GitLab personal access token") && PLACEHOLDER_RE.test(m[0])) {
|
|
44321
|
+
continue;
|
|
44322
|
+
}
|
|
44188
44323
|
if (pattern.name === "PEM private key" && !pemHasInlineBody(lines, i2)) {
|
|
44189
44324
|
continue;
|
|
44190
44325
|
}
|
|
@@ -49424,6 +49559,8 @@ async function analyze(code, filePath, language, options = {}) {
|
|
|
49424
49559
|
pipeline.add(new InterproceduralPass({
|
|
49425
49560
|
enableEntryPointGate: options.enableEntryPointGate ?? true
|
|
49426
49561
|
}));
|
|
49562
|
+
if (!disabledPasses.has("param-source-flow-gate"))
|
|
49563
|
+
pipeline.add(new ParamSourceFlowGatePass(options.speculativeParamSources === true));
|
|
49427
49564
|
if (!disabledPasses.has("library-profile-cwe22-path-gate"))
|
|
49428
49565
|
pipeline.add(new LibraryProfileCwe22PathGatePass);
|
|
49429
49566
|
if (!disabledPasses.has("scan-secrets"))
|
|
@@ -50874,7 +51011,7 @@ var colors = {
|
|
|
50874
51011
|
};
|
|
50875
51012
|
|
|
50876
51013
|
// src/version.ts
|
|
50877
|
-
var version = "4.
|
|
51014
|
+
var version = "4.11.0";
|
|
50878
51015
|
|
|
50879
51016
|
// src/formatters.ts
|
|
50880
51017
|
var LIBRARY_API_SURFACE_TAG2 = "library-api-surface:caller-responsibility";
|
|
@@ -51426,8 +51563,8 @@ function generateSarifResults(results, crossFileData) {
|
|
|
51426
51563
|
|
|
51427
51564
|
// src/build-info.ts
|
|
51428
51565
|
var buildInfo = {
|
|
51429
|
-
gitSha: "
|
|
51430
|
-
builtAt: "2026-10-
|
|
51566
|
+
gitSha: "165e82d",
|
|
51567
|
+
builtAt: "2026-10-07T23:49:13.604Z"
|
|
51431
51568
|
};
|
|
51432
51569
|
|
|
51433
51570
|
// src/utils/args.ts
|
|
@@ -51678,7 +51815,7 @@ function loadConfig(profilePath) {
|
|
|
51678
51815
|
const content = readFileSync(configPath, "utf-8");
|
|
51679
51816
|
return JSON.parse(content);
|
|
51680
51817
|
} catch (err2) {
|
|
51681
|
-
throw new Error(`Failed to parse ${configPath}: ${err2 instanceof Error ? err2.message : String(err2)}. ` + "Fix the JSON or remove the file.");
|
|
51818
|
+
throw new Error(`Failed to parse ${configPath}: ${err2 instanceof Error ? err2.message : String(err2)}. ` + "Fix the JSON or remove the file.", { cause: err2 });
|
|
51682
51819
|
}
|
|
51683
51820
|
}
|
|
51684
51821
|
function convertConfigToPassOptions(config) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cognium-dev",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.11.0",
|
|
4
4
|
"description": "Static Application Security Testing CLI for detecting security vulnerabilities via taint tracking",
|
|
5
5
|
"bin": {
|
|
6
6
|
"cognium-dev": "dist/cli.js"
|
|
@@ -65,10 +65,10 @@
|
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|
|
67
67
|
"@cognium/project-profile-detect": "1.1.2",
|
|
68
|
-
"circle-ir": "4.
|
|
68
|
+
"circle-ir": "4.11.0"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
|
-
"@types/node": "^26.6.
|
|
71
|
+
"@types/node": "^26.6.4",
|
|
72
72
|
"ajv": "^8.17.1",
|
|
73
73
|
"ajv-draft-04": "^1.0.0",
|
|
74
74
|
"bun-types": "^1.4.2",
|