cognium-dev 3.99.0 → 3.101.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 +172 -1
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -23490,6 +23490,106 @@ var JS_XSS_SANITIZERS = [
|
|
|
23490
23490
|
/\btrustAsHtml\s*\(/,
|
|
23491
23491
|
/\bbypassSecurityTrust/
|
|
23492
23492
|
];
|
|
23493
|
+
var DATA_PARSER_TYPES = new Set([
|
|
23494
|
+
"Parser",
|
|
23495
|
+
"CommandLine",
|
|
23496
|
+
"JCommander",
|
|
23497
|
+
"DateParser",
|
|
23498
|
+
"FastDateFormat",
|
|
23499
|
+
"FastDatePrinter",
|
|
23500
|
+
"ResultParser",
|
|
23501
|
+
"DateFormat",
|
|
23502
|
+
"SimpleDateFormat",
|
|
23503
|
+
"NumberFormat",
|
|
23504
|
+
"DecimalFormat",
|
|
23505
|
+
"OptionParser",
|
|
23506
|
+
"CmdLineParser"
|
|
23507
|
+
]);
|
|
23508
|
+
var COMPILED_TEMPLATE_TYPES = new Set([
|
|
23509
|
+
"Template",
|
|
23510
|
+
"JetTemplate",
|
|
23511
|
+
"ITemplate",
|
|
23512
|
+
"VelocityTemplate",
|
|
23513
|
+
"BeetlTemplate"
|
|
23514
|
+
]);
|
|
23515
|
+
var REFLECTION_LITERAL_METHODS = new Set([
|
|
23516
|
+
"forName",
|
|
23517
|
+
"loadClass",
|
|
23518
|
+
"getMethod",
|
|
23519
|
+
"getDeclaredMethod",
|
|
23520
|
+
"getConstructor",
|
|
23521
|
+
"getDeclaredConstructor",
|
|
23522
|
+
"parseExpression",
|
|
23523
|
+
"invoke"
|
|
23524
|
+
]);
|
|
23525
|
+
var JAVA_DECL_RE_TEMPLATE = "(?:\\b(?:final|public|private|protected|static)\\s+)*" + "([A-Z]\\w*(?:\\.[A-Z]\\w*)?(?:<[^>]*>)?)\\s+RECV\\b\\s*[=;,)]";
|
|
23526
|
+
var PROTOCOL_WIRE_METHODS = new Set([
|
|
23527
|
+
"executeCommand",
|
|
23528
|
+
"execute",
|
|
23529
|
+
"dispatch",
|
|
23530
|
+
"send",
|
|
23531
|
+
"publish",
|
|
23532
|
+
"command",
|
|
23533
|
+
"run"
|
|
23534
|
+
]);
|
|
23535
|
+
var PROTOCOL_CLIENT_PACKAGES = [
|
|
23536
|
+
"redis.clients.jedis",
|
|
23537
|
+
"io.lettuce",
|
|
23538
|
+
"org.springframework.data.redis",
|
|
23539
|
+
"org.springframework.data.mongodb",
|
|
23540
|
+
"org.springframework.amqp",
|
|
23541
|
+
"com.rabbitmq",
|
|
23542
|
+
"org.apache.kafka",
|
|
23543
|
+
"org.eclipse.paho"
|
|
23544
|
+
];
|
|
23545
|
+
var OS_EXEC_RECEIVER_RE = /\b(?:Runtime|ProcessBuilder|DefaultExecutor|Executor|Exec|Launcher|ProcStarter|ProcessExecutor|RuntimeUtil)\s*[.(]/;
|
|
23546
|
+
function resolveJavaReceiverType(receiver, sinkLine, sourceLines) {
|
|
23547
|
+
if (!receiver || !/^[A-Za-z_]\w*$/.test(receiver))
|
|
23548
|
+
return null;
|
|
23549
|
+
const start2 = Math.max(0, sinkLine - 31);
|
|
23550
|
+
const declRe = new RegExp(JAVA_DECL_RE_TEMPLATE.replace("RECV", receiver));
|
|
23551
|
+
for (let i2 = sinkLine - 2;i2 >= start2; i2--) {
|
|
23552
|
+
const ln = sourceLines[i2] ?? "";
|
|
23553
|
+
const m = ln.match(declRe);
|
|
23554
|
+
if (m) {
|
|
23555
|
+
const raw = m[1].replace(/<[^>]*>/g, "").trim();
|
|
23556
|
+
const parts2 = raw.split(".");
|
|
23557
|
+
return parts2[parts2.length - 1] ?? null;
|
|
23558
|
+
}
|
|
23559
|
+
}
|
|
23560
|
+
return null;
|
|
23561
|
+
}
|
|
23562
|
+
function isJavaLiteralOrAnnotationAccessor(expr) {
|
|
23563
|
+
const e = expr.trim();
|
|
23564
|
+
if (e === "")
|
|
23565
|
+
return true;
|
|
23566
|
+
if (/^"(?:[^"\\]|\\.)*"$/.test(e))
|
|
23567
|
+
return true;
|
|
23568
|
+
if (/^[A-Za-z_]\w*\s*\.\s*(?:value|name|key)\s*\(\s*\)$/.test(e))
|
|
23569
|
+
return true;
|
|
23570
|
+
return false;
|
|
23571
|
+
}
|
|
23572
|
+
function extractJavaCallArgs(method, line) {
|
|
23573
|
+
const re = new RegExp(`\\b${method}\\s*\\(([^()]*(?:\\([^()]*\\)[^()]*)*)\\)`);
|
|
23574
|
+
const m = line.match(re);
|
|
23575
|
+
if (!m)
|
|
23576
|
+
return null;
|
|
23577
|
+
const argsText = m[1].trim();
|
|
23578
|
+
if (argsText === "")
|
|
23579
|
+
return [];
|
|
23580
|
+
return argsText.split(",").map((s) => s.trim());
|
|
23581
|
+
}
|
|
23582
|
+
function hasJavaImportFromPackage(packagePrefix, sourceLines) {
|
|
23583
|
+
if (!/^[A-Za-z_][\w.]*$/.test(packagePrefix))
|
|
23584
|
+
return false;
|
|
23585
|
+
const limit = Math.min(sourceLines.length, 80);
|
|
23586
|
+
const re = new RegExp(`^\\s*import\\s+(?:static\\s+)?${packagePrefix.replace(/\./g, "\\.")}\\b`);
|
|
23587
|
+
for (let i2 = 0;i2 < limit; i2++) {
|
|
23588
|
+
if (re.test(sourceLines[i2] ?? ""))
|
|
23589
|
+
return true;
|
|
23590
|
+
}
|
|
23591
|
+
return false;
|
|
23592
|
+
}
|
|
23493
23593
|
|
|
23494
23594
|
class SinkFilterPass {
|
|
23495
23595
|
name = "sink-filter";
|
|
@@ -23653,6 +23753,67 @@ class SinkFilterPass {
|
|
|
23653
23753
|
return true;
|
|
23654
23754
|
});
|
|
23655
23755
|
}
|
|
23756
|
+
if (language === "java") {
|
|
23757
|
+
const sourceLines = ctx.code.split(`
|
|
23758
|
+
`);
|
|
23759
|
+
filtered = filtered.filter((sink) => {
|
|
23760
|
+
if (sink.type !== "code_injection")
|
|
23761
|
+
return true;
|
|
23762
|
+
const sinkLineText = sourceLines[sink.line - 1] ?? "";
|
|
23763
|
+
const receiverMatch = sinkLineText.match(/\b(\w+)\s*\.\s*(\w+)\s*\(/);
|
|
23764
|
+
const receiver = receiverMatch?.[1];
|
|
23765
|
+
const method = sink.method ?? receiverMatch?.[2];
|
|
23766
|
+
if (method === "parse" && receiver) {
|
|
23767
|
+
const recvType = resolveJavaReceiverType(receiver, sink.line, sourceLines);
|
|
23768
|
+
if (recvType && DATA_PARSER_TYPES.has(recvType))
|
|
23769
|
+
return false;
|
|
23770
|
+
}
|
|
23771
|
+
if ((method === "render" || method === "process" || method === "merge" || method === "renderTo") && receiver) {
|
|
23772
|
+
const recvType = resolveJavaReceiverType(receiver, sink.line, sourceLines);
|
|
23773
|
+
if (recvType && COMPILED_TEMPLATE_TYPES.has(recvType))
|
|
23774
|
+
return false;
|
|
23775
|
+
}
|
|
23776
|
+
if (method && REFLECTION_LITERAL_METHODS.has(method)) {
|
|
23777
|
+
const args2 = extractJavaCallArgs(method, sinkLineText);
|
|
23778
|
+
if (args2 !== null) {
|
|
23779
|
+
if (method === "invoke") {
|
|
23780
|
+
if (args2.length <= 1)
|
|
23781
|
+
return false;
|
|
23782
|
+
} else {
|
|
23783
|
+
const firstArg = args2[0] ?? "";
|
|
23784
|
+
if (isJavaLiteralOrAnnotationAccessor(firstArg))
|
|
23785
|
+
return false;
|
|
23786
|
+
}
|
|
23787
|
+
}
|
|
23788
|
+
}
|
|
23789
|
+
if (method === "newInstance" && /\.\s*newInstance\s*\(\s*\)/.test(sinkLineText)) {
|
|
23790
|
+
return false;
|
|
23791
|
+
}
|
|
23792
|
+
return true;
|
|
23793
|
+
});
|
|
23794
|
+
}
|
|
23795
|
+
if (language === "java") {
|
|
23796
|
+
const sourceLines = ctx.code.split(`
|
|
23797
|
+
`);
|
|
23798
|
+
filtered = filtered.filter((sink) => {
|
|
23799
|
+
if (sink.type !== "command_injection")
|
|
23800
|
+
return true;
|
|
23801
|
+
const sinkLineText = sourceLines[sink.line - 1] ?? "";
|
|
23802
|
+
if (sink.method === "CommandLine" && /\bnew\s+CommandLine\s*\(/.test(sinkLineText) && hasJavaImportFromPackage("picocli", sourceLines)) {
|
|
23803
|
+
return false;
|
|
23804
|
+
}
|
|
23805
|
+
if (sink.method && PROTOCOL_WIRE_METHODS.has(sink.method)) {
|
|
23806
|
+
for (const pkg of PROTOCOL_CLIENT_PACKAGES) {
|
|
23807
|
+
if (hasJavaImportFromPackage(pkg, sourceLines)) {
|
|
23808
|
+
if (!OS_EXEC_RECEIVER_RE.test(sinkLineText)) {
|
|
23809
|
+
return false;
|
|
23810
|
+
}
|
|
23811
|
+
}
|
|
23812
|
+
}
|
|
23813
|
+
}
|
|
23814
|
+
return true;
|
|
23815
|
+
});
|
|
23816
|
+
}
|
|
23656
23817
|
return { sources, sinks: filtered, sanitizers };
|
|
23657
23818
|
}
|
|
23658
23819
|
}
|
|
@@ -33203,6 +33364,10 @@ var JAVA_FACTORIES = new Set([
|
|
|
33203
33364
|
"TransformerFactory"
|
|
33204
33365
|
]);
|
|
33205
33366
|
var JAVA_SAFE_EVIDENCE_RE = /(disallow-doctype-decl|external-general-entities|external-parameter-entities|SUPPORT_DTD|ACCESS_EXTERNAL_DTD|ACCESS_EXTERNAL_SCHEMA|setXIncludeAware\s*\(\s*false\s*\)|setExpandEntityReferences\s*\(\s*false\s*\))/;
|
|
33367
|
+
var JAVA_XML_OUTPUT_ONLY_RE = /\bnew\s+(?:DOMSource|StreamResult)\s*\(/;
|
|
33368
|
+
var JAVA_XML_PARSE_INPUT_RE = /\bnew\s+(?:StreamSource|SAXSource|InputSource)\s*\(/;
|
|
33369
|
+
var JAVA_DOC_BUILDER_NEW_DOCUMENT_RE = /\.\s*newDocument\s*\(\s*\)/;
|
|
33370
|
+
var JAVA_DOC_BUILDER_PARSE_RE = /(?:DocumentBuilder|builder)\s*\.\s*parse\s*\(/;
|
|
33206
33371
|
var PY_LXML_PARSER_INSECURE_DEFAULT_RE = /\bresolve_entities\s*=\s*False\b/;
|
|
33207
33372
|
|
|
33208
33373
|
class XmlEntityExpansionPass {
|
|
@@ -33217,10 +33382,16 @@ class XmlEntityExpansionPass {
|
|
|
33217
33382
|
const safeInFile = JAVA_SAFE_EVIDENCE_RE.test(code);
|
|
33218
33383
|
if (safeInFile)
|
|
33219
33384
|
return { findings };
|
|
33385
|
+
const isXmlOutputOnly = JAVA_XML_OUTPUT_ONLY_RE.test(code) && !JAVA_XML_PARSE_INPUT_RE.test(code);
|
|
33386
|
+
const isDocumentBuilderEmptyOnly = JAVA_DOC_BUILDER_NEW_DOCUMENT_RE.test(code) && !JAVA_DOC_BUILDER_PARSE_RE.test(code);
|
|
33220
33387
|
for (const call of graph.ir.calls) {
|
|
33221
33388
|
const det = this.detectJavaCall(call);
|
|
33222
33389
|
if (!det)
|
|
33223
33390
|
continue;
|
|
33391
|
+
if (det.api === "TransformerFactory" && isXmlOutputOnly)
|
|
33392
|
+
continue;
|
|
33393
|
+
if (det.api === "DocumentBuilderFactory" && isDocumentBuilderEmptyOnly)
|
|
33394
|
+
continue;
|
|
33224
33395
|
const line = call.location.line;
|
|
33225
33396
|
findings.push({ line, language, ...det });
|
|
33226
33397
|
ctx.addFinding({
|
|
@@ -34768,7 +34939,7 @@ var colors = {
|
|
|
34768
34939
|
};
|
|
34769
34940
|
|
|
34770
34941
|
// src/version.ts
|
|
34771
|
-
var version = "3.
|
|
34942
|
+
var version = "3.101.0";
|
|
34772
34943
|
|
|
34773
34944
|
// src/formatters.ts
|
|
34774
34945
|
var SINK_SEVERITY = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cognium-dev",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.101.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",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"registry": "https://registry.npmjs.org/"
|
|
66
66
|
},
|
|
67
67
|
"dependencies": {
|
|
68
|
-
"circle-ir": "^3.
|
|
68
|
+
"circle-ir": "^3.101.0"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
71
|
"@types/node": "^25.5.0",
|