cognium-dev 4.10.0 → 4.12.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 +274 -13
- package/package.json +3 -3
package/dist/cli.js
CHANGED
|
@@ -9403,6 +9403,31 @@ function processStatement2(stmt, startDefId, startUseId, scopeStack, isJavaScrip
|
|
|
9403
9403
|
}
|
|
9404
9404
|
break;
|
|
9405
9405
|
}
|
|
9406
|
+
case "switch_expression":
|
|
9407
|
+
case "switch_statement": {
|
|
9408
|
+
const value = stmt.childForFieldName("condition") ?? stmt.childForFieldName("value");
|
|
9409
|
+
if (value) {
|
|
9410
|
+
const valueUses = extractUses(value, useId, scopeStack, isJavaScript);
|
|
9411
|
+
uses.push(...valueUses.uses);
|
|
9412
|
+
useId = valueUses.nextId;
|
|
9413
|
+
}
|
|
9414
|
+
const body2 = stmt.childForFieldName("body");
|
|
9415
|
+
if (body2) {
|
|
9416
|
+
scopeStack.push(new Map);
|
|
9417
|
+
for (let i2 = 0;i2 < body2.childCount; i2++) {
|
|
9418
|
+
const group = body2.child(i2);
|
|
9419
|
+
if (!group)
|
|
9420
|
+
continue;
|
|
9421
|
+
const result = processBlock(group, defId, useId, scopeStack, isJavaScript);
|
|
9422
|
+
defs.push(...result.defs);
|
|
9423
|
+
uses.push(...result.uses);
|
|
9424
|
+
defId = result.nextDefId;
|
|
9425
|
+
useId = result.nextUseId;
|
|
9426
|
+
}
|
|
9427
|
+
scopeStack.pop();
|
|
9428
|
+
}
|
|
9429
|
+
break;
|
|
9430
|
+
}
|
|
9406
9431
|
case "block":
|
|
9407
9432
|
case "statement_block": {
|
|
9408
9433
|
scopeStack.push(new Map);
|
|
@@ -11404,6 +11429,7 @@ var DEFAULT_SOURCES = [
|
|
|
11404
11429
|
{ method: "get", class: "ConcurrentHashMap", type: "plugin_param", severity: "high", return_tainted: true },
|
|
11405
11430
|
{ method: "get", class: "Hashtable", type: "plugin_param", severity: "high", return_tainted: true },
|
|
11406
11431
|
{ method: "get", class: "Properties", type: "config_param", severity: "high", return_tainted: true },
|
|
11432
|
+
{ method: "getProperty", class: "Properties", type: "config_param", severity: "high", return_tainted: true },
|
|
11407
11433
|
{ method: "getText", class: "Message", type: "io_input", severity: "high", return_tainted: true },
|
|
11408
11434
|
{ method: "getPayload", type: "io_input", severity: "high", return_tainted: true },
|
|
11409
11435
|
{ method: "getData", type: "io_input", severity: "high", return_tainted: true },
|
|
@@ -11986,8 +12012,8 @@ var DEFAULT_SINKS = [
|
|
|
11986
12012
|
{ method: "write", class: "PrintWriter", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0] },
|
|
11987
12013
|
{ method: "println", class: "PrintWriter", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0] },
|
|
11988
12014
|
{ method: "print", class: "PrintWriter", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0] },
|
|
11989
|
-
{ method: "format", class: "PrintWriter", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0, 1] },
|
|
11990
|
-
{ method: "printf", class: "PrintWriter", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0, 1] },
|
|
12015
|
+
{ method: "format", class: "PrintWriter", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0, 1, 2, 3, 4, 5, 6, 7] },
|
|
12016
|
+
{ method: "printf", class: "PrintWriter", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0, 1, 2, 3, 4, 5, 6, 7] },
|
|
11991
12017
|
{ method: "write", class: "ServletOutputStream", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0] },
|
|
11992
12018
|
{ method: "print", class: "ServletOutputStream", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0] },
|
|
11993
12019
|
{ method: "println", class: "ServletOutputStream", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0] },
|
|
@@ -20183,9 +20209,18 @@ class ConstantPropagator {
|
|
|
20183
20209
|
}
|
|
20184
20210
|
}
|
|
20185
20211
|
} else {
|
|
20212
|
+
const taintedBefore = new Set(this.tainted);
|
|
20213
|
+
const taintedAfter = new Set(taintedBefore);
|
|
20214
|
+
const wasInConditional = this.inConditionalBranch;
|
|
20215
|
+
this.inConditionalBranch = true;
|
|
20186
20216
|
for (const caseGroup of caseGroups) {
|
|
20217
|
+
this.tainted = new Set(taintedBefore);
|
|
20187
20218
|
this.visit(caseGroup);
|
|
20219
|
+
for (const v of this.tainted)
|
|
20220
|
+
taintedAfter.add(v);
|
|
20188
20221
|
}
|
|
20222
|
+
this.inConditionalBranch = wasInConditional;
|
|
20223
|
+
this.tainted = taintedAfter;
|
|
20189
20224
|
}
|
|
20190
20225
|
}
|
|
20191
20226
|
handleTernary(node) {
|
|
@@ -21260,7 +21295,11 @@ function annotationsInclude(annotations, targets) {
|
|
|
21260
21295
|
return false;
|
|
21261
21296
|
}
|
|
21262
21297
|
function simpleTypeName(ref) {
|
|
21263
|
-
|
|
21298
|
+
const name2 = ref.replace(/<.*$/, "").trim();
|
|
21299
|
+
return name2.substring(name2.lastIndexOf(".") + 1);
|
|
21300
|
+
}
|
|
21301
|
+
function isSupertypeLifecycleMethod(supertype, methodName) {
|
|
21302
|
+
return TIER_1_BY_SUPERTYPE.get(simpleTypeName(supertype))?.has(methodName) ?? false;
|
|
21264
21303
|
}
|
|
21265
21304
|
function looksLikeMainMethod(method) {
|
|
21266
21305
|
if (method.name !== "main")
|
|
@@ -21822,7 +21861,7 @@ function applyRequireEntryPath(fileAnalyses, options = {}) {
|
|
|
21822
21861
|
if (graph.methodsByKey.size === 0)
|
|
21823
21862
|
return;
|
|
21824
21863
|
const fileContext = buildFileContext(fileAnalyses);
|
|
21825
|
-
const entryPointKeys = collectEntryPointKeys(graph, fileContext);
|
|
21864
|
+
const entryPointKeys = collectEntryPointKeys(graph, fileContext, indexTypesByName(fileAnalyses));
|
|
21826
21865
|
const entryPointKeysByLanguage = countEntryPointKeysByLanguage(graph, entryPointKeys);
|
|
21827
21866
|
const profileResolver = makeProfileResolver(options.projectProfile);
|
|
21828
21867
|
for (const fa of fileAnalyses) {
|
|
@@ -21984,7 +22023,7 @@ function resolveCalleeKeys(call, methodsByKey, methodsByName) {
|
|
|
21984
22023
|
}
|
|
21985
22024
|
return candidates;
|
|
21986
22025
|
}
|
|
21987
|
-
function collectEntryPointKeys(graph, fileContext) {
|
|
22026
|
+
function collectEntryPointKeys(graph, fileContext, typesByName) {
|
|
21988
22027
|
const entryPoints = new Set;
|
|
21989
22028
|
for (const rec of graph.methodsByKey.values()) {
|
|
21990
22029
|
const fileCtx = fileContext.get(rec.file);
|
|
@@ -21995,11 +22034,48 @@ function collectEntryPointKeys(graph, fileContext) {
|
|
|
21995
22034
|
calls: fileCtx?.calls ?? null,
|
|
21996
22035
|
runtimeRegistrations: fileCtx?.runtimeRegistrations ?? null
|
|
21997
22036
|
});
|
|
21998
|
-
if (tier === "TIER_1_ENTRY_POINT")
|
|
22037
|
+
if (tier === "TIER_1_ENTRY_POINT" || inheritsLifecycleEntry(rec.method.name, rec.enclosingType, typesByName)) {
|
|
21999
22038
|
entryPoints.add(rec.key);
|
|
22039
|
+
}
|
|
22000
22040
|
}
|
|
22001
22041
|
return entryPoints;
|
|
22002
22042
|
}
|
|
22043
|
+
function indexTypesByName(fileAnalyses) {
|
|
22044
|
+
const byName = new Map;
|
|
22045
|
+
for (const fa of fileAnalyses) {
|
|
22046
|
+
for (const t of fa.analysis.types ?? []) {
|
|
22047
|
+
const list = byName.get(t.name) ?? [];
|
|
22048
|
+
list.push(t);
|
|
22049
|
+
byName.set(t.name, list);
|
|
22050
|
+
}
|
|
22051
|
+
}
|
|
22052
|
+
return byName;
|
|
22053
|
+
}
|
|
22054
|
+
var simpleName = (ref) => {
|
|
22055
|
+
const name2 = ref.replace(/<.*$/, "").trim();
|
|
22056
|
+
return name2.substring(name2.lastIndexOf(".") + 1);
|
|
22057
|
+
};
|
|
22058
|
+
function inheritsLifecycleEntry(methodName, enclosingType, typesByName) {
|
|
22059
|
+
if (!methodName || !enclosingType?.extends)
|
|
22060
|
+
return false;
|
|
22061
|
+
const seen = new Set([enclosingType]);
|
|
22062
|
+
let frontier = typesByName.get(simpleName(enclosingType.extends)) ?? [];
|
|
22063
|
+
for (let depth = 0;depth < 8 && frontier.length > 0; depth++) {
|
|
22064
|
+
const next = [];
|
|
22065
|
+
for (const ancestor of frontier) {
|
|
22066
|
+
if (seen.has(ancestor))
|
|
22067
|
+
continue;
|
|
22068
|
+
seen.add(ancestor);
|
|
22069
|
+
const supers = [ancestor.extends, ...ancestor.implements ?? []].filter((x) => !!x);
|
|
22070
|
+
if (supers.some((sup) => isSupertypeLifecycleMethod(sup, methodName)))
|
|
22071
|
+
return true;
|
|
22072
|
+
if (ancestor.extends)
|
|
22073
|
+
next.push(...typesByName.get(simpleName(ancestor.extends)) ?? []);
|
|
22074
|
+
}
|
|
22075
|
+
frontier = next;
|
|
22076
|
+
}
|
|
22077
|
+
return false;
|
|
22078
|
+
}
|
|
22003
22079
|
function buildFileContext(fileAnalyses) {
|
|
22004
22080
|
const out2 = new Map;
|
|
22005
22081
|
for (const fa of fileAnalyses) {
|
|
@@ -26307,7 +26383,8 @@ class LanguageSourcesPass {
|
|
|
26307
26383
|
for (const finding of findJavaPatternFindings(code, graph.ir.meta.file)) {
|
|
26308
26384
|
ctx.addFinding(finding);
|
|
26309
26385
|
}
|
|
26310
|
-
|
|
26386
|
+
const xssSinkLines = new Set(ctx.getResult("taint-matcher").sinks.filter((s) => s.type === "xss").map((s) => s.line));
|
|
26387
|
+
for (const finding of findJavaResponseWriterXssFindings(code, graph.ir.meta.file, xssSinkLines)) {
|
|
26311
26388
|
ctx.addFinding(finding);
|
|
26312
26389
|
}
|
|
26313
26390
|
for (const finding of findJavaMongoNosqlInjectionFindings(code, graph.ir.meta.file)) {
|
|
@@ -27299,6 +27376,27 @@ function findPythonAssignmentSources(sourceCode, language) {
|
|
|
27299
27376
|
const lineNumber = lineNum + 1;
|
|
27300
27377
|
if (line.trimStart().startsWith("#"))
|
|
27301
27378
|
continue;
|
|
27379
|
+
const forTargetMatch = line.match(/^\s*for\s+([\p{L}\p{N}_]+)\s+in\s+(.+?)\s*:\s*$/u);
|
|
27380
|
+
if (forTargetMatch) {
|
|
27381
|
+
const [, iterVar, iterExpr] = forTargetMatch;
|
|
27382
|
+
for (const { pattern, type } of PYTHON_TAINTED_PATTERNS2) {
|
|
27383
|
+
if (!pattern.test(iterExpr))
|
|
27384
|
+
continue;
|
|
27385
|
+
const alreadyExists = sources.some((s2) => s2.line === lineNumber && s2.type === type);
|
|
27386
|
+
if (!alreadyExists) {
|
|
27387
|
+
sources.push({
|
|
27388
|
+
type,
|
|
27389
|
+
location: `for ${iterVar} in ${iterExpr.trim().substring(0, 50)}${iterExpr.length > 50 ? "..." : ""}`,
|
|
27390
|
+
severity: "high",
|
|
27391
|
+
line: lineNumber,
|
|
27392
|
+
confidence: 0.95,
|
|
27393
|
+
variable: iterVar
|
|
27394
|
+
});
|
|
27395
|
+
}
|
|
27396
|
+
break;
|
|
27397
|
+
}
|
|
27398
|
+
continue;
|
|
27399
|
+
}
|
|
27302
27400
|
const assignmentMatch = line.match(/^(\s*\w[\w.]*)\s*(?::\s*\w[\w\[\], .]*)?\s*=\s*(.+)/);
|
|
27303
27401
|
if (!assignmentMatch)
|
|
27304
27402
|
continue;
|
|
@@ -30840,7 +30938,7 @@ function findGoXssFindings(code, file) {
|
|
|
30840
30938
|
}
|
|
30841
30939
|
return out2;
|
|
30842
30940
|
}
|
|
30843
|
-
function findJavaResponseWriterXssFindings(code, file) {
|
|
30941
|
+
function findJavaResponseWriterXssFindings(code, file, taintSinkLines = new Set) {
|
|
30844
30942
|
const out2 = [];
|
|
30845
30943
|
const lines = code.split(`
|
|
30846
30944
|
`);
|
|
@@ -30876,6 +30974,8 @@ function findJavaResponseWriterXssFindings(code, file) {
|
|
|
30876
30974
|
const m = trimmed.match(chainRe);
|
|
30877
30975
|
if (!m)
|
|
30878
30976
|
continue;
|
|
30977
|
+
if (taintSinkLines.has(i2 + 1))
|
|
30978
|
+
continue;
|
|
30879
30979
|
const recv = m[1];
|
|
30880
30980
|
if (!respNames.has(recv))
|
|
30881
30981
|
continue;
|
|
@@ -36572,6 +36672,103 @@ class SpeculativePromptParamSourcePass {
|
|
|
36572
36672
|
}
|
|
36573
36673
|
}
|
|
36574
36674
|
|
|
36675
|
+
// ../circle-ir/dist/analysis/passes/param-source-flow-gate-pass.js
|
|
36676
|
+
var EXEMPT_LANGUAGES = new Set(["java", "csharp"]);
|
|
36677
|
+
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;
|
|
36678
|
+
var RUST_ROUTE_ATTR = /^\s*#\[\s*(?:[A-Za-z_][\w]*::)*(?:get|post|put|patch|delete|head|options|route|handler)\s*[(\]]/;
|
|
36679
|
+
var RUST_HANDLER_RETURN = /\b(?:HttpResponse|Responder|Reply|IntoResponse|Response(?:<[^>]*>)?)\b/;
|
|
36680
|
+
function enclosingMethod(methods, line) {
|
|
36681
|
+
let best;
|
|
36682
|
+
for (const m of methods) {
|
|
36683
|
+
if (m.start_line <= line && line <= m.end_line) {
|
|
36684
|
+
if (!best || m.end_line - m.start_line < best.end_line - best.start_line)
|
|
36685
|
+
best = m;
|
|
36686
|
+
}
|
|
36687
|
+
}
|
|
36688
|
+
return best;
|
|
36689
|
+
}
|
|
36690
|
+
function rustAttributesAbove(lines, startLine) {
|
|
36691
|
+
const out2 = [];
|
|
36692
|
+
for (let i2 = startLine - 2;i2 >= 0; i2--) {
|
|
36693
|
+
const t = (lines[i2] ?? "").trim();
|
|
36694
|
+
if (t.startsWith("#[")) {
|
|
36695
|
+
out2.push(t);
|
|
36696
|
+
continue;
|
|
36697
|
+
}
|
|
36698
|
+
if (t === "" || t.startsWith("//"))
|
|
36699
|
+
continue;
|
|
36700
|
+
break;
|
|
36701
|
+
}
|
|
36702
|
+
return out2;
|
|
36703
|
+
}
|
|
36704
|
+
function isFrameworkHandler(method, language, lines) {
|
|
36705
|
+
if (method.annotations.some((a) => ROUTE_ANNOTATION.test(a)))
|
|
36706
|
+
return true;
|
|
36707
|
+
if (language === "rust") {
|
|
36708
|
+
if (rustAttributesAbove(lines, method.start_line).some((a) => RUST_ROUTE_ATTR.test(a)))
|
|
36709
|
+
return true;
|
|
36710
|
+
if (method.return_type && RUST_HANDLER_RETURN.test(method.return_type))
|
|
36711
|
+
return true;
|
|
36712
|
+
}
|
|
36713
|
+
return false;
|
|
36714
|
+
}
|
|
36715
|
+
|
|
36716
|
+
class ParamSourceFlowGatePass {
|
|
36717
|
+
keepParamSourcedFlows;
|
|
36718
|
+
name = "param-source-flow-gate";
|
|
36719
|
+
category = "security";
|
|
36720
|
+
constructor(keepParamSourcedFlows) {
|
|
36721
|
+
this.keepParamSourcedFlows = keepParamSourcedFlows;
|
|
36722
|
+
}
|
|
36723
|
+
run(ctx) {
|
|
36724
|
+
const result = { applied: false, dropped: 0, droppedBySinkType: {} };
|
|
36725
|
+
if (this.keepParamSourcedFlows || EXEMPT_LANGUAGES.has(ctx.language))
|
|
36726
|
+
return result;
|
|
36727
|
+
if (!ctx.hasResult("interprocedural"))
|
|
36728
|
+
return result;
|
|
36729
|
+
const flows = ctx.getResult("interprocedural").additionalFlows;
|
|
36730
|
+
result.applied = true;
|
|
36731
|
+
if (flows.length === 0)
|
|
36732
|
+
return result;
|
|
36733
|
+
const methods = ctx.graph.ir.types.flatMap((t) => t.methods);
|
|
36734
|
+
const lines = ctx.code.split(`
|
|
36735
|
+
`);
|
|
36736
|
+
const handlerCache = new Map;
|
|
36737
|
+
const isHandler = (m) => {
|
|
36738
|
+
let v = handlerCache.get(m);
|
|
36739
|
+
if (v === undefined) {
|
|
36740
|
+
v = isFrameworkHandler(m, ctx.language, lines);
|
|
36741
|
+
handlerCache.set(m, v);
|
|
36742
|
+
}
|
|
36743
|
+
return v;
|
|
36744
|
+
};
|
|
36745
|
+
const realSourceLines = new Set;
|
|
36746
|
+
if (ctx.hasResult("sink-filter")) {
|
|
36747
|
+
const sources = ctx.getResult("sink-filter").sources;
|
|
36748
|
+
for (const s of sources) {
|
|
36749
|
+
if (s.type !== "interprocedural_param")
|
|
36750
|
+
realSourceLines.add(s.line);
|
|
36751
|
+
}
|
|
36752
|
+
}
|
|
36753
|
+
let w = 0;
|
|
36754
|
+
for (const f of flows) {
|
|
36755
|
+
let keep = true;
|
|
36756
|
+
if (f.source_type === "interprocedural_param" && !realSourceLines.has(f.source_line)) {
|
|
36757
|
+
const m = enclosingMethod(methods, f.source_line);
|
|
36758
|
+
keep = m !== undefined && isHandler(m);
|
|
36759
|
+
}
|
|
36760
|
+
if (keep)
|
|
36761
|
+
flows[w++] = f;
|
|
36762
|
+
else {
|
|
36763
|
+
result.dropped++;
|
|
36764
|
+
result.droppedBySinkType[f.sink_type] = (result.droppedBySinkType[f.sink_type] ?? 0) + 1;
|
|
36765
|
+
}
|
|
36766
|
+
}
|
|
36767
|
+
flows.length = w;
|
|
36768
|
+
return result;
|
|
36769
|
+
}
|
|
36770
|
+
}
|
|
36771
|
+
|
|
36575
36772
|
// ../circle-ir/dist/analysis/passes/cli-main-reflection-suppress-pass.js
|
|
36576
36773
|
var REFLECTION_SINK_METHODS = new Set([
|
|
36577
36774
|
"forName",
|
|
@@ -37801,8 +37998,53 @@ function isReassignedToLiteralBetween(code, variable, srcLine, sinkLine) {
|
|
|
37801
37998
|
const line = lines[i2];
|
|
37802
37999
|
if (!line)
|
|
37803
38000
|
continue;
|
|
37804
|
-
if (
|
|
38001
|
+
if (reGuarded.test(line))
|
|
37805
38002
|
return true;
|
|
38003
|
+
if (!reNaked.test(line) && !reSwitchCase.test(line))
|
|
38004
|
+
continue;
|
|
38005
|
+
if (switchAlsoAssignsNonLiteral(lines, i2, variable, strLit))
|
|
38006
|
+
continue;
|
|
38007
|
+
return true;
|
|
38008
|
+
}
|
|
38009
|
+
return false;
|
|
38010
|
+
}
|
|
38011
|
+
function switchAlsoAssignsNonLiteral(lines, idx, variable, strLit) {
|
|
38012
|
+
let depth = 0;
|
|
38013
|
+
let start2 = -1;
|
|
38014
|
+
for (let i2 = idx;i2 >= 0; i2--) {
|
|
38015
|
+
const line = lines[i2];
|
|
38016
|
+
for (let c = line.length - 1;c >= 0; c--) {
|
|
38017
|
+
if (line[c] === "}")
|
|
38018
|
+
depth++;
|
|
38019
|
+
else if (line[c] === "{")
|
|
38020
|
+
depth--;
|
|
38021
|
+
}
|
|
38022
|
+
if (depth < 0) {
|
|
38023
|
+
if (/\bswitch\b/.test(line))
|
|
38024
|
+
start2 = i2;
|
|
38025
|
+
break;
|
|
38026
|
+
}
|
|
38027
|
+
}
|
|
38028
|
+
if (start2 < 0)
|
|
38029
|
+
return false;
|
|
38030
|
+
const assign = new RegExp(`(?:^|[^\\w.$])${variable}\\s*(?::?=)(?!=)\\s*(.*?)\\s*;?\\s*(?:break\\s*;?)?\\s*$`);
|
|
38031
|
+
const literalOnly = new RegExp(`^${strLit}$`);
|
|
38032
|
+
depth = 0;
|
|
38033
|
+
for (let i2 = start2;i2 < lines.length; i2++) {
|
|
38034
|
+
const line = lines[i2];
|
|
38035
|
+
if (i2 > start2 || line.includes("{")) {
|
|
38036
|
+
const m = assign.exec(line);
|
|
38037
|
+
if (m && m[1] && !literalOnly.test(m[1]))
|
|
38038
|
+
return true;
|
|
38039
|
+
}
|
|
38040
|
+
for (const ch of line) {
|
|
38041
|
+
if (ch === "{")
|
|
38042
|
+
depth++;
|
|
38043
|
+
else if (ch === "}")
|
|
38044
|
+
depth--;
|
|
38045
|
+
}
|
|
38046
|
+
if (i2 > start2 && depth <= 0)
|
|
38047
|
+
break;
|
|
37806
38048
|
}
|
|
37807
38049
|
return false;
|
|
37808
38050
|
}
|
|
@@ -43827,6 +44069,13 @@ var PROVIDER_PATTERNS = [
|
|
|
43827
44069
|
level: "error",
|
|
43828
44070
|
fix: "Revoke the GitHub refresh token and store secrets outside source control."
|
|
43829
44071
|
},
|
|
44072
|
+
{
|
|
44073
|
+
name: "GitLab personal access token",
|
|
44074
|
+
regex: /\bglpat-[A-Za-z0-9_-]{20,}\b/,
|
|
44075
|
+
severity: "critical",
|
|
44076
|
+
level: "error",
|
|
44077
|
+
fix: "Revoke the GitLab personal access token and store it outside source control."
|
|
44078
|
+
},
|
|
43830
44079
|
{
|
|
43831
44080
|
name: "Stripe live secret key",
|
|
43832
44081
|
regex: /\bsk_live_[A-Za-z0-9]{24,}\b/,
|
|
@@ -43834,6 +44083,13 @@ var PROVIDER_PATTERNS = [
|
|
|
43834
44083
|
level: "error",
|
|
43835
44084
|
fix: "Rotate the Stripe secret key in the Stripe Dashboard and load it from a secrets manager."
|
|
43836
44085
|
},
|
|
44086
|
+
{
|
|
44087
|
+
name: "Stripe live restricted key",
|
|
44088
|
+
regex: /\brk_live_[A-Za-z0-9]{24,}\b/,
|
|
44089
|
+
severity: "critical",
|
|
44090
|
+
level: "error",
|
|
44091
|
+
fix: "Rotate the Stripe restricted key in the Stripe Dashboard and load it from a secrets manager."
|
|
44092
|
+
},
|
|
43837
44093
|
{
|
|
43838
44094
|
name: "Stripe live publishable key",
|
|
43839
44095
|
regex: /\bpk_live_[A-Za-z0-9]{24,}\b/,
|
|
@@ -44185,6 +44441,9 @@ class ScanSecretsPass {
|
|
|
44185
44441
|
const m = pattern.regex.exec(lineText);
|
|
44186
44442
|
if (!m)
|
|
44187
44443
|
continue;
|
|
44444
|
+
if ((pattern.name === "Stripe live restricted key" || pattern.name === "GitLab personal access token") && PLACEHOLDER_RE.test(m[0])) {
|
|
44445
|
+
continue;
|
|
44446
|
+
}
|
|
44188
44447
|
if (pattern.name === "PEM private key" && !pemHasInlineBody(lines, i2)) {
|
|
44189
44448
|
continue;
|
|
44190
44449
|
}
|
|
@@ -49424,6 +49683,8 @@ async function analyze(code, filePath, language, options = {}) {
|
|
|
49424
49683
|
pipeline.add(new InterproceduralPass({
|
|
49425
49684
|
enableEntryPointGate: options.enableEntryPointGate ?? true
|
|
49426
49685
|
}));
|
|
49686
|
+
if (!disabledPasses.has("param-source-flow-gate"))
|
|
49687
|
+
pipeline.add(new ParamSourceFlowGatePass(options.speculativeParamSources === true));
|
|
49427
49688
|
if (!disabledPasses.has("library-profile-cwe22-path-gate"))
|
|
49428
49689
|
pipeline.add(new LibraryProfileCwe22PathGatePass);
|
|
49429
49690
|
if (!disabledPasses.has("scan-secrets"))
|
|
@@ -50874,7 +51135,7 @@ var colors = {
|
|
|
50874
51135
|
};
|
|
50875
51136
|
|
|
50876
51137
|
// src/version.ts
|
|
50877
|
-
var version = "4.
|
|
51138
|
+
var version = "4.12.0";
|
|
50878
51139
|
|
|
50879
51140
|
// src/formatters.ts
|
|
50880
51141
|
var LIBRARY_API_SURFACE_TAG2 = "library-api-surface:caller-responsibility";
|
|
@@ -51426,8 +51687,8 @@ function generateSarifResults(results, crossFileData) {
|
|
|
51426
51687
|
|
|
51427
51688
|
// src/build-info.ts
|
|
51428
51689
|
var buildInfo = {
|
|
51429
|
-
gitSha: "
|
|
51430
|
-
builtAt: "2026-10-
|
|
51690
|
+
gitSha: "8c284bc",
|
|
51691
|
+
builtAt: "2026-10-08T00:42:12.776Z"
|
|
51431
51692
|
};
|
|
51432
51693
|
|
|
51433
51694
|
// src/utils/args.ts
|
|
@@ -51678,7 +51939,7 @@ function loadConfig(profilePath) {
|
|
|
51678
51939
|
const content = readFileSync(configPath, "utf-8");
|
|
51679
51940
|
return JSON.parse(content);
|
|
51680
51941
|
} catch (err2) {
|
|
51681
|
-
throw new Error(`Failed to parse ${configPath}: ${err2 instanceof Error ? err2.message : String(err2)}. ` + "Fix the JSON or remove the file.");
|
|
51942
|
+
throw new Error(`Failed to parse ${configPath}: ${err2 instanceof Error ? err2.message : String(err2)}. ` + "Fix the JSON or remove the file.", { cause: err2 });
|
|
51682
51943
|
}
|
|
51683
51944
|
}
|
|
51684
51945
|
function convertConfigToPassOptions(config) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cognium-dev",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.12.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.12.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",
|