cognium-dev 3.151.0 → 3.153.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 +555 -217
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -10611,10 +10611,6 @@ var DEFAULT_SINKS = [
|
|
|
10611
10611
|
{ method: "FileOutputStream", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10612
10612
|
{ method: "FileReader", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10613
10613
|
{ method: "FileWriter", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10614
|
-
{ method: "getResource", class: "ClassLoader", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10615
|
-
{ method: "getResourceAsStream", class: "ClassLoader", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10616
|
-
{ method: "getResource", class: "Class", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10617
|
-
{ method: "getResourceAsStream", class: "Class", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10618
10614
|
{ method: "get", class: "Paths", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10619
10615
|
{ method: "of", class: "Path", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10620
10616
|
{ method: "readAllBytes", class: "Files", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
@@ -10968,6 +10964,9 @@ var DEFAULT_SINKS = [
|
|
|
10968
10964
|
{ method: "parseObject", class: "JSON", type: "deserialization", cwe: "CWE-502", severity: "high", arg_positions: [0], safe_if_class_literal_at: 1 },
|
|
10969
10965
|
{ method: "parseObject", class: "JSONObject", type: "deserialization", cwe: "CWE-502", severity: "high", arg_positions: [0], safe_if_class_literal_at: 1 },
|
|
10970
10966
|
{ method: "fromJson", class: "Gson", type: "deserialization", cwe: "CWE-502", severity: "medium", arg_positions: [0], safe_if_class_literal_at: 1 },
|
|
10967
|
+
{ method: "readValue", class: "ObjectReader", type: "deserialization", cwe: "CWE-502", severity: "high", arg_positions: [0], safe_if_class_literal_at: 1 },
|
|
10968
|
+
{ method: "convertValue", class: "ObjectMapper", type: "deserialization", cwe: "CWE-502", severity: "medium", arg_positions: [0], safe_if_class_literal_at: 1 },
|
|
10969
|
+
{ method: "readObject", class: "Kryo", type: "deserialization", cwe: "CWE-502", severity: "high", arg_positions: [0], safe_if_class_literal_at: 1 },
|
|
10971
10970
|
{ method: "readObject", class: "XMLDecoder", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [] },
|
|
10972
10971
|
{ method: "ObjectInputStream", class: "constructor", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0] },
|
|
10973
10972
|
{ method: "search", class: "DirContext", type: "ldap_injection", cwe: "CWE-90", severity: "high", arg_positions: [0, 1] },
|
|
@@ -12455,7 +12454,21 @@ function argIsClassLiteral(call, position) {
|
|
|
12455
12454
|
const expr = (arg.literal ?? arg.expression ?? "").trim();
|
|
12456
12455
|
if (!expr)
|
|
12457
12456
|
return false;
|
|
12458
|
-
|
|
12457
|
+
if (CLASS_LITERAL_RE.test(expr))
|
|
12458
|
+
return true;
|
|
12459
|
+
return TYPE_TOKEN_RE.test(expr);
|
|
12460
|
+
}
|
|
12461
|
+
var TYPE_TOKEN_RE = /^new\s+(?:TypeReference|TypeToken)\s*<[\s\S]*>\s*\(\s*\)\s*\{\s*\}$/;
|
|
12462
|
+
function argIsStringLiteral(call, position) {
|
|
12463
|
+
const arg = call.arguments.find((a) => a.position === position);
|
|
12464
|
+
if (!arg)
|
|
12465
|
+
return false;
|
|
12466
|
+
if (arg.literal !== undefined && arg.literal !== null && arg.literal !== "")
|
|
12467
|
+
return true;
|
|
12468
|
+
const expr = (arg.expression ?? "").trim();
|
|
12469
|
+
if (!expr)
|
|
12470
|
+
return false;
|
|
12471
|
+
return expr.startsWith('"') && expr.endsWith('"') && expr.length >= 2 || expr.startsWith("'") && expr.endsWith("'") && expr.length >= 2 || expr.startsWith('"""') && expr.endsWith('"""');
|
|
12459
12472
|
}
|
|
12460
12473
|
var CWE_78_RECEIVER_ALLOWLIST = new Set([
|
|
12461
12474
|
"Runtime",
|
|
@@ -12649,6 +12662,9 @@ function findSinks(calls, patterns, typeHierarchy, language, sourceLines) {
|
|
|
12649
12662
|
if (pattern.safe_if_class_literal_at !== undefined && argIsClassLiteral(call, pattern.safe_if_class_literal_at)) {
|
|
12650
12663
|
continue;
|
|
12651
12664
|
}
|
|
12665
|
+
if (pattern.safe_if_string_literal_at !== undefined && argIsStringLiteral(call, pattern.safe_if_string_literal_at)) {
|
|
12666
|
+
continue;
|
|
12667
|
+
}
|
|
12652
12668
|
if (pattern.type === "command_injection") {
|
|
12653
12669
|
if (call.is_constructor) {
|
|
12654
12670
|
if (!CWE_78_RECEIVER_ALLOWLIST.has(call.method_name)) {
|
|
@@ -18460,6 +18476,470 @@ function applyLibraryApiSurfaceDowngrade(findings) {
|
|
|
18460
18476
|
});
|
|
18461
18477
|
}
|
|
18462
18478
|
|
|
18479
|
+
// ../circle-ir/dist/analysis/entry-point-detection.js
|
|
18480
|
+
var TIER_1_METHOD_ANNOTATIONS = new Set([
|
|
18481
|
+
"RequestMapping",
|
|
18482
|
+
"GetMapping",
|
|
18483
|
+
"PostMapping",
|
|
18484
|
+
"PutMapping",
|
|
18485
|
+
"DeleteMapping",
|
|
18486
|
+
"PatchMapping",
|
|
18487
|
+
"MessageMapping",
|
|
18488
|
+
"SubscribeMapping",
|
|
18489
|
+
"KafkaListener",
|
|
18490
|
+
"KafkaHandler",
|
|
18491
|
+
"RabbitListener",
|
|
18492
|
+
"RabbitHandler",
|
|
18493
|
+
"JmsListener",
|
|
18494
|
+
"StreamListener",
|
|
18495
|
+
"SqsListener",
|
|
18496
|
+
"SqsHandler",
|
|
18497
|
+
"EventListener",
|
|
18498
|
+
"Scheduled",
|
|
18499
|
+
"Path",
|
|
18500
|
+
"GET",
|
|
18501
|
+
"POST",
|
|
18502
|
+
"PUT",
|
|
18503
|
+
"DELETE",
|
|
18504
|
+
"PATCH",
|
|
18505
|
+
"HEAD",
|
|
18506
|
+
"OPTIONS",
|
|
18507
|
+
"DataBoundConstructor",
|
|
18508
|
+
"DataBoundSetter"
|
|
18509
|
+
]);
|
|
18510
|
+
var TIER_1_CLASS_ANNOTATIONS = new Set([
|
|
18511
|
+
"RestController",
|
|
18512
|
+
"Controller",
|
|
18513
|
+
"Service",
|
|
18514
|
+
"Repository",
|
|
18515
|
+
"Component",
|
|
18516
|
+
"Path",
|
|
18517
|
+
"WebServlet",
|
|
18518
|
+
"ServerEndpoint",
|
|
18519
|
+
"FeignClient"
|
|
18520
|
+
]);
|
|
18521
|
+
var TIER_1_BY_SUPERTYPE = new Map([
|
|
18522
|
+
["HttpServlet", new Set(["doGet", "doPost", "doPut", "doDelete", "doHead", "doOptions", "doTrace", "service"])],
|
|
18523
|
+
["GenericServlet", new Set(["service"])],
|
|
18524
|
+
["Filter", new Set(["doFilter"])],
|
|
18525
|
+
["HandlerInterceptor", new Set(["preHandle", "postHandle", "afterCompletion"])],
|
|
18526
|
+
["AsyncHandlerInterceptor", new Set(["preHandle", "postHandle", "afterCompletion", "afterConcurrentHandlingStarted"])],
|
|
18527
|
+
["CommandLineRunner", new Set(["run"])],
|
|
18528
|
+
["ApplicationRunner", new Set(["run"])],
|
|
18529
|
+
["SimpleChannelInboundHandler", new Set(["channelRead0", "messageReceived"])],
|
|
18530
|
+
["ChannelInboundHandler", new Set(["channelRead", "channelReadComplete"])],
|
|
18531
|
+
["ChannelInboundHandlerAdapter", new Set(["channelRead", "channelReadComplete"])],
|
|
18532
|
+
["ChannelDuplexHandler", new Set(["channelRead", "channelReadComplete"])],
|
|
18533
|
+
["NettyRequestProcessor", new Set(["process"])],
|
|
18534
|
+
["Converter", new Set(["marshal", "unmarshal"])],
|
|
18535
|
+
["SingleValueConverter", new Set(["fromString", "toString"])],
|
|
18536
|
+
["ConverterMatcher", new Set(["marshal", "unmarshal"])],
|
|
18537
|
+
["AbstractReflectionConverter", new Set(["marshal", "unmarshal", "doMarshal", "doUnmarshal"])],
|
|
18538
|
+
["AbstractSingleValueConverter", new Set(["fromString", "toString"])],
|
|
18539
|
+
["AbstractCollectionConverter", new Set(["marshal", "unmarshal"])]
|
|
18540
|
+
]);
|
|
18541
|
+
var TIER_3_CLASS_SUFFIXES = [
|
|
18542
|
+
"Util",
|
|
18543
|
+
"Utils",
|
|
18544
|
+
"Helper",
|
|
18545
|
+
"Helpers"
|
|
18546
|
+
];
|
|
18547
|
+
var TIER_3_PACKAGE_FRAGMENTS = [
|
|
18548
|
+
".template.",
|
|
18549
|
+
".templates.",
|
|
18550
|
+
".engine.",
|
|
18551
|
+
".engines."
|
|
18552
|
+
];
|
|
18553
|
+
var TIER_3_JDK_FACADE_INTERFACES = new Set([
|
|
18554
|
+
"Collection",
|
|
18555
|
+
"List",
|
|
18556
|
+
"Set",
|
|
18557
|
+
"Map",
|
|
18558
|
+
"Queue",
|
|
18559
|
+
"Deque",
|
|
18560
|
+
"SortedSet",
|
|
18561
|
+
"SortedMap",
|
|
18562
|
+
"NavigableSet",
|
|
18563
|
+
"NavigableMap",
|
|
18564
|
+
"Iterator",
|
|
18565
|
+
"Iterable",
|
|
18566
|
+
"ListIterator",
|
|
18567
|
+
"Comparator",
|
|
18568
|
+
"Comparable",
|
|
18569
|
+
"Serializable",
|
|
18570
|
+
"Externalizable",
|
|
18571
|
+
"Cloneable"
|
|
18572
|
+
]);
|
|
18573
|
+
function classNameLooksLikeUtility(name2) {
|
|
18574
|
+
if (!name2)
|
|
18575
|
+
return false;
|
|
18576
|
+
for (const suffix of TIER_3_CLASS_SUFFIXES) {
|
|
18577
|
+
if (name2.length > suffix.length && name2.endsWith(suffix))
|
|
18578
|
+
return true;
|
|
18579
|
+
}
|
|
18580
|
+
return false;
|
|
18581
|
+
}
|
|
18582
|
+
function packageLooksLikeTemplateOrEngine(pkg) {
|
|
18583
|
+
if (!pkg)
|
|
18584
|
+
return false;
|
|
18585
|
+
const padded = `.${pkg}.`;
|
|
18586
|
+
for (const frag of TIER_3_PACKAGE_FRAGMENTS) {
|
|
18587
|
+
if (padded.includes(frag))
|
|
18588
|
+
return true;
|
|
18589
|
+
}
|
|
18590
|
+
return false;
|
|
18591
|
+
}
|
|
18592
|
+
function implementsJdkFacade(t) {
|
|
18593
|
+
if (!t)
|
|
18594
|
+
return false;
|
|
18595
|
+
for (const impl of t.implements ?? []) {
|
|
18596
|
+
if (TIER_3_JDK_FACADE_INTERFACES.has(simpleTypeName(impl)))
|
|
18597
|
+
return true;
|
|
18598
|
+
}
|
|
18599
|
+
return false;
|
|
18600
|
+
}
|
|
18601
|
+
function classShapeIsLibraryFacade(enclosingType) {
|
|
18602
|
+
if (!enclosingType)
|
|
18603
|
+
return false;
|
|
18604
|
+
if (classNameLooksLikeUtility(enclosingType.name))
|
|
18605
|
+
return true;
|
|
18606
|
+
if (packageLooksLikeTemplateOrEngine(enclosingType.package))
|
|
18607
|
+
return true;
|
|
18608
|
+
if (implementsJdkFacade(enclosingType))
|
|
18609
|
+
return true;
|
|
18610
|
+
return false;
|
|
18611
|
+
}
|
|
18612
|
+
function annotationsInclude(annotations, targets) {
|
|
18613
|
+
if (!annotations || annotations.length === 0)
|
|
18614
|
+
return false;
|
|
18615
|
+
for (const raw of annotations) {
|
|
18616
|
+
const simple = raw.replace(/^@/, "").replace(/[<(].*$/, "").trim();
|
|
18617
|
+
if (targets.has(simple))
|
|
18618
|
+
return true;
|
|
18619
|
+
}
|
|
18620
|
+
return false;
|
|
18621
|
+
}
|
|
18622
|
+
function simpleTypeName(ref) {
|
|
18623
|
+
return ref.replace(/<.*$/, "").trim();
|
|
18624
|
+
}
|
|
18625
|
+
function looksLikeMainMethod(method) {
|
|
18626
|
+
if (method.name !== "main")
|
|
18627
|
+
return false;
|
|
18628
|
+
const params = method.parameters ?? [];
|
|
18629
|
+
if (params.length !== 1)
|
|
18630
|
+
return false;
|
|
18631
|
+
const t = (params[0].type ?? "").replace(/\s+/g, "");
|
|
18632
|
+
return t === "String[]" || t === "String..." || t === "java.lang.String[]";
|
|
18633
|
+
}
|
|
18634
|
+
function methodIsSupertypeLifecycleEntryPoint(method, enclosingType) {
|
|
18635
|
+
if (!method.name)
|
|
18636
|
+
return false;
|
|
18637
|
+
if (!enclosingType)
|
|
18638
|
+
return false;
|
|
18639
|
+
const candidates = [];
|
|
18640
|
+
if (enclosingType.extends)
|
|
18641
|
+
candidates.push(simpleTypeName(enclosingType.extends));
|
|
18642
|
+
for (const i2 of enclosingType.implements ?? [])
|
|
18643
|
+
candidates.push(simpleTypeName(i2));
|
|
18644
|
+
for (const supertype of candidates) {
|
|
18645
|
+
const lifecycleMethods = TIER_1_BY_SUPERTYPE.get(supertype);
|
|
18646
|
+
if (lifecycleMethods?.has(method.name))
|
|
18647
|
+
return true;
|
|
18648
|
+
}
|
|
18649
|
+
return false;
|
|
18650
|
+
}
|
|
18651
|
+
function classifyEntryPointTier(method, enclosingType, ctx) {
|
|
18652
|
+
const language = (ctx.language ?? "").toLowerCase();
|
|
18653
|
+
if (language !== "java")
|
|
18654
|
+
return "TIER_UNKNOWN";
|
|
18655
|
+
if (!method)
|
|
18656
|
+
return "TIER_UNKNOWN";
|
|
18657
|
+
if (classShapeIsLibraryFacade(enclosingType)) {
|
|
18658
|
+
return "TIER_3_LIBRARY_API";
|
|
18659
|
+
}
|
|
18660
|
+
if (annotationsInclude(method.annotations, TIER_1_METHOD_ANNOTATIONS)) {
|
|
18661
|
+
return "TIER_1_ENTRY_POINT";
|
|
18662
|
+
}
|
|
18663
|
+
if (enclosingType && annotationsInclude(enclosingType.annotations, TIER_1_CLASS_ANNOTATIONS)) {
|
|
18664
|
+
return "TIER_1_ENTRY_POINT";
|
|
18665
|
+
}
|
|
18666
|
+
if (methodIsSupertypeLifecycleEntryPoint(method, enclosingType)) {
|
|
18667
|
+
return "TIER_1_ENTRY_POINT";
|
|
18668
|
+
}
|
|
18669
|
+
if (looksLikeMainMethod(method)) {
|
|
18670
|
+
return "TIER_1_ENTRY_POINT";
|
|
18671
|
+
}
|
|
18672
|
+
return "TIER_3_LIBRARY_API";
|
|
18673
|
+
}
|
|
18674
|
+
function shouldGateInterproceduralParam(sourceType, enclosingMethod, enclosingType, ctx) {
|
|
18675
|
+
if (sourceType !== "interprocedural_param")
|
|
18676
|
+
return false;
|
|
18677
|
+
if (!enclosingMethod)
|
|
18678
|
+
return false;
|
|
18679
|
+
const tier = classifyEntryPointTier(enclosingMethod, enclosingType, ctx);
|
|
18680
|
+
return tier === "TIER_3_LIBRARY_API";
|
|
18681
|
+
}
|
|
18682
|
+
|
|
18683
|
+
// ../circle-ir/dist/analysis/require-entry-path.js
|
|
18684
|
+
var RULE_ID_REQUIRE_ENTRY_PATH = "require-entry-path";
|
|
18685
|
+
var MAX_VISITED_METHODS = 2000;
|
|
18686
|
+
function applyRequireEntryPath(fileAnalyses, options = {}) {
|
|
18687
|
+
const disabledSet = normalizeDisabled(options.disabledPasses);
|
|
18688
|
+
if (disabledSet.has(RULE_ID_REQUIRE_ENTRY_PATH))
|
|
18689
|
+
return;
|
|
18690
|
+
const graph = buildProjectMethodGraph(fileAnalyses);
|
|
18691
|
+
if (graph.methodsByKey.size === 0)
|
|
18692
|
+
return;
|
|
18693
|
+
const entryPointKeys = collectEntryPointKeys(graph);
|
|
18694
|
+
const profileResolver = makeProfileResolver(options.projectProfile);
|
|
18695
|
+
for (const fa of fileAnalyses) {
|
|
18696
|
+
const findings = fa.analysis.findings;
|
|
18697
|
+
if (!findings || findings.length === 0)
|
|
18698
|
+
continue;
|
|
18699
|
+
const kept = [];
|
|
18700
|
+
for (const finding of findings) {
|
|
18701
|
+
const decision = classifyFinding(finding, fa.analysis, graph, entryPointKeys, profileResolver(fa.file));
|
|
18702
|
+
switch (decision.action) {
|
|
18703
|
+
case "keep":
|
|
18704
|
+
kept.push(finding);
|
|
18705
|
+
break;
|
|
18706
|
+
case "annotate":
|
|
18707
|
+
kept.push({
|
|
18708
|
+
...finding,
|
|
18709
|
+
entryPath: decision.entryPath,
|
|
18710
|
+
entryPathTier: decision.tier
|
|
18711
|
+
});
|
|
18712
|
+
break;
|
|
18713
|
+
case "drop":
|
|
18714
|
+
break;
|
|
18715
|
+
}
|
|
18716
|
+
}
|
|
18717
|
+
fa.analysis.findings = kept.length > 0 ? kept : undefined;
|
|
18718
|
+
}
|
|
18719
|
+
}
|
|
18720
|
+
function buildProjectMethodGraph(fileAnalyses) {
|
|
18721
|
+
const methodsByKey = new Map;
|
|
18722
|
+
const methodsByName = new Map;
|
|
18723
|
+
const callersOf = new Map;
|
|
18724
|
+
for (const fa of fileAnalyses) {
|
|
18725
|
+
const language = (fa.analysis.meta.language ?? "").toLowerCase();
|
|
18726
|
+
for (const type of fa.analysis.types ?? []) {
|
|
18727
|
+
for (const method of type.methods ?? []) {
|
|
18728
|
+
const key = makeMethodKey(fa.file, type.name, method.name, method.start_line);
|
|
18729
|
+
methodsByKey.set(key, {
|
|
18730
|
+
key,
|
|
18731
|
+
file: fa.file,
|
|
18732
|
+
className: type.name,
|
|
18733
|
+
method,
|
|
18734
|
+
enclosingType: type,
|
|
18735
|
+
language
|
|
18736
|
+
});
|
|
18737
|
+
const bucket = methodsByName.get(method.name);
|
|
18738
|
+
if (bucket)
|
|
18739
|
+
bucket.push(key);
|
|
18740
|
+
else
|
|
18741
|
+
methodsByName.set(method.name, [key]);
|
|
18742
|
+
}
|
|
18743
|
+
}
|
|
18744
|
+
}
|
|
18745
|
+
for (const fa of fileAnalyses) {
|
|
18746
|
+
const calls = fa.analysis.calls ?? [];
|
|
18747
|
+
for (const call of calls) {
|
|
18748
|
+
if (!call.in_method)
|
|
18749
|
+
continue;
|
|
18750
|
+
const callerKey = resolveCallerKey(fa, call.in_method, call.location.line);
|
|
18751
|
+
if (!callerKey)
|
|
18752
|
+
continue;
|
|
18753
|
+
const calleeKeys = resolveCalleeKeys(call, methodsByKey, methodsByName);
|
|
18754
|
+
if (calleeKeys.length === 0)
|
|
18755
|
+
continue;
|
|
18756
|
+
const code = call.receiver ? `${call.receiver}.${call.method_name}(...)` : `${call.method_name}(...)`;
|
|
18757
|
+
for (const calleeKey of calleeKeys) {
|
|
18758
|
+
const edge = {
|
|
18759
|
+
callerKey,
|
|
18760
|
+
calleeKey,
|
|
18761
|
+
callSiteLine: call.location.line,
|
|
18762
|
+
code
|
|
18763
|
+
};
|
|
18764
|
+
const bucket = callersOf.get(calleeKey);
|
|
18765
|
+
if (bucket)
|
|
18766
|
+
bucket.push(edge);
|
|
18767
|
+
else
|
|
18768
|
+
callersOf.set(calleeKey, [edge]);
|
|
18769
|
+
}
|
|
18770
|
+
}
|
|
18771
|
+
}
|
|
18772
|
+
return { methodsByKey, methodsByName, callersOf };
|
|
18773
|
+
}
|
|
18774
|
+
function makeMethodKey(file, className, methodName, startLine) {
|
|
18775
|
+
return `${file}|${className}#${methodName}@${startLine}`;
|
|
18776
|
+
}
|
|
18777
|
+
function resolveCallerKey(fa, inMethod, callLine) {
|
|
18778
|
+
for (const type of fa.analysis.types ?? []) {
|
|
18779
|
+
for (const method of type.methods ?? []) {
|
|
18780
|
+
if (method.name !== inMethod)
|
|
18781
|
+
continue;
|
|
18782
|
+
if (callLine >= method.start_line && callLine <= method.end_line) {
|
|
18783
|
+
return makeMethodKey(fa.file, type.name, method.name, method.start_line);
|
|
18784
|
+
}
|
|
18785
|
+
}
|
|
18786
|
+
}
|
|
18787
|
+
return null;
|
|
18788
|
+
}
|
|
18789
|
+
function resolveCalleeKeys(call, methodsByKey, methodsByName) {
|
|
18790
|
+
const candidates = methodsByName.get(call.method_name);
|
|
18791
|
+
if (!candidates || candidates.length === 0)
|
|
18792
|
+
return [];
|
|
18793
|
+
if (call.receiver_type) {
|
|
18794
|
+
const simple = call.receiver_type.replace(/<.*$/, "").trim();
|
|
18795
|
+
const matches = [];
|
|
18796
|
+
for (const key of candidates) {
|
|
18797
|
+
const rec = methodsByKey.get(key);
|
|
18798
|
+
if (rec?.className === simple)
|
|
18799
|
+
matches.push(key);
|
|
18800
|
+
}
|
|
18801
|
+
if (matches.length > 0)
|
|
18802
|
+
return matches;
|
|
18803
|
+
}
|
|
18804
|
+
return candidates;
|
|
18805
|
+
}
|
|
18806
|
+
function collectEntryPointKeys(graph) {
|
|
18807
|
+
const entryPoints = new Set;
|
|
18808
|
+
for (const rec of graph.methodsByKey.values()) {
|
|
18809
|
+
const tier = classifyEntryPointTier(rec.method, rec.enclosingType, {
|
|
18810
|
+
types: [rec.enclosingType],
|
|
18811
|
+
language: rec.language
|
|
18812
|
+
});
|
|
18813
|
+
if (tier === "TIER_1_ENTRY_POINT")
|
|
18814
|
+
entryPoints.add(rec.key);
|
|
18815
|
+
}
|
|
18816
|
+
return entryPoints;
|
|
18817
|
+
}
|
|
18818
|
+
function classifyFinding(finding, ir, graph, entryPointKeys, profile) {
|
|
18819
|
+
if (finding.category !== "security")
|
|
18820
|
+
return { action: "keep" };
|
|
18821
|
+
const isHighOrCritical = finding.severity === "high" || finding.severity === "critical";
|
|
18822
|
+
const language = (ir.meta.language ?? "").toLowerCase();
|
|
18823
|
+
if (language !== "java")
|
|
18824
|
+
return { action: "keep" };
|
|
18825
|
+
const containing = findContainingMethod(finding, ir, graph);
|
|
18826
|
+
if (!containing) {
|
|
18827
|
+
return { action: "keep" };
|
|
18828
|
+
}
|
|
18829
|
+
const bfs = reverseBfsToEntryPoint(containing.key, graph, entryPointKeys);
|
|
18830
|
+
if (bfs.status === "hit") {
|
|
18831
|
+
const entryPath = reconstructPath(bfs.entryKey, containing.key, bfs.parent, graph, finding);
|
|
18832
|
+
return {
|
|
18833
|
+
action: "annotate",
|
|
18834
|
+
entryPath,
|
|
18835
|
+
tier: "tier1-entry-point"
|
|
18836
|
+
};
|
|
18837
|
+
}
|
|
18838
|
+
if (bfs.status === "budget") {
|
|
18839
|
+
return { action: "keep" };
|
|
18840
|
+
}
|
|
18841
|
+
if (!isHighOrCritical)
|
|
18842
|
+
return { action: "keep" };
|
|
18843
|
+
if (!shouldDropUnderProfile(profile))
|
|
18844
|
+
return { action: "keep" };
|
|
18845
|
+
return { action: "drop" };
|
|
18846
|
+
}
|
|
18847
|
+
function findContainingMethod(finding, ir, graph) {
|
|
18848
|
+
const line = finding.line;
|
|
18849
|
+
for (const type of ir.types ?? []) {
|
|
18850
|
+
for (const method of type.methods ?? []) {
|
|
18851
|
+
if (line >= method.start_line && line <= method.end_line) {
|
|
18852
|
+
const key = makeMethodKey(finding.file, type.name, method.name, method.start_line);
|
|
18853
|
+
const rec = graph.methodsByKey.get(key);
|
|
18854
|
+
if (rec)
|
|
18855
|
+
return rec;
|
|
18856
|
+
}
|
|
18857
|
+
}
|
|
18858
|
+
}
|
|
18859
|
+
return null;
|
|
18860
|
+
}
|
|
18861
|
+
function reverseBfsToEntryPoint(startKey, graph, entryPointKeys) {
|
|
18862
|
+
const parent = new Map;
|
|
18863
|
+
const visited = new Set([startKey]);
|
|
18864
|
+
const queue = [startKey];
|
|
18865
|
+
if (entryPointKeys.has(startKey)) {
|
|
18866
|
+
return { status: "hit", entryKey: startKey, parent };
|
|
18867
|
+
}
|
|
18868
|
+
while (queue.length > 0) {
|
|
18869
|
+
if (visited.size > MAX_VISITED_METHODS) {
|
|
18870
|
+
return { status: "budget", entryKey: null, parent };
|
|
18871
|
+
}
|
|
18872
|
+
const current = queue.shift();
|
|
18873
|
+
const incoming = graph.callersOf.get(current) ?? [];
|
|
18874
|
+
incoming.sort((a, b) => a.callerKey.localeCompare(b.callerKey));
|
|
18875
|
+
for (const edge of incoming) {
|
|
18876
|
+
if (visited.has(edge.callerKey))
|
|
18877
|
+
continue;
|
|
18878
|
+
visited.add(edge.callerKey);
|
|
18879
|
+
parent.set(edge.callerKey, edge);
|
|
18880
|
+
if (entryPointKeys.has(edge.callerKey)) {
|
|
18881
|
+
return { status: "hit", entryKey: edge.callerKey, parent };
|
|
18882
|
+
}
|
|
18883
|
+
queue.push(edge.callerKey);
|
|
18884
|
+
}
|
|
18885
|
+
}
|
|
18886
|
+
return { status: "miss", entryKey: null, parent };
|
|
18887
|
+
}
|
|
18888
|
+
function reconstructPath(entryKey, sinkKey, parent, graph, finding) {
|
|
18889
|
+
const hops = [];
|
|
18890
|
+
let cursor = entryKey;
|
|
18891
|
+
const guard = new Set;
|
|
18892
|
+
while (cursor !== sinkKey) {
|
|
18893
|
+
if (guard.has(cursor))
|
|
18894
|
+
break;
|
|
18895
|
+
guard.add(cursor);
|
|
18896
|
+
const rec = graph.methodsByKey.get(cursor);
|
|
18897
|
+
const edge = parent.get(cursor);
|
|
18898
|
+
if (!rec || !edge)
|
|
18899
|
+
break;
|
|
18900
|
+
hops.push({
|
|
18901
|
+
file: rec.file,
|
|
18902
|
+
method: `${rec.className}.${rec.method.name}`,
|
|
18903
|
+
line: edge.callSiteLine,
|
|
18904
|
+
code: edge.code,
|
|
18905
|
+
variable: ""
|
|
18906
|
+
});
|
|
18907
|
+
cursor = edge.calleeKey;
|
|
18908
|
+
}
|
|
18909
|
+
const sinkRec = graph.methodsByKey.get(sinkKey);
|
|
18910
|
+
if (sinkRec) {
|
|
18911
|
+
hops.push({
|
|
18912
|
+
file: sinkRec.file,
|
|
18913
|
+
method: `${sinkRec.className}.${sinkRec.method.name}`,
|
|
18914
|
+
line: finding.line,
|
|
18915
|
+
code: finding.message,
|
|
18916
|
+
variable: ""
|
|
18917
|
+
});
|
|
18918
|
+
}
|
|
18919
|
+
return hops;
|
|
18920
|
+
}
|
|
18921
|
+
function shouldDropUnderProfile(profile) {
|
|
18922
|
+
if (profile === "unknown")
|
|
18923
|
+
return true;
|
|
18924
|
+
if (profile.startsWith("library/"))
|
|
18925
|
+
return false;
|
|
18926
|
+
return true;
|
|
18927
|
+
}
|
|
18928
|
+
function makeProfileResolver(input) {
|
|
18929
|
+
if (input === undefined)
|
|
18930
|
+
return () => "unknown";
|
|
18931
|
+
if (typeof input === "string")
|
|
18932
|
+
return () => input;
|
|
18933
|
+
return (file) => input.get(file) ?? "unknown";
|
|
18934
|
+
}
|
|
18935
|
+
function normalizeDisabled(input) {
|
|
18936
|
+
if (!input)
|
|
18937
|
+
return new Set;
|
|
18938
|
+
if (input instanceof Set)
|
|
18939
|
+
return input;
|
|
18940
|
+
return new Set(input);
|
|
18941
|
+
}
|
|
18942
|
+
|
|
18463
18943
|
// ../circle-ir/dist/analysis/project-profile-transform.js
|
|
18464
18944
|
var DOWNGRADE_ELIGIBLE_RULE_IDS = new Set([
|
|
18465
18945
|
"code_injection",
|
|
@@ -30433,7 +30913,7 @@ var REFLECTION_SINK_METHODS = new Set([
|
|
|
30433
30913
|
"loadClass",
|
|
30434
30914
|
"defineClass"
|
|
30435
30915
|
]);
|
|
30436
|
-
var
|
|
30916
|
+
var TIER_1_CLASS_ANNOTATIONS2 = new Set([
|
|
30437
30917
|
"RestController",
|
|
30438
30918
|
"Controller",
|
|
30439
30919
|
"Service",
|
|
@@ -30444,7 +30924,7 @@ var TIER_1_CLASS_ANNOTATIONS = new Set([
|
|
|
30444
30924
|
"ServerEndpoint",
|
|
30445
30925
|
"FeignClient"
|
|
30446
30926
|
]);
|
|
30447
|
-
var
|
|
30927
|
+
var TIER_1_METHOD_ANNOTATIONS2 = new Set([
|
|
30448
30928
|
"RequestMapping",
|
|
30449
30929
|
"GetMapping",
|
|
30450
30930
|
"PostMapping",
|
|
@@ -30547,7 +31027,7 @@ class CliMainReflectionSuppressPass {
|
|
|
30547
31027
|
let hasFrameworkSignal = false;
|
|
30548
31028
|
for (const type of types) {
|
|
30549
31029
|
for (const ann of type.annotations) {
|
|
30550
|
-
if (
|
|
31030
|
+
if (TIER_1_CLASS_ANNOTATIONS2.has(normalizeAnnotation(ann))) {
|
|
30551
31031
|
hasFrameworkSignal = true;
|
|
30552
31032
|
break;
|
|
30553
31033
|
}
|
|
@@ -30568,7 +31048,7 @@ class CliMainReflectionSuppressPass {
|
|
|
30568
31048
|
break;
|
|
30569
31049
|
for (const method of type.methods) {
|
|
30570
31050
|
for (const ann of method.annotations) {
|
|
30571
|
-
if (
|
|
31051
|
+
if (TIER_1_METHOD_ANNOTATIONS2.has(normalizeAnnotation(ann))) {
|
|
30572
31052
|
hasFrameworkSignal = true;
|
|
30573
31053
|
break;
|
|
30574
31054
|
}
|
|
@@ -30609,6 +31089,62 @@ class CliMainReflectionSuppressPass {
|
|
|
30609
31089
|
}
|
|
30610
31090
|
}
|
|
30611
31091
|
|
|
31092
|
+
// ../circle-ir/dist/analysis/passes/library-profile-sink-gate-pass.js
|
|
31093
|
+
var DROPPED_SINK_TYPES = new Set([
|
|
31094
|
+
"log_injection"
|
|
31095
|
+
]);
|
|
31096
|
+
function isLibraryShape2(profile) {
|
|
31097
|
+
if (!profile || profile === "unknown")
|
|
31098
|
+
return false;
|
|
31099
|
+
return profile.startsWith("library/");
|
|
31100
|
+
}
|
|
31101
|
+
|
|
31102
|
+
class LibraryProfileSinkGatePass {
|
|
31103
|
+
name = "library-profile-sink-gate";
|
|
31104
|
+
category = "security";
|
|
31105
|
+
run(ctx) {
|
|
31106
|
+
const { graph } = ctx;
|
|
31107
|
+
const profile = graph.ir.meta.projectProfile;
|
|
31108
|
+
if (!isLibraryShape2(profile)) {
|
|
31109
|
+
return {
|
|
31110
|
+
profile,
|
|
31111
|
+
applied: false,
|
|
31112
|
+
dropped: 0,
|
|
31113
|
+
droppedByType: {}
|
|
31114
|
+
};
|
|
31115
|
+
}
|
|
31116
|
+
const sinks = ctx.hasResult("sink-filter") ? ctx.getResult("sink-filter").sinks : graph.ir.taint.sinks;
|
|
31117
|
+
if (sinks.length === 0) {
|
|
31118
|
+
return {
|
|
31119
|
+
profile,
|
|
31120
|
+
applied: true,
|
|
31121
|
+
dropped: 0,
|
|
31122
|
+
droppedByType: {}
|
|
31123
|
+
};
|
|
31124
|
+
}
|
|
31125
|
+
const droppedByType = {};
|
|
31126
|
+
const kept = [];
|
|
31127
|
+
for (const sink of sinks) {
|
|
31128
|
+
if (DROPPED_SINK_TYPES.has(sink.type)) {
|
|
31129
|
+
droppedByType[sink.type] = (droppedByType[sink.type] ?? 0) + 1;
|
|
31130
|
+
continue;
|
|
31131
|
+
}
|
|
31132
|
+
kept.push(sink);
|
|
31133
|
+
}
|
|
31134
|
+
const dropped = sinks.length - kept.length;
|
|
31135
|
+
if (dropped > 0) {
|
|
31136
|
+
sinks.length = 0;
|
|
31137
|
+
sinks.push(...kept);
|
|
31138
|
+
}
|
|
31139
|
+
return {
|
|
31140
|
+
profile,
|
|
31141
|
+
applied: true,
|
|
31142
|
+
dropped,
|
|
31143
|
+
droppedByType
|
|
31144
|
+
};
|
|
31145
|
+
}
|
|
31146
|
+
}
|
|
31147
|
+
|
|
30612
31148
|
// ../circle-ir/dist/analysis/passes/taint-propagation-pass.js
|
|
30613
31149
|
class TaintPropagationPass {
|
|
30614
31150
|
name = "taint-propagation";
|
|
@@ -31975,210 +32511,6 @@ function findTaintBridges2(result) {
|
|
|
31975
32511
|
return bridges;
|
|
31976
32512
|
}
|
|
31977
32513
|
|
|
31978
|
-
// ../circle-ir/dist/analysis/entry-point-detection.js
|
|
31979
|
-
var TIER_1_METHOD_ANNOTATIONS2 = new Set([
|
|
31980
|
-
"RequestMapping",
|
|
31981
|
-
"GetMapping",
|
|
31982
|
-
"PostMapping",
|
|
31983
|
-
"PutMapping",
|
|
31984
|
-
"DeleteMapping",
|
|
31985
|
-
"PatchMapping",
|
|
31986
|
-
"MessageMapping",
|
|
31987
|
-
"SubscribeMapping",
|
|
31988
|
-
"KafkaListener",
|
|
31989
|
-
"KafkaHandler",
|
|
31990
|
-
"RabbitListener",
|
|
31991
|
-
"RabbitHandler",
|
|
31992
|
-
"JmsListener",
|
|
31993
|
-
"StreamListener",
|
|
31994
|
-
"SqsListener",
|
|
31995
|
-
"SqsHandler",
|
|
31996
|
-
"EventListener",
|
|
31997
|
-
"Scheduled",
|
|
31998
|
-
"Path",
|
|
31999
|
-
"GET",
|
|
32000
|
-
"POST",
|
|
32001
|
-
"PUT",
|
|
32002
|
-
"DELETE",
|
|
32003
|
-
"PATCH",
|
|
32004
|
-
"HEAD",
|
|
32005
|
-
"OPTIONS",
|
|
32006
|
-
"DataBoundConstructor",
|
|
32007
|
-
"DataBoundSetter"
|
|
32008
|
-
]);
|
|
32009
|
-
var TIER_1_CLASS_ANNOTATIONS2 = new Set([
|
|
32010
|
-
"RestController",
|
|
32011
|
-
"Controller",
|
|
32012
|
-
"Service",
|
|
32013
|
-
"Repository",
|
|
32014
|
-
"Component",
|
|
32015
|
-
"Path",
|
|
32016
|
-
"WebServlet",
|
|
32017
|
-
"ServerEndpoint",
|
|
32018
|
-
"FeignClient"
|
|
32019
|
-
]);
|
|
32020
|
-
var TIER_1_BY_SUPERTYPE = new Map([
|
|
32021
|
-
["HttpServlet", new Set(["doGet", "doPost", "doPut", "doDelete", "doHead", "doOptions", "doTrace", "service"])],
|
|
32022
|
-
["GenericServlet", new Set(["service"])],
|
|
32023
|
-
["Filter", new Set(["doFilter"])],
|
|
32024
|
-
["HandlerInterceptor", new Set(["preHandle", "postHandle", "afterCompletion"])],
|
|
32025
|
-
["AsyncHandlerInterceptor", new Set(["preHandle", "postHandle", "afterCompletion", "afterConcurrentHandlingStarted"])],
|
|
32026
|
-
["CommandLineRunner", new Set(["run"])],
|
|
32027
|
-
["ApplicationRunner", new Set(["run"])],
|
|
32028
|
-
["SimpleChannelInboundHandler", new Set(["channelRead0", "messageReceived"])],
|
|
32029
|
-
["ChannelInboundHandler", new Set(["channelRead", "channelReadComplete"])],
|
|
32030
|
-
["ChannelInboundHandlerAdapter", new Set(["channelRead", "channelReadComplete"])],
|
|
32031
|
-
["ChannelDuplexHandler", new Set(["channelRead", "channelReadComplete"])],
|
|
32032
|
-
["NettyRequestProcessor", new Set(["process"])],
|
|
32033
|
-
["Converter", new Set(["marshal", "unmarshal"])],
|
|
32034
|
-
["SingleValueConverter", new Set(["fromString", "toString"])],
|
|
32035
|
-
["ConverterMatcher", new Set(["marshal", "unmarshal"])],
|
|
32036
|
-
["AbstractReflectionConverter", new Set(["marshal", "unmarshal", "doMarshal", "doUnmarshal"])],
|
|
32037
|
-
["AbstractSingleValueConverter", new Set(["fromString", "toString"])],
|
|
32038
|
-
["AbstractCollectionConverter", new Set(["marshal", "unmarshal"])]
|
|
32039
|
-
]);
|
|
32040
|
-
var TIER_3_CLASS_SUFFIXES = [
|
|
32041
|
-
"Util",
|
|
32042
|
-
"Utils",
|
|
32043
|
-
"Helper",
|
|
32044
|
-
"Helpers"
|
|
32045
|
-
];
|
|
32046
|
-
var TIER_3_PACKAGE_FRAGMENTS = [
|
|
32047
|
-
".template.",
|
|
32048
|
-
".templates.",
|
|
32049
|
-
".engine.",
|
|
32050
|
-
".engines."
|
|
32051
|
-
];
|
|
32052
|
-
var TIER_3_JDK_FACADE_INTERFACES = new Set([
|
|
32053
|
-
"Collection",
|
|
32054
|
-
"List",
|
|
32055
|
-
"Set",
|
|
32056
|
-
"Map",
|
|
32057
|
-
"Queue",
|
|
32058
|
-
"Deque",
|
|
32059
|
-
"SortedSet",
|
|
32060
|
-
"SortedMap",
|
|
32061
|
-
"NavigableSet",
|
|
32062
|
-
"NavigableMap",
|
|
32063
|
-
"Iterator",
|
|
32064
|
-
"Iterable",
|
|
32065
|
-
"ListIterator",
|
|
32066
|
-
"Comparator",
|
|
32067
|
-
"Comparable",
|
|
32068
|
-
"Serializable",
|
|
32069
|
-
"Externalizable",
|
|
32070
|
-
"Cloneable"
|
|
32071
|
-
]);
|
|
32072
|
-
function classNameLooksLikeUtility(name2) {
|
|
32073
|
-
if (!name2)
|
|
32074
|
-
return false;
|
|
32075
|
-
for (const suffix of TIER_3_CLASS_SUFFIXES) {
|
|
32076
|
-
if (name2.length > suffix.length && name2.endsWith(suffix))
|
|
32077
|
-
return true;
|
|
32078
|
-
}
|
|
32079
|
-
return false;
|
|
32080
|
-
}
|
|
32081
|
-
function packageLooksLikeTemplateOrEngine(pkg) {
|
|
32082
|
-
if (!pkg)
|
|
32083
|
-
return false;
|
|
32084
|
-
const padded = `.${pkg}.`;
|
|
32085
|
-
for (const frag of TIER_3_PACKAGE_FRAGMENTS) {
|
|
32086
|
-
if (padded.includes(frag))
|
|
32087
|
-
return true;
|
|
32088
|
-
}
|
|
32089
|
-
return false;
|
|
32090
|
-
}
|
|
32091
|
-
function implementsJdkFacade(t) {
|
|
32092
|
-
if (!t)
|
|
32093
|
-
return false;
|
|
32094
|
-
for (const impl of t.implements ?? []) {
|
|
32095
|
-
if (TIER_3_JDK_FACADE_INTERFACES.has(simpleTypeName(impl)))
|
|
32096
|
-
return true;
|
|
32097
|
-
}
|
|
32098
|
-
return false;
|
|
32099
|
-
}
|
|
32100
|
-
function classShapeIsLibraryFacade(enclosingType) {
|
|
32101
|
-
if (!enclosingType)
|
|
32102
|
-
return false;
|
|
32103
|
-
if (classNameLooksLikeUtility(enclosingType.name))
|
|
32104
|
-
return true;
|
|
32105
|
-
if (packageLooksLikeTemplateOrEngine(enclosingType.package))
|
|
32106
|
-
return true;
|
|
32107
|
-
if (implementsJdkFacade(enclosingType))
|
|
32108
|
-
return true;
|
|
32109
|
-
return false;
|
|
32110
|
-
}
|
|
32111
|
-
function annotationsInclude(annotations, targets) {
|
|
32112
|
-
if (!annotations || annotations.length === 0)
|
|
32113
|
-
return false;
|
|
32114
|
-
for (const raw of annotations) {
|
|
32115
|
-
const simple = raw.replace(/^@/, "").replace(/[<(].*$/, "").trim();
|
|
32116
|
-
if (targets.has(simple))
|
|
32117
|
-
return true;
|
|
32118
|
-
}
|
|
32119
|
-
return false;
|
|
32120
|
-
}
|
|
32121
|
-
function simpleTypeName(ref) {
|
|
32122
|
-
return ref.replace(/<.*$/, "").trim();
|
|
32123
|
-
}
|
|
32124
|
-
function looksLikeMainMethod(method) {
|
|
32125
|
-
if (method.name !== "main")
|
|
32126
|
-
return false;
|
|
32127
|
-
const params = method.parameters ?? [];
|
|
32128
|
-
if (params.length !== 1)
|
|
32129
|
-
return false;
|
|
32130
|
-
const t = (params[0].type ?? "").replace(/\s+/g, "");
|
|
32131
|
-
return t === "String[]" || t === "String..." || t === "java.lang.String[]";
|
|
32132
|
-
}
|
|
32133
|
-
function methodIsSupertypeLifecycleEntryPoint(method, enclosingType) {
|
|
32134
|
-
if (!method.name)
|
|
32135
|
-
return false;
|
|
32136
|
-
if (!enclosingType)
|
|
32137
|
-
return false;
|
|
32138
|
-
const candidates = [];
|
|
32139
|
-
if (enclosingType.extends)
|
|
32140
|
-
candidates.push(simpleTypeName(enclosingType.extends));
|
|
32141
|
-
for (const i2 of enclosingType.implements ?? [])
|
|
32142
|
-
candidates.push(simpleTypeName(i2));
|
|
32143
|
-
for (const supertype of candidates) {
|
|
32144
|
-
const lifecycleMethods = TIER_1_BY_SUPERTYPE.get(supertype);
|
|
32145
|
-
if (lifecycleMethods?.has(method.name))
|
|
32146
|
-
return true;
|
|
32147
|
-
}
|
|
32148
|
-
return false;
|
|
32149
|
-
}
|
|
32150
|
-
function classifyEntryPointTier(method, enclosingType, ctx) {
|
|
32151
|
-
const language = (ctx.language ?? "").toLowerCase();
|
|
32152
|
-
if (language !== "java")
|
|
32153
|
-
return "TIER_UNKNOWN";
|
|
32154
|
-
if (!method)
|
|
32155
|
-
return "TIER_UNKNOWN";
|
|
32156
|
-
if (classShapeIsLibraryFacade(enclosingType)) {
|
|
32157
|
-
return "TIER_3_LIBRARY_API";
|
|
32158
|
-
}
|
|
32159
|
-
if (annotationsInclude(method.annotations, TIER_1_METHOD_ANNOTATIONS2)) {
|
|
32160
|
-
return "TIER_1_ENTRY_POINT";
|
|
32161
|
-
}
|
|
32162
|
-
if (enclosingType && annotationsInclude(enclosingType.annotations, TIER_1_CLASS_ANNOTATIONS2)) {
|
|
32163
|
-
return "TIER_1_ENTRY_POINT";
|
|
32164
|
-
}
|
|
32165
|
-
if (methodIsSupertypeLifecycleEntryPoint(method, enclosingType)) {
|
|
32166
|
-
return "TIER_1_ENTRY_POINT";
|
|
32167
|
-
}
|
|
32168
|
-
if (looksLikeMainMethod(method)) {
|
|
32169
|
-
return "TIER_1_ENTRY_POINT";
|
|
32170
|
-
}
|
|
32171
|
-
return "TIER_3_LIBRARY_API";
|
|
32172
|
-
}
|
|
32173
|
-
function shouldGateInterproceduralParam(sourceType, enclosingMethod, enclosingType, ctx) {
|
|
32174
|
-
if (sourceType !== "interprocedural_param")
|
|
32175
|
-
return false;
|
|
32176
|
-
if (!enclosingMethod)
|
|
32177
|
-
return false;
|
|
32178
|
-
const tier = classifyEntryPointTier(enclosingMethod, enclosingType, ctx);
|
|
32179
|
-
return tier === "TIER_3_LIBRARY_API";
|
|
32180
|
-
}
|
|
32181
|
-
|
|
32182
32514
|
// ../circle-ir/dist/analysis/passes/interprocedural-pass.js
|
|
32183
32515
|
class InterproceduralPass {
|
|
32184
32516
|
name = "interprocedural";
|
|
@@ -41619,7 +41951,7 @@ function getNodeTypesForLanguage(language) {
|
|
|
41619
41951
|
]);
|
|
41620
41952
|
}
|
|
41621
41953
|
}
|
|
41622
|
-
function
|
|
41954
|
+
function makeProfileResolver2(p) {
|
|
41623
41955
|
if (p === undefined)
|
|
41624
41956
|
return () => "unknown";
|
|
41625
41957
|
if (typeof p === "string")
|
|
@@ -41688,7 +42020,7 @@ async function analyze(code, filePath, language, options = {}) {
|
|
|
41688
42020
|
const nodeCache = collectAllNodes(tree.rootNode, getNodeTypesForLanguage(language));
|
|
41689
42021
|
const meta = extractMeta(code, tree, filePath, language);
|
|
41690
42022
|
if (options.projectProfile !== undefined) {
|
|
41691
|
-
meta.projectProfile =
|
|
42023
|
+
meta.projectProfile = makeProfileResolver2(options.projectProfile)(filePath);
|
|
41692
42024
|
}
|
|
41693
42025
|
const types = extractTypes(tree, nodeCache, language);
|
|
41694
42026
|
const calls = extractCalls(tree, nodeCache, language);
|
|
@@ -41725,6 +42057,8 @@ async function analyze(code, filePath, language, options = {}) {
|
|
|
41725
42057
|
pipeline.add(new SinkSemanticsPass);
|
|
41726
42058
|
if (!disabledPasses.has("cli-main-reflection-suppress"))
|
|
41727
42059
|
pipeline.add(new CliMainReflectionSuppressPass);
|
|
42060
|
+
if (!disabledPasses.has("library-profile-sink-gate"))
|
|
42061
|
+
pipeline.add(new LibraryProfileSinkGatePass);
|
|
41728
42062
|
pipeline.add(new TaintPropagationPass);
|
|
41729
42063
|
pipeline.add(new InterproceduralPass({
|
|
41730
42064
|
enableEntryPointGate: options.enableEntryPointGate ?? true
|
|
@@ -41877,7 +42211,7 @@ async function analyze(code, filePath, language, options = {}) {
|
|
|
41877
42211
|
emitFindingsInstrumentation(filePath, findings, taint);
|
|
41878
42212
|
const verifiedFindings = applyConfidenceFilter(findings, options.includeSpeculative === true);
|
|
41879
42213
|
const downgradedFindings = applyLibraryApiSurfaceDowngrade(verifiedFindings);
|
|
41880
|
-
const profiledFindings = applyProjectProfileTransform(downgradedFindings,
|
|
42214
|
+
const profiledFindings = applyProjectProfileTransform(downgradedFindings, makeProfileResolver2(options.projectProfile));
|
|
41881
42215
|
const cappedFindings = applyPerFileFindingCap(filePath, profiledFindings, options.perFileFindingCap ?? DEFAULT_PER_FILE_FINDING_CAP);
|
|
41882
42216
|
return {
|
|
41883
42217
|
meta,
|
|
@@ -42001,6 +42335,10 @@ async function analyzeProject(files, options = {}) {
|
|
|
42001
42335
|
fa.analysis.findings = [...fa.analysis.findings ?? [], finding];
|
|
42002
42336
|
}
|
|
42003
42337
|
}
|
|
42338
|
+
applyRequireEntryPath(fileAnalyses, {
|
|
42339
|
+
projectProfile: options.projectProfile,
|
|
42340
|
+
disabledPasses: options.disabledPasses
|
|
42341
|
+
});
|
|
42004
42342
|
const filePaths = files.map((f) => f.filePath);
|
|
42005
42343
|
const totalLoc = fileAnalyses.reduce((sum, f) => sum + (f.analysis.meta.loc ?? 0), 0);
|
|
42006
42344
|
const meta = {
|
|
@@ -42655,7 +42993,7 @@ var colors = {
|
|
|
42655
42993
|
};
|
|
42656
42994
|
|
|
42657
42995
|
// src/version.ts
|
|
42658
|
-
var version = "3.
|
|
42996
|
+
var version = "3.153.0";
|
|
42659
42997
|
|
|
42660
42998
|
// src/formatters.ts
|
|
42661
42999
|
var LIBRARY_API_SURFACE_TAG2 = "library-api-surface:caller-responsibility";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cognium-dev",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.153.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.153.0"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@types/node": "^25.5.0",
|