@cyclonedx/cdxgen 10.4.1 → 10.4.3
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 +11 -5
- package/analyzer.js +10 -11
- package/bin/cdxgen.js +6 -2
- package/bin/repl.js +4 -4
- package/bin/verify.js +3 -4
- package/binary.js +21 -21
- package/cbomutils.js +2 -2
- package/display.js +6 -7
- package/docker.js +56 -63
- package/envcontext.js +6 -7
- package/evinser.js +33 -33
- package/index.js +929 -1032
- package/package.json +11 -13
- package/postgen.js +3 -3
- package/protobom.test.js +1 -1
- package/types/analyzer.d.ts.map +1 -1
- package/types/display.d.ts.map +1 -1
- package/types/docker.d.ts.map +1 -1
- package/types/evinser.d.ts.map +1 -1
- package/types/index.d.ts.map +1 -1
- package/types/utils.d.ts.map +1 -1
- package/types/validator.d.ts.map +1 -1
- package/utils.js +254 -322
- package/utils.test.js +8 -9
- package/validator.js +11 -14
package/README.md
CHANGED
|
@@ -80,7 +80,7 @@ For node.js projects, lock files are parsed initially, so the SBOM would include
|
|
|
80
80
|
|
|
81
81
|
This attribute can be later used for various purposes. For example, [dep-scan](https://github.com/cyclonedx/dep-scan) uses this attribute to prioritize vulnerabilities. Unfortunately, tools such as dependency track, do not include this feature and might over-report the CVEs.
|
|
82
82
|
|
|
83
|
-
|
|
83
|
+
With the argument `--required-only`, you can limit the SBOM only to include packages with the scope "required", commonly called production or non-dev dependencies. Combine with `--no-babel` to limit this list to only non-dev dependencies based on the `dev` attribute being false in the lock files.
|
|
84
84
|
|
|
85
85
|
For go, `go mod why` command is used to identify required packages. For php, composer lock file is parsed to distinguish required (packages) from optional (packages-dev).
|
|
86
86
|
|
|
@@ -98,18 +98,18 @@ If you are a [Homebrew](https://brew.sh/) user, you can also install [cdxgen](ht
|
|
|
98
98
|
$ brew install cdxgen
|
|
99
99
|
```
|
|
100
100
|
|
|
101
|
-
Deno
|
|
101
|
+
Deno and bun runtime can be used with limited support.
|
|
102
102
|
|
|
103
103
|
```shell
|
|
104
104
|
deno install --allow-read --allow-env --allow-run --allow-sys=uid,systemMemoryInfo,gid --allow-write --allow-net -n cdxgen "npm:@cyclonedx/cdxgen/cdxgen"
|
|
105
105
|
```
|
|
106
106
|
|
|
107
|
-
You can also use the cdxgen container image
|
|
107
|
+
You can also use the cdxgen container image with node, deno, or bun runtime versions.
|
|
108
|
+
|
|
109
|
+
The default version uses Node.js 20
|
|
108
110
|
|
|
109
111
|
```bash
|
|
110
112
|
docker run --rm -v /tmp:/tmp -v $(pwd):/app:rw -t ghcr.io/cyclonedx/cdxgen -r /app -o /app/bom.json
|
|
111
|
-
|
|
112
|
-
docker run --rm -v /tmp:/tmp -v $(pwd):/app:rw -t ghcr.io/cyclonedx/cdxgen:v8.6.0 -r /app -o /app/bom.json
|
|
113
113
|
```
|
|
114
114
|
|
|
115
115
|
To use the deno version, use `ghcr.io/cyclonedx/cdxgen-deno` as the image name.
|
|
@@ -118,6 +118,12 @@ To use the deno version, use `ghcr.io/cyclonedx/cdxgen-deno` as the image name.
|
|
|
118
118
|
docker run --rm -v /tmp:/tmp -v $(pwd):/app:rw -t ghcr.io/cyclonedx/cdxgen-deno -r /app -o /app/bom.json
|
|
119
119
|
```
|
|
120
120
|
|
|
121
|
+
For the bun version, use `ghcr.io/cyclonedx/cdxgen-bun` as the image name.
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
docker run --rm -v /tmp:/tmp -v $(pwd):/app:rw -t ghcr.io/cyclonedx/cdxgen-bun -r /app -o /app/bom.json
|
|
125
|
+
```
|
|
126
|
+
|
|
121
127
|
In deno applications, cdxgen could be directly imported without any conversion. Please see the section on [integration as library](#integration-as-library)
|
|
122
128
|
|
|
123
129
|
```ts
|
package/analyzer.js
CHANGED
|
@@ -26,7 +26,6 @@ const IGNORE_DIRS = process.env.ASTGEN_IGNORE_DIRS
|
|
|
26
26
|
"codemods",
|
|
27
27
|
"flow-typed",
|
|
28
28
|
"i18n",
|
|
29
|
-
"__tests__",
|
|
30
29
|
];
|
|
31
30
|
|
|
32
31
|
const IGNORE_FILE_PATTERN = new RegExp(
|
|
@@ -54,6 +53,7 @@ const getAllFiles = (deep, dir, extn, files, result, regex) => {
|
|
|
54
53
|
const dirName = basename(file);
|
|
55
54
|
if (
|
|
56
55
|
dirName.startsWith(".") ||
|
|
56
|
+
dirName.startsWith("__") ||
|
|
57
57
|
IGNORE_DIRS.includes(dirName.toLowerCase())
|
|
58
58
|
) {
|
|
59
59
|
continue;
|
|
@@ -141,8 +141,8 @@ const setFileRef = (
|
|
|
141
141
|
exportedModules,
|
|
142
142
|
isExternal: true,
|
|
143
143
|
fileName: fileRelativeLoc,
|
|
144
|
-
lineNumber: sourceLoc
|
|
145
|
-
columnNumber: sourceLoc
|
|
144
|
+
lineNumber: sourceLoc?.line ? sourceLoc.line : undefined,
|
|
145
|
+
columnNumber: sourceLoc?.column ? sourceLoc.column : undefined,
|
|
146
146
|
};
|
|
147
147
|
// replace relative imports with full path
|
|
148
148
|
let moduleFullPath = pathway;
|
|
@@ -167,7 +167,7 @@ const setFileRef = (
|
|
|
167
167
|
allImports[modPkg] = allImports[modPkg] || new Set();
|
|
168
168
|
allImports[modPkg].add(occurrence);
|
|
169
169
|
}
|
|
170
|
-
if (exportedModules
|
|
170
|
+
if (exportedModules?.length) {
|
|
171
171
|
moduleFullPath = moduleFullPath
|
|
172
172
|
.replace("node_modules/", "")
|
|
173
173
|
.replace("dist/", "")
|
|
@@ -192,7 +192,7 @@ const fileToParseableCode = (file) => {
|
|
|
192
192
|
.replace(vueCommentRegex, (match) => match.replaceAll(/\S/g, " "))
|
|
193
193
|
.replace(
|
|
194
194
|
vueCleaningRegex,
|
|
195
|
-
(match) => match.replaceAll(/\S/g, " ").substring(1)
|
|
195
|
+
(match) => `${match.replaceAll(/\S/g, " ").substring(1)};`,
|
|
196
196
|
)
|
|
197
197
|
.replace(
|
|
198
198
|
vueBindRegex,
|
|
@@ -201,7 +201,7 @@ const fileToParseableCode = (file) => {
|
|
|
201
201
|
)
|
|
202
202
|
.replace(
|
|
203
203
|
vuePropRegex,
|
|
204
|
-
(match, grA, grB) =>
|
|
204
|
+
(match, grA, grB) => ` ${grA.replace(/[.:@]/g, " ")}${grB}`,
|
|
205
205
|
)
|
|
206
206
|
.replace(
|
|
207
207
|
vueTemplateRegex,
|
|
@@ -220,7 +220,7 @@ const parseFileASTTree = (src, file, allImports, allExports) => {
|
|
|
220
220
|
const ast = parse(fileToParseableCode(file), babelParserOptions);
|
|
221
221
|
traverse.default(ast, {
|
|
222
222
|
ImportDeclaration: (path) => {
|
|
223
|
-
if (path
|
|
223
|
+
if (path?.node) {
|
|
224
224
|
setFileRef(
|
|
225
225
|
allImports,
|
|
226
226
|
allExports,
|
|
@@ -234,8 +234,7 @@ const parseFileASTTree = (src, file, allImports, allExports) => {
|
|
|
234
234
|
// For require('') statements
|
|
235
235
|
Identifier: (path) => {
|
|
236
236
|
if (
|
|
237
|
-
path &&
|
|
238
|
-
path.node &&
|
|
237
|
+
path?.node &&
|
|
239
238
|
path.node.name === "require" &&
|
|
240
239
|
path.parent.type === "CallExpression"
|
|
241
240
|
) {
|
|
@@ -244,7 +243,7 @@ const parseFileASTTree = (src, file, allImports, allExports) => {
|
|
|
244
243
|
},
|
|
245
244
|
// Use for dynamic imports like routes.jsx
|
|
246
245
|
CallExpression: (path) => {
|
|
247
|
-
if (path
|
|
246
|
+
if (path?.node && path.node.callee.type === "Import") {
|
|
248
247
|
setFileRef(allImports, allExports, src, file, path.node.arguments[0]);
|
|
249
248
|
}
|
|
250
249
|
},
|
|
@@ -254,7 +253,7 @@ const parseFileASTTree = (src, file, allImports, allExports) => {
|
|
|
254
253
|
},
|
|
255
254
|
ExportNamedDeclaration: (path) => {
|
|
256
255
|
// ensure there is a path export
|
|
257
|
-
if (path
|
|
256
|
+
if (path?.node?.source) {
|
|
258
257
|
setFileRef(
|
|
259
258
|
allImports,
|
|
260
259
|
allExports,
|
package/bin/cdxgen.js
CHANGED
|
@@ -371,10 +371,13 @@ const applyAdvancedOptions = (options) => {
|
|
|
371
371
|
"aab",
|
|
372
372
|
"go",
|
|
373
373
|
"golang",
|
|
374
|
+
"rust",
|
|
375
|
+
"rust-lang",
|
|
376
|
+
"cargo",
|
|
374
377
|
].includes(options.projectType)
|
|
375
378
|
) {
|
|
376
379
|
console.log(
|
|
377
|
-
"PREVIEW: post-build lifecycle SBOM generation is supported only for android, dotnet, and
|
|
380
|
+
"PREVIEW: post-build lifecycle SBOM generation is supported only for android, dotnet, go, and Rust projects. Please specify the type using the -t argument.",
|
|
378
381
|
);
|
|
379
382
|
process.exit(1);
|
|
380
383
|
}
|
|
@@ -591,7 +594,7 @@ const checkPermissions = (filePath) => {
|
|
|
591
594
|
}
|
|
592
595
|
// bom ns mapping
|
|
593
596
|
if (bomNSData.nsMapping && Object.keys(bomNSData.nsMapping).length) {
|
|
594
|
-
const nsFile = jsonFile
|
|
597
|
+
const nsFile = `${jsonFile}.map`;
|
|
595
598
|
fs.writeFileSync(nsFile, JSON.stringify(bomNSData.nsMapping));
|
|
596
599
|
}
|
|
597
600
|
} else if (!options.print) {
|
|
@@ -646,6 +649,7 @@ const checkPermissions = (filePath) => {
|
|
|
646
649
|
}
|
|
647
650
|
}
|
|
648
651
|
// Automatically submit the bom data
|
|
652
|
+
// biome-ignore lint/suspicious/noDoubleEquals: yargs passes true for empty values
|
|
649
653
|
if (options.serverUrl && options.serverUrl != true && options.apiKey) {
|
|
650
654
|
try {
|
|
651
655
|
const dbody = await submitBom(options, bomNSData.bomJson);
|
package/bin/repl.js
CHANGED
|
@@ -58,7 +58,7 @@ if (!process.env.CDXGEN_REPL_HISTORY && !fs.existsSync(historyConfigDir)) {
|
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
export const importSbom = (sbomOrPath) => {
|
|
61
|
-
if (sbomOrPath
|
|
61
|
+
if (sbomOrPath?.endsWith(".json") && fs.existsSync(sbomOrPath)) {
|
|
62
62
|
try {
|
|
63
63
|
sbom = JSON.parse(fs.readFileSync(sbomOrPath, "utf-8"));
|
|
64
64
|
console.log(`✅ SBOM imported successfully from ${sbomOrPath}`);
|
|
@@ -298,12 +298,12 @@ cdxgenRepl.defineCommand("update", {
|
|
|
298
298
|
return;
|
|
299
299
|
}
|
|
300
300
|
if (!updateSpec.startsWith("|")) {
|
|
301
|
-
updateSpec =
|
|
301
|
+
updateSpec = `|${updateSpec}`;
|
|
302
302
|
}
|
|
303
303
|
if (!updateSpec.endsWith("|")) {
|
|
304
|
-
updateSpec = updateSpec
|
|
304
|
+
updateSpec = `${updateSpec}|`;
|
|
305
305
|
}
|
|
306
|
-
updateSpec =
|
|
306
|
+
updateSpec = `$ ~> ${updateSpec}`;
|
|
307
307
|
const expression = jsonata(updateSpec);
|
|
308
308
|
const newSbom = await expression.evaluate(sbom);
|
|
309
309
|
if (newSbom && newSbom.components.length <= sbom.components.length) {
|
package/bin/verify.js
CHANGED
|
@@ -61,10 +61,9 @@ for (const comp of bomJson.components) {
|
|
|
61
61
|
if (hasInvalidComp) {
|
|
62
62
|
process.exit(1);
|
|
63
63
|
}
|
|
64
|
-
const bomSignature =
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
: undefined;
|
|
64
|
+
const bomSignature = bomJson.signature?.value
|
|
65
|
+
? bomJson.signature.value
|
|
66
|
+
: undefined;
|
|
68
67
|
if (!bomSignature) {
|
|
69
68
|
console.log("No signature was found!");
|
|
70
69
|
} else {
|
package/binary.js
CHANGED
|
@@ -71,7 +71,7 @@ let CDXGEN_PLUGINS_DIR = process.env.CDXGEN_PLUGINS_DIR;
|
|
|
71
71
|
if (
|
|
72
72
|
!CDXGEN_PLUGINS_DIR &&
|
|
73
73
|
existsSync(join(dirName, "plugins")) &&
|
|
74
|
-
existsSync(join(dirName, "plugins", "
|
|
74
|
+
existsSync(join(dirName, "plugins", "trivy"))
|
|
75
75
|
) {
|
|
76
76
|
CDXGEN_PLUGINS_DIR = join(dirName, "plugins");
|
|
77
77
|
}
|
|
@@ -83,7 +83,7 @@ if (
|
|
|
83
83
|
dirName,
|
|
84
84
|
"node_modules",
|
|
85
85
|
"@cyclonedx",
|
|
86
|
-
|
|
86
|
+
`cdxgen-plugins-bin${pluginsBinSuffix}`,
|
|
87
87
|
"plugins",
|
|
88
88
|
),
|
|
89
89
|
) &&
|
|
@@ -92,9 +92,9 @@ if (
|
|
|
92
92
|
dirName,
|
|
93
93
|
"node_modules",
|
|
94
94
|
"@cyclonedx",
|
|
95
|
-
|
|
95
|
+
`cdxgen-plugins-bin${pluginsBinSuffix}`,
|
|
96
96
|
"plugins",
|
|
97
|
-
"
|
|
97
|
+
"trivy",
|
|
98
98
|
),
|
|
99
99
|
)
|
|
100
100
|
) {
|
|
@@ -102,7 +102,7 @@ if (
|
|
|
102
102
|
dirName,
|
|
103
103
|
"node_modules",
|
|
104
104
|
"@cyclonedx",
|
|
105
|
-
|
|
105
|
+
`cdxgen-plugins-bin${pluginsBinSuffix}`,
|
|
106
106
|
"plugins",
|
|
107
107
|
);
|
|
108
108
|
}
|
|
@@ -120,7 +120,7 @@ if (!CDXGEN_PLUGINS_DIR) {
|
|
|
120
120
|
if (result) {
|
|
121
121
|
const stdout = result.stdout;
|
|
122
122
|
if (stdout) {
|
|
123
|
-
globalNodePath = Buffer.from(stdout).toString().trim()
|
|
123
|
+
globalNodePath = `${Buffer.from(stdout).toString().trim()}/`;
|
|
124
124
|
}
|
|
125
125
|
}
|
|
126
126
|
}
|
|
@@ -128,7 +128,7 @@ if (!CDXGEN_PLUGINS_DIR) {
|
|
|
128
128
|
const globalPlugins = join(
|
|
129
129
|
globalNodePath,
|
|
130
130
|
"@cyclonedx",
|
|
131
|
-
|
|
131
|
+
`cdxgen-plugins-bin${pluginsBinSuffix}`,
|
|
132
132
|
"plugins",
|
|
133
133
|
);
|
|
134
134
|
if (existsSync(globalPlugins)) {
|
|
@@ -153,7 +153,7 @@ if (existsSync(join(CDXGEN_PLUGINS_DIR, "goversion"))) {
|
|
|
153
153
|
GOVERSION_BIN = join(
|
|
154
154
|
CDXGEN_PLUGINS_DIR,
|
|
155
155
|
"goversion",
|
|
156
|
-
|
|
156
|
+
`goversion-${platform}-${arch}${extn}`,
|
|
157
157
|
);
|
|
158
158
|
}
|
|
159
159
|
let TRIVY_BIN = null;
|
|
@@ -161,7 +161,7 @@ if (existsSync(join(CDXGEN_PLUGINS_DIR, "trivy"))) {
|
|
|
161
161
|
TRIVY_BIN = join(
|
|
162
162
|
CDXGEN_PLUGINS_DIR,
|
|
163
163
|
"trivy",
|
|
164
|
-
|
|
164
|
+
`trivy-cdxgen-${platform}-${arch}${extn}`,
|
|
165
165
|
);
|
|
166
166
|
} else if (process.env.TRIVY_CMD) {
|
|
167
167
|
TRIVY_BIN = process.env.TRIVY_CMD;
|
|
@@ -171,7 +171,7 @@ if (existsSync(join(CDXGEN_PLUGINS_DIR, "cargo-auditable"))) {
|
|
|
171
171
|
CARGO_AUDITABLE_BIN = join(
|
|
172
172
|
CDXGEN_PLUGINS_DIR,
|
|
173
173
|
"cargo-auditable",
|
|
174
|
-
|
|
174
|
+
`cargo-auditable-cdxgen-${platform}-${arch}${extn}`,
|
|
175
175
|
);
|
|
176
176
|
} else if (process.env.CARGO_AUDITABLE_CMD) {
|
|
177
177
|
CARGO_AUDITABLE_BIN = process.env.CARGO_AUDITABLE_CMD;
|
|
@@ -181,7 +181,7 @@ if (existsSync(join(CDXGEN_PLUGINS_DIR, "osquery"))) {
|
|
|
181
181
|
OSQUERY_BIN = join(
|
|
182
182
|
CDXGEN_PLUGINS_DIR,
|
|
183
183
|
"osquery",
|
|
184
|
-
|
|
184
|
+
`osqueryi-${platform}-${arch}${extn}`,
|
|
185
185
|
);
|
|
186
186
|
// osqueryi-darwin-amd64.app/Contents/MacOS/osqueryd
|
|
187
187
|
if (platform === "darwin") {
|
|
@@ -199,7 +199,7 @@ if (existsSync(join(CDXGEN_PLUGINS_DIR, "dosai"))) {
|
|
|
199
199
|
DOSAI_BIN = join(
|
|
200
200
|
CDXGEN_PLUGINS_DIR,
|
|
201
201
|
"dosai",
|
|
202
|
-
|
|
202
|
+
`dosai-${platformToUse}-${arch}${extn}`,
|
|
203
203
|
);
|
|
204
204
|
} else if (process.env.DOSAI_CMD) {
|
|
205
205
|
DOSAI_BIN = process.env.DOSAI_CMD;
|
|
@@ -389,7 +389,7 @@ export function getOSPackages(src) {
|
|
|
389
389
|
// ignore errors
|
|
390
390
|
}
|
|
391
391
|
// Clean up
|
|
392
|
-
if (tempDir
|
|
392
|
+
if (tempDir?.startsWith(tmpdir())) {
|
|
393
393
|
if (DEBUG_MODE) {
|
|
394
394
|
console.log(`Cleaning up ${tempDir}`);
|
|
395
395
|
}
|
|
@@ -451,13 +451,13 @@ export function getOSPackages(src) {
|
|
|
451
451
|
break;
|
|
452
452
|
}
|
|
453
453
|
if (osReleaseData["VERSION_ID"]) {
|
|
454
|
-
distro_id = distro_id
|
|
454
|
+
distro_id = `${distro_id}-${osReleaseData["VERSION_ID"]}`;
|
|
455
455
|
}
|
|
456
456
|
const tmpDependencies = {};
|
|
457
457
|
(tmpBom.dependencies || []).forEach((d) => {
|
|
458
458
|
tmpDependencies[d.ref] = d.dependsOn;
|
|
459
459
|
});
|
|
460
|
-
if (tmpBom
|
|
460
|
+
if (tmpBom?.components) {
|
|
461
461
|
for (const comp of tmpBom.components) {
|
|
462
462
|
if (comp.purl) {
|
|
463
463
|
// Retain go components alone from trivy
|
|
@@ -497,10 +497,10 @@ export function getOSPackages(src) {
|
|
|
497
497
|
purlObj.namespace = group;
|
|
498
498
|
}
|
|
499
499
|
purlObj.qualifiers = purlObj.qualifiers || {};
|
|
500
|
-
if (distro_id
|
|
500
|
+
if (distro_id?.length) {
|
|
501
501
|
purlObj.qualifiers["distro"] = distro_id;
|
|
502
502
|
}
|
|
503
|
-
if (distro_codename
|
|
503
|
+
if (distro_codename?.length) {
|
|
504
504
|
purlObj.qualifiers["distro_name"] = distro_codename;
|
|
505
505
|
}
|
|
506
506
|
// Bug fix for mageia and oracle linux
|
|
@@ -509,7 +509,7 @@ export function getOSPackages(src) {
|
|
|
509
509
|
purlObj["type"] = purl_type;
|
|
510
510
|
purlObj["namespace"] = "";
|
|
511
511
|
comp.group = "";
|
|
512
|
-
if (comp.purl
|
|
512
|
+
if (comp.purl?.includes(".mga")) {
|
|
513
513
|
purlObj["namespace"] = "mageia";
|
|
514
514
|
comp.group = "mageia";
|
|
515
515
|
purlObj.qualifiers["distro"] = "mageia";
|
|
@@ -529,7 +529,7 @@ export function getOSPackages(src) {
|
|
|
529
529
|
allTypes.add(purlObj.type);
|
|
530
530
|
}
|
|
531
531
|
// Prefix distro codename for ubuntu
|
|
532
|
-
if (purlObj.qualifiers
|
|
532
|
+
if (purlObj.qualifiers?.distro) {
|
|
533
533
|
allTypes.add(purlObj.qualifiers.distro);
|
|
534
534
|
if (OS_DISTRO_ALIAS[purlObj.qualifiers.distro]) {
|
|
535
535
|
distro_codename =
|
|
@@ -537,7 +537,7 @@ export function getOSPackages(src) {
|
|
|
537
537
|
} else if (group === "alpine") {
|
|
538
538
|
const dtmpA = purlObj.qualifiers.distro.split(".");
|
|
539
539
|
if (dtmpA && dtmpA.length > 2) {
|
|
540
|
-
distro_codename = dtmpA[0]
|
|
540
|
+
distro_codename = `${dtmpA[0]}.${dtmpA[1]}`;
|
|
541
541
|
}
|
|
542
542
|
} else if (group === "photon") {
|
|
543
543
|
const dtmpA = purlObj.qualifiers.distro.split("-");
|
|
@@ -699,7 +699,7 @@ const retrieveDependencies = (tmpDependencies, origBomRef, comp) => {
|
|
|
699
699
|
export function executeOsQuery(query) {
|
|
700
700
|
if (OSQUERY_BIN) {
|
|
701
701
|
if (!query.endsWith(";")) {
|
|
702
|
-
query = query
|
|
702
|
+
query = `${query};`;
|
|
703
703
|
}
|
|
704
704
|
const args = ["--json", query];
|
|
705
705
|
// On darwin, we need to disable the safety check and run cdxgen with sudo
|
package/cbomutils.js
CHANGED
|
@@ -26,10 +26,10 @@ export function collectOSCryptoLibs(options) {
|
|
|
26
26
|
results,
|
|
27
27
|
false,
|
|
28
28
|
);
|
|
29
|
-
if (dlist
|
|
29
|
+
if (dlist?.length) {
|
|
30
30
|
osPkgsList = osPkgsList.concat(dlist);
|
|
31
31
|
// Should we downgrade from cryptographic-asset to data for < 1.6 spec
|
|
32
|
-
if (options
|
|
32
|
+
if (options?.specVersion && options.specVersion < 1.6) {
|
|
33
33
|
for (const apkg of osPkgsList) {
|
|
34
34
|
if (apkg.type === "cryptographic-asset") {
|
|
35
35
|
apkg.type = "data";
|
package/display.js
CHANGED
|
@@ -17,8 +17,7 @@ export const printTable = (bomJson) => {
|
|
|
17
17
|
return;
|
|
18
18
|
}
|
|
19
19
|
if (
|
|
20
|
-
bomJson.metadata &&
|
|
21
|
-
bomJson.metadata.component &&
|
|
20
|
+
bomJson.metadata?.component &&
|
|
22
21
|
["operating-system", "platform"].includes(bomJson.metadata.component.type)
|
|
23
22
|
) {
|
|
24
23
|
return printOSTable(bomJson);
|
|
@@ -109,7 +108,7 @@ const locationComparator = (a, b) => {
|
|
|
109
108
|
const tmpA = a.split("#");
|
|
110
109
|
const tmpB = b.split("#");
|
|
111
110
|
if (tmpA.length === 2 && tmpB.length === 2) {
|
|
112
|
-
if (tmpA[0]
|
|
111
|
+
if (tmpA[0] === tmpB[0]) {
|
|
113
112
|
return tmpA[1] - tmpB[1];
|
|
114
113
|
}
|
|
115
114
|
}
|
|
@@ -162,7 +161,7 @@ export const printCallStack = (bomJson) => {
|
|
|
162
161
|
const frames = Array.from(
|
|
163
162
|
new Set(
|
|
164
163
|
comp.evidence.callstack.frames.map(
|
|
165
|
-
(c) => `${c.fullFilename}${c.line ?
|
|
164
|
+
(c) => `${c.fullFilename}${c.line ? `#${c.line}` : ""}`,
|
|
166
165
|
),
|
|
167
166
|
),
|
|
168
167
|
).sort(locationComparator);
|
|
@@ -199,7 +198,7 @@ export const printDependencyTree = (bomJson) => {
|
|
|
199
198
|
}
|
|
200
199
|
const depMap = {};
|
|
201
200
|
for (const d of dependencies) {
|
|
202
|
-
if (d.dependsOn
|
|
201
|
+
if (d.dependsOn?.length) {
|
|
203
202
|
depMap[d.ref] = d.dependsOn.sort();
|
|
204
203
|
}
|
|
205
204
|
}
|
|
@@ -261,7 +260,7 @@ const recursePrint = (depMap, subtree, level, shownList, treeGraphics) => {
|
|
|
261
260
|
level > 0
|
|
262
261
|
) {
|
|
263
262
|
treeGraphics.push(
|
|
264
|
-
`${levelPrefix(level, i
|
|
263
|
+
`${levelPrefix(level, i === listToUse.length - 1)}${refStr}`,
|
|
265
264
|
);
|
|
266
265
|
shownList.push(refStr.toLowerCase());
|
|
267
266
|
if (l && depMap[refStr]) {
|
|
@@ -299,7 +298,7 @@ export const printReachables = (sliceArtefacts) => {
|
|
|
299
298
|
);
|
|
300
299
|
const data = [["Package URL", "Reachable Flows"]];
|
|
301
300
|
for (const apurl of Object.keys(sortedPurls)) {
|
|
302
|
-
data.push([apurl,
|
|
301
|
+
data.push([apurl, `${sortedPurls[apurl]}`]);
|
|
303
302
|
}
|
|
304
303
|
const config = {
|
|
305
304
|
header: {
|