@cyclonedx/cdxgen 10.3.4 → 10.4.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/README.md +2 -4
- package/analyzer.js +18 -18
- package/bin/cdxgen.js +79 -77
- package/bin/evinse.js +26 -26
- package/bin/repl.js +56 -62
- package/bin/verify.js +9 -9
- package/binary.js +55 -54
- package/cbomutils.js +6 -6
- package/db.js +17 -17
- package/display.js +30 -30
- package/display.test.js +2 -2
- package/docker.js +92 -89
- package/docker.test.js +30 -30
- package/envcontext.js +15 -15
- package/envcontext.test.js +1 -1
- package/evinser.js +94 -93
- package/evinser.test.js +24 -24
- package/index.js +523 -483
- package/package.json +8 -16
- package/piptree.js +6 -6
- package/postgen.js +2 -2
- package/postgen.test.js +5 -5
- package/protobom.js +37 -7
- package/protobom.test.js +6 -6
- package/server.js +16 -16
- package/types/analyzer.d.ts +7 -4
- package/types/binary.d.ts +12 -8
- package/types/cbomutils.d.ts +1 -1
- package/types/db.d.ts +23 -11
- package/types/display.d.ts +1 -1
- package/types/docker.d.ts +52 -32
- package/types/envcontext.d.ts +40 -40
- package/types/evinser.d.ts +3436 -717
- package/types/index.d.ts +66 -40
- package/types/jest.config.d.ts +2 -2
- package/types/piptree.d.ts +6 -2
- package/types/postgen.d.ts +1 -1
- package/types/protobom.d.ts +7 -3
- package/types/protobom.d.ts.map +1 -1
- package/types/server.d.ts +1 -1
- package/types/utils.d.ts +496 -302
- package/types/validator.d.ts +1 -1
- package/utils.js +742 -675
- package/utils.test.js +716 -674
- package/validator.js +20 -17
package/binary.js
CHANGED
|
@@ -1,18 +1,24 @@
|
|
|
1
|
-
import { arch as _arch, platform as _platform, homedir, tmpdir } from "node:os";
|
|
2
|
-
import process from "node:process";
|
|
3
1
|
import { Buffer } from "node:buffer";
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
4
3
|
import {
|
|
5
4
|
existsSync,
|
|
5
|
+
lstatSync,
|
|
6
6
|
mkdirSync,
|
|
7
7
|
mkdtempSync,
|
|
8
8
|
readFileSync,
|
|
9
9
|
rmSync,
|
|
10
|
-
lstatSync
|
|
11
10
|
} from "node:fs";
|
|
11
|
+
import { arch as _arch, platform as _platform, homedir, tmpdir } from "node:os";
|
|
12
12
|
import { basename, dirname, join, resolve } from "node:path";
|
|
13
|
-
import
|
|
13
|
+
import process from "node:process";
|
|
14
14
|
import { PackageURL } from "packageurl-js";
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
DEBUG_MODE,
|
|
17
|
+
TIMEOUT_MS,
|
|
18
|
+
adjustLicenseInformation,
|
|
19
|
+
findLicenseId,
|
|
20
|
+
isSpdxLicenseExpression,
|
|
21
|
+
} from "./utils.js";
|
|
16
22
|
|
|
17
23
|
import { URL, fileURLToPath } from "node:url";
|
|
18
24
|
|
|
@@ -78,8 +84,8 @@ if (
|
|
|
78
84
|
"node_modules",
|
|
79
85
|
"@cyclonedx",
|
|
80
86
|
"cdxgen-plugins-bin" + pluginsBinSuffix,
|
|
81
|
-
"plugins"
|
|
82
|
-
)
|
|
87
|
+
"plugins",
|
|
88
|
+
),
|
|
83
89
|
) &&
|
|
84
90
|
existsSync(
|
|
85
91
|
join(
|
|
@@ -88,8 +94,8 @@ if (
|
|
|
88
94
|
"@cyclonedx",
|
|
89
95
|
"cdxgen-plugins-bin" + pluginsBinSuffix,
|
|
90
96
|
"plugins",
|
|
91
|
-
"goversion"
|
|
92
|
-
)
|
|
97
|
+
"goversion",
|
|
98
|
+
),
|
|
93
99
|
)
|
|
94
100
|
) {
|
|
95
101
|
CDXGEN_PLUGINS_DIR = join(
|
|
@@ -97,7 +103,7 @@ if (
|
|
|
97
103
|
"node_modules",
|
|
98
104
|
"@cyclonedx",
|
|
99
105
|
"cdxgen-plugins-bin" + pluginsBinSuffix,
|
|
100
|
-
"plugins"
|
|
106
|
+
"plugins",
|
|
101
107
|
);
|
|
102
108
|
}
|
|
103
109
|
|
|
@@ -108,8 +114,8 @@ if (!CDXGEN_PLUGINS_DIR) {
|
|
|
108
114
|
isWin ? "npm.cmd" : "npm",
|
|
109
115
|
["root", "--quiet", "-g"],
|
|
110
116
|
{
|
|
111
|
-
encoding: "utf-8"
|
|
112
|
-
}
|
|
117
|
+
encoding: "utf-8",
|
|
118
|
+
},
|
|
113
119
|
);
|
|
114
120
|
if (result) {
|
|
115
121
|
const stdout = result.stdout;
|
|
@@ -123,7 +129,7 @@ if (!CDXGEN_PLUGINS_DIR) {
|
|
|
123
129
|
globalNodePath,
|
|
124
130
|
"@cyclonedx",
|
|
125
131
|
"cdxgen-plugins-bin" + pluginsBinSuffix,
|
|
126
|
-
"plugins"
|
|
132
|
+
"plugins",
|
|
127
133
|
);
|
|
128
134
|
if (existsSync(globalPlugins)) {
|
|
129
135
|
CDXGEN_PLUGINS_DIR = globalPlugins;
|
|
@@ -137,7 +143,7 @@ if (!CDXGEN_PLUGINS_DIR) {
|
|
|
137
143
|
if (!CDXGEN_PLUGINS_DIR) {
|
|
138
144
|
if (DEBUG_MODE) {
|
|
139
145
|
console.warn(
|
|
140
|
-
"cdxgen plugins was not found. Please install with npm install -g @cyclonedx/cdxgen-plugins-bin"
|
|
146
|
+
"cdxgen plugins was not found. Please install with npm install -g @cyclonedx/cdxgen-plugins-bin",
|
|
141
147
|
);
|
|
142
148
|
}
|
|
143
149
|
CDXGEN_PLUGINS_DIR = "";
|
|
@@ -147,7 +153,7 @@ if (existsSync(join(CDXGEN_PLUGINS_DIR, "goversion"))) {
|
|
|
147
153
|
GOVERSION_BIN = join(
|
|
148
154
|
CDXGEN_PLUGINS_DIR,
|
|
149
155
|
"goversion",
|
|
150
|
-
"goversion-" + platform + "-" + arch + extn
|
|
156
|
+
"goversion-" + platform + "-" + arch + extn,
|
|
151
157
|
);
|
|
152
158
|
}
|
|
153
159
|
let TRIVY_BIN = null;
|
|
@@ -155,7 +161,7 @@ if (existsSync(join(CDXGEN_PLUGINS_DIR, "trivy"))) {
|
|
|
155
161
|
TRIVY_BIN = join(
|
|
156
162
|
CDXGEN_PLUGINS_DIR,
|
|
157
163
|
"trivy",
|
|
158
|
-
"trivy-cdxgen-" + platform + "-" + arch + extn
|
|
164
|
+
"trivy-cdxgen-" + platform + "-" + arch + extn,
|
|
159
165
|
);
|
|
160
166
|
} else if (process.env.TRIVY_CMD) {
|
|
161
167
|
TRIVY_BIN = process.env.TRIVY_CMD;
|
|
@@ -165,7 +171,7 @@ if (existsSync(join(CDXGEN_PLUGINS_DIR, "cargo-auditable"))) {
|
|
|
165
171
|
CARGO_AUDITABLE_BIN = join(
|
|
166
172
|
CDXGEN_PLUGINS_DIR,
|
|
167
173
|
"cargo-auditable",
|
|
168
|
-
"cargo-auditable-cdxgen-" + platform + "-" + arch + extn
|
|
174
|
+
"cargo-auditable-cdxgen-" + platform + "-" + arch + extn,
|
|
169
175
|
);
|
|
170
176
|
} else if (process.env.CARGO_AUDITABLE_CMD) {
|
|
171
177
|
CARGO_AUDITABLE_BIN = process.env.CARGO_AUDITABLE_CMD;
|
|
@@ -175,7 +181,7 @@ if (existsSync(join(CDXGEN_PLUGINS_DIR, "osquery"))) {
|
|
|
175
181
|
OSQUERY_BIN = join(
|
|
176
182
|
CDXGEN_PLUGINS_DIR,
|
|
177
183
|
"osquery",
|
|
178
|
-
"osqueryi-" + platform + "-" + arch + extn
|
|
184
|
+
"osqueryi-" + platform + "-" + arch + extn,
|
|
179
185
|
);
|
|
180
186
|
// osqueryi-darwin-amd64.app/Contents/MacOS/osqueryd
|
|
181
187
|
if (platform === "darwin") {
|
|
@@ -193,7 +199,7 @@ if (existsSync(join(CDXGEN_PLUGINS_DIR, "dosai"))) {
|
|
|
193
199
|
DOSAI_BIN = join(
|
|
194
200
|
CDXGEN_PLUGINS_DIR,
|
|
195
201
|
"dosai",
|
|
196
|
-
"dosai-" + platformToUse + "-" + arch + extn
|
|
202
|
+
"dosai-" + platformToUse + "-" + arch + extn,
|
|
197
203
|
);
|
|
198
204
|
} else if (process.env.DOSAI_CMD) {
|
|
199
205
|
DOSAI_BIN = process.env.DOSAI_CMD;
|
|
@@ -265,13 +271,13 @@ const OS_DISTRO_ALIAS = {
|
|
|
265
271
|
"debian-2": "hamm",
|
|
266
272
|
"debian-1.3": "bo",
|
|
267
273
|
"debian-1.2": "rex",
|
|
268
|
-
"debian-1.1": "buzz"
|
|
274
|
+
"debian-1.1": "buzz",
|
|
269
275
|
};
|
|
270
276
|
|
|
271
277
|
export function getGoBuildInfo(src) {
|
|
272
278
|
if (GOVERSION_BIN) {
|
|
273
279
|
let result = spawnSync(GOVERSION_BIN, [src], {
|
|
274
|
-
encoding: "utf-8"
|
|
280
|
+
encoding: "utf-8",
|
|
275
281
|
});
|
|
276
282
|
if (result.status !== 0 || result.error || !result.stdout) {
|
|
277
283
|
if (result.stdout || result.stderr) {
|
|
@@ -281,7 +287,7 @@ export function getGoBuildInfo(src) {
|
|
|
281
287
|
console.log("Falling back to go version command");
|
|
282
288
|
}
|
|
283
289
|
result = spawnSync("go", ["version", "-v", "-m", src], {
|
|
284
|
-
encoding: "utf-8"
|
|
290
|
+
encoding: "utf-8",
|
|
285
291
|
});
|
|
286
292
|
if (result.status !== 0 || result.error) {
|
|
287
293
|
if (result.stdout || result.stderr) {
|
|
@@ -303,7 +309,7 @@ export function getGoBuildInfo(src) {
|
|
|
303
309
|
export function getCargoAuditableInfo(src) {
|
|
304
310
|
if (CARGO_AUDITABLE_BIN) {
|
|
305
311
|
const result = spawnSync(CARGO_AUDITABLE_BIN, [src], {
|
|
306
|
-
encoding: "utf-8"
|
|
312
|
+
encoding: "utf-8",
|
|
307
313
|
});
|
|
308
314
|
if (result.status !== 0 || result.error) {
|
|
309
315
|
if (result.stdout || result.stderr) {
|
|
@@ -354,7 +360,7 @@ export function getOSPackages(src) {
|
|
|
354
360
|
"--cache-dir",
|
|
355
361
|
trivyCacheDir,
|
|
356
362
|
"--output",
|
|
357
|
-
bomJsonFile
|
|
363
|
+
bomJsonFile,
|
|
358
364
|
];
|
|
359
365
|
if (!DEBUG_MODE) {
|
|
360
366
|
args.push("-q");
|
|
@@ -364,7 +370,7 @@ export function getOSPackages(src) {
|
|
|
364
370
|
console.log("Executing", TRIVY_BIN, args.join(" "));
|
|
365
371
|
}
|
|
366
372
|
const result = spawnSync(TRIVY_BIN, args, {
|
|
367
|
-
encoding: "utf-8"
|
|
373
|
+
encoding: "utf-8",
|
|
368
374
|
});
|
|
369
375
|
if (result.status !== 0 || result.error) {
|
|
370
376
|
if (result.stdout || result.stderr) {
|
|
@@ -376,8 +382,8 @@ export function getOSPackages(src) {
|
|
|
376
382
|
try {
|
|
377
383
|
tmpBom = JSON.parse(
|
|
378
384
|
readFileSync(bomJsonFile, {
|
|
379
|
-
encoding: "utf-8"
|
|
380
|
-
})
|
|
385
|
+
encoding: "utf-8",
|
|
386
|
+
}),
|
|
381
387
|
);
|
|
382
388
|
} catch (e) {
|
|
383
389
|
// ignore errors
|
|
@@ -515,7 +521,7 @@ export function getOSPackages(src) {
|
|
|
515
521
|
name,
|
|
516
522
|
purlObj.version,
|
|
517
523
|
purlObj.qualifiers,
|
|
518
|
-
purlObj.subpath
|
|
524
|
+
purlObj.subpath,
|
|
519
525
|
).toString();
|
|
520
526
|
comp["bom-ref"] = decodeURIComponent(comp.purl);
|
|
521
527
|
}
|
|
@@ -543,7 +549,7 @@ export function getOSPackages(src) {
|
|
|
543
549
|
if (dtmpA && dtmpA.length > 1) {
|
|
544
550
|
distro_codename = dtmpA[0].replace(
|
|
545
551
|
"redhat",
|
|
546
|
-
"enterprise_linux"
|
|
552
|
+
"enterprise_linux",
|
|
547
553
|
);
|
|
548
554
|
}
|
|
549
555
|
}
|
|
@@ -557,7 +563,7 @@ export function getOSPackages(src) {
|
|
|
557
563
|
name,
|
|
558
564
|
purlObj.version,
|
|
559
565
|
purlObj.qualifiers,
|
|
560
|
-
purlObj.subpath
|
|
566
|
+
purlObj.subpath,
|
|
561
567
|
).toString();
|
|
562
568
|
comp["bom-ref"] = decodeURIComponent(comp.purl);
|
|
563
569
|
}
|
|
@@ -572,33 +578,28 @@ export function getOSPackages(src) {
|
|
|
572
578
|
comp.licenses.length
|
|
573
579
|
) {
|
|
574
580
|
const newLicenses = [];
|
|
575
|
-
for (const
|
|
576
|
-
if (
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
comp.licenses.length == 1 &&
|
|
580
|
-
(alic.license.name.toUpperCase().includes(" AND ") ||
|
|
581
|
-
alic.license.name.toUpperCase().includes(" OR "))
|
|
582
|
-
) {
|
|
583
|
-
newLicenses.push({ expression: alic.license.name });
|
|
581
|
+
for (const aLic of comp.licenses) {
|
|
582
|
+
if (aLic.license.name) {
|
|
583
|
+
if (isSpdxLicenseExpression(aLic.license.name)) {
|
|
584
|
+
newLicenses.push({ expression: aLic.license.name });
|
|
584
585
|
} else {
|
|
585
|
-
const possibleId = findLicenseId(
|
|
586
|
-
if (possibleId !==
|
|
586
|
+
const possibleId = findLicenseId(aLic.license.name);
|
|
587
|
+
if (possibleId !== aLic.license.name) {
|
|
587
588
|
newLicenses.push({ license: { id: possibleId } });
|
|
588
589
|
} else {
|
|
589
590
|
newLicenses.push({
|
|
590
|
-
license: { name:
|
|
591
|
+
license: { name: aLic.license.name },
|
|
591
592
|
});
|
|
592
593
|
}
|
|
593
594
|
}
|
|
594
595
|
} else if (
|
|
595
|
-
Object.keys(
|
|
596
|
-
Object.keys(
|
|
596
|
+
Object.keys(aLic).length &&
|
|
597
|
+
Object.keys(aLic.license).length
|
|
597
598
|
) {
|
|
598
|
-
newLicenses.push(
|
|
599
|
+
newLicenses.push(aLic);
|
|
599
600
|
}
|
|
600
601
|
}
|
|
601
|
-
comp.licenses = newLicenses;
|
|
602
|
+
comp.licenses = adjustLicenseInformation(newLicenses);
|
|
602
603
|
}
|
|
603
604
|
// Fix hashes
|
|
604
605
|
if (
|
|
@@ -629,7 +630,7 @@ export function getOSPackages(src) {
|
|
|
629
630
|
const compDeps = retrieveDependencies(
|
|
630
631
|
tmpDependencies,
|
|
631
632
|
origBomRef,
|
|
632
|
-
comp
|
|
633
|
+
comp,
|
|
633
634
|
);
|
|
634
635
|
if (compDeps) {
|
|
635
636
|
dependenciesList.push(compDeps);
|
|
@@ -646,7 +647,7 @@ export function getOSPackages(src) {
|
|
|
646
647
|
srcName,
|
|
647
648
|
srcVersion,
|
|
648
649
|
purlObj.qualifiers,
|
|
649
|
-
purlObj.subpath
|
|
650
|
+
purlObj.subpath,
|
|
650
651
|
).toString();
|
|
651
652
|
}
|
|
652
653
|
newComp["bom-ref"] = decodeURIComponent(newComp.purl);
|
|
@@ -660,7 +661,7 @@ export function getOSPackages(src) {
|
|
|
660
661
|
return {
|
|
661
662
|
osPackages: pkgList,
|
|
662
663
|
dependenciesList,
|
|
663
|
-
allTypes: Array.from(allTypes)
|
|
664
|
+
allTypes: Array.from(allTypes),
|
|
664
665
|
};
|
|
665
666
|
}
|
|
666
667
|
|
|
@@ -714,7 +715,7 @@ export function executeOsQuery(query) {
|
|
|
714
715
|
const result = spawnSync(OSQUERY_BIN, args, {
|
|
715
716
|
encoding: "utf-8",
|
|
716
717
|
maxBuffer: 50 * 1024 * 1024,
|
|
717
|
-
timeout: 60 * 1000
|
|
718
|
+
timeout: 60 * 1000,
|
|
718
719
|
});
|
|
719
720
|
if (result.status !== 0 || result.error) {
|
|
720
721
|
if (DEBUG_MODE && result.stderr) {
|
|
@@ -733,7 +734,7 @@ export function executeOsQuery(query) {
|
|
|
733
734
|
if (DEBUG_MODE) {
|
|
734
735
|
console.log("Unable to parse the output from query", query);
|
|
735
736
|
console.log(
|
|
736
|
-
"This could be due to the amount of data returned or the query being invalid for the given platform."
|
|
737
|
+
"This could be due to the amount of data returned or the query being invalid for the given platform.",
|
|
737
738
|
);
|
|
738
739
|
}
|
|
739
740
|
}
|
|
@@ -763,7 +764,7 @@ export function getDotnetSlices(src, slicesFile) {
|
|
|
763
764
|
const result = spawnSync(DOSAI_BIN, args, {
|
|
764
765
|
encoding: "utf-8",
|
|
765
766
|
timeout: TIMEOUT_MS,
|
|
766
|
-
cwd: src
|
|
767
|
+
cwd: src,
|
|
767
768
|
});
|
|
768
769
|
if (result.status !== 0 || result.error) {
|
|
769
770
|
if (DEBUG_MODE && result.error) {
|
|
@@ -802,14 +803,14 @@ export function getBinaryBom(src, binaryBomFile, deepMode) {
|
|
|
802
803
|
const result = spawnSync(BLINT_BIN, args, {
|
|
803
804
|
encoding: "utf-8",
|
|
804
805
|
timeout: TIMEOUT_MS,
|
|
805
|
-
cwd
|
|
806
|
+
cwd,
|
|
806
807
|
});
|
|
807
808
|
if (result.status !== 0 || result.error) {
|
|
808
809
|
if (result.stderr) {
|
|
809
810
|
console.error(result.stdout, result.stderr);
|
|
810
811
|
} else {
|
|
811
812
|
console.log(
|
|
812
|
-
"Install blint using 'pip install blint' or use the cdxgen container image."
|
|
813
|
+
"Install blint using 'pip install blint' or use the cdxgen container image.",
|
|
813
814
|
);
|
|
814
815
|
}
|
|
815
816
|
return false;
|
package/cbomutils.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
|
-
import { convertOSQueryResults, dirNameStr } from "./utils.js";
|
|
3
|
-
import { executeOsQuery } from "./binary.js";
|
|
4
2
|
import { join } from "node:path";
|
|
3
|
+
import { executeOsQuery } from "./binary.js";
|
|
4
|
+
import { convertOSQueryResults, dirNameStr } from "./utils.js";
|
|
5
5
|
const cbomosDbQueries = JSON.parse(
|
|
6
|
-
readFileSync(join(dirNameStr, "data", "cbomosdb-queries.json"), "utf-8")
|
|
6
|
+
readFileSync(join(dirNameStr, "data", "cbomosdb-queries.json"), "utf-8"),
|
|
7
7
|
);
|
|
8
8
|
const cbomCryptoOids = JSON.parse(
|
|
9
|
-
readFileSync(join(dirNameStr, "data", "crypto-oid.json"), "utf-8")
|
|
9
|
+
readFileSync(join(dirNameStr, "data", "crypto-oid.json"), "utf-8"),
|
|
10
10
|
);
|
|
11
11
|
|
|
12
12
|
/**
|
|
@@ -24,7 +24,7 @@ export function collectOSCryptoLibs(options) {
|
|
|
24
24
|
queryCategory,
|
|
25
25
|
queryObj,
|
|
26
26
|
results,
|
|
27
|
-
false
|
|
27
|
+
false,
|
|
28
28
|
);
|
|
29
29
|
if (dlist && dlist.length) {
|
|
30
30
|
osPkgsList = osPkgsList.concat(dlist);
|
|
@@ -59,7 +59,7 @@ export function findCryptoAlgos(code) {
|
|
|
59
59
|
cryptoAlgos.push({
|
|
60
60
|
...cbomCryptoOids[algoName],
|
|
61
61
|
name: algoName,
|
|
62
|
-
ref: `crypto/algorithm/${algoName}@${cbomCryptoOids[algoName].oid}
|
|
62
|
+
ref: `crypto/algorithm/${algoName}@${cbomCryptoOids[algoName].oid}`,
|
|
63
63
|
});
|
|
64
64
|
}
|
|
65
65
|
}
|
package/db.js
CHANGED
|
@@ -9,7 +9,7 @@ class DataFlows extends Model {}
|
|
|
9
9
|
export const createOrLoad = async (dbName, dbPath, logging = false) => {
|
|
10
10
|
const sequelize = new Sequelize({
|
|
11
11
|
define: {
|
|
12
|
-
freezeTableName: true
|
|
12
|
+
freezeTableName: true,
|
|
13
13
|
},
|
|
14
14
|
dialect: "sqlite",
|
|
15
15
|
dialectOptions: {
|
|
@@ -17,7 +17,7 @@ export const createOrLoad = async (dbName, dbPath, logging = false) => {
|
|
|
17
17
|
SQLite.OPEN_READWRITE |
|
|
18
18
|
SQLite.OPEN_CREATE |
|
|
19
19
|
SQLite.OPEN_NOMUTEX |
|
|
20
|
-
SQLite.OPEN_SHAREDCACHE
|
|
20
|
+
SQLite.OPEN_SHAREDCACHE,
|
|
21
21
|
},
|
|
22
22
|
storage: dbPath.includes("memory") ? dbPath : path.join(dbPath, dbName),
|
|
23
23
|
logging,
|
|
@@ -25,56 +25,56 @@ export const createOrLoad = async (dbName, dbPath, logging = false) => {
|
|
|
25
25
|
max: 5,
|
|
26
26
|
min: 0,
|
|
27
27
|
acquire: 30000,
|
|
28
|
-
idle: 10000
|
|
29
|
-
}
|
|
28
|
+
idle: 10000,
|
|
29
|
+
},
|
|
30
30
|
});
|
|
31
31
|
Namespaces.init(
|
|
32
32
|
{
|
|
33
33
|
purl: {
|
|
34
34
|
type: DataTypes.STRING,
|
|
35
35
|
allowNull: false,
|
|
36
|
-
primaryKey: true
|
|
36
|
+
primaryKey: true,
|
|
37
37
|
},
|
|
38
38
|
data: {
|
|
39
39
|
type: DataTypes.JSON,
|
|
40
|
-
allowNull: false
|
|
41
|
-
}
|
|
40
|
+
allowNull: false,
|
|
41
|
+
},
|
|
42
42
|
},
|
|
43
|
-
{ sequelize, modelName: "Namespaces" }
|
|
43
|
+
{ sequelize, modelName: "Namespaces" },
|
|
44
44
|
);
|
|
45
45
|
Usages.init(
|
|
46
46
|
{
|
|
47
47
|
purl: {
|
|
48
48
|
type: DataTypes.STRING,
|
|
49
49
|
allowNull: false,
|
|
50
|
-
primaryKey: true
|
|
50
|
+
primaryKey: true,
|
|
51
51
|
},
|
|
52
52
|
data: {
|
|
53
53
|
type: DataTypes.JSON,
|
|
54
|
-
allowNull: false
|
|
55
|
-
}
|
|
54
|
+
allowNull: false,
|
|
55
|
+
},
|
|
56
56
|
},
|
|
57
|
-
{ sequelize, modelName: "Usages" }
|
|
57
|
+
{ sequelize, modelName: "Usages" },
|
|
58
58
|
);
|
|
59
59
|
DataFlows.init(
|
|
60
60
|
{
|
|
61
61
|
purl: {
|
|
62
62
|
type: DataTypes.STRING,
|
|
63
63
|
allowNull: false,
|
|
64
|
-
primaryKey: true
|
|
64
|
+
primaryKey: true,
|
|
65
65
|
},
|
|
66
66
|
data: {
|
|
67
67
|
type: DataTypes.JSON,
|
|
68
|
-
allowNull: false
|
|
69
|
-
}
|
|
68
|
+
allowNull: false,
|
|
69
|
+
},
|
|
70
70
|
},
|
|
71
|
-
{ sequelize, modelName: "DataFlows" }
|
|
71
|
+
{ sequelize, modelName: "DataFlows" },
|
|
72
72
|
);
|
|
73
73
|
await sequelize.sync();
|
|
74
74
|
return {
|
|
75
75
|
sequelize,
|
|
76
76
|
Namespaces,
|
|
77
77
|
Usages,
|
|
78
|
-
DataFlows
|
|
78
|
+
DataFlows,
|
|
79
79
|
};
|
|
80
80
|
};
|
package/display.js
CHANGED
|
@@ -7,7 +7,7 @@ const SYMBOLS_ANSI = {
|
|
|
7
7
|
EMPTY: "",
|
|
8
8
|
INDENT: " ",
|
|
9
9
|
LAST_BRANCH: "└── ",
|
|
10
|
-
VERTICAL: "│ "
|
|
10
|
+
VERTICAL: "│ ",
|
|
11
11
|
};
|
|
12
12
|
|
|
13
13
|
const MAX_TREE_DEPTH = 6;
|
|
@@ -25,15 +25,15 @@ export const printTable = (bomJson) => {
|
|
|
25
25
|
}
|
|
26
26
|
const config = {
|
|
27
27
|
columnDefault: {
|
|
28
|
-
width: 30
|
|
28
|
+
width: 30,
|
|
29
29
|
},
|
|
30
30
|
columnCount: 4,
|
|
31
31
|
columns: [
|
|
32
32
|
{ width: 25 },
|
|
33
33
|
{ width: 35 },
|
|
34
34
|
{ width: 25, alignment: "right" },
|
|
35
|
-
{ width: 15 }
|
|
36
|
-
]
|
|
35
|
+
{ width: 15 },
|
|
36
|
+
],
|
|
37
37
|
};
|
|
38
38
|
const stream = createStream(config);
|
|
39
39
|
stream.write(["Group", "Name", "Version", "Scope"]);
|
|
@@ -42,7 +42,7 @@ export const printTable = (bomJson) => {
|
|
|
42
42
|
comp.group || "",
|
|
43
43
|
comp.name,
|
|
44
44
|
`\x1b[1;35m${comp.version || ""}\x1b[0m`,
|
|
45
|
-
comp.scope || ""
|
|
45
|
+
comp.scope || "",
|
|
46
46
|
]);
|
|
47
47
|
}
|
|
48
48
|
console.log();
|
|
@@ -51,7 +51,7 @@ export const printTable = (bomJson) => {
|
|
|
51
51
|
bomJson.components.length,
|
|
52
52
|
"components and",
|
|
53
53
|
bomJson.dependencies.length,
|
|
54
|
-
"dependencies"
|
|
54
|
+
"dependencies",
|
|
55
55
|
);
|
|
56
56
|
};
|
|
57
57
|
const formatProps = (props) => {
|
|
@@ -64,10 +64,10 @@ const formatProps = (props) => {
|
|
|
64
64
|
export const printOSTable = (bomJson) => {
|
|
65
65
|
const config = {
|
|
66
66
|
columnDefault: {
|
|
67
|
-
width: 50
|
|
67
|
+
width: 50,
|
|
68
68
|
},
|
|
69
69
|
columnCount: 3,
|
|
70
|
-
columns: [{ width: 20 }, { width: 40 }, { width: 50 }]
|
|
70
|
+
columns: [{ width: 20 }, { width: 40 }, { width: 50 }],
|
|
71
71
|
};
|
|
72
72
|
const stream = createStream(config);
|
|
73
73
|
stream.write(["Type", "Title", "Properties"]);
|
|
@@ -75,7 +75,7 @@ export const printOSTable = (bomJson) => {
|
|
|
75
75
|
stream.write([
|
|
76
76
|
comp.type,
|
|
77
77
|
`\x1b[1;35m${comp.name.replace(/\+/g, " ").replace(/--/g, "::")}\x1b[0m`,
|
|
78
|
-
formatProps(comp.properties || [])
|
|
78
|
+
formatProps(comp.properties || []),
|
|
79
79
|
]);
|
|
80
80
|
}
|
|
81
81
|
console.log();
|
|
@@ -90,14 +90,14 @@ export const printServices = (bomJson) => {
|
|
|
90
90
|
aservice.name || "",
|
|
91
91
|
aservice.endpoints ? aservice.endpoints.join("\n") : "",
|
|
92
92
|
aservice.authenticated ? "\x1b[1;35mYes\x1b[0m" : "",
|
|
93
|
-
aservice.xTrustBoundary ? "\x1b[1;35mYes\x1b[0m" : ""
|
|
93
|
+
aservice.xTrustBoundary ? "\x1b[1;35mYes\x1b[0m" : "",
|
|
94
94
|
]);
|
|
95
95
|
}
|
|
96
96
|
const config = {
|
|
97
97
|
header: {
|
|
98
98
|
alignment: "center",
|
|
99
|
-
content: "List of Services\nGenerated with \u2665 by cdxgen"
|
|
100
|
-
}
|
|
99
|
+
content: "List of Services\nGenerated with \u2665 by cdxgen",
|
|
100
|
+
},
|
|
101
101
|
};
|
|
102
102
|
if (data.length > 1) {
|
|
103
103
|
console.log(table(data, config));
|
|
@@ -133,14 +133,14 @@ export const printOccurrences = (bomJson) => {
|
|
|
133
133
|
comp.evidence.occurrences
|
|
134
134
|
.map((l) => l.location)
|
|
135
135
|
.sort(locationComparator)
|
|
136
|
-
.join("\n")
|
|
136
|
+
.join("\n"),
|
|
137
137
|
]);
|
|
138
138
|
}
|
|
139
139
|
const config = {
|
|
140
140
|
header: {
|
|
141
141
|
alignment: "center",
|
|
142
|
-
content: "Component Evidence\nGenerated with \u2665 by cdxgen"
|
|
143
|
-
}
|
|
142
|
+
content: "Component Evidence\nGenerated with \u2665 by cdxgen",
|
|
143
|
+
},
|
|
144
144
|
};
|
|
145
145
|
if (data.length > 1) {
|
|
146
146
|
console.log(table(data, config));
|
|
@@ -162,9 +162,9 @@ export const printCallStack = (bomJson) => {
|
|
|
162
162
|
const frames = Array.from(
|
|
163
163
|
new Set(
|
|
164
164
|
comp.evidence.callstack.frames.map(
|
|
165
|
-
(c) => `${c.fullFilename}${c.line ? "#" + c.line : ""}
|
|
166
|
-
)
|
|
167
|
-
)
|
|
165
|
+
(c) => `${c.fullFilename}${c.line ? "#" + c.line : ""}`,
|
|
166
|
+
),
|
|
167
|
+
),
|
|
168
168
|
).sort(locationComparator);
|
|
169
169
|
const frameDisplay = [frames[0]];
|
|
170
170
|
if (frames.length > 1) {
|
|
@@ -172,21 +172,21 @@ export const printCallStack = (bomJson) => {
|
|
|
172
172
|
frameDisplay.push(`${SYMBOLS_ANSI.BRANCH} ${frames[i]}`);
|
|
173
173
|
}
|
|
174
174
|
frameDisplay.push(
|
|
175
|
-
`${SYMBOLS_ANSI.LAST_BRANCH} ${frames[frames.length - 1]}
|
|
175
|
+
`${SYMBOLS_ANSI.LAST_BRANCH} ${frames[frames.length - 1]}`,
|
|
176
176
|
);
|
|
177
177
|
}
|
|
178
178
|
data.push([
|
|
179
179
|
comp.group || "",
|
|
180
180
|
comp.name,
|
|
181
181
|
comp.version || "",
|
|
182
|
-
frameDisplay.join("\n")
|
|
182
|
+
frameDisplay.join("\n"),
|
|
183
183
|
]);
|
|
184
184
|
}
|
|
185
185
|
const config = {
|
|
186
186
|
header: {
|
|
187
187
|
alignment: "center",
|
|
188
|
-
content: "Component Call Stack Evidence\nGenerated with \u2665 by cdxgen"
|
|
189
|
-
}
|
|
188
|
+
content: "Component Call Stack Evidence\nGenerated with \u2665 by cdxgen",
|
|
189
|
+
},
|
|
190
190
|
};
|
|
191
191
|
if (data.length > 1) {
|
|
192
192
|
console.log(table(data, config));
|
|
@@ -212,8 +212,8 @@ export const printDependencyTree = (bomJson) => {
|
|
|
212
212
|
const config = {
|
|
213
213
|
header: {
|
|
214
214
|
alignment: "center",
|
|
215
|
-
content: "Dependency Tree\nGenerated with \u2665 by cdxgen"
|
|
216
|
-
}
|
|
215
|
+
content: "Dependency Tree\nGenerated with \u2665 by cdxgen",
|
|
216
|
+
},
|
|
217
217
|
};
|
|
218
218
|
console.log(table([[treeGraphics.join("\n")]], config));
|
|
219
219
|
} else {
|
|
@@ -261,7 +261,7 @@ const recursePrint = (depMap, subtree, level, shownList, treeGraphics) => {
|
|
|
261
261
|
level > 0
|
|
262
262
|
) {
|
|
263
263
|
treeGraphics.push(
|
|
264
|
-
`${levelPrefix(level, i == listToUse.length - 1)}${refStr}
|
|
264
|
+
`${levelPrefix(level, i == listToUse.length - 1)}${refStr}`,
|
|
265
265
|
);
|
|
266
266
|
shownList.push(refStr.toLowerCase());
|
|
267
267
|
if (l && depMap[refStr]) {
|
|
@@ -271,7 +271,7 @@ const recursePrint = (depMap, subtree, level, shownList, treeGraphics) => {
|
|
|
271
271
|
depMap[refStr],
|
|
272
272
|
level + 1,
|
|
273
273
|
shownList,
|
|
274
|
-
treeGraphics
|
|
274
|
+
treeGraphics,
|
|
275
275
|
);
|
|
276
276
|
}
|
|
277
277
|
}
|
|
@@ -286,7 +286,7 @@ export const printReachables = (sliceArtefacts) => {
|
|
|
286
286
|
}
|
|
287
287
|
const purlCounts = {};
|
|
288
288
|
const reachablesSlices = JSON.parse(
|
|
289
|
-
readFileSync(reachablesSlicesFile, "utf-8")
|
|
289
|
+
readFileSync(reachablesSlicesFile, "utf-8"),
|
|
290
290
|
);
|
|
291
291
|
for (const areachable of reachablesSlices.reachables || []) {
|
|
292
292
|
const purls = areachable.purls || [];
|
|
@@ -295,7 +295,7 @@ export const printReachables = (sliceArtefacts) => {
|
|
|
295
295
|
}
|
|
296
296
|
}
|
|
297
297
|
const sortedPurls = Object.fromEntries(
|
|
298
|
-
Object.entries(purlCounts).sort(([, a], [, b]) => b - a)
|
|
298
|
+
Object.entries(purlCounts).sort(([, a], [, b]) => b - a),
|
|
299
299
|
);
|
|
300
300
|
const data = [["Package URL", "Reachable Flows"]];
|
|
301
301
|
for (const apurl of Object.keys(sortedPurls)) {
|
|
@@ -304,8 +304,8 @@ export const printReachables = (sliceArtefacts) => {
|
|
|
304
304
|
const config = {
|
|
305
305
|
header: {
|
|
306
306
|
alignment: "center",
|
|
307
|
-
content: "Reachable Components\nGenerated with \u2665 by cdxgen"
|
|
308
|
-
}
|
|
307
|
+
content: "Reachable Components\nGenerated with \u2665 by cdxgen",
|
|
308
|
+
},
|
|
309
309
|
};
|
|
310
310
|
if (data.length > 1) {
|
|
311
311
|
console.log(table(data, config));
|
package/display.test.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { test } from "@jest/globals";
|
|
2
1
|
import { readFileSync } from "node:fs";
|
|
2
|
+
import { test } from "@jest/globals";
|
|
3
3
|
import { printDependencyTree } from "./display.js";
|
|
4
4
|
|
|
5
5
|
test("print tree test", () => {
|
|
6
6
|
const bomJson = JSON.parse(
|
|
7
|
-
readFileSync("./test/data/vuln-spring-1.5.bom.json", { encoding: "utf-8" })
|
|
7
|
+
readFileSync("./test/data/vuln-spring-1.5.bom.json", { encoding: "utf-8" }),
|
|
8
8
|
);
|
|
9
9
|
printDependencyTree(bomJson);
|
|
10
10
|
});
|