cognium-dev 4.9.25 → 4.9.26
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 +134 -17
- package/package.json +3 -3
package/dist/cli.js
CHANGED
|
@@ -3349,8 +3349,9 @@ async function initParser(options = {}) {
|
|
|
3349
3349
|
});
|
|
3350
3350
|
}
|
|
3351
3351
|
parserInitialized = true;
|
|
3352
|
+
})().finally(() => {
|
|
3352
3353
|
parserInitializing = null;
|
|
3353
|
-
})
|
|
3354
|
+
});
|
|
3354
3355
|
return parserInitializing;
|
|
3355
3356
|
}
|
|
3356
3357
|
async function loadLanguage(language, wasmPath) {
|
|
@@ -26727,6 +26728,52 @@ function findGoRequestBodySources(sourceCode, language) {
|
|
|
26727
26728
|
continue;
|
|
26728
26729
|
}
|
|
26729
26730
|
}
|
|
26731
|
+
const wrapRe = new RegExp(`^\\s*(?:var\\s+)?([A-Za-z_]\\w*)\\s*:?=\\s*bufio\\s*\\.\\s*New(?:Scanner|Reader|ReaderSize)\\s*\\(.*${bodyRef}`);
|
|
26732
|
+
const braceDelta = (s) => {
|
|
26733
|
+
const code = s.replace(/"(?:[^"\\]|\\.)*"|`[^`]*`|'(?:[^'\\]|\\.)*'/g, '""').replace(/\/\/.*$/, "");
|
|
26734
|
+
let d = 0;
|
|
26735
|
+
for (const ch of code) {
|
|
26736
|
+
if (ch === "{")
|
|
26737
|
+
d++;
|
|
26738
|
+
else if (ch === "}")
|
|
26739
|
+
d--;
|
|
26740
|
+
}
|
|
26741
|
+
return d;
|
|
26742
|
+
};
|
|
26743
|
+
for (let i2 = 0;i2 < lines.length; i2++) {
|
|
26744
|
+
const w = wrapRe.exec(lines[i2]);
|
|
26745
|
+
if (!w)
|
|
26746
|
+
continue;
|
|
26747
|
+
const wrapper = w[1];
|
|
26748
|
+
if (wrapper === "_")
|
|
26749
|
+
continue;
|
|
26750
|
+
const readRe = new RegExp(`(?<![\\w.])${wrapper}\\s*\\.\\s*(Text|Bytes|ReadString|ReadBytes|ReadLine|ReadSlice)\\s*\\(`);
|
|
26751
|
+
const assignRe = new RegExp(`^\\s*(?:var\\s+)?([A-Za-z_][\\w\\s,]*?)\\s*:?=(?!=)\\s*(?:string\\s*\\(\\s*)?${wrapper}\\s*\\.\\s*(?:Text|Bytes|ReadString|ReadBytes|ReadLine|ReadSlice)\\s*\\(`);
|
|
26752
|
+
const rebindRe = new RegExp(`(?<![\\w.])${wrapper}\\s*:?=(?!=)`);
|
|
26753
|
+
let depth = 0;
|
|
26754
|
+
for (let j = i2 + 1;j < lines.length; j++) {
|
|
26755
|
+
depth += braceDelta(lines[j - 1]);
|
|
26756
|
+
if (depth < 0)
|
|
26757
|
+
break;
|
|
26758
|
+
const line = lines[j];
|
|
26759
|
+
if (/^\s*\/\//.test(line))
|
|
26760
|
+
continue;
|
|
26761
|
+
if (rebindRe.test(line))
|
|
26762
|
+
break;
|
|
26763
|
+
const rd = readRe.exec(line);
|
|
26764
|
+
if (!rd)
|
|
26765
|
+
continue;
|
|
26766
|
+
const as = assignRe.exec(line);
|
|
26767
|
+
let variable = "<inline>";
|
|
26768
|
+
if (as) {
|
|
26769
|
+
const bound = as[1].split(",").map((v) => v.trim()).find((v) => v !== "_" && v !== "err" && /^[A-Za-z_]\w*$/.test(v));
|
|
26770
|
+
if (!bound)
|
|
26771
|
+
continue;
|
|
26772
|
+
variable = bound;
|
|
26773
|
+
}
|
|
26774
|
+
push(variable, j + 1, `bufio ${wrapper}.${rd[1]}() over req.Body`);
|
|
26775
|
+
}
|
|
26776
|
+
}
|
|
26730
26777
|
return sources;
|
|
26731
26778
|
}
|
|
26732
26779
|
function findCSharpRequestSources(sourceCode, language) {
|
|
@@ -26748,12 +26795,57 @@ function findCSharpRequestSources(sourceCode, language) {
|
|
|
26748
26795
|
formFileParams.add(d[1]);
|
|
26749
26796
|
}
|
|
26750
26797
|
const formFileReadRe = formFileParams.size > 0 ? new RegExp(`\\b(?:${[...formFileParams].join("|")})\\s*\\.\\s*(?:FileName|ContentType)\\b`) : null;
|
|
26798
|
+
const classify = (text) => requestReadRe.test(text) ? "http_param" : formFileReadRe?.test(text) ? "http_param" : consoleReadRe.test(text) ? "io_input" : envReadRe.test(text) ? "env_input" : null;
|
|
26799
|
+
const inlineReads = [
|
|
26800
|
+
[requestReadRe, "http_param"],
|
|
26801
|
+
[formFileReadRe, "http_param"],
|
|
26802
|
+
[consoleReadRe, "io_input"],
|
|
26803
|
+
[envReadRe, "env_input"]
|
|
26804
|
+
];
|
|
26805
|
+
const inlineRead = (text) => {
|
|
26806
|
+
const argsStart = text.indexOf("(");
|
|
26807
|
+
for (const [re, type] of inlineReads) {
|
|
26808
|
+
if (!re)
|
|
26809
|
+
continue;
|
|
26810
|
+
const g = new RegExp(re.source, "g");
|
|
26811
|
+
let hit;
|
|
26812
|
+
while ((hit = g.exec(text)) !== null) {
|
|
26813
|
+
if (hit.index > argsStart) {
|
|
26814
|
+
return { type, read: hit[0].replace(/\s+/g, "").replace(/[([]$/, "") };
|
|
26815
|
+
}
|
|
26816
|
+
}
|
|
26817
|
+
}
|
|
26818
|
+
return null;
|
|
26819
|
+
};
|
|
26820
|
+
const exprStmtCallRe = /^\s*(?:await\s+)?[A-Za-z_][\w.]*(?:<[^>]*>)?\s*\(.*\)\s*;\s*$/;
|
|
26821
|
+
const nonCallKeywordRe = /^\s*(?:await\s+)?(?:if|while|for|foreach|switch|using|lock|return|throw|catch|when|nameof|typeof|sizeof|default)\b/;
|
|
26751
26822
|
for (let i2 = 0;i2 < lines.length; i2++) {
|
|
26752
26823
|
const m = assignRe.exec(lines[i2]);
|
|
26753
|
-
if (!m)
|
|
26824
|
+
if (!m) {
|
|
26825
|
+
const stmt = lines[i2];
|
|
26826
|
+
if (!exprStmtCallRe.test(stmt) || nonCallKeywordRe.test(stmt))
|
|
26827
|
+
continue;
|
|
26828
|
+
const hit = inlineRead(stmt);
|
|
26829
|
+
if (!hit)
|
|
26830
|
+
continue;
|
|
26831
|
+
const { type: type2, read } = hit;
|
|
26832
|
+
const lineNumber2 = i2 + 1;
|
|
26833
|
+
if (sources.some((s) => s.line === lineNumber2))
|
|
26834
|
+
continue;
|
|
26835
|
+
const code = stmt.trim();
|
|
26836
|
+
sources.push({
|
|
26837
|
+
type: type2,
|
|
26838
|
+
location: `${read} in ${code.substring(0, 50)}${code.length > 50 ? "..." : ""}`,
|
|
26839
|
+
severity: "high",
|
|
26840
|
+
line: lineNumber2,
|
|
26841
|
+
confidence: 1,
|
|
26842
|
+
variable: "<inline>",
|
|
26843
|
+
code
|
|
26844
|
+
});
|
|
26754
26845
|
continue;
|
|
26846
|
+
}
|
|
26755
26847
|
const [, varName, rhs] = m;
|
|
26756
|
-
const type =
|
|
26848
|
+
const type = classify(rhs);
|
|
26757
26849
|
if (!type)
|
|
26758
26850
|
continue;
|
|
26759
26851
|
const lineNumber = i2 + 1;
|
|
@@ -37425,6 +37517,18 @@ function maskStringLiteralsForTokenScan(expr) {
|
|
|
37425
37517
|
}
|
|
37426
37518
|
function detectExpressionScanFlows(calls, sources, sinks, sanitizers, unreachableLines, tainted, code, language, types) {
|
|
37427
37519
|
const flows = [];
|
|
37520
|
+
const goFnRanges = language === "go" && types ? types.flatMap((t) => t.methods.map((m) => [m.start_line, m.end_line])) : [];
|
|
37521
|
+
const goFnStart = (line) => {
|
|
37522
|
+
let best = -1;
|
|
37523
|
+
let bestSpan = -1;
|
|
37524
|
+
for (const [start2, end] of goFnRanges) {
|
|
37525
|
+
if (line >= start2 && line <= end && end - start2 > bestSpan) {
|
|
37526
|
+
best = start2;
|
|
37527
|
+
bestSpan = end - start2;
|
|
37528
|
+
}
|
|
37529
|
+
}
|
|
37530
|
+
return best;
|
|
37531
|
+
};
|
|
37428
37532
|
const sourcesWithVar = sources.filter((s) => typeof s.variable === "string" && s.variable.length > 0);
|
|
37429
37533
|
const aliasSanitizedFor = new Map;
|
|
37430
37534
|
if (language === "python" && typeof code === "string") {
|
|
@@ -37833,6 +37937,12 @@ function detectExpressionScanFlows(calls, sources, sinks, sanitizers, unreachabl
|
|
|
37833
37937
|
if (source.in_method && call.in_method && source.in_method !== call.in_method) {
|
|
37834
37938
|
continue;
|
|
37835
37939
|
}
|
|
37940
|
+
if (goFnRanges.length > 0) {
|
|
37941
|
+
const srcFn = goFnStart(source.line);
|
|
37942
|
+
const sinkFn = goFnStart(sink.line);
|
|
37943
|
+
if (srcFn !== -1 && sinkFn !== -1 && srcFn !== sinkFn)
|
|
37944
|
+
continue;
|
|
37945
|
+
}
|
|
37836
37946
|
if (complex) {
|
|
37837
37947
|
const re = reCache.get(source.variable);
|
|
37838
37948
|
if (!re || !re.test(expr))
|
|
@@ -49945,18 +50055,24 @@ async function enumerate(dir, out2) {
|
|
|
49945
50055
|
}
|
|
49946
50056
|
}
|
|
49947
50057
|
}
|
|
49948
|
-
function
|
|
49949
|
-
|
|
49950
|
-
let bestLen = -1;
|
|
50058
|
+
function createOwnerIndex(modules) {
|
|
50059
|
+
const byRoot = new Map;
|
|
49951
50060
|
for (const m of modules) {
|
|
49952
|
-
if (
|
|
49953
|
-
|
|
49954
|
-
|
|
49955
|
-
|
|
49956
|
-
|
|
50061
|
+
if (!byRoot.has(m.root))
|
|
50062
|
+
byRoot.set(m.root, m);
|
|
50063
|
+
}
|
|
50064
|
+
return (file) => {
|
|
50065
|
+
let p = file;
|
|
50066
|
+
for (;; ) {
|
|
50067
|
+
const hit = byRoot.get(p);
|
|
50068
|
+
if (hit)
|
|
50069
|
+
return hit;
|
|
50070
|
+
const slash = p.lastIndexOf("/");
|
|
50071
|
+
if (slash <= 0)
|
|
50072
|
+
return;
|
|
50073
|
+
p = p.slice(0, slash);
|
|
49957
50074
|
}
|
|
49958
|
-
}
|
|
49959
|
-
return best;
|
|
50075
|
+
};
|
|
49960
50076
|
}
|
|
49961
50077
|
|
|
49962
50078
|
// ../project-profile-detect/dist/publication-detect.js
|
|
@@ -50115,6 +50231,7 @@ async function detectProjectProfiles(scanRoot, options = {}) {
|
|
|
50115
50231
|
}
|
|
50116
50232
|
const profileByFile = new Map;
|
|
50117
50233
|
const unknownFiles = [];
|
|
50234
|
+
const ownerIndex = createOwnerIndex(modules);
|
|
50118
50235
|
for (const file of files) {
|
|
50119
50236
|
const rel = relative3(scanRoot, file);
|
|
50120
50237
|
const ov = applyOverrides(rel, compiledOverrides);
|
|
@@ -50128,7 +50245,7 @@ async function detectProjectProfiles(scanRoot, options = {}) {
|
|
|
50128
50245
|
profileByFile.set(file, `${shape2}/${env2}`);
|
|
50129
50246
|
continue;
|
|
50130
50247
|
}
|
|
50131
|
-
const owner =
|
|
50248
|
+
const owner = ownerIndex(file);
|
|
50132
50249
|
if (!owner) {
|
|
50133
50250
|
profileByFile.set(file, "unknown");
|
|
50134
50251
|
unknownFiles.push(file);
|
|
@@ -50179,7 +50296,7 @@ var colors = {
|
|
|
50179
50296
|
};
|
|
50180
50297
|
|
|
50181
50298
|
// src/version.ts
|
|
50182
|
-
var version = "4.9.
|
|
50299
|
+
var version = "4.9.26";
|
|
50183
50300
|
|
|
50184
50301
|
// src/formatters.ts
|
|
50185
50302
|
var LIBRARY_API_SURFACE_TAG2 = "library-api-surface:caller-responsibility";
|
|
@@ -50724,8 +50841,8 @@ function generateSarifResults(results, crossFileData) {
|
|
|
50724
50841
|
|
|
50725
50842
|
// src/build-info.ts
|
|
50726
50843
|
var buildInfo = {
|
|
50727
|
-
gitSha: "
|
|
50728
|
-
builtAt: "2026-09-
|
|
50844
|
+
gitSha: "178c681",
|
|
50845
|
+
builtAt: "2026-09-24T18:11:45.249Z"
|
|
50729
50846
|
};
|
|
50730
50847
|
|
|
50731
50848
|
// src/utils/args.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cognium-dev",
|
|
3
|
-
"version": "4.9.
|
|
3
|
+
"version": "4.9.26",
|
|
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"
|
|
@@ -64,8 +64,8 @@
|
|
|
64
64
|
"registry": "https://registry.npmjs.org/"
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|
|
67
|
-
"@cognium/project-profile-detect": "1.1.
|
|
68
|
-
"circle-ir": "4.9.
|
|
67
|
+
"@cognium/project-profile-detect": "1.1.2",
|
|
68
|
+
"circle-ir": "4.9.26"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
71
|
"@types/node": "^26.6.1",
|