@cyclonedx/cdxgen 9.9.1 → 9.9.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 +5 -1
- package/bin/cdxgen.js +73 -21
- package/data/wrapdb-releases.json +503 -206
- package/evinser.js +26 -20
- package/index.js +252 -122
- package/package.json +3 -3
- package/server.js +1 -1
- package/utils.js +221 -71
- package/utils.test.js +23 -3
package/README.md
CHANGED
|
@@ -181,6 +181,10 @@ Options:
|
|
|
181
181
|
--author The person(s) who created the BOM. Set this value
|
|
182
182
|
if you're intending the modify the BOM and claim
|
|
183
183
|
authorship.[array] [default: "OWASP Foundation"]
|
|
184
|
+
--profile BOM profile to use for generation. Default generi
|
|
185
|
+
c.
|
|
186
|
+
[choices: "appsec", "research", "operational", "threat-modeling", "license-com
|
|
187
|
+
pliance", "generic"] [default: "generic"]
|
|
184
188
|
--auto-compositions Automatically set compositions when the BOM was f
|
|
185
189
|
iltered. Defaults to true
|
|
186
190
|
[boolean] [default: true]
|
|
@@ -373,7 +377,7 @@ cdxgen can retain the dependency tree under the `dependencies` attribute for a s
|
|
|
373
377
|
| SBOM_SIGN_ALGORITHM | Signature algorithm. Some valid values are RS256, RS384, RS512, PS256, PS384, PS512, ES256 etc |
|
|
374
378
|
| SBOM_SIGN_PRIVATE_KEY | Private key to use for signing |
|
|
375
379
|
| SBOM_SIGN_PUBLIC_KEY | Optional. Public key to include in the SBOM signature |
|
|
376
|
-
| CDX_MAVEN_PLUGIN | CycloneDX Maven plugin to use. Default "org.cyclonedx:cyclonedx-maven-plugin:2.7.
|
|
380
|
+
| CDX_MAVEN_PLUGIN | CycloneDX Maven plugin to use. Default "org.cyclonedx:cyclonedx-maven-plugin:2.7.10" |
|
|
377
381
|
| CDX_MAVEN_GOAL | CycloneDX Maven plugin goal to use. Default makeAggregateBom. Other options: makeBom, makePackageBom |
|
|
378
382
|
| CDX_MAVEN_INCLUDE_TEST_SCOPE | Whether test scoped dependencies should be included from Maven projects, Default: true |
|
|
379
383
|
| ASTGEN_IGNORE_DIRS | Comma separated list of directories to ignore while analyzing using babel. The environment variable is also used by atom and astgen. |
|
package/bin/cdxgen.js
CHANGED
|
@@ -21,7 +21,6 @@ import {
|
|
|
21
21
|
import { findUpSync } from "find-up";
|
|
22
22
|
import { load as _load } from "js-yaml";
|
|
23
23
|
import { postProcess } from "../postgen.js";
|
|
24
|
-
import { analyzeProject, createEvinseFile, prepareDB } from "../evinser.js";
|
|
25
24
|
import { ATOM_DB } from "../utils.js";
|
|
26
25
|
|
|
27
26
|
// Support for config files
|
|
@@ -151,6 +150,7 @@ const args = yargs(hideBin(process.argv))
|
|
|
151
150
|
})
|
|
152
151
|
.option("install-deps", {
|
|
153
152
|
type: "boolean",
|
|
153
|
+
hidden: true,
|
|
154
154
|
default: true,
|
|
155
155
|
description:
|
|
156
156
|
"Install dependencies automatically for some projects. Defaults to true but disabled for containers and oci scans. Use --no-install-deps to disable this feature."
|
|
@@ -204,10 +204,27 @@ const args = yargs(hideBin(process.argv))
|
|
|
204
204
|
"The person(s) who created the BOM. Set this value if you're intending the modify the BOM and claim authorship.",
|
|
205
205
|
default: "OWASP Foundation"
|
|
206
206
|
})
|
|
207
|
+
.option("profile", {
|
|
208
|
+
description: "BOM profile to use for generation. Default generic.",
|
|
209
|
+
default: "generic",
|
|
210
|
+
choices: [
|
|
211
|
+
"appsec",
|
|
212
|
+
"research",
|
|
213
|
+
"operational",
|
|
214
|
+
"threat-modeling",
|
|
215
|
+
"license-compliance",
|
|
216
|
+
"generic"
|
|
217
|
+
]
|
|
218
|
+
})
|
|
219
|
+
.option("exclude", {
|
|
220
|
+
description: "Additional glob pattern(s) to ignore",
|
|
221
|
+
hidden: true
|
|
222
|
+
})
|
|
207
223
|
.completion("completion", "Generate bash/zsh completion")
|
|
208
224
|
.array("filter")
|
|
209
225
|
.array("only")
|
|
210
226
|
.array("author")
|
|
227
|
+
.array("exclude")
|
|
211
228
|
.option("auto-compositions", {
|
|
212
229
|
type: "boolean",
|
|
213
230
|
default: true,
|
|
@@ -259,6 +276,32 @@ if (process.argv[1].includes("obom") && !args.type) {
|
|
|
259
276
|
args.type = "os";
|
|
260
277
|
}
|
|
261
278
|
|
|
279
|
+
const applyProfile = (options) => {
|
|
280
|
+
switch (options.profile) {
|
|
281
|
+
case "appsec":
|
|
282
|
+
options.deep = true;
|
|
283
|
+
break;
|
|
284
|
+
case "research":
|
|
285
|
+
options.deep = true;
|
|
286
|
+
options.evidence = true;
|
|
287
|
+
process.env.CDX_MAVEN_INCLUDE_TEST_SCOPE = true;
|
|
288
|
+
process.env.ASTGEN_IGNORE_DIRS = "";
|
|
289
|
+
process.env.ASTGEN_IGNORE_FILE_PATTERN = "";
|
|
290
|
+
break;
|
|
291
|
+
case "operational":
|
|
292
|
+
options.projectType = options.projectType || "os";
|
|
293
|
+
break;
|
|
294
|
+
case "threat-modeling": // unused
|
|
295
|
+
break;
|
|
296
|
+
case "license-compliance":
|
|
297
|
+
process.env.FETCH_LICENSE = true;
|
|
298
|
+
break;
|
|
299
|
+
default:
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
302
|
+
return options;
|
|
303
|
+
};
|
|
304
|
+
|
|
262
305
|
/**
|
|
263
306
|
* Command line options
|
|
264
307
|
*/
|
|
@@ -266,8 +309,10 @@ const options = Object.assign({}, args, {
|
|
|
266
309
|
projectType: args.type,
|
|
267
310
|
multiProject: args.recurse,
|
|
268
311
|
noBabel: args.noBabel || args.babel === false,
|
|
269
|
-
project: args.projectId
|
|
312
|
+
project: args.projectId,
|
|
313
|
+
deep: args.deep || args.evidence
|
|
270
314
|
});
|
|
315
|
+
applyProfile(options);
|
|
271
316
|
|
|
272
317
|
/**
|
|
273
318
|
* Check for node >= 20 permissions
|
|
@@ -306,7 +351,7 @@ const checkPermissions = (filePath) => {
|
|
|
306
351
|
*/
|
|
307
352
|
(async () => {
|
|
308
353
|
// Start SBOM server
|
|
309
|
-
if (
|
|
354
|
+
if (options.server) {
|
|
310
355
|
const serverModule = await import("../server.js");
|
|
311
356
|
return serverModule.start(options);
|
|
312
357
|
}
|
|
@@ -323,15 +368,15 @@ const checkPermissions = (filePath) => {
|
|
|
323
368
|
bomNSData = postProcess(bomNSData, options);
|
|
324
369
|
}
|
|
325
370
|
if (
|
|
326
|
-
|
|
327
|
-
(typeof
|
|
371
|
+
options.output &&
|
|
372
|
+
(typeof options.output === "string" || options.output instanceof String)
|
|
328
373
|
) {
|
|
329
374
|
if (bomNSData.bomXmlFiles) {
|
|
330
375
|
console.log("BOM files produced:", bomNSData.bomXmlFiles);
|
|
331
376
|
} else {
|
|
332
|
-
const jsonFile =
|
|
377
|
+
const jsonFile = options.output.replace(".xml", ".json");
|
|
333
378
|
// Create bom json file
|
|
334
|
-
if (!
|
|
379
|
+
if (!options.output.endsWith(".xml") && bomNSData.bomJson) {
|
|
335
380
|
let jsonPayload = undefined;
|
|
336
381
|
if (
|
|
337
382
|
typeof bomNSData.bomJson === "string" ||
|
|
@@ -345,7 +390,7 @@ const checkPermissions = (filePath) => {
|
|
|
345
390
|
}
|
|
346
391
|
if (
|
|
347
392
|
jsonPayload &&
|
|
348
|
-
(
|
|
393
|
+
(options.generateKeyAndSign ||
|
|
349
394
|
(process.env.SBOM_SIGN_ALGORITHM &&
|
|
350
395
|
process.env.SBOM_SIGN_ALGORITHM !== "none" &&
|
|
351
396
|
process.env.SBOM_SIGN_PRIVATE_KEY &&
|
|
@@ -358,7 +403,7 @@ const checkPermissions = (filePath) => {
|
|
|
358
403
|
let privateKeyToUse = undefined;
|
|
359
404
|
let jwkPublicKey = undefined;
|
|
360
405
|
let publicKeyFile = undefined;
|
|
361
|
-
if (
|
|
406
|
+
if (options.generateKeyAndSign) {
|
|
362
407
|
const jdirName = dirname(jsonFile);
|
|
363
408
|
publicKeyFile = join(jdirName, "public.key");
|
|
364
409
|
const privateKeyFile = join(jdirName, "private.key");
|
|
@@ -468,8 +513,8 @@ const checkPermissions = (filePath) => {
|
|
|
468
513
|
}
|
|
469
514
|
}
|
|
470
515
|
// Create bom xml file
|
|
471
|
-
if (
|
|
472
|
-
fs.writeFileSync(
|
|
516
|
+
if (options.output.endsWith(".xml") && bomNSData.bomXml) {
|
|
517
|
+
fs.writeFileSync(options.output, bomNSData.bomXml);
|
|
473
518
|
}
|
|
474
519
|
//
|
|
475
520
|
if (bomNSData.nsMapping && Object.keys(bomNSData.nsMapping).length) {
|
|
@@ -478,7 +523,7 @@ const checkPermissions = (filePath) => {
|
|
|
478
523
|
console.log("Namespace mapping file written to", nsFile);
|
|
479
524
|
}
|
|
480
525
|
}
|
|
481
|
-
} else if (!
|
|
526
|
+
} else if (!options.print) {
|
|
482
527
|
if (bomNSData.bomJson) {
|
|
483
528
|
console.log(JSON.stringify(bomNSData.bomJson, null, 2));
|
|
484
529
|
} else if (bomNSData.bomXml) {
|
|
@@ -489,7 +534,8 @@ const checkPermissions = (filePath) => {
|
|
|
489
534
|
}
|
|
490
535
|
}
|
|
491
536
|
// Evidence generation
|
|
492
|
-
if (
|
|
537
|
+
if (options.evidence) {
|
|
538
|
+
const evinserModule = await import("../evinser.js");
|
|
493
539
|
const evinseOptions = {
|
|
494
540
|
_: args._,
|
|
495
541
|
input: options.output,
|
|
@@ -503,12 +549,18 @@ const checkPermissions = (filePath) => {
|
|
|
503
549
|
dataFlowSlicesFile: options.dataFlowSlicesFile,
|
|
504
550
|
reachablesSlicesFile: options.reachablesSlicesFile
|
|
505
551
|
};
|
|
506
|
-
const dbObjMap = await prepareDB(evinseOptions);
|
|
552
|
+
const dbObjMap = await evinserModule.prepareDB(evinseOptions);
|
|
507
553
|
if (dbObjMap) {
|
|
508
|
-
const sliceArtefacts = await analyzeProject(
|
|
509
|
-
|
|
554
|
+
const sliceArtefacts = await evinserModule.analyzeProject(
|
|
555
|
+
dbObjMap,
|
|
556
|
+
evinseOptions
|
|
557
|
+
);
|
|
558
|
+
const evinseJson = evinserModule.createEvinseFile(
|
|
559
|
+
sliceArtefacts,
|
|
560
|
+
evinseOptions
|
|
561
|
+
);
|
|
510
562
|
bomNSData.bomJson = evinseJson;
|
|
511
|
-
if (
|
|
563
|
+
if (options.print && evinseJson) {
|
|
512
564
|
printOccurrences(evinseJson);
|
|
513
565
|
printCallStack(evinseJson);
|
|
514
566
|
printReachables(sliceArtefacts);
|
|
@@ -517,22 +569,22 @@ const checkPermissions = (filePath) => {
|
|
|
517
569
|
}
|
|
518
570
|
}
|
|
519
571
|
// Perform automatic validation
|
|
520
|
-
if (
|
|
572
|
+
if (options.validate) {
|
|
521
573
|
if (!validateBom(bomNSData.bomJson)) {
|
|
522
574
|
process.exit(1);
|
|
523
575
|
}
|
|
524
576
|
}
|
|
525
577
|
// Automatically submit the bom data
|
|
526
|
-
if (
|
|
578
|
+
if (options.serverUrl && options.serverUrl != true && options.apiKey) {
|
|
527
579
|
try {
|
|
528
|
-
const dbody = await submitBom(
|
|
580
|
+
const dbody = await submitBom(options, bomNSData.bomJson);
|
|
529
581
|
console.log("Response from server", dbody);
|
|
530
582
|
} catch (err) {
|
|
531
583
|
console.log(err);
|
|
532
584
|
}
|
|
533
585
|
}
|
|
534
586
|
|
|
535
|
-
if (
|
|
587
|
+
if (options.print && bomNSData.bomJson && bomNSData.bomJson.components) {
|
|
536
588
|
printDependencyTree(bomNSData.bomJson);
|
|
537
589
|
printTable(bomNSData.bomJson);
|
|
538
590
|
}
|