@cyclonedx/cdxgen 9.9.1 → 9.9.2

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 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.8" |
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
@@ -204,6 +203,18 @@ const args = yargs(hideBin(process.argv))
204
203
  "The person(s) who created the BOM. Set this value if you're intending the modify the BOM and claim authorship.",
205
204
  default: "OWASP Foundation"
206
205
  })
206
+ .option("profile", {
207
+ description: "BOM profile to use for generation. Default generic.",
208
+ default: "generic",
209
+ choices: [
210
+ "appsec",
211
+ "research",
212
+ "operational",
213
+ "threat-modeling",
214
+ "license-compliance",
215
+ "generic"
216
+ ]
217
+ })
207
218
  .completion("completion", "Generate bash/zsh completion")
208
219
  .array("filter")
209
220
  .array("only")
@@ -259,6 +270,32 @@ if (process.argv[1].includes("obom") && !args.type) {
259
270
  args.type = "os";
260
271
  }
261
272
 
273
+ const applyProfile = (options) => {
274
+ switch (options.profile) {
275
+ case "appsec":
276
+ options.deep = true;
277
+ break;
278
+ case "research":
279
+ options.deep = true;
280
+ options.evidence = true;
281
+ process.env.CDX_MAVEN_INCLUDE_TEST_SCOPE = true;
282
+ process.env.ASTGEN_IGNORE_DIRS = "";
283
+ process.env.ASTGEN_IGNORE_FILE_PATTERN = "";
284
+ break;
285
+ case "operational":
286
+ options.projectType = options.projectType || "os";
287
+ break;
288
+ case "threat-modeling": // unused
289
+ break;
290
+ case "license-compliance":
291
+ process.env.FETCH_LICENSE = true;
292
+ break;
293
+ default:
294
+ break;
295
+ }
296
+ return options;
297
+ };
298
+
262
299
  /**
263
300
  * Command line options
264
301
  */
@@ -266,8 +303,10 @@ const options = Object.assign({}, args, {
266
303
  projectType: args.type,
267
304
  multiProject: args.recurse,
268
305
  noBabel: args.noBabel || args.babel === false,
269
- project: args.projectId
306
+ project: args.projectId,
307
+ deep: args.deep || args.evidence
270
308
  });
309
+ applyProfile(options);
271
310
 
272
311
  /**
273
312
  * Check for node >= 20 permissions
@@ -306,7 +345,7 @@ const checkPermissions = (filePath) => {
306
345
  */
