cognium-dev 3.159.0 → 3.160.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 +55 -6
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -12982,7 +12982,10 @@ function matchesSinkPattern(call, pattern, typeHierarchy, language) {
|
|
|
12982
12982
|
return true;
|
|
12983
12983
|
}
|
|
12984
12984
|
const subtypeArgArityOk = !pattern.arg_positions || pattern.arg_positions.length === 0 || pattern.arg_positions.every((pos) => pos < (call.arguments?.length ?? 0));
|
|
12985
|
-
if (call.receiver_type && call.receiver_type === pattern.class) {} else if (call.receiver_type && typeHierarchy && subtypeArgArityOk && typeHierarchy.isSubtypeOf(call.receiver_type, pattern.class)) {} else if (call.receiver_type_fqn && call.receiver_type_fqn.endsWith("." + pattern.class)) {} else if (call.receiver_type_fqn && typeHierarchy && subtypeArgArityOk && typeHierarchy.isSubtypeOf(call.receiver_type_fqn, pattern.class)) {} else if (call.
|
|
12985
|
+
if (call.receiver_type && call.receiver_type === pattern.class) {} else if (call.receiver_type && typeHierarchy && subtypeArgArityOk && typeHierarchy.isSubtypeOf(call.receiver_type, pattern.class)) {} else if (call.receiver_type_fqn && call.receiver_type_fqn.endsWith("." + pattern.class)) {} else if (call.receiver_type_fqn && typeHierarchy && subtypeArgArityOk && typeHierarchy.isSubtypeOf(call.receiver_type_fqn, pattern.class)) {} else if (!call.receiver_type && !call.receiver_type_fqn && call.receiver && typeHierarchy && subtypeArgArityOk && (() => {
|
|
12986
|
+
const factoryReturn = typeHierarchy.resolveFactoryReturnType(call.receiver);
|
|
12987
|
+
return factoryReturn !== null && typeHierarchy.isSubtypeOf(factoryReturn, pattern.class);
|
|
12988
|
+
})()) {} else if (call.receiver && !receiverMightBeClass(call.receiver, pattern.class)) {
|
|
12986
12989
|
if (typeHierarchy && typeHierarchy.couldBeType(call.receiver, pattern.class)) {
|
|
12987
12990
|
return true;
|
|
12988
12991
|
}
|
|
@@ -13915,6 +13918,7 @@ class TypeHierarchyResolver {
|
|
|
13915
13918
|
implementations = new Map;
|
|
13916
13919
|
_subtypeCache = new Map;
|
|
13917
13920
|
_implCache = new Map;
|
|
13921
|
+
factoryReturnTypes = new Map;
|
|
13918
13922
|
addFromIR(ir, filePath) {
|
|
13919
13923
|
for (const type of ir.types) {
|
|
13920
13924
|
this.addType(type, filePath, ir.meta.package || null);
|
|
@@ -14120,11 +14124,22 @@ class TypeHierarchyResolver {
|
|
|
14120
14124
|
getAllTypes() {
|
|
14121
14125
|
return Array.from(this.types.values());
|
|
14122
14126
|
}
|
|
14127
|
+
registerFactoryReturnType(factoryClass, method, returnFqn) {
|
|
14128
|
+
this.factoryReturnTypes.set(`${factoryClass}.${method}`, returnFqn);
|
|
14129
|
+
}
|
|
14130
|
+
resolveFactoryReturnType(receiver) {
|
|
14131
|
+
const m = receiver.match(/(?:^|\.)([A-Z]\w*)\.(\w+)\(\)$/);
|
|
14132
|
+
if (!m)
|
|
14133
|
+
return null;
|
|
14134
|
+
const key = `${m[1]}.${m[2]}`;
|
|
14135
|
+
return this.factoryReturnTypes.get(key) ?? null;
|
|
14136
|
+
}
|
|
14123
14137
|
clear() {
|
|
14124
14138
|
this.types.clear();
|
|
14125
14139
|
this.nameToFqn.clear();
|
|
14126
14140
|
this.subtypes.clear();
|
|
14127
14141
|
this.implementations.clear();
|
|
14142
|
+
this.factoryReturnTypes.clear();
|
|
14128
14143
|
}
|
|
14129
14144
|
resolveTypeName(name2, currentPackage) {
|
|
14130
14145
|
if (name2.includes("."))
|
|
@@ -14463,6 +14478,9 @@ function registerCommonLibraries(resolver) {
|
|
|
14463
14478
|
for (const type of [...apacheHttpClient4x, ...apacheHttpClient5x]) {
|
|
14464
14479
|
resolver.addType(type, "common-libraries", type.package);
|
|
14465
14480
|
}
|
|
14481
|
+
resolver.registerFactoryReturnType("HttpClients", "createDefault", "org.apache.http.impl.client.CloseableHttpClient");
|
|
14482
|
+
resolver.registerFactoryReturnType("HttpClients", "createSystem", "org.apache.http.impl.client.CloseableHttpClient");
|
|
14483
|
+
resolver.registerFactoryReturnType("HttpClients", "createMinimal", "org.apache.http.impl.client.MinimalHttpClient");
|
|
14466
14484
|
}
|
|
14467
14485
|
// ../circle-ir/dist/resolution/symbol-table.js
|
|
14468
14486
|
class SymbolTable {
|
|
@@ -29828,6 +29846,12 @@ function correlateDollarBraceToArgPositions(method, refs) {
|
|
|
29828
29846
|
}
|
|
29829
29847
|
}
|
|
29830
29848
|
});
|
|
29849
|
+
const declaredNameToIndex = new Map;
|
|
29850
|
+
method.parameters.forEach((param, idx) => {
|
|
29851
|
+
if (param.name && !declaredNameToIndex.has(param.name)) {
|
|
29852
|
+
declaredNameToIndex.set(param.name, idx);
|
|
29853
|
+
}
|
|
29854
|
+
});
|
|
29831
29855
|
const positions = new Set;
|
|
29832
29856
|
for (const ref of refs) {
|
|
29833
29857
|
const namedIdx = paramNameToIndex.get(ref);
|
|
@@ -29835,6 +29859,11 @@ function correlateDollarBraceToArgPositions(method, refs) {
|
|
|
29835
29859
|
positions.add(namedIdx);
|
|
29836
29860
|
continue;
|
|
29837
29861
|
}
|
|
29862
|
+
const declaredIdx = declaredNameToIndex.get(ref);
|
|
29863
|
+
if (declaredIdx !== undefined) {
|
|
29864
|
+
positions.add(declaredIdx);
|
|
29865
|
+
continue;
|
|
29866
|
+
}
|
|
29838
29867
|
const positionalIdx = parsePositionalRef(ref);
|
|
29839
29868
|
if (positionalIdx !== null && positionalIdx < method.parameters.length) {
|
|
29840
29869
|
positions.add(positionalIdx);
|
|
@@ -29865,11 +29894,11 @@ class MyBatisAnnotationSqlSinkPass {
|
|
|
29865
29894
|
category = "security";
|
|
29866
29895
|
run(ctx) {
|
|
29867
29896
|
if (ctx.language !== "java") {
|
|
29868
|
-
return { annotatedMethodCount: 0, addedSinkCount: 0 };
|
|
29897
|
+
return { annotatedMethodCount: 0, addedSinkCount: 0, declarationFindingCount: 0 };
|
|
29869
29898
|
}
|
|
29870
29899
|
const { types, imports, calls } = ctx.graph.ir;
|
|
29871
29900
|
if (!fileImportsMyBatis(imports)) {
|
|
29872
|
-
return { annotatedMethodCount: 0, addedSinkCount: 0 };
|
|
29901
|
+
return { annotatedMethodCount: 0, addedSinkCount: 0, declarationFindingCount: 0 };
|
|
29873
29902
|
}
|
|
29874
29903
|
const mapperMethods = [];
|
|
29875
29904
|
for (const type of types) {
|
|
@@ -29898,6 +29927,7 @@ class MyBatisAnnotationSqlSinkPass {
|
|
|
29898
29927
|
interfaceSimpleName: type.name,
|
|
29899
29928
|
interfaceFqn,
|
|
29900
29929
|
methodName: method.name,
|
|
29930
|
+
declarationLine: method.start_line,
|
|
29901
29931
|
taintedArgPositions: positions
|
|
29902
29932
|
});
|
|
29903
29933
|
}
|
|
@@ -29905,9 +29935,27 @@ class MyBatisAnnotationSqlSinkPass {
|
|
|
29905
29935
|
if (mapperMethods.length === 0) {
|
|
29906
29936
|
return {
|
|
29907
29937
|
annotatedMethodCount: 0,
|
|
29908
|
-
addedSinkCount: 0
|
|
29938
|
+
addedSinkCount: 0,
|
|
29939
|
+
declarationFindingCount: 0
|
|
29909
29940
|
};
|
|
29910
29941
|
}
|
|
29942
|
+
const file = ctx.graph.ir.meta.file;
|
|
29943
|
+
let declarationFindingCount = 0;
|
|
29944
|
+
for (const rec of mapperMethods) {
|
|
29945
|
+
ctx.addFinding({
|
|
29946
|
+
id: `${this.name}-${file}-${rec.declarationLine}-${rec.methodName}`,
|
|
29947
|
+
pass: this.name,
|
|
29948
|
+
category: this.category,
|
|
29949
|
+
rule_id: this.name,
|
|
29950
|
+
cwe: "CWE-89",
|
|
29951
|
+
severity: "critical",
|
|
29952
|
+
level: "error",
|
|
29953
|
+
message: `MyBatis Mapper method \`${rec.interfaceSimpleName}.${rec.methodName}\` uses raw ` + `\`\${}\` interpolation in its @Select/@Update/@Insert/@Delete annotation. ` + `Any caller passing dynamic input into arg position(s) ` + `${rec.taintedArgPositions.join(", ")} will execute unbound SQL (CWE-89). ` + `Replace \`\${x}\` with \`#{x}\` to enable JDBC parameter binding.`,
|
|
29954
|
+
file,
|
|
29955
|
+
line: rec.declarationLine
|
|
29956
|
+
});
|
|
29957
|
+
declarationFindingCount++;
|
|
29958
|
+
}
|
|
29911
29959
|
const sinks = ctx.hasResult("taint-matcher") ? ctx.getResult("taint-matcher").sinks : ctx.graph.ir.taint.sinks;
|
|
29912
29960
|
let addedSinkCount = 0;
|
|
29913
29961
|
for (const call of calls) {
|
|
@@ -29935,7 +29983,8 @@ class MyBatisAnnotationSqlSinkPass {
|
|
|
29935
29983
|
}
|
|
29936
29984
|
return {
|
|
29937
29985
|
annotatedMethodCount: mapperMethods.length,
|
|
29938
|
-
addedSinkCount
|
|
29986
|
+
addedSinkCount,
|
|
29987
|
+
declarationFindingCount
|
|
29939
29988
|
};
|
|
29940
29989
|
}
|
|
29941
29990
|
}
|
|
@@ -43751,7 +43800,7 @@ var colors = {
|
|
|
43751
43800
|
};
|
|
43752
43801
|
|
|
43753
43802
|
// src/version.ts
|
|
43754
|
-
var version = "3.
|
|
43803
|
+
var version = "3.160.0";
|
|
43755
43804
|
|
|
43756
43805
|
// src/formatters.ts
|
|
43757
43806
|
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.160.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.160.0"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@types/node": "^25.5.0",
|