cognium-dev 3.106.2 → 3.107.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 +343 -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,65 @@ 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
|
+
if (!/^[A-Za-z_]\w*$/.test(sqlVar))
|
|
24315
|
+
return true;
|
|
24316
|
+
const lo = Math.max(0, sink.line - 31);
|
|
24317
|
+
const assignRe = new RegExp(JAVA_SQL_ASSIGN_RE_TEMPLATE.replace("SQLVAR", sqlVar));
|
|
24318
|
+
let rhs = null;
|
|
24319
|
+
for (let i2 = sink.line - 2;i2 >= lo; i2--) {
|
|
24320
|
+
const ln = sourceLines[i2] ?? "";
|
|
24321
|
+
const m = ln.match(assignRe);
|
|
24322
|
+
if (m) {
|
|
24323
|
+
rhs = m[1] ?? null;
|
|
24324
|
+
break;
|
|
24325
|
+
}
|
|
24326
|
+
}
|
|
24327
|
+
if (!rhs)
|
|
24328
|
+
return true;
|
|
24329
|
+
const tokens = splitJavaConcatTokens(rhs);
|
|
24330
|
+
if (tokens.length < 2)
|
|
24331
|
+
return true;
|
|
24332
|
+
let hasPlaceholder = false;
|
|
24333
|
+
const methodCallNames = [];
|
|
24334
|
+
for (const tk of tokens) {
|
|
24335
|
+
if (/^"(?:[^"\\]|\\.)*"$/.test(tk)) {
|
|
24336
|
+
if (tk.includes("?"))
|
|
24337
|
+
hasPlaceholder = true;
|
|
24338
|
+
continue;
|
|
24339
|
+
}
|
|
24340
|
+
const callMatch = tk.match(/^([A-Za-z_]\w*)\s*\(/);
|
|
24341
|
+
if (callMatch) {
|
|
24342
|
+
methodCallNames.push(callMatch[1] ?? "");
|
|
24343
|
+
continue;
|
|
24344
|
+
}
|
|
24345
|
+
return true;
|
|
24346
|
+
}
|
|
24347
|
+
if (!hasPlaceholder)
|
|
24348
|
+
return true;
|
|
24349
|
+
if (methodCallNames.length === 0)
|
|
24350
|
+
return true;
|
|
24351
|
+
for (const mname of methodCallNames) {
|
|
24352
|
+
const body2 = findJavaMethodBody(mname, sourceLines);
|
|
24353
|
+
if (body2 && javaBodyHasInlineRegexAllowlistThrow(body2))
|
|
24354
|
+
return false;
|
|
24355
|
+
}
|
|
24356
|
+
return true;
|
|
24357
|
+
});
|
|
24358
|
+
}
|
|
24161
24359
|
return { sources, sinks: filtered, sanitizers };
|
|
24162
24360
|
}
|
|
24163
24361
|
}
|
|
@@ -24580,6 +24778,23 @@ class TaintPropagationPass {
|
|
|
24580
24778
|
});
|
|
24581
24779
|
}
|
|
24582
24780
|
}
|
|
24781
|
+
const setIntervalLines = new Set;
|
|
24782
|
+
for (const s of sinks) {
|
|
24783
|
+
if (s.type === "code_injection" && (s.method === "setInterval" || s.method === "setTimeout")) {
|
|
24784
|
+
setIntervalLines.add(s.line);
|
|
24785
|
+
}
|
|
24786
|
+
}
|
|
24787
|
+
if (setIntervalLines.size > 0) {
|
|
24788
|
+
finalFlows = finalFlows.filter((f) => {
|
|
24789
|
+
if (f.sink_type !== "code_injection")
|
|
24790
|
+
return true;
|
|
24791
|
+
if (f.source_type !== "interprocedural_param")
|
|
24792
|
+
return true;
|
|
24793
|
+
if (!setIntervalLines.has(f.sink_line))
|
|
24794
|
+
return true;
|
|
24795
|
+
return false;
|
|
24796
|
+
});
|
|
24797
|
+
}
|
|
24583
24798
|
if (finalFlows.length > 1) {
|
|
24584
24799
|
const bestByKey = new Map;
|
|
24585
24800
|
for (const f of finalFlows) {
|
|
@@ -35373,11 +35588,11 @@ function deriveProjectRoot(paths) {
|
|
|
35373
35588
|
return common.join("/") || "/";
|
|
35374
35589
|
}
|
|
35375
35590
|
// ../project-profile-detect/dist/index.js
|
|
35376
|
-
import { relative as
|
|
35591
|
+
import { relative as relative3 } from "path";
|
|
35377
35592
|
|
|
35378
35593
|
// ../project-profile-detect/dist/walk.js
|
|
35379
35594
|
import { readdir, readFile, stat } from "fs/promises";
|
|
35380
|
-
import { join, relative } from "path";
|
|
35595
|
+
import { join, relative as relative2 } from "path";
|
|
35381
35596
|
|
|
35382
35597
|
// ../project-profile-detect/dist/maven-parse.js
|
|
35383
35598
|
var TAG = (name2) => new RegExp(`<${name2}\\b[^>]*>([\\s\\S]*?)<\\/${name2}>`, "i");
|
|
@@ -35403,7 +35618,12 @@ var MAVEN_PLUGIN_MAP = {
|
|
|
35403
35618
|
"exec-maven-plugin": "application",
|
|
35404
35619
|
"maven-assembly-plugin": "application"
|
|
35405
35620
|
};
|
|
35621
|
+
var MAVEN_PUBLISH_PLUGIN_URLS = {
|
|
35622
|
+
"central-publishing-maven-plugin": "https://central.sonatype.com/",
|
|
35623
|
+
"nexus-staging-maven-plugin": "https://oss.sonatype.org/"
|
|
35624
|
+
};
|
|
35406
35625
|
function parseMavenPom(xml, moduleRoot, buildFile, directorySignals) {
|
|
35626
|
+
const parentRef = extractParentRef(xml);
|
|
35407
35627
|
const stripped = xml.replace(/<parent\b[\s\S]*?<\/parent>/i, "");
|
|
35408
35628
|
const groupId = firstTag(stripped, "groupId");
|
|
35409
35629
|
const artifactId = firstTag(stripped, "artifactId");
|
|
@@ -35412,10 +35632,15 @@ function parseMavenPom(xml, moduleRoot, buildFile, directorySignals) {
|
|
|
35412
35632
|
const buildBlock = firstTag(xml, "build") ?? "";
|
|
35413
35633
|
const pluginBlocks = allTags(buildBlock, "plugin");
|
|
35414
35634
|
const plugins = new Set;
|
|
35635
|
+
const publishUrls = new Set;
|
|
35415
35636
|
for (const p of pluginBlocks) {
|
|
35416
35637
|
const aid = firstTag(p, "artifactId");
|
|
35417
|
-
if (aid
|
|
35638
|
+
if (!aid)
|
|
35639
|
+
continue;
|
|
35640
|
+
if (MAVEN_PLUGIN_MAP[aid])
|
|
35418
35641
|
plugins.add(MAVEN_PLUGIN_MAP[aid]);
|
|
35642
|
+
if (MAVEN_PUBLISH_PLUGIN_URLS[aid])
|
|
35643
|
+
publishUrls.add(MAVEN_PUBLISH_PLUGIN_URLS[aid]);
|
|
35419
35644
|
}
|
|
35420
35645
|
if (/<parent\b[\s\S]*?<artifactId>\s*spring-boot-starter-parent\s*<\/artifactId>/i.test(xml)) {
|
|
35421
35646
|
plugins.add("spring-boot");
|
|
@@ -35428,7 +35653,8 @@ function parseMavenPom(xml, moduleRoot, buildFile, directorySignals) {
|
|
|
35428
35653
|
plugins.add("maven-plugin");
|
|
35429
35654
|
const distBlock = firstTag(xml, "distributionManagement") ?? "";
|
|
35430
35655
|
const urls = [
|
|
35431
|
-
...allTags(distBlock, "url")
|
|
35656
|
+
...allTags(distBlock, "url"),
|
|
35657
|
+
...publishUrls
|
|
35432
35658
|
].map((u) => u.trim()).filter(Boolean);
|
|
35433
35659
|
const signals = {
|
|
35434
35660
|
...directorySignals,
|
|
@@ -35443,9 +35669,34 @@ function parseMavenPom(xml, moduleRoot, buildFile, directorySignals) {
|
|
|
35443
35669
|
groupId,
|
|
35444
35670
|
artifactId,
|
|
35445
35671
|
version,
|
|
35446
|
-
signals
|
|
35672
|
+
signals,
|
|
35673
|
+
parentRef
|
|
35447
35674
|
};
|
|
35448
35675
|
}
|
|
35676
|
+
function extractParentRef(xml) {
|
|
35677
|
+
const block = TAG("parent").exec(xml);
|
|
35678
|
+
if (!block)
|
|
35679
|
+
return;
|
|
35680
|
+
const inner = block[1];
|
|
35681
|
+
const groupId = firstTag(inner, "groupId");
|
|
35682
|
+
const artifactId = firstTag(inner, "artifactId");
|
|
35683
|
+
const version = firstTag(inner, "version");
|
|
35684
|
+
let relativePath;
|
|
35685
|
+
let emptyRelativePath = false;
|
|
35686
|
+
const selfClosing = /<relativePath\b[^>]*\/\s*>/i.test(inner);
|
|
35687
|
+
if (selfClosing) {
|
|
35688
|
+
emptyRelativePath = true;
|
|
35689
|
+
} else {
|
|
35690
|
+
const rp = firstTag(inner, "relativePath");
|
|
35691
|
+
if (rp !== undefined) {
|
|
35692
|
+
if (rp.length === 0)
|
|
35693
|
+
emptyRelativePath = true;
|
|
35694
|
+
else
|
|
35695
|
+
relativePath = rp;
|
|
35696
|
+
}
|
|
35697
|
+
}
|
|
35698
|
+
return { groupId, artifactId, version, relativePath, emptyRelativePath };
|
|
35699
|
+
}
|
|
35449
35700
|
|
|
35450
35701
|
// ../project-profile-detect/dist/gradle-parse.js
|
|
35451
35702
|
var GRADLE_PLUGIN_MAP = {
|
|
@@ -35512,6 +35763,70 @@ function parseGradleBuild(text, moduleRoot, buildFile, buildSystem, directorySig
|
|
|
35512
35763
|
};
|
|
35513
35764
|
}
|
|
35514
35765
|
|
|
35766
|
+
// ../project-profile-detect/dist/maven-inherit.js
|
|
35767
|
+
import { dirname as dirname2, isAbsolute, normalize, relative, resolve } from "path";
|
|
35768
|
+
var MAX_DEPTH = 6;
|
|
35769
|
+
var DEFAULT_RELATIVE_PATH = "../pom.xml";
|
|
35770
|
+
function mergeMavenInheritance(modules, scanRoot) {
|
|
35771
|
+
const normalizedScanRoot = normalize(scanRoot);
|
|
35772
|
+
const byBuildFile = new Map;
|
|
35773
|
+
for (const m of modules) {
|
|
35774
|
+
if (m.buildSystem === "maven") {
|
|
35775
|
+
byBuildFile.set(normalize(m.buildFile), m);
|
|
35776
|
+
}
|
|
35777
|
+
}
|
|
35778
|
+
for (const child of modules) {
|
|
35779
|
+
if (child.buildSystem !== "maven")
|
|
35780
|
+
continue;
|
|
35781
|
+
if (!child.parentRef)
|
|
35782
|
+
continue;
|
|
35783
|
+
const inheritedUrls = new Set;
|
|
35784
|
+
const inheritedPlugins = new Set;
|
|
35785
|
+
walkParents(child, byBuildFile, normalizedScanRoot, inheritedUrls, inheritedPlugins);
|
|
35786
|
+
if (inheritedUrls.size === 0 && inheritedPlugins.size === 0)
|
|
35787
|
+
continue;
|
|
35788
|
+
const existingUrls = new Set(child.signals.distributionUrls);
|
|
35789
|
+
for (const u of inheritedUrls) {
|
|
35790
|
+
if (!existingUrls.has(u))
|
|
35791
|
+
child.signals.distributionUrls.push(u);
|
|
35792
|
+
}
|
|
35793
|
+
const existingPlugins = new Set(child.signals.plugins);
|
|
35794
|
+
for (const p of inheritedPlugins) {
|
|
35795
|
+
if (!existingPlugins.has(p))
|
|
35796
|
+
child.signals.plugins.push(p);
|
|
35797
|
+
}
|
|
35798
|
+
}
|
|
35799
|
+
}
|
|
35800
|
+
function walkParents(start2, byBuildFile, scanRoot, outUrls, outPlugins) {
|
|
35801
|
+
const visited = new Set([normalize(start2.buildFile)]);
|
|
35802
|
+
let current = start2;
|
|
35803
|
+
for (let depth = 0;depth < MAX_DEPTH; depth++) {
|
|
35804
|
+
const ref = current.parentRef;
|
|
35805
|
+
if (!ref)
|
|
35806
|
+
return;
|
|
35807
|
+
if (ref.emptyRelativePath)
|
|
35808
|
+
return;
|
|
35809
|
+
const childDir = dirname2(current.buildFile);
|
|
35810
|
+
const rel = ref.relativePath ?? DEFAULT_RELATIVE_PATH;
|
|
35811
|
+
const candidateAbs = normalize(isAbsolute(rel) ? rel : resolve(childDir, rel));
|
|
35812
|
+
const parentBuildFile = candidateAbs.endsWith("pom.xml") ? candidateAbs : normalize(resolve(candidateAbs, "pom.xml"));
|
|
35813
|
+
const relToRoot = relative(scanRoot, parentBuildFile);
|
|
35814
|
+
if (relToRoot.startsWith("..") || isAbsolute(relToRoot))
|
|
35815
|
+
return;
|
|
35816
|
+
if (visited.has(parentBuildFile))
|
|
35817
|
+
return;
|
|
35818
|
+
visited.add(parentBuildFile);
|
|
35819
|
+
const parent = byBuildFile.get(parentBuildFile);
|
|
35820
|
+
if (!parent)
|
|
35821
|
+
return;
|
|
35822
|
+
for (const u of parent.signals.distributionUrls)
|
|
35823
|
+
outUrls.add(u);
|
|
35824
|
+
for (const p of parent.signals.plugins)
|
|
35825
|
+
outPlugins.add(p);
|
|
35826
|
+
current = parent;
|
|
35827
|
+
}
|
|
35828
|
+
}
|
|
35829
|
+
|
|
35515
35830
|
// ../project-profile-detect/dist/walk.js
|
|
35516
35831
|
var BUILD_FILES = ["pom.xml", "build.gradle", "build.gradle.kts"];
|
|
35517
35832
|
var SKIP_DIRS = new Set([
|
|
@@ -35532,6 +35847,7 @@ var SKIP_DIRS = new Set([
|
|
|
35532
35847
|
async function discoverBuildModules(scanRoot) {
|
|
35533
35848
|
const modules = [];
|
|
35534
35849
|
await walk(scanRoot, modules);
|
|
35850
|
+
mergeMavenInheritance(modules, scanRoot);
|
|
35535
35851
|
return modules;
|
|
35536
35852
|
}
|
|
35537
35853
|
async function walk(dir, out2) {
|
|
@@ -35739,6 +36055,10 @@ function resolveShape(mod) {
|
|
|
35739
36055
|
reasons.push(...libSignals, "no public-registry distribution (internal helper)");
|
|
35740
36056
|
return { shape: "application", reasons };
|
|
35741
36057
|
}
|
|
36058
|
+
if (isPubliclyPublished(sig.distributionUrls)) {
|
|
36059
|
+
reasons.push("public-registry distribution", "no application/server/plugin signals → implicit library");
|
|
36060
|
+
return { shape: "library", reasons };
|
|
36061
|
+
}
|
|
35742
36062
|
reasons.push("no shape signals");
|
|
35743
36063
|
return { shape: "unknown", reasons };
|
|
35744
36064
|
}
|
|
@@ -35826,7 +36146,7 @@ async function detectProjectProfiles(scanRoot, options = {}) {
|
|
|
35826
36146
|
const profileByFile = new Map;
|
|
35827
36147
|
const unknownFiles = [];
|
|
35828
36148
|
for (const file of files) {
|
|
35829
|
-
const rel =
|
|
36149
|
+
const rel = relative3(scanRoot, file);
|
|
35830
36150
|
const ov = applyOverrides(rel, compiledOverrides);
|
|
35831
36151
|
if (ov) {
|
|
35832
36152
|
profileByFile.set(file, ov.profile);
|
|
@@ -35878,7 +36198,7 @@ var colors = {
|
|
|
35878
36198
|
};
|
|
35879
36199
|
|
|
35880
36200
|
// src/version.ts
|
|
35881
|
-
var version = "3.
|
|
36201
|
+
var version = "3.107.0";
|
|
35882
36202
|
|
|
35883
36203
|
// src/formatters.ts
|
|
35884
36204
|
var LIBRARY_API_SURFACE_TAG2 = "library-api-surface:caller-responsibility";
|
|
@@ -36679,7 +36999,7 @@ function applySuppressionsToResults(results, suppressions, basePath) {
|
|
|
36679
36999
|
if (suppressions.length === 0)
|
|
36680
37000
|
return results;
|
|
36681
37001
|
return results.map((result) => {
|
|
36682
|
-
const relativeFile =
|
|
37002
|
+
const relativeFile = relative4(basePath, result.file) || result.file;
|
|
36683
37003
|
const filteredVulns = result.vulnerabilities.filter((vuln) => {
|
|
36684
37004
|
for (const supp of suppressions) {
|
|
36685
37005
|
if (supp.pass !== vuln.type)
|
|
@@ -36768,7 +37088,7 @@ async function collectFiles(targetPath, options = {}) {
|
|
|
36768
37088
|
return files;
|
|
36769
37089
|
}
|
|
36770
37090
|
if (fileMatchesLanguage(targetPath, language)) {
|
|
36771
|
-
const relativePath = basePath ?
|
|
37091
|
+
const relativePath = basePath ? relative4(basePath, targetPath) : targetPath;
|
|
36772
37092
|
if (includePatterns && includePatterns.length > 0) {
|
|
36773
37093
|
if (!matchesAnyPattern(relativePath, includePatterns)) {
|
|
36774
37094
|
return files;
|
|
@@ -36787,7 +37107,7 @@ async function collectFiles(targetPath, options = {}) {
|
|
|
36787
37107
|
if (excludeTests && /^(test|tests|__tests__|spec|__mocks__)$/i.test(entry.name))
|
|
36788
37108
|
continue;
|
|
36789
37109
|
const fullPath = join2(targetPath, entry.name);
|
|
36790
|
-
const relativePath = basePath ?
|
|
37110
|
+
const relativePath = basePath ? relative4(basePath, fullPath) : fullPath;
|
|
36791
37111
|
if (excludePatterns && entry.isDirectory()) {
|
|
36792
37112
|
const dirPattern = relativePath + "/";
|
|
36793
37113
|
if (excludePatterns.some((p) => matchesGlob(dirPattern, p) || matchesGlob(relativePath, p))) {
|
|
@@ -36885,14 +37205,14 @@ async function scanProject(files, language, analyzeOpts, crossFileBudgetMs) {
|
|
|
36885
37205
|
async function initWasm(spin) {
|
|
36886
37206
|
const isStandalone = import.meta.url.includes("/$bunfs/");
|
|
36887
37207
|
if (isStandalone) {
|
|
36888
|
-
const { dirname:
|
|
36889
|
-
const binaryDir =
|
|
37208
|
+
const { dirname: dirname4, join: join3 } = await import("path");
|
|
37209
|
+
const binaryDir = dirname4(process.execPath);
|
|
36890
37210
|
const cwd = process.cwd();
|
|
36891
37211
|
let scriptDir = null;
|
|
36892
37212
|
if (!import.meta.url.includes("/$bunfs/")) {
|
|
36893
37213
|
try {
|
|
36894
37214
|
const { fileURLToPath } = await import("url");
|
|
36895
|
-
scriptDir =
|
|
37215
|
+
scriptDir = dirname4(fileURLToPath(import.meta.url));
|
|
36896
37216
|
} catch {}
|
|
36897
37217
|
}
|
|
36898
37218
|
const wasmLocations = [
|
|
@@ -36945,7 +37265,7 @@ Please ensure the wasm/ directory is located next to the binary or in your curre
|
|
|
36945
37265
|
} else {
|
|
36946
37266
|
const require2 = createRequire2(import.meta.url);
|
|
36947
37267
|
const circleIrPkg = require2.resolve("circle-ir/package.json");
|
|
36948
|
-
const wasmBasePath = join2(
|
|
37268
|
+
const wasmBasePath = join2(dirname3(circleIrPkg), "dist", "wasm") + "/";
|
|
36949
37269
|
await initAnalyzer({
|
|
36950
37270
|
wasmPath: wasmBasePath + "web-tree-sitter.wasm",
|
|
36951
37271
|
languagePaths: {
|
|
@@ -36974,7 +37294,7 @@ function buildProfileSummary(scanRoot, modules, resolvedProfiles) {
|
|
|
36974
37294
|
return {
|
|
36975
37295
|
scanRoot,
|
|
36976
37296
|
modules: modules.map((m) => ({
|
|
36977
|
-
root:
|
|
37297
|
+
root: relative4(scanRoot, m.module.root) || ".",
|
|
36978
37298
|
profile: m.profile,
|
|
36979
37299
|
reasons: m.reasons,
|
|
36980
37300
|
buildSystem: m.module.buildSystem
|
|
@@ -37003,9 +37323,9 @@ function printProfileExplain(scanRoot, detection) {
|
|
|
37003
37323
|
out2.push(" (no pom.xml, build.gradle, or build.gradle.kts found)");
|
|
37004
37324
|
} else {
|
|
37005
37325
|
for (const r of detection.modules) {
|
|
37006
|
-
const rel =
|
|
37326
|
+
const rel = relative4(scanRoot, r.module.root) || ".";
|
|
37007
37327
|
out2.push(` ${colors.cyan(rel || ".")} → ${colors.bold(r.profile)}`);
|
|
37008
|
-
out2.push(` build: ${r.module.buildSystem} (${
|
|
37328
|
+
out2.push(` build: ${r.module.buildSystem} (${relative4(scanRoot, r.module.buildFile)})`);
|
|
37009
37329
|
if (r.module.artifactId) {
|
|
37010
37330
|
out2.push(` coords: ${r.module.groupId ?? "?"}:${r.module.artifactId}:${r.module.version ?? "?"}`);
|
|
37011
37331
|
}
|
|
@@ -37050,7 +37370,7 @@ async function runScan(targetPath, options) {
|
|
|
37050
37370
|
await initWasm(spin);
|
|
37051
37371
|
if (spin)
|
|
37052
37372
|
spin.text = "Collecting files...";
|
|
37053
|
-
const absPath =
|
|
37373
|
+
const absPath = resolve2(targetPath);
|
|
37054
37374
|
if (!existsSync(absPath)) {
|
|
37055
37375
|
if (spin)
|
|
37056
37376
|
spin.fail(`Path not found: ${absPath}`);
|
|
@@ -37114,7 +37434,7 @@ async function runScan(targetPath, options) {
|
|
|
37114
37434
|
results = [];
|
|
37115
37435
|
let processed = 0;
|
|
37116
37436
|
const formatCurrentFile = (file) => {
|
|
37117
|
-
const rel =
|
|
37437
|
+
const rel = relative4(absPath, file) || file;
|
|
37118
37438
|
return rel.length > 80 ? `...${rel.slice(-77)}` : rel;
|
|
37119
37439
|
};
|
|
37120
37440
|
const concurrency = options.threads;
|
|
@@ -37290,7 +37610,7 @@ async function runMetrics(targetPath, options) {
|
|
|
37290
37610
|
await initWasm(spin);
|
|
37291
37611
|
if (spin)
|
|
37292
37612
|
spin.text = "Collecting files...";
|
|
37293
|
-
const absPath =
|
|
37613
|
+
const absPath = resolve2(targetPath);
|
|
37294
37614
|
if (!existsSync(absPath)) {
|
|
37295
37615
|
if (spin)
|
|
37296
37616
|
spin.fail(`Path not found: ${absPath}`);
|
|
@@ -37318,7 +37638,7 @@ async function runMetrics(targetPath, options) {
|
|
|
37318
37638
|
continue;
|
|
37319
37639
|
}
|
|
37320
37640
|
if (spin) {
|
|
37321
|
-
const rel =
|
|
37641
|
+
const rel = relative4(absPath, file) || file;
|
|
37322
37642
|
const maxLen = 80;
|
|
37323
37643
|
const label = rel.length > maxLen ? `...${rel.slice(-(maxLen - 3))}` : rel;
|
|
37324
37644
|
spin.text = `Analyzing ${label}... (${processed}/${totalFiles})`;
|
|
@@ -37363,7 +37683,7 @@ async function runMetrics(targetPath, options) {
|
|
|
37363
37683
|
} else {
|
|
37364
37684
|
const lines = [];
|
|
37365
37685
|
for (const fm of filtered) {
|
|
37366
|
-
const rel =
|
|
37686
|
+
const rel = relative4(absPath, fm.file) || fm.file;
|
|
37367
37687
|
lines.push(rel);
|
|
37368
37688
|
const byCategory = new Map;
|
|
37369
37689
|
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.107.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.107.0"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@types/node": "^25.5.0",
|