307
346
  (async () => {
308
347
  // Start SBOM server
309
- if (args.server) {
348
+ if (options.server) {
310
349
  const serverModule = await import("../server.js");
311
350
  return serverModule.start(options);
312
351
  }
@@ -323,15 +362,15 @@ const checkPermissions = (filePath) => {
323
362
  bomNSData = postProcess(bomNSData, options);
324
363
  }
325
364
  if (
326
- args.output &&
327
- (typeof args.output === "string" || args.output instanceof String)
365
+ options.output &&
366
+ (typeof options.output === "string" || options.output instanceof String)
328
367
  ) {
329
368
  if (bomNSData.bomXmlFiles) {
330
369
  console.log("BOM files produced:", bomNSData.bomXmlFiles);
331
370
  } else {
332
- const jsonFile = args.output.replace(".xml", ".json");
371
+ const jsonFile = options.output.replace(".xml", ".json");
333
372
  // Create bom json file
334
- if (!args.output.endsWith(".xml") && bomNSData.bomJson) {
373
+ if (!options.output.endsWith(".xml") && bomNSData.bomJson) {
335
374
  let jsonPayload = undefined;
336
375
  if (
337
376
  typeof bomNSData.bomJson === "string" ||
@@ -345,7 +384,7 @@ const checkPermissions = (filePath) => {
345
384
  }
346
385
  if (
347
386
  jsonPayload &&
348
- (args.generateKeyAndSign ||
387
+ (options.generateKeyAndSign ||
349
388
  (process.env.SBOM_SIGN_ALGORITHM &&
350
389
  process.env.SBOM_SIGN_ALGORITHM !== "none" &&
351
390
  process.env.SBOM_SIGN_PRIVATE_KEY &&
@@ -358,7 +397,7 @@ const checkPermissions = (filePath) => {
358
397
  let privateKeyToUse = undefined;
359
398
  let jwkPublicKey = undefined;
360
399
  let publicKeyFile = undefined;
361
- if (args.generateKeyAndSign) {
400
+ if (options.generateKeyAndSign) {
362
401
  const jdirName = dirname(jsonFile);
363
402
  publicKeyFile = join(jdirName, "public.key");
364
403
  const privateKeyFile = join(jdirName, "private.key");
@@ -468,8 +507,8 @@ const checkPermissions = (filePath) => {
468
507
  }
469
508
  }
470
509
  // Create bom xml file
471
- if (args.output.endsWith(".xml") && bomNSData.bomXml) {
472
- fs.writeFileSync(args.output, bomNSData.bomXml);
510
+ if (options.output.endsWith(".xml") && bomNSData.bomXml) {
511
+ fs.writeFileSync(options.output, bomNSData.bomXml);
473
512
  }
474
513
  //
475
514
  if (bomNSData.nsMapping && Object.keys(bomNSData.nsMapping).length) {
@@ -478,7 +517,7 @@ const checkPermissions = (filePath) => {
478
517
  console.log("Namespace mapping file written to", nsFile);
479
518
  }
480
519
  }
481
- } else if (!args.print) {
520
+ } else if (!options.print) {
482
521
  if (bomNSData.bomJson) {
483
522
  console.log(JSON.stringify(bomNSData.bomJson, null, 2));
484
523
  } else if (bomNSData.bomXml) {
@@ -489,7 +528,8 @@ const checkPermissions = (filePath) => {
489
528
  }
490
529
  }
491
530
  // Evidence generation
492
- if (args.evidence) {
531
+ if (options.evidence) {
532
+ const evinserModule = await import("../evinser.js");
493
533
  const evinseOptions = {
494
534
  _: args._,
495
535
  input: options.output,
@@ -503,12 +543,18 @@ const checkPermissions = (filePath) => {
503
543
  dataFlowSlicesFile: options.dataFlowSlicesFile,
504
544
  reachablesSlicesFile: options.reachablesSlicesFile
505
545
  };
506
- const dbObjMap = await prepareDB(evinseOptions);
546
+ const dbObjMap = await evinserModule.prepareDB(evinseOptions);
507
547
  if (dbObjMap) {
508
- const sliceArtefacts = await analyzeProject(dbObjMap, evinseOptions);
509
- const evinseJson = createEvinseFile(sliceArtefacts, evinseOptions);
548
+ const sliceArtefacts = await evinserModule.analyzeProject(
549
+ dbObjMap,
550
+ evinseOptions
551
+ );
552
+ const evinseJson = evinserModule.createEvinseFile(
553
+ sliceArtefacts,
554
+ evinseOptions
555
+ );
510
556
  bomNSData.bomJson = evinseJson;
511
- if (args.print && evinseJson) {
557
+ if (options.print && evinseJson) {
512
558
  printOccurrences(evinseJson);
513
559
  printCallStack(evinseJson);
514
560
  printReachables(sliceArtefacts);
@@ -517,22 +563,22 @@ const checkPermissions = (filePath) => {
517
563
  }
518
564
  }
519
565
  // Perform automatic validation
520
- if (args.validate) {
566
+ if (options.validate) {
521
567
  if (!validateBom(bomNSData.bomJson)) {
522
568
  process.exit(1);
523
569
  }
524
570
  }
525
571
  // Automatically submit the bom data
526
- if (args.serverUrl && args.serverUrl != true && args.apiKey) {
572
+ if (options.serverUrl && options.serverUrl != true && options.apiKey) {
527
573
  try {
528
- const dbody = await submitBom(args, bomNSData.bomJson);
574
+ const dbody = await submitBom(options, bomNSData.bomJson);
529
575
  console.log("Response from server", dbody);
530
576
  } catch (err) {
531
577
  console.log(err);
532
578
  }
533
579
  }
534
580
 
535
- if (args.print && bomNSData.bomJson && bomNSData.bomJson.components) {
581
+ if (options.print && bomNSData.bomJson && bomNSData.bomJson.components) {
536
582
  printDependencyTree(bomNSData.bomJson);
537
583
  printTable(bomNSData.bomJson);
538
584
  }