cognium-dev 3.140.0 → 3.145.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 +442 -26
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -5668,6 +5668,12 @@ function resolveReceiverType(receiver, context) {
|
|
|
5668
5668
|
}
|
|
5669
5669
|
if (receiver === "super")
|
|
5670
5670
|
return { simpleName: null, fqn: null };
|
|
5671
|
+
const ctorMatch = receiver.match(/^new\s+([A-Za-z_$][\w$.]*)\s*[<(]/);
|
|
5672
|
+
if (ctorMatch) {
|
|
5673
|
+
const ctorClass = ctorMatch[1];
|
|
5674
|
+
const simple = ctorClass.includes(".") ? ctorClass.substring(ctorClass.lastIndexOf(".") + 1) : ctorClass;
|
|
5675
|
+
return resolveFqn(simple, context);
|
|
5676
|
+
}
|
|
5671
5677
|
const declaredType = context.localVarTypes.get(receiver) ?? context.paramTypes.get(receiver) ?? context.fieldTypes.get(receiver);
|
|
5672
5678
|
if (declaredType) {
|
|
5673
5679
|
return resolveFqn(stripGenerics(declaredType), context);
|
|
@@ -5678,19 +5684,48 @@ function resolveReceiverType(receiver, context) {
|
|
|
5678
5684
|
return resolveFqn(simple, context);
|
|
5679
5685
|
}
|
|
5680
5686
|
}
|
|
5681
|
-
const
|
|
5682
|
-
if (
|
|
5683
|
-
const
|
|
5684
|
-
|
|
5685
|
-
|
|
5686
|
-
if (varType) {
|
|
5687
|
-
const returnType = JAVA_CHAINED_FACTORY_RETURN_TYPES[stripGenerics(varType)]?.[methodName];
|
|
5687
|
+
const chain = splitChainedReceiver(receiver);
|
|
5688
|
+
if (chain) {
|
|
5689
|
+
const prefixType = resolveReceiverType(chain.prefix, context);
|
|
5690
|
+
if (prefixType.simpleName) {
|
|
5691
|
+
const returnType = JAVA_CHAINED_FACTORY_RETURN_TYPES[prefixType.simpleName]?.[chain.methodName];
|
|
5688
5692
|
if (returnType)
|
|
5689
5693
|
return resolveFqn(returnType, context);
|
|
5690
5694
|
}
|
|
5691
5695
|
}
|
|
5692
5696
|
return { simpleName: null, fqn: null };
|
|
5693
5697
|
}
|
|
5698
|
+
function splitChainedReceiver(receiver) {
|
|
5699
|
+
if (!receiver.endsWith(")"))
|
|
5700
|
+
return null;
|
|
5701
|
+
let depth = 0;
|
|
5702
|
+
let openIdx = -1;
|
|
5703
|
+
for (let i2 = receiver.length - 1;i2 >= 0; i2--) {
|
|
5704
|
+
const c = receiver[i2];
|
|
5705
|
+
if (c === ")")
|
|
5706
|
+
depth++;
|
|
5707
|
+
else if (c === "(") {
|
|
5708
|
+
depth--;
|
|
5709
|
+
if (depth === 0) {
|
|
5710
|
+
openIdx = i2;
|
|
5711
|
+
break;
|
|
5712
|
+
}
|
|
5713
|
+
}
|
|
5714
|
+
}
|
|
5715
|
+
if (openIdx <= 0)
|
|
5716
|
+
return null;
|
|
5717
|
+
const beforeParen = receiver.substring(0, openIdx);
|
|
5718
|
+
const dotIdx = beforeParen.lastIndexOf(".");
|
|
5719
|
+
if (dotIdx <= 0)
|
|
5720
|
+
return null;
|
|
5721
|
+
const methodName = beforeParen.substring(dotIdx + 1).trim();
|
|
5722
|
+
if (!/^[A-Za-z_$][\w$]*$/.test(methodName))
|
|
5723
|
+
return null;
|
|
5724
|
+
const prefix = beforeParen.substring(0, dotIdx).trim();
|
|
5725
|
+
if (!prefix)
|
|
5726
|
+
return null;
|
|
5727
|
+
return { prefix, methodName };
|
|
5728
|
+
}
|
|
5694
5729
|
var JAVA_CHAINED_FACTORY_RETURN_TYPES = {
|
|
5695
5730
|
HttpServletRequest: {
|
|
5696
5731
|
getSession: "HttpSession",
|
|
@@ -5702,6 +5737,31 @@ var JAVA_CHAINED_FACTORY_RETURN_TYPES = {
|
|
|
5702
5737
|
},
|
|
5703
5738
|
ServletContext: {
|
|
5704
5739
|
getRequestDispatcher: "RequestDispatcher"
|
|
5740
|
+
},
|
|
5741
|
+
DocumentBuilderFactory: {
|
|
5742
|
+
newInstance: "DocumentBuilderFactory",
|
|
5743
|
+
newDocumentBuilder: "DocumentBuilder"
|
|
5744
|
+
},
|
|
5745
|
+
SAXParserFactory: {
|
|
5746
|
+
newInstance: "SAXParserFactory",
|
|
5747
|
+
newSAXParser: "SAXParser"
|
|
5748
|
+
},
|
|
5749
|
+
SAXParser: {
|
|
5750
|
+
getXMLReader: "XMLReader"
|
|
5751
|
+
},
|
|
5752
|
+
XPathFactory: {
|
|
5753
|
+
newInstance: "XPathFactory",
|
|
5754
|
+
newXPath: "XPath"
|
|
5755
|
+
},
|
|
5756
|
+
TransformerFactory: {
|
|
5757
|
+
newInstance: "TransformerFactory",
|
|
5758
|
+
newTransformer: "Transformer"
|
|
5759
|
+
},
|
|
5760
|
+
XMLInputFactory: {
|
|
5761
|
+
newInstance: "XMLInputFactory",
|
|
5762
|
+
newFactory: "XMLInputFactory",
|
|
5763
|
+
createXMLStreamReader: "XMLStreamReader",
|
|
5764
|
+
createXMLEventReader: "XMLEventReader"
|
|
5705
5765
|
}
|
|
5706
5766
|
};
|
|
5707
5767
|
function resolveFqn(simpleName, context) {
|
|
@@ -10678,6 +10738,8 @@ var DEFAULT_SINKS = [
|
|
|
10678
10738
|
{ method: "sendError", class: "HttpServletResponse", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [1] },
|
|
10679
10739
|
{ method: "setHeader", class: "HttpServletResponse", type: "crlf", cwe: "CWE-113", severity: "medium", arg_positions: [1] },
|
|
10680
10740
|
{ method: "addHeader", class: "HttpServletResponse", type: "crlf", cwe: "CWE-113", severity: "medium", arg_positions: [1] },
|
|
10741
|
+
{ method: "Cookie", class: "constructor", type: "crlf", cwe: "CWE-113", severity: "medium", arg_positions: [0, 1] },
|
|
10742
|
+
{ method: "addCookie", class: "HttpServletResponse", type: "crlf", cwe: "CWE-113", severity: "medium", arg_positions: [0] },
|
|
10681
10743
|
{ method: "setContentType", class: "HttpServletResponse", type: "xss", cwe: "CWE-79", severity: "medium", arg_positions: [0] },
|
|
10682
10744
|
{ method: "setAttribute", class: "PageContext", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [1] },
|
|
10683
10745
|
{ method: "addAttribute", class: "Model", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [1] },
|
|
@@ -11614,11 +11676,62 @@ var DEFAULT_SANITIZERS = [
|
|
|
11614
11676
|
{ method: "UUID", class: "uuid", removes: ["sql_injection", "command_injection", "path_traversal", "code_injection"] },
|
|
11615
11677
|
{ method: "Decimal", class: "decimal", removes: ["sql_injection", "command_injection", "path_traversal", "code_injection"] }
|
|
11616
11678
|
];
|
|
11679
|
+
var DEFAULT_SINK_SEMANTICS = [
|
|
11680
|
+
{
|
|
11681
|
+
signature: "Jedis#executeCommand",
|
|
11682
|
+
real_class: "db_protocol",
|
|
11683
|
+
overrides: ["command_injection", "code_injection"],
|
|
11684
|
+
note: "Redis wire-protocol serialization, not OS exec"
|
|
11685
|
+
},
|
|
11686
|
+
{
|
|
11687
|
+
signature: "Connection#executeCommand",
|
|
11688
|
+
real_class: "db_protocol",
|
|
11689
|
+
overrides: ["command_injection", "code_injection"],
|
|
11690
|
+
note: "Jedis abstract Connection base"
|
|
11691
|
+
},
|
|
11692
|
+
{
|
|
11693
|
+
signature: "JedisCluster#executeCommand",
|
|
11694
|
+
real_class: "db_protocol",
|
|
11695
|
+
overrides: ["command_injection", "code_injection"],
|
|
11696
|
+
note: "Jedis cluster client"
|
|
11697
|
+
},
|
|
11698
|
+
{
|
|
11699
|
+
signature: "Func1#exec",
|
|
11700
|
+
real_class: "functional_dispatch",
|
|
11701
|
+
overrides: ["command_injection", "code_injection"],
|
|
11702
|
+
note: "RxJava functional dispatch, not OS exec"
|
|
11703
|
+
},
|
|
11704
|
+
{
|
|
11705
|
+
signature: "Action0#call",
|
|
11706
|
+
real_class: "functional_dispatch",
|
|
11707
|
+
overrides: ["command_injection"],
|
|
11708
|
+
note: "RxJava Action0 dispatch"
|
|
11709
|
+
},
|
|
11710
|
+
{
|
|
11711
|
+
signature: "Action1#call",
|
|
11712
|
+
real_class: "functional_dispatch",
|
|
11713
|
+
overrides: ["command_injection"],
|
|
11714
|
+
note: "RxJava Action1 dispatch"
|
|
11715
|
+
},
|
|
11716
|
+
{
|
|
11717
|
+
signature: "Unsafe#defineAnonymousClass",
|
|
11718
|
+
real_class: "jdk_internal",
|
|
11719
|
+
overrides: ["code_injection"],
|
|
11720
|
+
note: "sun.misc.Unsafe JDK-internal reflective bridge"
|
|
11721
|
+
},
|
|
11722
|
+
{
|
|
11723
|
+
signature: "MethodHandle#invokeExact",
|
|
11724
|
+
real_class: "jdk_internal",
|
|
11725
|
+
overrides: ["code_injection"],
|
|
11726
|
+
note: "java.lang.invoke.MethodHandle — JDK-internal"
|
|
11727
|
+
}
|
|
11728
|
+
];
|
|
11617
11729
|
function getDefaultConfig() {
|
|
11618
11730
|
return {
|
|
11619
11731
|
sources: DEFAULT_SOURCES,
|
|
11620
11732
|
sinks: DEFAULT_SINKS,
|
|
11621
|
-
sanitizers: DEFAULT_SANITIZERS
|
|
11733
|
+
sanitizers: DEFAULT_SANITIZERS,
|
|
11734
|
+
sinkSemantics: DEFAULT_SINK_SEMANTICS
|
|
11622
11735
|
};
|
|
11623
11736
|
}
|
|
11624
11737
|
var DEFAULT_HEADER_RULES = [
|
|
@@ -11947,7 +12060,8 @@ function findSources(calls, types, patterns, sourceLines, language) {
|
|
|
11947
12060
|
severity: "medium",
|
|
11948
12061
|
line: paramLine,
|
|
11949
12062
|
confidence: param.type ? 0.7 : 0.5,
|
|
11950
|
-
in_method: method.name
|
|
12063
|
+
in_method: method.name,
|
|
12064
|
+
...language === "java" ? { variable: param.name } : {}
|
|
11951
12065
|
});
|
|
11952
12066
|
}
|
|
11953
12067
|
}
|
|
@@ -12445,7 +12559,19 @@ function isSafeGoJsonUnmarshalCall(call, pattern, language, sourceLines) {
|
|
|
12445
12559
|
return false;
|
|
12446
12560
|
}
|
|
12447
12561
|
var TEMPLATE_LITERAL_RECEIVER_RE = /^Template\(\s*(?:"[^"\\]*"|'[^'\\]*')\s*\)$/;
|
|
12448
|
-
|
|
12562
|
+
var JINJA_AUTOESCAPE_TRUE_RE = /\bEnvironment\s*\([^)]*\bautoescape\s*=\s*True\b/;
|
|
12563
|
+
var JINJA_SELECT_AUTOESCAPE_RE = /\bEnvironment\s*\([^)]*\bautoescape\s*=\s*select_autoescape\s*\(/;
|
|
12564
|
+
var JINJA_AUTOESCAPE_FALSE_RE = /\bEnvironment\s*\([^)]*\bautoescape\s*=\s*False\b/;
|
|
12565
|
+
function fileHasSafeJinjaEnvironment(sourceLines) {
|
|
12566
|
+
if (!sourceLines || sourceLines.length === 0)
|
|
12567
|
+
return false;
|
|
12568
|
+
const text = sourceLines.join(`
|
|
12569
|
+
`);
|
|
12570
|
+
if (JINJA_AUTOESCAPE_FALSE_RE.test(text))
|
|
12571
|
+
return false;
|
|
12572
|
+
return JINJA_AUTOESCAPE_TRUE_RE.test(text) || JINJA_SELECT_AUTOESCAPE_RE.test(text);
|
|
12573
|
+
}
|
|
12574
|
+
function isSafeJinjaRenderCall(call, pattern, language, sourceLines) {
|
|
12449
12575
|
if (language !== "python")
|
|
12450
12576
|
return false;
|
|
12451
12577
|
if (pattern.type !== "xss" && pattern.type !== "code_injection")
|
|
@@ -12461,7 +12587,10 @@ function isSafeJinjaRenderCall(call, pattern, language) {
|
|
|
12461
12587
|
}
|
|
12462
12588
|
if (method === "render") {
|
|
12463
12589
|
const receiver = (call.receiver ?? "").trim();
|
|
12464
|
-
|
|
12590
|
+
if (TEMPLATE_LITERAL_RECEIVER_RE.test(receiver))
|
|
12591
|
+
return true;
|
|
12592
|
+
if (fileHasSafeJinjaEnvironment(sourceLines))
|
|
12593
|
+
return true;
|
|
12465
12594
|
}
|
|
12466
12595
|
return false;
|
|
12467
12596
|
}
|
|
@@ -12509,7 +12638,7 @@ function findSinks(calls, patterns, typeHierarchy, language, sourceLines) {
|
|
|
12509
12638
|
if (isSafeGoJsonUnmarshalCall(call, pattern, language, sourceLines)) {
|
|
12510
12639
|
continue;
|
|
12511
12640
|
}
|
|
12512
|
-
if (isSafeJinjaRenderCall(call, pattern, language)) {
|
|
12641
|
+
if (isSafeJinjaRenderCall(call, pattern, language, sourceLines)) {
|
|
12513
12642
|
continue;
|
|
12514
12643
|
}
|
|
12515
12644
|
const location = formatCallLocation(call);
|
|
@@ -12517,6 +12646,8 @@ function findSinks(calls, patterns, typeHierarchy, language, sourceLines) {
|
|
|
12517
12646
|
const confidence = calculateSinkConfidence(call, pattern);
|
|
12518
12647
|
const existing = sinkMap.get(key);
|
|
12519
12648
|
if (!existing || confidence > existing.confidence) {
|
|
12649
|
+
const receiverType = call.receiver_type;
|
|
12650
|
+
const simpleClass = receiverType ? receiverType.split(".").pop() || undefined : undefined;
|
|
12520
12651
|
sinkMap.set(key, {
|
|
12521
12652
|
type: pattern.type,
|
|
12522
12653
|
cwe: pattern.cwe,
|
|
@@ -12524,7 +12655,8 @@ function findSinks(calls, patterns, typeHierarchy, language, sourceLines) {
|
|
|
12524
12655
|
line: call.location.line,
|
|
12525
12656
|
confidence,
|
|
12526
12657
|
method: call.method_name,
|
|
12527
|
-
argPositions: pattern.arg_positions
|
|
12658
|
+
argPositions: pattern.arg_positions,
|
|
12659
|
+
class: simpleClass
|
|
12528
12660
|
});
|
|
12529
12661
|
}
|
|
12530
12662
|
}
|
|
@@ -13424,12 +13556,12 @@ function formatCallCode(call) {
|
|
|
13424
13556
|
// ../circle-ir/dist/analysis/findings.js
|
|
13425
13557
|
function canSourceReachSink(sourceType, sinkType) {
|
|
13426
13558
|
const sourceToSinkMapping = {
|
|
13427
|
-
http_param: ["sql_injection", "command_injection", "path_traversal", "xss", "xpath_injection", "ldap_injection", "ssrf", "mybatis_mapper_call", "code_injection", "crlf", "mass_assignment", "open_redirect", "trust_boundary"],
|
|
13559
|
+
http_param: ["sql_injection", "command_injection", "path_traversal", "xss", "xpath_injection", "ldap_injection", "ssrf", "mybatis_mapper_call", "code_injection", "crlf", "mass_assignment", "open_redirect", "trust_boundary", "deserialization"],
|
|
13428
13560
|
http_body: ["sql_injection", "command_injection", "deserialization", "xxe", "xss", "code_injection", "mybatis_mapper_call", "crlf", "mass_assignment", "open_redirect", "trust_boundary"],
|
|
13429
13561
|
http_header: ["sql_injection", "xss", "ssrf", "mybatis_mapper_call", "code_injection", "crlf", "open_redirect", "trust_boundary"],
|
|
13430
13562
|
http_cookie: ["sql_injection", "xss", "mybatis_mapper_call", "code_injection", "crlf", "open_redirect", "trust_boundary"],
|
|
13431
13563
|
http_path: ["path_traversal", "sql_injection", "ssrf", "mybatis_mapper_call", "open_redirect", "trust_boundary"],
|
|
13432
|
-
http_query: ["sql_injection", "command_injection", "xss", "ssrf", "mybatis_mapper_call", "code_injection", "crlf", "mass_assignment", "open_redirect", "trust_boundary"],
|
|
13564
|
+
http_query: ["sql_injection", "command_injection", "xss", "ssrf", "mybatis_mapper_call", "code_injection", "crlf", "mass_assignment", "open_redirect", "trust_boundary", "deserialization"],
|
|
13433
13565
|
io_input: ["command_injection", "path_traversal", "deserialization", "xxe", "code_injection", "xss", "ssrf"],
|
|
13434
13566
|
env_input: ["command_injection", "path_traversal"],
|
|
13435
13567
|
db_input: ["xss", "sql_injection"],
|
|
@@ -13442,6 +13574,15 @@ function canSourceReachSink(sourceType, sinkType) {
|
|
|
13442
13574
|
const validSinks = sourceToSinkMapping[sourceType];
|
|
13443
13575
|
return validSinks ? validSinks.includes(sinkType) : false;
|
|
13444
13576
|
}
|
|
13577
|
+
function sourceSemanticsAllowed(source, sinkType) {
|
|
13578
|
+
if (source.constant === true) {
|
|
13579
|
+
return false;
|
|
13580
|
+
}
|
|
13581
|
+
if (source.spi === true) {
|
|
13582
|
+
return sinkType === "code_injection";
|
|
13583
|
+
}
|
|
13584
|
+
return true;
|
|
13585
|
+
}
|
|
13445
13586
|
|
|
13446
13587
|
// ../circle-ir/dist/analysis/findings-instrumentation.js
|
|
13447
13588
|
var instrumentEnabled = false;
|
|
@@ -23548,6 +23689,68 @@ function buildRustTaintedVars(sourceCode, seedVars) {
|
|
|
23548
23689
|
}
|
|
23549
23690
|
return derived;
|
|
23550
23691
|
}
|
|
23692
|
+
function buildJavaTaintedVars(sourceCode, seedVars) {
|
|
23693
|
+
const derived = new Map;
|
|
23694
|
+
const knownTainted = new Set(seedVars);
|
|
23695
|
+
const lines = sourceCode.split(`
|
|
23696
|
+
`);
|
|
23697
|
+
const declRe = /^\s*(?:public|private|protected|static|final|volatile|transient|\s)*\s*(?:[A-Za-z_][\w.]*(?:\s*<[^>]*>)?(?:\s*\[\s*\])*)\s+([A-Za-z_]\w*)\s*=\s*(.+?);\s*$/;
|
|
23698
|
+
const assignRe = /^\s*([A-Za-z_]\w*)\s*=\s*(.+?);\s*$/;
|
|
23699
|
+
const JAVA_KEYWORDS = new Set([
|
|
23700
|
+
"if",
|
|
23701
|
+
"else",
|
|
23702
|
+
"while",
|
|
23703
|
+
"for",
|
|
23704
|
+
"do",
|
|
23705
|
+
"switch",
|
|
23706
|
+
"case",
|
|
23707
|
+
"return",
|
|
23708
|
+
"throw",
|
|
23709
|
+
"try",
|
|
23710
|
+
"catch",
|
|
23711
|
+
"finally",
|
|
23712
|
+
"new",
|
|
23713
|
+
"this",
|
|
23714
|
+
"super",
|
|
23715
|
+
"break",
|
|
23716
|
+
"continue",
|
|
23717
|
+
"default",
|
|
23718
|
+
"class",
|
|
23719
|
+
"interface",
|
|
23720
|
+
"enum"
|
|
23721
|
+
]);
|
|
23722
|
+
let changed = true;
|
|
23723
|
+
let guard = 0;
|
|
23724
|
+
while (changed && guard < lines.length + 2) {
|
|
23725
|
+
changed = false;
|
|
23726
|
+
guard++;
|
|
23727
|
+
for (let i2 = 0;i2 < lines.length; i2++) {
|
|
23728
|
+
const line = lines[i2];
|
|
23729
|
+
const trimmed = line.trimStart();
|
|
23730
|
+
if (trimmed.startsWith("//") || trimmed.startsWith("*"))
|
|
23731
|
+
continue;
|
|
23732
|
+
const declMatch = declRe.exec(line);
|
|
23733
|
+
const assignMatch = !declMatch ? assignRe.exec(line) : null;
|
|
23734
|
+
const m = declMatch ?? assignMatch;
|
|
23735
|
+
if (!m)
|
|
23736
|
+
continue;
|
|
23737
|
+
const lhs = m[1];
|
|
23738
|
+
const rhs = m[2];
|
|
23739
|
+
if (JAVA_KEYWORDS.has(lhs))
|
|
23740
|
+
continue;
|
|
23741
|
+
if (knownTainted.has(lhs))
|
|
23742
|
+
continue;
|
|
23743
|
+
const escaped = (v) => v.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
23744
|
+
const ref = [...knownTainted].some((v) => new RegExp(`(?<![\\p{L}\\p{N}_])${escaped(v)}(?![\\p{L}\\p{N}_])`, "u").test(rhs));
|
|
23745
|
+
if (ref) {
|
|
23746
|
+
derived.set(lhs, i2 + 1);
|
|
23747
|
+
knownTainted.add(lhs);
|
|
23748
|
+
changed = true;
|
|
23749
|
+
}
|
|
23750
|
+
}
|
|
23751
|
+
}
|
|
23752
|
+
return derived;
|
|
23753
|
+
}
|
|
23551
23754
|
var BASH_POSITIONAL_PARAMS = new Set(["1", "2", "3", "4", "5", "6", "7", "8", "9", "@", "*"]);
|
|
23552
23755
|
var BASH_UNTRUSTED_ENV_PATTERNS = [
|
|
23553
23756
|
/^USER_INPUT$/i,
|
|
@@ -23928,7 +24131,7 @@ function findBashRealpathPrefixGuardSanitizers(code) {
|
|
|
23928
24131
|
const caseOpen = /^\s*case\s+"?\$\{?\w+\}?"?\s+in\b/;
|
|
23929
24132
|
const esacClose = /^\s*esac\b/;
|
|
23930
24133
|
const armOpener = /^\s*([^)\s][^)]*?)\)/;
|
|
23931
|
-
const prefixArm = /^(?:"\$\{?\w+\}?"|"[^"]*"|\/[\w\-./]+|\$\{?\w+\}?|[\w\-./]+)(?:\/|\*)/;
|
|
24134
|
+
const prefixArm = /^(?:"\$\{?\w+\}?"|"[^"]*"|\/[\w\-./]+|\$\{?\w+\}?|https?:\/\/[\w\-.]+|[\w\-./]+)(?:\/|\*)/;
|
|
23932
24135
|
const catchAllArm = /^(?:\*|\\\*)$/;
|
|
23933
24136
|
let i2 = 0;
|
|
23934
24137
|
while (i2 < lines.length) {
|
|
@@ -24861,10 +25064,13 @@ function findJavaArgvFormExecSanitizers(code) {
|
|
|
24861
25064
|
`);
|
|
24862
25065
|
const argvExecRe = /\.\s*exec\s*\(\s*new\s+String\s*\[\s*\]\s*\{/;
|
|
24863
25066
|
const argvPbRe = /\bnew\s+ProcessBuilder\s*\(\s*new\s+String\s*\[\s*\]\s*\{/;
|
|
25067
|
+
const shellInStringRe = /new\s+String\s*\[\s*\]\s*\{\s*"(?:\/(?:usr\/)?bin\/(?:sh|bash|zsh|ksh|dash)|(?:sh|bash|zsh|ksh|dash)|cmd(?:\.exe)?|powershell(?:\.exe)?|pwsh)"\s*,\s*"(?:-c|\/c|-Command|-command)"/i;
|
|
24864
25068
|
for (let i2 = 0;i2 < lines.length; i2++) {
|
|
24865
25069
|
const text = lines[i2];
|
|
24866
25070
|
if (!argvExecRe.test(text) && !argvPbRe.test(text))
|
|
24867
25071
|
continue;
|
|
25072
|
+
if (shellInStringRe.test(text))
|
|
25073
|
+
continue;
|
|
24868
25074
|
sanitizers.push({
|
|
24869
25075
|
type: "java_argv_form_exec",
|
|
24870
25076
|
method: "exec",
|
|
@@ -27015,6 +27221,20 @@ function findPythonMongoengineWhereNosqlInjectionFindings(code, file) {
|
|
|
27015
27221
|
}
|
|
27016
27222
|
return findings;
|
|
27017
27223
|
}
|
|
27224
|
+
function hasHostAllowlistBeforeSink(taintedVars, lines, sinkLineIdx) {
|
|
27225
|
+
for (let i2 = 0;i2 < sinkLineIdx; i2++) {
|
|
27226
|
+
const t = lines[i2];
|
|
27227
|
+
for (const v of taintedVars) {
|
|
27228
|
+
const containsRe = new RegExp(`\\.\\s*contains\\s*\\(\\s*${v}\\s*\\.\\s*getHost\\s*\\(\\s*\\)\\s*\\)`);
|
|
27229
|
+
if (containsRe.test(t))
|
|
27230
|
+
return true;
|
|
27231
|
+
const equalsRe = new RegExp(`\\b${v}\\s*\\.\\s*getHost\\s*\\(\\s*\\)\\s*\\.\\s*equals(?:IgnoreCase)?\\s*\\(\\s*"[^"]+"\\s*\\)`);
|
|
27232
|
+
if (equalsRe.test(t))
|
|
27233
|
+
return true;
|
|
27234
|
+
}
|
|
27235
|
+
}
|
|
27236
|
+
return false;
|
|
27237
|
+
}
|
|
27018
27238
|
function findJavaUrlOpenStreamSsrfFindings(code, file) {
|
|
27019
27239
|
const findings = [];
|
|
27020
27240
|
if (typeof code !== "string" || code.length === 0)
|
|
@@ -27079,6 +27299,8 @@ function findJavaUrlOpenStreamSsrfFindings(code, file) {
|
|
|
27079
27299
|
}
|
|
27080
27300
|
if (!tainted)
|
|
27081
27301
|
continue;
|
|
27302
|
+
if (hasHostAllowlistBeforeSink(taintedVars, lines, i2))
|
|
27303
|
+
continue;
|
|
27082
27304
|
const key = `${i2 + 1}:${op}`;
|
|
27083
27305
|
if (seen.has(key))
|
|
27084
27306
|
continue;
|
|
@@ -28389,6 +28611,94 @@ function findJsTemplateInjectionSstiFindings(code, file) {
|
|
|
28389
28611
|
return findings;
|
|
28390
28612
|
}
|
|
28391
28613
|
|
|
28614
|
+
// ../circle-ir/dist/analysis/passes/source-semantics-pass.js
|
|
28615
|
+
var DEMO_PATH_RE = /(?:^|\/)(?:demo|example|examples|samples|integration-tests|integration_tests)(?:\/|$)/i;
|
|
28616
|
+
var CONST_STRING_ASSIGN_RE = /^\s*(?:final\s+|static\s+final\s+)?[A-Za-z_][\w.<>\[\]]*\s+[A-Za-z_]\w*\s*=\s*"[^"]*"\s*;?\s*$/;
|
|
28617
|
+
var STATIC_FINAL_RE = /^\s*(?:public\s+|private\s+|protected\s+)?static\s+final\s+/;
|
|
28618
|
+
var ENUM_CONST_REF_RE = /=\s*[A-Z][A-Za-z0-9_]*\.[A-Z][A-Z0-9_]*\s*;?\s*$/;
|
|
28619
|
+
function isConstantSource(code) {
|
|
28620
|
+
if (!code)
|
|
28621
|
+
return false;
|
|
28622
|
+
if (CONST_STRING_ASSIGN_RE.test(code))
|
|
28623
|
+
return true;
|
|
28624
|
+
if (STATIC_FINAL_RE.test(code)) {
|
|
28625
|
+
const rhs = code.split("=").slice(1).join("=").trim();
|
|
28626
|
+
if (rhs.length === 0)
|
|
28627
|
+
return false;
|
|
28628
|
+
if (/^"[^"]*"\s*;?\s*$/.test(rhs))
|
|
28629
|
+
return true;
|
|
28630
|
+
if (/^-?\d+(?:\.\d+)?[fFdDlL]?\s*;?\s*$/.test(rhs))
|
|
28631
|
+
return true;
|
|
28632
|
+
if (/^(?:true|false)\s*;?\s*$/.test(rhs))
|
|
28633
|
+
return true;
|
|
28634
|
+
if (/^[A-Za-z_][\w.]*\s*;?\s*$/.test(rhs))
|
|
28635
|
+
return true;
|
|
28636
|
+
return false;
|
|
28637
|
+
}
|
|
28638
|
+
if (ENUM_CONST_REF_RE.test(code))
|
|
28639
|
+
return true;
|
|
28640
|
+
return false;
|
|
28641
|
+
}
|
|
28642
|
+
var SERVICE_LOADER_RE = /\bServiceLoader\.(?:load|loadInstalled|stream)\s*\(/;
|
|
28643
|
+
var CLASS_FOR_NAME_RE = /\bClass\.forName\s*\(/;
|
|
28644
|
+
var META_INF_SERVICES_RE = /getResources?\s*\(\s*"META-INF\/services\//;
|
|
28645
|
+
var SPI_WINDOW = 30;
|
|
28646
|
+
function isSpiSource(source, lines) {
|
|
28647
|
+
const code = source.code;
|
|
28648
|
+
if (!code)
|
|
28649
|
+
return false;
|
|
28650
|
+
if (SERVICE_LOADER_RE.test(code))
|
|
28651
|
+
return true;
|
|
28652
|
+
if (CLASS_FOR_NAME_RE.test(code)) {
|
|
28653
|
+
const start2 = Math.max(0, source.line - 1 - SPI_WINDOW);
|
|
28654
|
+
const end = Math.min(lines.length, source.line - 1 + SPI_WINDOW + 1);
|
|
28655
|
+
for (let i2 = start2;i2 < end; i2++) {
|
|
28656
|
+
if (META_INF_SERVICES_RE.test(lines[i2]))
|
|
28657
|
+
return true;
|
|
28658
|
+
}
|
|
28659
|
+
}
|
|
28660
|
+
return false;
|
|
28661
|
+
}
|
|
28662
|
+
function isDemoPathFile(file) {
|
|
28663
|
+
if (!file)
|
|
28664
|
+
return false;
|
|
28665
|
+
return DEMO_PATH_RE.test(file);
|
|
28666
|
+
}
|
|
28667
|
+
|
|
28668
|
+
class SourceSemanticsPass {
|
|
28669
|
+
name = "source-semantics";
|
|
28670
|
+
category = "security";
|
|
28671
|
+
run(ctx) {
|
|
28672
|
+
const { graph, code } = ctx;
|
|
28673
|
+
const sources = graph.ir.taint.sources;
|
|
28674
|
+
if (sources.length === 0) {
|
|
28675
|
+
return { constantCount: 0, spiCount: 0, demoPathCount: 0 };
|
|
28676
|
+
}
|
|
28677
|
+
const file = graph.ir.meta.file;
|
|
28678
|
+
const demoPath = isDemoPathFile(file);
|
|
28679
|
+
const lines = code.split(`
|
|
28680
|
+
`);
|
|
28681
|
+
let constantCount = 0;
|
|
28682
|
+
let spiCount = 0;
|
|
28683
|
+
let demoPathCount = 0;
|
|
28684
|
+
for (const source of sources) {
|
|
28685
|
+
if (isConstantSource(source.code)) {
|
|
28686
|
+
source.constant = true;
|
|
28687
|
+
constantCount++;
|
|
28688
|
+
}
|
|
28689
|
+
if (isSpiSource(source, lines)) {
|
|
28690
|
+
source.spi = true;
|
|
28691
|
+
spiCount++;
|
|
28692
|
+
}
|
|
28693
|
+
if (demoPath) {
|
|
28694
|
+
source.demoPath = true;
|
|
28695
|
+
demoPathCount++;
|
|
28696
|
+
}
|
|
28697
|
+
}
|
|
28698
|
+
return { constantCount, spiCount, demoPathCount };
|
|
28699
|
+
}
|
|
28700
|
+
}
|
|
28701
|
+
|
|
28392
28702
|
// ../circle-ir/dist/analysis/passes/sink-filter-pass.js
|
|
28393
28703
|
var JS_XSS_SANITIZERS = [
|
|
28394
28704
|
/\bDOMPurify\.sanitize\s*\(/,
|
|
@@ -28970,7 +29280,7 @@ class SinkFilterPass {
|
|
|
28970
29280
|
filtered = filtered.filter((sink) => {
|
|
28971
29281
|
if (sink.type !== "command_injection")
|
|
28972
29282
|
return true;
|
|
28973
|
-
if (sink.method !== "ProcessBuilder")
|
|
29283
|
+
if (sink.method !== "ProcessBuilder" && sink.method !== "start")
|
|
28974
29284
|
return true;
|
|
28975
29285
|
const sinkLineText = sourceLines[sink.line - 1] ?? "";
|
|
28976
29286
|
if (!/\bnew\s+ProcessBuilder\s*\(/.test(sinkLineText))
|
|
@@ -29807,6 +30117,54 @@ function filterSanitizedSinks(sinks, sanitizers, calls) {
|
|
|
29807
30117
|
});
|
|
29808
30118
|
}
|
|
29809
30119
|
|
|
30120
|
+
// ../circle-ir/dist/analysis/passes/sink-semantics-pass.js
|
|
30121
|
+
function buildRegistry(entries) {
|
|
30122
|
+
const registry = new Map;
|
|
30123
|
+
for (const entry of entries) {
|
|
30124
|
+
const existing = registry.get(entry.signature);
|
|
30125
|
+
if (existing) {
|
|
30126
|
+
for (const t of entry.overrides)
|
|
30127
|
+
existing.add(t);
|
|
30128
|
+
} else {
|
|
30129
|
+
registry.set(entry.signature, new Set(entry.overrides));
|
|
30130
|
+
}
|
|
30131
|
+
}
|
|
30132
|
+
return registry;
|
|
30133
|
+
}
|
|
30134
|
+
|
|
30135
|
+
class SinkSemanticsPass {
|
|
30136
|
+
name = "sink-semantics";
|
|
30137
|
+
category = "security";
|
|
30138
|
+
run(ctx) {
|
|
30139
|
+
const { graph, config } = ctx;
|
|
30140
|
+
const entries = config.sinkSemantics ?? [];
|
|
30141
|
+
if (entries.length === 0) {
|
|
30142
|
+
return { droppedCount: 0, registrySize: 0 };
|
|
30143
|
+
}
|
|
30144
|
+
const registry = buildRegistry(entries);
|
|
30145
|
+
const sinks = graph.ir.taint.sinks;
|
|
30146
|
+
let droppedCount = 0;
|
|
30147
|
+
const kept = sinks.filter((sink) => {
|
|
30148
|
+
if (!sink.class || !sink.method)
|
|
30149
|
+
return true;
|
|
30150
|
+
const signature = `${sink.class}#${sink.method}`;
|
|
30151
|
+
const overrides = registry.get(signature);
|
|
30152
|
+
if (!overrides)
|
|
30153
|
+
return true;
|
|
30154
|
+
if (overrides.has(sink.type)) {
|
|
30155
|
+
droppedCount++;
|
|
30156
|
+
return false;
|
|
30157
|
+
}
|
|
30158
|
+
return true;
|
|
30159
|
+
});
|
|
30160
|
+
if (droppedCount > 0) {
|
|
30161
|
+
sinks.length = 0;
|
|
30162
|
+
sinks.push(...kept);
|
|
30163
|
+
}
|
|
30164
|
+
return { droppedCount, registrySize: registry.size };
|
|
30165
|
+
}
|
|
30166
|
+
}
|
|
30167
|
+
|
|
29810
30168
|
// ../circle-ir/dist/analysis/passes/taint-propagation-pass.js
|
|
29811
30169
|
class TaintPropagationPass {
|
|
29812
30170
|
name = "taint-propagation";
|
|
@@ -30501,6 +30859,27 @@ function detectExpressionScanFlows(calls, sources, sinks, sanitizers, unreachabl
|
|
|
30501
30859
|
}
|
|
30502
30860
|
}
|
|
30503
30861
|
}
|
|
30862
|
+
if (language === "java" && typeof code === "string" && sourcesWithVar.length > 0) {
|
|
30863
|
+
const seedVars = new Set(sourcesWithVar.map((s) => s.variable));
|
|
30864
|
+
const derived = buildJavaTaintedVars(code, seedVars);
|
|
30865
|
+
if (derived.size > 0) {
|
|
30866
|
+
let anchor = sourcesWithVar[0];
|
|
30867
|
+
for (const s of sourcesWithVar) {
|
|
30868
|
+
if (s.line < anchor.line)
|
|
30869
|
+
anchor = s;
|
|
30870
|
+
}
|
|
30871
|
+
const existingVars = new Set(sourcesWithVar.map((s) => s.variable));
|
|
30872
|
+
for (const [varName] of derived) {
|
|
30873
|
+
if (!varName || existingVars.has(varName))
|
|
30874
|
+
continue;
|
|
30875
|
+
sourcesWithVar.push({
|
|
30876
|
+
...anchor,
|
|
30877
|
+
variable: varName
|
|
30878
|
+
});
|
|
30879
|
+
existingVars.add(varName);
|
|
30880
|
+
}
|
|
30881
|
+
}
|
|
30882
|
+
}
|
|
30504
30883
|
const reCache = new Map;
|
|
30505
30884
|
for (const s of sourcesWithVar) {
|
|
30506
30885
|
if (reCache.has(s.variable))
|
|
@@ -30535,6 +30914,8 @@ function detectExpressionScanFlows(calls, sources, sinks, sanitizers, unreachabl
|
|
|
30535
30914
|
const re = reCache.get(source.variable);
|
|
30536
30915
|
if (!re || !re.test(expr))
|
|
30537
30916
|
continue;
|
|
30917
|
+
if (!sourceSemanticsAllowed(source, sink.type))
|
|
30918
|
+
continue;
|
|
30538
30919
|
if (flows.some((f) => f.source_line === source.line && f.sink_line === sink.line && f.sink_type === sink.type))
|
|
30539
30920
|
continue;
|
|
30540
30921
|
if (aliasSanitizedFor.get(source.variable)?.has(sink.type)) {
|
|
@@ -30562,8 +30943,6 @@ function detectExpressionScanFlows(calls, sources, sinks, sanitizers, unreachabl
|
|
|
30562
30943
|
}
|
|
30563
30944
|
const sourcesByLine = new Map;
|
|
30564
30945
|
for (const s of sources) {
|
|
30565
|
-
if (s.variable && s.variable.length > 0)
|
|
30566
|
-
continue;
|
|
30567
30946
|
const arr = sourcesByLine.get(s.line) ?? [];
|
|
30568
30947
|
arr.push(s);
|
|
30569
30948
|
sourcesByLine.set(s.line, arr);
|
|
@@ -30577,6 +30956,20 @@ function detectExpressionScanFlows(calls, sources, sinks, sanitizers, unreachabl
|
|
|
30577
30956
|
for (const source of colocSources) {
|
|
30578
30957
|
if (!canSourceReachSink(source.type, sink.type))
|
|
30579
30958
|
continue;
|
|
30959
|
+
if (!sourceSemanticsAllowed(source, sink.type))
|
|
30960
|
+
continue;
|
|
30961
|
+
const sourceVar = source.variable;
|
|
30962
|
+
if (sourceVar && sourceVar.length > 0) {
|
|
30963
|
+
const sinkCode = sink.code;
|
|
30964
|
+
if (!sinkCode) {
|
|
30965
|
+
continue;
|
|
30966
|
+
}
|
|
30967
|
+
const assignMatch = sinkCode.match(/^\s*(?:[A-Za-z_][\w.<>[\]\s,?]*\s+)?[A-Za-z_]\w*\s*=(?!=)\s*/);
|
|
30968
|
+
const rhs = assignMatch ? sinkCode.slice(assignMatch[0].length) : sinkCode;
|
|
30969
|
+
if (new RegExp(`\\b${sourceVar}\\b`).test(rhs)) {
|
|
30970
|
+
continue;
|
|
30971
|
+
}
|
|
30972
|
+
}
|
|
30580
30973
|
if (source.type === "file_input" && sink.type === "path_traversal" && sink.method && source.location.includes(`${sink.method}(`)) {
|
|
30581
30974
|
continue;
|
|
30582
30975
|
}
|
|
@@ -31165,7 +31558,9 @@ var TIER_1_METHOD_ANNOTATIONS = new Set([
|
|
|
31165
31558
|
"DELETE",
|
|
31166
31559
|
"PATCH",
|
|
31167
31560
|
"HEAD",
|
|
31168
|
-
"OPTIONS"
|
|
31561
|
+
"OPTIONS",
|
|
31562
|
+
"DataBoundConstructor",
|
|
31563
|
+
"DataBoundSetter"
|
|
31169
31564
|
]);
|
|
31170
31565
|
var TIER_1_CLASS_ANNOTATIONS = new Set([
|
|
31171
31566
|
"RestController",
|
|
@@ -31190,7 +31585,13 @@ var TIER_1_BY_SUPERTYPE = new Map([
|
|
|
31190
31585
|
["ChannelInboundHandler", new Set(["channelRead", "channelReadComplete"])],
|
|
31191
31586
|
["ChannelInboundHandlerAdapter", new Set(["channelRead", "channelReadComplete"])],
|
|
31192
31587
|
["ChannelDuplexHandler", new Set(["channelRead", "channelReadComplete"])],
|
|
31193
|
-
["NettyRequestProcessor", new Set(["process"])]
|
|
31588
|
+
["NettyRequestProcessor", new Set(["process"])],
|
|
31589
|
+
["Converter", new Set(["marshal", "unmarshal"])],
|
|
31590
|
+
["SingleValueConverter", new Set(["fromString", "toString"])],
|
|
31591
|
+
["ConverterMatcher", new Set(["marshal", "unmarshal"])],
|
|
31592
|
+
["AbstractReflectionConverter", new Set(["marshal", "unmarshal", "doMarshal", "doUnmarshal"])],
|
|
31593
|
+
["AbstractSingleValueConverter", new Set(["fromString", "toString"])],
|
|
31594
|
+
["AbstractCollectionConverter", new Set(["marshal", "unmarshal"])]
|
|
31194
31595
|
]);
|
|
31195
31596
|
var TIER_3_CLASS_SUFFIXES = [
|
|
31196
31597
|
"Util",
|
|
@@ -35700,6 +36101,14 @@ function isProtocolMandatedCryptoFile(file, code) {
|
|
|
35700
36101
|
}
|
|
35701
36102
|
|
|
35702
36103
|
// ../circle-ir/dist/analysis/passes/scan-secrets-pass.js
|
|
36104
|
+
function applyDemoDowngrade(demoPath, severity, level) {
|
|
36105
|
+
if (!demoPath)
|
|
36106
|
+
return { severity, level };
|
|
36107
|
+
if (severity === "high") {
|
|
36108
|
+
return { severity: "low", level: "note" };
|
|
36109
|
+
}
|
|
36110
|
+
return { severity, level };
|
|
36111
|
+
}
|
|
35703
36112
|
var TEST_PATH_RE3 = /(?:^|[\\/])(?:test|tests|spec|specs|__tests?__|__mocks?__|fixtures?|testdata)(?:[\\/]|$)/i;
|
|
35704
36113
|
var TEST_FILENAME_RE = /(?:\.(?:test|spec)\.[cm]?[jt]sx?|_test\.go|_test\.py|Test\.java|Tests\.java)$/i;
|
|
35705
36114
|
function isTestFile(file) {
|
|
@@ -36050,6 +36459,7 @@ class ScanSecretsPass {
|
|
|
36050
36459
|
if (isTestFile(file) || isGeneratedFile(file)) {
|
|
36051
36460
|
return { providerFindings: 0, entropyFindings: 0 };
|
|
36052
36461
|
}
|
|
36462
|
+
const demoPath = DEMO_PATH_RE.test(file);
|
|
36053
36463
|
const lines = ctx.code.split(`
|
|
36054
36464
|
`);
|
|
36055
36465
|
const prior = ctx.getFindings?.() ?? [];
|
|
@@ -36080,14 +36490,15 @@ class ScanSecretsPass {
|
|
|
36080
36490
|
if (seen.has(key))
|
|
36081
36491
|
continue;
|
|
36082
36492
|
seen.add(key);
|
|
36493
|
+
const dg = applyDemoDowngrade(demoPath, pattern.severity, pattern.level);
|
|
36083
36494
|
ctx.addFinding({
|
|
36084
36495
|
id: `hardcoded-credential-${file}-${lineNum}`,
|
|
36085
36496
|
pass: this.name,
|
|
36086
36497
|
category: this.category,
|
|
36087
36498
|
rule_id: "hardcoded-credential",
|
|
36088
36499
|
cwe: "CWE-798",
|
|
36089
|
-
severity:
|
|
36090
|
-
level:
|
|
36500
|
+
severity: dg.severity,
|
|
36501
|
+
level: dg.level,
|
|
36091
36502
|
message: `Hardcoded credential: ${pattern.name} detected`,
|
|
36092
36503
|
file,
|
|
36093
36504
|
line: lineNum,
|
|
@@ -36109,14 +36520,15 @@ class ScanSecretsPass {
|
|
|
36109
36520
|
if (seen.has(key))
|
|
36110
36521
|
continue;
|
|
36111
36522
|
seen.add(key);
|
|
36523
|
+
const dg = applyDemoDowngrade(demoPath, "high", "error");
|
|
36112
36524
|
ctx.addFinding({
|
|
36113
36525
|
id: `hardcoded-credential-${file}-${lineNum}`,
|
|
36114
36526
|
pass: this.name,
|
|
36115
36527
|
category: this.category,
|
|
36116
36528
|
rule_id: "hardcoded-credential",
|
|
36117
36529
|
cwe: "CWE-798",
|
|
36118
|
-
severity:
|
|
36119
|
-
level:
|
|
36530
|
+
severity: dg.severity,
|
|
36531
|
+
level: dg.level,
|
|
36120
36532
|
message: `Hardcoded credential: \`${hit.name}\` assigned a literal value`,
|
|
36121
36533
|
file,
|
|
36122
36534
|
line: lineNum,
|
|
@@ -40737,7 +41149,11 @@ async function analyze(code, filePath, language, options = {}) {
|
|
|
40737
41149
|
pipeline.add(new TaintMatcherPass);
|
|
40738
41150
|
pipeline.add(new ConstantPropagationPass(tree));
|
|
40739
41151
|
pipeline.add(new LanguageSourcesPass);
|
|
41152
|
+
if (!disabledPasses.has("source-semantics"))
|
|
41153
|
+
pipeline.add(new SourceSemanticsPass);
|
|
40740
41154
|
pipeline.add(new SinkFilterPass);
|
|
41155
|
+
if (!disabledPasses.has("sink-semantics"))
|
|
41156
|
+
pipeline.add(new SinkSemanticsPass);
|
|
40741
41157
|
pipeline.add(new TaintPropagationPass);
|
|
40742
41158
|
pipeline.add(new InterproceduralPass({
|
|
40743
41159
|
enableEntryPointGate: options.enableEntryPointGate ?? true
|
|
@@ -41665,7 +42081,7 @@ var colors = {
|
|
|
41665
42081
|
};
|
|
41666
42082
|
|
|
41667
42083
|
// src/version.ts
|
|
41668
|
-
var version = "3.
|
|
42084
|
+
var version = "3.145.0";
|
|
41669
42085
|
|
|
41670
42086
|
// src/formatters.ts
|
|
41671
42087
|
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.145.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.145.0"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@types/node": "^25.5.0",
|