cognium-dev 3.106.2 → 3.108.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 +345 -23
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -5,7 +5,7 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
|
5
5
|
// src/cli.ts
|
|
6
6
|
import { readFileSync, existsSync } from "fs";
|
|
7
7
|
import { stat as stat2, readdir as readdir2 } from "fs/promises";
|
|
8
|
-
import { join as join2, dirname as
|
|
8
|
+
import { join as join2, dirname as dirname3, extname, resolve as resolve2, relative as relative4 } from "path";
|
|
9
9
|
import { createRequire as createRequire2 } from "module";
|
|
10
10
|
|
|
11
11
|
// ../../node_modules/web-tree-sitter/web-tree-sitter.js
|
|
@@ -23657,6 +23657,17 @@ var SQL_BUILDER_WRAPPER_CALL_RE = /\.(?:wrap|quote|escape|identifier)\s*\(/;
|
|
|
23657
23657
|
var SQL_EXTRACTION_RETURN_RE = /^(?:String|CharSequence|Optional\s*<\s*String\s*>)$/;
|
|
23658
23658
|
var SQL_EXTRACTION_NAME_RE = /^(?:get|extract|build).*(?:[Ss]ql|[Qq]uery)|^toSql|.*Statement.*ToString$|.*Query.*String$/;
|
|
23659
23659
|
var SQL_EXTRACTION_PRIMITIVE_INPUT_RE = /^(?:String|CharSequence)$/;
|
|
23660
|
+
var SQL_EXEC_METHODS = new Set([
|
|
23661
|
+
"prepareStatement",
|
|
23662
|
+
"prepareCall",
|
|
23663
|
+
"execute",
|
|
23664
|
+
"executeQuery",
|
|
23665
|
+
"executeUpdate",
|
|
23666
|
+
"executeLargeUpdate",
|
|
23667
|
+
"addBatch"
|
|
23668
|
+
]);
|
|
23669
|
+
var JAVA_SQL_ASSIGN_RE_TEMPLATE = "\\b(?:String|CharSequence|final\\s+String|var)\\s+SQLVAR\\b\\s*=\\s*(.+?);";
|
|
23670
|
+
var JAVA_INLINE_MATCHES_RE = /\.\s*matches\s*\(\s*"((?:[^"\\]|\\.)*)"\s*\)/g;
|
|
23660
23671
|
function resolveJavaReceiverType(receiver, sinkLine, sourceLines) {
|
|
23661
23672
|
if (!receiver || !/^[A-Za-z_]\w*$/.test(receiver))
|
|
23662
23673
|
return null;
|
|
@@ -23715,6 +23726,116 @@ function findEnclosingMethodFromIr(types, sinkLine) {
|
|
|
23715
23726
|
}
|
|
23716
23727
|
return null;
|
|
23717
23728
|
}
|
|
23729
|
+
function splitJavaConcatTokens(rhs) {
|
|
23730
|
+
const tokens = [];
|
|
23731
|
+
let cur = "";
|
|
23732
|
+
let depth = 0;
|
|
23733
|
+
let inString = false;
|
|
23734
|
+
let i2 = 0;
|
|
23735
|
+
while (i2 < rhs.length) {
|
|
23736
|
+
const ch = rhs[i2] ?? "";
|
|
23737
|
+
if (inString) {
|
|
23738
|
+
cur += ch;
|
|
23739
|
+
if (ch === "\\" && i2 + 1 < rhs.length) {
|
|
23740
|
+
cur += rhs[i2 + 1] ?? "";
|
|
23741
|
+
i2 += 2;
|
|
23742
|
+
continue;
|
|
23743
|
+
}
|
|
23744
|
+
if (ch === '"')
|
|
23745
|
+
inString = false;
|
|
23746
|
+
i2++;
|
|
23747
|
+
continue;
|
|
23748
|
+
}
|
|
23749
|
+
if (ch === '"') {
|
|
23750
|
+
inString = true;
|
|
23751
|
+
cur += ch;
|
|
23752
|
+
i2++;
|
|
23753
|
+
continue;
|
|
23754
|
+
}
|
|
23755
|
+
if (ch === "(" || ch === "[" || ch === "{") {
|
|
23756
|
+
depth++;
|
|
23757
|
+
cur += ch;
|
|
23758
|
+
i2++;
|
|
23759
|
+
continue;
|
|
23760
|
+
}
|
|
23761
|
+
if (ch === ")" || ch === "]" || ch === "}") {
|
|
23762
|
+
depth--;
|
|
23763
|
+
cur += ch;
|
|
23764
|
+
i2++;
|
|
23765
|
+
continue;
|
|
23766
|
+
}
|
|
23767
|
+
if (ch === "+" && depth === 0) {
|
|
23768
|
+
tokens.push(cur.trim());
|
|
23769
|
+
cur = "";
|
|
23770
|
+
i2++;
|
|
23771
|
+
continue;
|
|
23772
|
+
}
|
|
23773
|
+
cur += ch;
|
|
23774
|
+
i2++;
|
|
23775
|
+
}
|
|
23776
|
+
if (cur.trim())
|
|
23777
|
+
tokens.push(cur.trim());
|
|
23778
|
+
return tokens;
|
|
23779
|
+
}
|
|
23780
|
+
function isImplicitlyAnchoredAllowlistRegex(re) {
|
|
23781
|
+
if (re === "")
|
|
23782
|
+
return false;
|
|
23783
|
+
const stripped = re.replace(/\[(?:[^\]\\]|\\.)*\]/g, "");
|
|
23784
|
+
const cleaned = stripped.replace(/\\./g, "");
|
|
23785
|
+
if (cleaned.includes("."))
|
|
23786
|
+
return false;
|
|
23787
|
+
if (cleaned.includes("|"))
|
|
23788
|
+
return false;
|
|
23789
|
+
return true;
|
|
23790
|
+
}
|
|
23791
|
+
function findJavaMethodBody(methodName, sourceLines) {
|
|
23792
|
+
if (!/^[A-Za-z_]\w*$/.test(methodName))
|
|
23793
|
+
return null;
|
|
23794
|
+
const sigRe = new RegExp(`\\b(?:public|private|protected|static|final|synchronized|\\s)+[\\w<>?,\\s\\[\\]]+?\\b${methodName}\\s*\\(`);
|
|
23795
|
+
for (let i2 = 0;i2 < sourceLines.length; i2++) {
|
|
23796
|
+
const ln = sourceLines[i2] ?? "";
|
|
23797
|
+
if (!sigRe.test(ln))
|
|
23798
|
+
continue;
|
|
23799
|
+
let braceLine = -1;
|
|
23800
|
+
for (let j = i2;j < Math.min(sourceLines.length, i2 + 4); j++) {
|
|
23801
|
+
if ((sourceLines[j] ?? "").includes("{")) {
|
|
23802
|
+
braceLine = j;
|
|
23803
|
+
break;
|
|
23804
|
+
}
|
|
23805
|
+
}
|
|
23806
|
+
if (braceLine < 0)
|
|
23807
|
+
continue;
|
|
23808
|
+
let depth = 0;
|
|
23809
|
+
const body2 = [];
|
|
23810
|
+
for (let j = braceLine;j < sourceLines.length; j++) {
|
|
23811
|
+
const ln2 = sourceLines[j] ?? "";
|
|
23812
|
+
body2.push(ln2);
|
|
23813
|
+
for (const ch of ln2) {
|
|
23814
|
+
if (ch === "{")
|
|
23815
|
+
depth++;
|
|
23816
|
+
else if (ch === "}")
|
|
23817
|
+
depth--;
|
|
23818
|
+
}
|
|
23819
|
+
if (depth <= 0 && j > braceLine)
|
|
23820
|
+
return body2;
|
|
23821
|
+
}
|
|
23822
|
+
return null;
|
|
23823
|
+
}
|
|
23824
|
+
return null;
|
|
23825
|
+
}
|
|
23826
|
+
function javaBodyHasInlineRegexAllowlistThrow(bodyLines) {
|
|
23827
|
+
const text = bodyLines.join(`
|
|
23828
|
+
`);
|
|
23829
|
+
if (!/\bthrow\s+/.test(text))
|
|
23830
|
+
return false;
|
|
23831
|
+
JAVA_INLINE_MATCHES_RE.lastIndex = 0;
|
|
23832
|
+
let m;
|
|
23833
|
+
while ((m = JAVA_INLINE_MATCHES_RE.exec(text)) !== null) {
|
|
23834
|
+
if (isImplicitlyAnchoredAllowlistRegex(m[1] ?? ""))
|
|
23835
|
+
return true;
|
|
23836
|
+
}
|
|
23837
|
+
return false;
|
|
23838
|
+
}
|
|
23718
23839
|
function isJavaLiteralOrAnnotationAccessor(expr) {
|
|
23719
23840
|
const e = expr.trim();
|
|
23720
23841
|
if (e === "")
|
|
@@ -23950,6 +24071,24 @@ class SinkFilterPass {
|
|
|
23950
24071
|
}
|
|
23951
24072
|
if (language === "java") {
|
|
23952
24073
|
const sourceLines = ctx.code.split(`
|
|
24074
|
+
`);
|
|
24075
|
+
filtered = filtered.filter((sink) => {
|
|
24076
|
+
if (sink.type !== "xxe")
|
|
24077
|
+
return true;
|
|
24078
|
+
const sinkLineText = sourceLines[sink.line - 1] ?? "";
|
|
24079
|
+
const receiverMatch = sinkLineText.match(/\b(\w+)\s*\.\s*(\w+)\s*\(/);
|
|
24080
|
+
const receiver = receiverMatch?.[1];
|
|
24081
|
+
const method = sink.method ?? receiverMatch?.[2];
|
|
24082
|
+
if (method === "parse" && receiver) {
|
|
24083
|
+
const recvType = resolveJavaReceiverType(receiver, sink.line, sourceLines);
|
|
24084
|
+
if (recvType && DATA_PARSER_TYPES.has(recvType))
|
|
24085
|
+
return false;
|
|
24086
|
+
}
|
|
24087
|
+
return true;
|
|
24088
|
+
});
|
|
24089
|
+
}
|
|
24090
|
+
if (language === "java") {
|
|
24091
|
+
const sourceLines = ctx.code.split(`
|
|
23953
24092
|
`);
|
|
23954
24093
|
filtered = filtered.filter((sink) => {
|
|
23955
24094
|
if (sink.type !== "command_injection")
|
|
@@ -24158,6 +24297,67 @@ class SinkFilterPass {
|
|
|
24158
24297
|
});
|
|
24159
24298
|
}
|
|
24160
24299
|
}
|
|
24300
|
+
if (language === "java") {
|
|
24301
|
+
const sourceLines = ctx.code.split(`
|
|
24302
|
+
`);
|
|
24303
|
+
filtered = filtered.filter((sink) => {
|
|
24304
|
+
if (sink.type !== "sql_injection")
|
|
24305
|
+
return true;
|
|
24306
|
+
const method = sink.method ?? "";
|
|
24307
|
+
if (!SQL_EXEC_METHODS.has(method))
|
|
24308
|
+
return true;
|
|
24309
|
+
const sinkLineText = sourceLines[sink.line - 1] ?? "";
|
|
24310
|
+
const callArgs = extractJavaCallArgs(method, sinkLineText);
|
|
24311
|
+
if (!callArgs || callArgs.length === 0)
|
|
24312
|
+
return true;
|
|
24313
|
+
const sqlVar = callArgs[0]?.trim() ?? "";
|
|
24314
|
+
let rhs = null;
|
|
24315
|
+
if (/^[A-Za-z_]\w*$/.test(sqlVar)) {
|
|
24316
|
+
const lo = Math.max(0, sink.line - 31);
|
|
24317
|
+
const assignRe = new RegExp(JAVA_SQL_ASSIGN_RE_TEMPLATE.replace("SQLVAR", sqlVar));
|
|
24318
|
+
for (let i2 = sink.line - 2;i2 >= lo; i2--) {
|
|
24319
|
+
const ln = sourceLines[i2] ?? "";
|
|
24320
|
+
const m = ln.match(assignRe);
|
|
24321
|
+
if (m) {
|
|
24322
|
+
rhs = m[1] ?? null;
|
|
24323
|
+
break;
|
|
24324
|
+
}
|
|
24325
|
+
}
|
|
24326
|
+
} else if (/"[^"]*"/.test(sqlVar) && sqlVar.includes("+")) {
|
|
24327
|
+
rhs = sqlVar;
|
|
24328
|
+
}
|
|
24329
|
+
if (!rhs)
|
|
24330
|
+
return true;
|
|
24331
|
+
const tokens = splitJavaConcatTokens(rhs);
|
|
24332
|
+
if (tokens.length < 2)
|
|
24333
|
+
return true;
|
|
24334
|
+
let hasPlaceholder = false;
|
|
24335
|
+
const methodCallNames = [];
|
|
24336
|
+
for (const tk of tokens) {
|
|
24337
|
+
if (/^"(?:[^"\\]|\\.)*"$/.test(tk)) {
|
|
24338
|
+
if (tk.includes("?"))
|
|
24339
|
+
hasPlaceholder = true;
|
|
24340
|
+
continue;
|
|
24341
|
+
}
|
|
24342
|
+
const callMatch = tk.match(/^([A-Za-z_]\w*)\s*\(/);
|
|
24343
|
+
if (callMatch) {
|
|
24344
|
+
methodCallNames.push(callMatch[1] ?? "");
|
|
24345
|
+
continue;
|
|
24346
|
+
}
|
|
24347
|
+
return true;
|
|
24348
|
+
}
|
|
24349
|
+
if (!hasPlaceholder)
|
|
24350
|
+
return true;
|
|
24351
|
+
if (methodCallNames.length === 0)
|
|
24352
|
+
return true;
|
|
24353
|
+
for (const mname of methodCallNames) {
|
|
24354
|
+
const body2 = findJavaMethodBody(mname, sourceLines);
|
|
24355
|
+
if (body2 && javaBodyHasInlineRegexAllowlistThrow(body2))
|
|
24356
|
+
return false;
|
|
24357
|
+
}
|
|
24358
|
+
return true;
|
|
24359
|
+
});
|
|
24360
|
+
}
|
|
24161
24361
|
return { sources, sinks: filtered, sanitizers };
|
|
24162
24362
|
}
|
|
24163
24363
|
}
|
|
@@ -24580,6 +24780,23 @@ class TaintPropagationPass {
|
|
|
24580
24780
|
});
|
|
24581
24781
|
}
|
|
24582
24782
|
}
|
|
24783
|
+
const setIntervalLines = new Set;
|
|
24784
|
+
for (const s of sinks) {
|
|
24785
|
+
if (s.type === "code_injection" && (s.method === "setInterval" || s.method === "setTimeout")) {
|
|
24786
|
+
setIntervalLines.add(s.line);
|
|
24787
|
+
}
|
|
24788
|
+
}
|
|
24789
|
+
if (setIntervalLines.size > 0) {
|
|
24790
|
+
finalFlows = finalFlows.filter((f) => {
|
|
24791
|
+
if (f.sink_type !== "code_injection")
|
|
24792
|
+
return true;
|
|
24793
|
+
if (f.source_type !== "interprocedural_param")
|
|
24794
|
+
return true;
|
|
24795
|
+
if (!setIntervalLines.has(f.sink_line))
|
|
24796
|
+
return true;
|
|
24797
|
+
return false;
|
|
24798
|
+
});
|
|
24799
|
+
}
|
|
24583
24800
|
if (finalFlows.length > 1) {
|
|
24584
24801
|
const bestByKey = new Map;
|
|
24585
24802
|
for (const f of finalFlows) {
|
|
@@ -35373,11 +35590,11 @@ function deriveProjectRoot(paths) {
|
|
|
35373
35590
|
return common.join("/") || "/";
|
|
35374
35591
|
}
|
|
35375
35592
|
// ../project-profile-detect/dist/index.js
|
|
35376
|
-
import { relative as
|
|
35593
|
+
import { relative as relative3 } from "path";
|
|
35377
35594
|
|
|
35378
35595
|
// ../project-profile-detect/dist/walk.js
|
|
35379
35596
|
import { readdir, readFile, stat } from "fs/promises";
|
|
35380
|
-
import { join, relative } from "path";
|
|
35597
|
+
import { join, relative as relative2 } from "path";
|
|
35381
35598
|
|
|
35382
35599
|
// ../project-profile-detect/dist/maven-parse.js
|
|
35383
35600
|
var TAG = (name2) => new RegExp(`<${name2}\\b[^>]*>([\\s\\S]*?)<\\/${name2}>`, "i");
|
|
@@ -35403,7 +35620,12 @@ var MAVEN_PLUGIN_MAP = {
|
|
|
35403
35620
|
"exec-maven-plugin": "application",
|
|
35404
35621
|
"maven-assembly-plugin": "application"
|
|
35405
35622
|
};
|
|
35623
|
+
var MAVEN_PUBLISH_PLUGIN_URLS = {
|
|
35624
|
+
"central-publishing-maven-plugin": "https://central.sonatype.com/",
|
|
35625
|
+
"nexus-staging-maven-plugin": "https://oss.sonatype.org/"
|
|
35626
|
+
};
|
|
35406
35627
|
function parseMavenPom(xml, moduleRoot, buildFile, directorySignals) {
|
|
35628
|
+
const parentRef = extractParentRef(xml);
|
|
35407
35629
|
const stripped = xml.replace(/<parent\b[\s\S]*?<\/parent>/i, "");
|
|
35408
35630
|
const groupId = firstTag(stripped, "groupId");
|
|
35409
35631
|
const artifactId = firstTag(stripped, "artifactId");
|
|
@@ -35412,10 +35634,15 @@ function parseMavenPom(xml, moduleRoot, buildFile, directorySignals) {
|
|
|
35412
35634
|
const buildBlock = firstTag(xml, "build") ?? "";
|
|
35413
35635
|
const pluginBlocks = allTags(buildBlock, "plugin");
|
|
35414
35636
|
const plugins = new Set;
|
|
35637
|
+
const publishUrls = new Set;
|
|
35415
35638
|
for (const p of pluginBlocks) {
|
|
35416
35639
|
const aid = firstTag(p, "artifactId");
|
|
35417
|
-
if (aid
|
|
35640
|
+
if (!aid)
|
|
35641
|
+
continue;
|
|
35642
|
+
if (MAVEN_PLUGIN_MAP[aid])
|
|
35418
35643
|
plugins.add(MAVEN_PLUGIN_MAP[aid]);
|
|
35644
|
+
if (MAVEN_PUBLISH_PLUGIN_URLS[aid])
|
|
35645
|
+
publishUrls.add(MAVEN_PUBLISH_PLUGIN_URLS[aid]);
|
|
35419
35646
|
}
|
|
35420
35647
|
if (/<parent\b[\s\S]*?<artifactId>\s*spring-boot-starter-parent\s*<\/artifactId>/i.test(xml)) {
|
|
35421
35648
|
plugins.add("spring-boot");
|
|
@@ -35428,7 +35655,8 @@ function parseMavenPom(xml, moduleRoot, buildFile, directorySignals) {
|
|
|
35428
35655
|
plugins.add("maven-plugin");
|
|
35429
35656
|
const distBlock = firstTag(xml, "distributionManagement") ?? "";
|
|
35430
35657
|
const urls = [
|
|
35431
|
-
...allTags(distBlock, "url")
|
|
35658
|
+
...allTags(distBlock, "url"),
|
|
35659
|
+
...publishUrls
|
|
35432
35660
|
].map((u) => u.trim()).filter(Boolean);
|
|
35433
35661
|
const signals = {
|
|
35434
35662
|
...directorySignals,
|
|
@@ -35443,9 +35671,34 @@ function parseMavenPom(xml, moduleRoot, buildFile, directorySignals) {
|
|
|
35443
35671
|
groupId,
|
|
35444
35672
|
artifactId,
|
|
35445
35673
|
version,
|
|
35446
|
-
signals
|
|
35674
|
+
signals,
|
|
35675
|
+
parentRef
|
|
35447
35676
|
};
|
|
35448
35677
|
}
|
|
35678
|
+
function extractParentRef(xml) {
|
|
35679
|
+
const block = TAG("parent").exec(xml);
|
|
35680
|
+
if (!block)
|
|
35681
|
+
return;
|
|
35682
|
+
const inner = block[1];
|
|
35683
|
+
const groupId = firstTag(inner, "groupId");
|
|
35684
|
+
const artifactId = firstTag(inner, "artifactId");
|
|
35685
|
+
const version = firstTag(inner, "version");
|
|
35686
|
+
let relativePath;
|
|
35687
|
+
let emptyRelativePath = false;
|
|
35688
|
+
const selfClosing = /<relativePath\b[^>]*\/\s*>/i.test(inner);
|
|
35689
|
+
if (selfClosing) {
|
|
35690
|
+
emptyRelativePath = true;
|
|
35691
|
+
} else {
|
|
35692
|
+
const rp = firstTag(inner, "relativePath");
|
|
35693
|
+
if (rp !== undefined) {
|
|
35694
|
+
if (rp.length === 0)
|
|
35695
|
+
emptyRelativePath = true;
|
|
35696
|
+
else
|
|
35697
|
+
relativePath = rp;
|
|
35698
|
+
}
|
|
35699
|
+
}
|
|
35700
|
+
return { groupId, artifactId, version, relativePath, emptyRelativePath };
|
|
35701
|
+
}
|
|
35449
35702
|
|
|
35450
35703
|
// ../project-profile-detect/dist/gradle-parse.js
|
|
35451
35704
|
var GRADLE_PLUGIN_MAP = {
|
|
@@ -35512,6 +35765,70 @@ function parseGradleBuild(text, moduleRoot, buildFile, buildSystem, directorySig
|
|
|
35512
35765
|
};
|
|
35513
35766
|
}
|
|
35514
35767
|
|
|
35768
|
+
// ../project-profile-detect/dist/maven-inherit.js
|
|
35769
|
+
import { dirname as dirname2, isAbsolute, normalize, relative, resolve } from "path";
|
|
35770
|
+
var MAX_DEPTH = 6;
|
|
35771
|
+
var DEFAULT_RELATIVE_PATH = "../pom.xml";
|
|
35772
|
+
function mergeMavenInheritance(modules, scanRoot) {
|
|
35773
|
+
const normalizedScanRoot = normalize(scanRoot);
|
|
35774
|
+
const byBuildFile = new Map;
|
|
35775
|
+
for (const m of modules) {
|
|
35776
|
+
if (m.buildSystem === "maven") {
|
|
35777
|
+
byBuildFile.set(normalize(m.buildFile), m);
|
|
35778
|
+
}
|
|
35779
|
+
}
|
|
35780
|
+
for (const child of modules) {
|
|
35781
|
+
if (child.buildSystem !== "maven")
|
|
35782
|
+
continue;
|
|
35783
|
+
if (!child.parentRef)
|
|
35784
|
+
continue;
|
|
35785
|
+
const inheritedUrls = new Set;
|
|
35786
|
+
const inheritedPlugins = new Set;
|
|
35787
|
+
walkParents(child, byBuildFile, normalizedScanRoot, inheritedUrls, inheritedPlugins);
|
|
35788
|
+
if (inheritedUrls.size === 0 && inheritedPlugins.size === 0)
|
|
35789
|
+
continue;
|
|
35790
|
+
const existingUrls = new Set(child.signals.distributionUrls);
|
|
35791
|
+
for (const u of inheritedUrls) {
|
|
35792
|
+
if (!existingUrls.has(u))
|
|
35793
|
+
child.signals.distributionUrls.push(u);
|
|
35794
|
+
}
|
|
35795
|
+
const existingPlugins = new Set(child.signals.plugins);
|
|
35796
|
+
for (const p of inheritedPlugins) {
|
|
35797
|
+
if (!existingPlugins.has(p))
|
|
35798
|
+
child.signals.plugins.push(p);
|
|
35799
|
+
}
|
|
35800
|
+
}
|
|
35801
|
+
}
|
|
35802
|
+
function walkParents(start2, byBuildFile, scanRoot, outUrls, outPlugins) {
|
|
35803
|
+
const visited = new Set([normalize(start2.buildFile)]);
|
|
35804
|
+
let current = start2;
|
|
35805
|
+
for (let depth = 0;depth < MAX_DEPTH; depth++) {
|
|
35806
|
+
const ref = current.parentRef;
|
|
35807
|
+
if (!ref)
|
|
35808
|
+
return;
|
|
35809
|
+
if (ref.emptyRelativePath)
|
|
35810
|
+
return;
|
|
35811
|
+
const childDir = dirname2(current.buildFile);
|
|
35812
|
+
const rel = ref.relativePath ?? DEFAULT_RELATIVE_PATH;
|
|
35813
|
+
const candidateAbs = normalize(isAbsolute(rel) ? rel : resolve(childDir, rel));
|
|
35814
|
+
const parentBuildFile = candidateAbs.endsWith("pom.xml") ? candidateAbs : normalize(resolve(candidateAbs, "pom.xml"));
|
|
35815
|
+
const relToRoot = relative(scanRoot, parentBuildFile);
|
|
35816
|
+
if (relToRoot.startsWith("..") || isAbsolute(relToRoot))
|
|
35817
|
+
return;
|
|
35818
|
+
if (visited.has(parentBuildFile))
|
|
35819
|
+
return;
|
|
35820
|
+
visited.add(parentBuildFile);
|
|
35821
|
+
const parent = byBuildFile.get(parentBuildFile);
|
|
35822
|
+
if (!parent)
|
|
35823
|
+
return;
|
|
35824
|
+
for (const u of parent.signals.distributionUrls)
|
|
35825
|
+
outUrls.add(u);
|
|
35826
|
+
for (const p of parent.signals.plugins)
|
|
35827
|
+
outPlugins.add(p);
|
|
35828
|
+
current = parent;
|
|
35829
|
+
}
|
|
35830
|
+
}
|
|
35831
|
+
|
|
35515
35832
|
// ../project-profile-detect/dist/walk.js
|
|
35516
35833
|
var BUILD_FILES = ["pom.xml", "build.gradle", "build.gradle.kts"];
|
|
35517
35834
|
var SKIP_DIRS = new Set([
|
|
@@ -35532,6 +35849,7 @@ var SKIP_DIRS = new Set([
|
|
|
35532
35849
|
async function discoverBuildModules(scanRoot) {
|
|
35533
35850
|
const modules = [];
|
|
35534
35851
|
await walk(scanRoot, modules);
|
|
35852
|
+
mergeMavenInheritance(modules, scanRoot);
|
|
35535
35853
|
return modules;
|
|
35536
35854
|
}
|
|
35537
35855
|
async function walk(dir, out2) {
|
|
@@ -35739,6 +36057,10 @@ function resolveShape(mod) {
|
|
|
35739
36057
|
reasons.push(...libSignals, "no public-registry distribution (internal helper)");
|
|
35740
36058
|
return { shape: "application", reasons };
|
|
35741
36059
|
}
|
|
36060
|
+
if (isPubliclyPublished(sig.distributionUrls)) {
|
|
36061
|
+
reasons.push("public-registry distribution", "no application/server/plugin signals → implicit library");
|
|
36062
|
+
return { shape: "library", reasons };
|
|
36063
|
+
}
|
|
35742
36064
|
reasons.push("no shape signals");
|
|
35743
36065
|
return { shape: "unknown", reasons };
|
|
35744
36066
|
}
|
|
@@ -35826,7 +36148,7 @@ async function detectProjectProfiles(scanRoot, options = {}) {
|
|
|
35826
36148
|
const profileByFile = new Map;
|
|
35827
36149
|
const unknownFiles = [];
|
|
35828
36150
|
for (const file of files) {
|
|
35829
|
-
const rel =
|
|
36151
|
+
const rel = relative3(scanRoot, file);
|
|
35830
36152
|
const ov = applyOverrides(rel, compiledOverrides);
|
|
35831
36153
|
if (ov) {
|
|
35832
36154
|
profileByFile.set(file, ov.profile);
|
|
@@ -35878,7 +36200,7 @@ var colors = {
|
|
|
35878
36200
|
};
|
|
35879
36201
|
|
|
35880
36202
|
// src/version.ts
|
|
35881
|
-
var version = "3.
|
|
36203
|
+
var version = "3.108.0";
|
|
35882
36204
|
|
|
35883
36205
|
// src/formatters.ts
|
|
35884
36206
|
var LIBRARY_API_SURFACE_TAG2 = "library-api-surface:caller-responsibility";
|
|
@@ -36679,7 +37001,7 @@ function applySuppressionsToResults(results, suppressions, basePath) {
|
|
|
36679
37001
|
if (suppressions.length === 0)
|
|
36680
37002
|
return results;
|
|
36681
37003
|
return results.map((result) => {
|
|
36682
|
-
const relativeFile =
|
|
37004
|
+
const relativeFile = relative4(basePath, result.file) || result.file;
|
|
36683
37005
|
const filteredVulns = result.vulnerabilities.filter((vuln) => {
|
|
36684
37006
|
for (const supp of suppressions) {
|
|
36685
37007
|
if (supp.pass !== vuln.type)
|
|
@@ -36768,7 +37090,7 @@ async function collectFiles(targetPath, options = {}) {
|
|
|
36768
37090
|
return files;
|
|
36769
37091
|
}
|
|
36770
37092
|
if (fileMatchesLanguage(targetPath, language)) {
|
|
36771
|
-
const relativePath = basePath ?
|
|
37093
|
+
const relativePath = basePath ? relative4(basePath, targetPath) : targetPath;
|
|
36772
37094
|
if (includePatterns && includePatterns.length > 0) {
|
|
36773
37095
|
if (!matchesAnyPattern(relativePath, includePatterns)) {
|
|
36774
37096
|
return files;
|
|
@@ -36787,7 +37109,7 @@ async function collectFiles(targetPath, options = {}) {
|
|
|
36787
37109
|
if (excludeTests && /^(test|tests|__tests__|spec|__mocks__)$/i.test(entry.name))
|
|
36788
37110
|
continue;
|
|
36789
37111
|
const fullPath = join2(targetPath, entry.name);
|
|
36790
|
-
const relativePath = basePath ?
|
|
37112
|
+
const relativePath = basePath ? relative4(basePath, fullPath) : fullPath;
|
|
36791
37113
|
if (excludePatterns && entry.isDirectory()) {
|
|
36792
37114
|
const dirPattern = relativePath + "/";
|
|
36793
37115
|
if (excludePatterns.some((p) => matchesGlob(dirPattern, p) || matchesGlob(relativePath, p))) {
|
|
@@ -36885,14 +37207,14 @@ async function scanProject(files, language, analyzeOpts, crossFileBudgetMs) {
|
|
|
36885
37207
|
async function initWasm(spin) {
|
|
36886
37208
|
const isStandalone = import.meta.url.includes("/$bunfs/");
|
|
36887
37209
|
if (isStandalone) {
|
|
36888
|
-
const { dirname:
|
|
36889
|
-
const binaryDir =
|
|
37210
|
+
const { dirname: dirname4, join: join3 } = await import("path");
|
|
37211
|
+
const binaryDir = dirname4(process.execPath);
|
|
36890
37212
|
const cwd = process.cwd();
|
|
36891
37213
|
let scriptDir = null;
|
|
36892
37214
|
if (!import.meta.url.includes("/$bunfs/")) {
|
|
36893
37215
|
try {
|
|
36894
37216
|
const { fileURLToPath } = await import("url");
|
|
36895
|
-
scriptDir =
|
|
37217
|
+
scriptDir = dirname4(fileURLToPath(import.meta.url));
|
|
36896
37218
|
} catch {}
|
|
36897
37219
|
}
|
|
36898
37220
|
const wasmLocations = [
|
|
@@ -36945,7 +37267,7 @@ Please ensure the wasm/ directory is located next to the binary or in your curre
|
|
|
36945
37267
|
} else {
|
|
36946
37268
|
const require2 = createRequire2(import.meta.url);
|
|
36947
37269
|
const circleIrPkg = require2.resolve("circle-ir/package.json");
|
|
36948
|
-
const wasmBasePath = join2(
|
|
37270
|
+
const wasmBasePath = join2(dirname3(circleIrPkg), "dist", "wasm") + "/";
|
|
36949
37271
|
await initAnalyzer({
|
|
36950
37272
|
wasmPath: wasmBasePath + "web-tree-sitter.wasm",
|
|
36951
37273
|
languagePaths: {
|
|
@@ -36974,7 +37296,7 @@ function buildProfileSummary(scanRoot, modules, resolvedProfiles) {
|
|
|
36974
37296
|
return {
|
|
36975
37297
|
scanRoot,
|
|
36976
37298
|
modules: modules.map((m) => ({
|
|
36977
|
-
root:
|
|
37299
|
+
root: relative4(scanRoot, m.module.root) || ".",
|
|
36978
37300
|
profile: m.profile,
|
|
36979
37301
|
reasons: m.reasons,
|
|
36980
37302
|
buildSystem: m.module.buildSystem
|
|
@@ -37003,9 +37325,9 @@ function printProfileExplain(scanRoot, detection) {
|
|
|
37003
37325
|
out2.push(" (no pom.xml, build.gradle, or build.gradle.kts found)");
|
|
37004
37326
|
} else {
|
|
37005
37327
|
for (const r of detection.modules) {
|
|
37006
|
-
const rel =
|
|
37328
|
+
const rel = relative4(scanRoot, r.module.root) || ".";
|
|
37007
37329
|
out2.push(` ${colors.cyan(rel || ".")} → ${colors.bold(r.profile)}`);
|
|
37008
|
-
out2.push(` build: ${r.module.buildSystem} (${
|
|
37330
|
+
out2.push(` build: ${r.module.buildSystem} (${relative4(scanRoot, r.module.buildFile)})`);
|
|
37009
37331
|
if (r.module.artifactId) {
|
|
37010
37332
|
out2.push(` coords: ${r.module.groupId ?? "?"}:${r.module.artifactId}:${r.module.version ?? "?"}`);
|
|
37011
37333
|
}
|
|
@@ -37050,7 +37372,7 @@ async function runScan(targetPath, options) {
|
|
|
37050
37372
|
await initWasm(spin);
|
|
37051
37373
|
if (spin)
|
|
37052
37374
|
spin.text = "Collecting files...";
|
|
37053
|
-
const absPath =
|
|
37375
|
+
const absPath = resolve2(targetPath);
|
|
37054
37376
|
if (!existsSync(absPath)) {
|
|
37055
37377
|
if (spin)
|
|
37056
37378
|
spin.fail(`Path not found: ${absPath}`);
|
|
@@ -37114,7 +37436,7 @@ async function runScan(targetPath, options) {
|
|
|
37114
37436
|
results = [];
|
|
37115
37437
|
let processed = 0;
|
|
37116
37438
|
const formatCurrentFile = (file) => {
|
|
37117
|
-
const rel =
|
|
37439
|
+
const rel = relative4(absPath, file) || file;
|
|
37118
37440
|
return rel.length > 80 ? `...${rel.slice(-77)}` : rel;
|
|
37119
37441
|
};
|
|
37120
37442
|
const concurrency = options.threads;
|
|
@@ -37290,7 +37612,7 @@ async function runMetrics(targetPath, options) {
|
|
|
37290
37612
|
await initWasm(spin);
|
|
37291
37613
|
if (spin)
|
|
37292
37614
|
spin.text = "Collecting files...";
|
|
37293
|
-
const absPath =
|
|
37615
|
+
const absPath = resolve2(targetPath);
|
|
37294
37616
|
if (!existsSync(absPath)) {
|
|
37295
37617
|
if (spin)
|
|
37296
37618
|
spin.fail(`Path not found: ${absPath}`);
|
|
@@ -37318,7 +37640,7 @@ async function runMetrics(targetPath, options) {
|
|
|
37318
37640
|
continue;
|
|
37319
37641
|
}
|
|
37320
37642
|
if (spin) {
|
|
37321
|
-
const rel =
|
|
37643
|
+
const rel = relative4(absPath, file) || file;
|
|
37322
37644
|
const maxLen = 80;
|
|
37323
37645
|
const label = rel.length > maxLen ? `...${rel.slice(-(maxLen - 3))}` : rel;
|
|
37324
37646
|
spin.text = `Analyzing ${label}... (${processed}/${totalFiles})`;
|
|
@@ -37363,7 +37685,7 @@ async function runMetrics(targetPath, options) {
|
|
|
37363
37685
|
} else {
|
|
37364
37686
|
const lines = [];
|
|
37365
37687
|
for (const fm of filtered) {
|
|
37366
|
-
const rel =
|
|
37688
|
+
const rel = relative4(absPath, fm.file) || fm.file;
|
|
37367
37689
|
lines.push(rel);
|
|
37368
37690
|
const byCategory = new Map;
|
|
37369
37691
|
for (const m of fm.metrics) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cognium-dev",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.108.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",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
},
|
|
67
67
|
"dependencies": {
|
|
68
68
|
"@cognium/project-profile-detect": "^1.1.0",
|
|
69
|
-
"circle-ir": "^3.
|
|
69
|
+
"circle-ir": "^3.108.0"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@types/node": "^25.5.0",
|