cognium-dev 3.177.0 → 3.178.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 +160 -2
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -19183,6 +19183,50 @@ function applyLibraryApiSurfaceDowngrade(findings) {
|
|
|
19183
19183
|
});
|
|
19184
19184
|
}
|
|
19185
19185
|
|
|
19186
|
+
// ../circle-ir/dist/analysis/note-coalescer.js
|
|
19187
|
+
function coalesceNoteLevelFindings(findings) {
|
|
19188
|
+
if (findings.length < 2)
|
|
19189
|
+
return [...findings];
|
|
19190
|
+
const groups = new Map;
|
|
19191
|
+
const order = [];
|
|
19192
|
+
for (const f of findings) {
|
|
19193
|
+
const key = `${f.file}\x00${f.line}`;
|
|
19194
|
+
const bucket = groups.get(key);
|
|
19195
|
+
if (bucket) {
|
|
19196
|
+
bucket.push(f);
|
|
19197
|
+
} else {
|
|
19198
|
+
groups.set(key, [f]);
|
|
19199
|
+
order.push(key);
|
|
19200
|
+
}
|
|
19201
|
+
}
|
|
19202
|
+
const out2 = [];
|
|
19203
|
+
for (const key of order) {
|
|
19204
|
+
const bucket = groups.get(key);
|
|
19205
|
+
if (bucket.length === 1) {
|
|
19206
|
+
out2.push(bucket[0]);
|
|
19207
|
+
continue;
|
|
19208
|
+
}
|
|
19209
|
+
const allNote = bucket.every((f) => f.level === "note");
|
|
19210
|
+
if (!allNote) {
|
|
19211
|
+
for (const f of bucket)
|
|
19212
|
+
out2.push(f);
|
|
19213
|
+
continue;
|
|
19214
|
+
}
|
|
19215
|
+
const uniqueRuleIds = new Set(bucket.map((f) => f.rule_id));
|
|
19216
|
+
if (uniqueRuleIds.size < 2) {
|
|
19217
|
+
for (const f of bucket)
|
|
19218
|
+
out2.push(f);
|
|
19219
|
+
continue;
|
|
19220
|
+
}
|
|
19221
|
+
const sorted = [...bucket].sort((a, b) => a.rule_id.localeCompare(b.rule_id));
|
|
19222
|
+
const primary = sorted[0];
|
|
19223
|
+
const additional = sorted.slice(1).map((f) => f.rule_id).concat(...sorted.map((f) => f.labels ?? []));
|
|
19224
|
+
const uniqueLabels = Array.from(new Set(additional)).filter((l) => l !== primary.rule_id);
|
|
19225
|
+
out2.push({ ...primary, labels: uniqueLabels });
|
|
19226
|
+
}
|
|
19227
|
+
return out2;
|
|
19228
|
+
}
|
|
19229
|
+
|
|
19186
19230
|
// ../circle-ir/dist/analysis/entry-point-detection.js
|
|
19187
19231
|
var TIER_1_METHOD_ANNOTATIONS = new Set([
|
|
19188
19232
|
"RequestMapping",
|
|
@@ -32583,6 +32627,117 @@ class SinkSemanticsPass {
|
|
|
32583
32627
|
}
|
|
32584
32628
|
}
|
|
32585
32629
|
|
|
32630
|
+
// ../circle-ir/dist/analysis/dependency-versions.js
|
|
32631
|
+
function resolveFastjsonFromPom(pomXml) {
|
|
32632
|
+
if (!pomXml)
|
|
32633
|
+
return null;
|
|
32634
|
+
const propMatch = pomXml.match(/<fastjson\.version>\s*([^<\s]+)\s*<\/fastjson\.version>/);
|
|
32635
|
+
if (propMatch) {
|
|
32636
|
+
const version = propMatch[1];
|
|
32637
|
+
return { version, noneAutotype: /_noneautotype/i.test(version) };
|
|
32638
|
+
}
|
|
32639
|
+
const depRe = /<dependency>[\s\S]*?<\/dependency>/g;
|
|
32640
|
+
let m;
|
|
32641
|
+
while ((m = depRe.exec(pomXml)) !== null) {
|
|
32642
|
+
const block = m[0];
|
|
32643
|
+
const gid = block.match(/<groupId>\s*([^<\s]+)\s*<\/groupId>/)?.[1];
|
|
32644
|
+
const aid = block.match(/<artifactId>\s*([^<\s]+)\s*<\/artifactId>/)?.[1];
|
|
32645
|
+
if (gid !== "com.alibaba")
|
|
32646
|
+
continue;
|
|
32647
|
+
if (aid !== "fastjson" && aid !== "fastjson2")
|
|
32648
|
+
continue;
|
|
32649
|
+
const ver = block.match(/<version>\s*([^<\s]+)\s*<\/version>/)?.[1];
|
|
32650
|
+
if (!ver)
|
|
32651
|
+
continue;
|
|
32652
|
+
if (/^\$\{/.test(ver))
|
|
32653
|
+
return null;
|
|
32654
|
+
return { version: ver, noneAutotype: /_noneautotype/i.test(ver) };
|
|
32655
|
+
}
|
|
32656
|
+
return null;
|
|
32657
|
+
}
|
|
32658
|
+
function fileReenablesFastjsonAutotype(source) {
|
|
32659
|
+
if (!source)
|
|
32660
|
+
return false;
|
|
32661
|
+
return /\bsetAutoTypeSupport\s*\(\s*true\b/.test(source);
|
|
32662
|
+
}
|
|
32663
|
+
function fileEnablesJacksonPolymorphism(source) {
|
|
32664
|
+
if (!source)
|
|
32665
|
+
return false;
|
|
32666
|
+
if (/\benableDefaultTyping\s*\(/.test(source))
|
|
32667
|
+
return true;
|
|
32668
|
+
if (/\bactivateDefaultTyping\s*\(/.test(source))
|
|
32669
|
+
return true;
|
|
32670
|
+
if (/@JsonTypeInfo\b/.test(source))
|
|
32671
|
+
return true;
|
|
32672
|
+
return false;
|
|
32673
|
+
}
|
|
32674
|
+
function fileConfiguresSnakeYamlSafely(source) {
|
|
32675
|
+
if (!source)
|
|
32676
|
+
return false;
|
|
32677
|
+
if (/\bnew\s+SafeConstructor\s*\(/.test(source))
|
|
32678
|
+
return true;
|
|
32679
|
+
if (/\bSafeConstructor\s+\w+\s*=/.test(source))
|
|
32680
|
+
return true;
|
|
32681
|
+
return false;
|
|
32682
|
+
}
|
|
32683
|
+
|
|
32684
|
+
// ../circle-ir/dist/analysis/passes/deserialization-safety-gate-pass.js
|
|
32685
|
+
var FASTJSON_METHODS = new Set(["parseObject", "parse"]);
|
|
32686
|
+
var FASTJSON_CLASSES = new Set(["JSON", "JSONObject"]);
|
|
32687
|
+
var JACKSON_METHODS = new Set(["readValue", "convertValue", "treeToValue"]);
|
|
32688
|
+
var JACKSON_CLASSES = new Set(["ObjectMapper", "ObjectReader"]);
|
|
32689
|
+
var SNAKEYAML_METHODS = new Set(["load", "loadAs", "loadAll"]);
|
|
32690
|
+
var SNAKEYAML_CLASSES = new Set(["Yaml"]);
|
|
32691
|
+
|
|
32692
|
+
class DeserializationSafetyGatePass {
|
|
32693
|
+
dependencyContext;
|
|
32694
|
+
name = "deserialization-safety-gate";
|
|
32695
|
+
category = "security";
|
|
32696
|
+
constructor(dependencyContext) {
|
|
32697
|
+
this.dependencyContext = dependencyContext;
|
|
32698
|
+
}
|
|
32699
|
+
run(ctx) {
|
|
32700
|
+
const { graph, language, code } = ctx;
|
|
32701
|
+
if (language !== "java") {
|
|
32702
|
+
return { droppedFastjson: 0, droppedJackson: 0, droppedSnakeYaml: 0 };
|
|
32703
|
+
}
|
|
32704
|
+
const sinks = ctx.hasResult("sink-filter") ? ctx.getResult("sink-filter").sinks : graph.ir.taint.sinks;
|
|
32705
|
+
const pomXml = this.dependencyContext?.java?.pomXml;
|
|
32706
|
+
const fastjson = pomXml ? resolveFastjsonFromPom(pomXml) : null;
|
|
32707
|
+
const fastjsonHardened = fastjson?.noneAutotype === true && !fileReenablesFastjsonAutotype(code);
|
|
32708
|
+
const jacksonSafe = !fileEnablesJacksonPolymorphism(code);
|
|
32709
|
+
const snakeYamlSafe = fileConfiguresSnakeYamlSafely(code);
|
|
32710
|
+
let droppedFastjson = 0;
|
|
32711
|
+
let droppedJackson = 0;
|
|
32712
|
+
let droppedSnakeYaml = 0;
|
|
32713
|
+
const kept = sinks.filter((sink) => {
|
|
32714
|
+
if (sink.type !== "deserialization")
|
|
32715
|
+
return true;
|
|
32716
|
+
if (!sink.method)
|
|
32717
|
+
return true;
|
|
32718
|
+
if (fastjsonHardened && FASTJSON_METHODS.has(sink.method) && (sink.class === undefined || FASTJSON_CLASSES.has(sink.class))) {
|
|
32719
|
+
droppedFastjson++;
|
|
32720
|
+
return false;
|
|
32721
|
+
}
|
|
32722
|
+
if (jacksonSafe && JACKSON_METHODS.has(sink.method) && sink.class !== undefined && JACKSON_CLASSES.has(sink.class)) {
|
|
32723
|
+
droppedJackson++;
|
|
32724
|
+
return false;
|
|
32725
|
+
}
|
|
32726
|
+
if (snakeYamlSafe && SNAKEYAML_METHODS.has(sink.method) && sink.class !== undefined && SNAKEYAML_CLASSES.has(sink.class)) {
|
|
32727
|
+
droppedSnakeYaml++;
|
|
32728
|
+
return false;
|
|
32729
|
+
}
|
|
32730
|
+
return true;
|
|
32731
|
+
});
|
|
32732
|
+
const totalDropped = droppedFastjson + droppedJackson + droppedSnakeYaml;
|
|
32733
|
+
if (totalDropped > 0) {
|
|
32734
|
+
sinks.length = 0;
|
|
32735
|
+
sinks.push(...kept);
|
|
32736
|
+
}
|
|
32737
|
+
return { droppedFastjson, droppedJackson, droppedSnakeYaml };
|
|
32738
|
+
}
|
|
32739
|
+
}
|
|
32740
|
+
|
|
32586
32741
|
// ../circle-ir/dist/analysis/passes/cli-main-reflection-suppress-pass.js
|
|
32587
32742
|
var REFLECTION_SINK_METHODS = new Set([
|
|
32588
32743
|
"forName",
|
|
@@ -44124,6 +44279,8 @@ async function analyze(code, filePath, language, options = {}) {
|
|
|
44124
44279
|
pipeline.add(new SinkFilterPass);
|
|
44125
44280
|
if (!disabledPasses.has("sink-semantics"))
|
|
44126
44281
|
pipeline.add(new SinkSemanticsPass);
|
|
44282
|
+
if (!disabledPasses.has("deserialization-safety-gate"))
|
|
44283
|
+
pipeline.add(new DeserializationSafetyGatePass(options.dependencyContext));
|
|
44127
44284
|
if (!disabledPasses.has("cli-main-reflection-suppress"))
|
|
44128
44285
|
pipeline.add(new CliMainReflectionSuppressPass);
|
|
44129
44286
|
if (!disabledPasses.has("library-profile-sink-gate"))
|
|
@@ -44285,7 +44442,8 @@ async function analyze(code, filePath, language, options = {}) {
|
|
|
44285
44442
|
const verifiedFindings = applyConfidenceFilter(findings, options.includeSpeculative === true);
|
|
44286
44443
|
const downgradedFindings = applyLibraryApiSurfaceDowngrade(verifiedFindings);
|
|
44287
44444
|
const profiledFindings = applyProjectProfileTransform(downgradedFindings, makeProfileResolver2(options.projectProfile));
|
|
44288
|
-
const
|
|
44445
|
+
const coalescedFindings = coalesceNoteLevelFindings(profiledFindings);
|
|
44446
|
+
const cappedFindings = applyPerFileFindingCap(filePath, coalescedFindings, options.perFileFindingCap ?? DEFAULT_PER_FILE_FINDING_CAP);
|
|
44289
44447
|
return {
|
|
44290
44448
|
meta,
|
|
44291
44449
|
types,
|
|
@@ -45066,7 +45224,7 @@ var colors = {
|
|
|
45066
45224
|
};
|
|
45067
45225
|
|
|
45068
45226
|
// src/version.ts
|
|
45069
|
-
var version = "3.
|
|
45227
|
+
var version = "3.178.0";
|
|
45070
45228
|
|
|
45071
45229
|
// src/formatters.ts
|
|
45072
45230
|
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.178.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.178.0"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@types/node": "^25.5.0",
|