@cyclonedx/cdxgen 11.1.8 → 11.1.10

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/bin/cdxgen.js CHANGED
@@ -21,6 +21,7 @@ import {
21
21
  printSummary,
22
22
  printTable,
23
23
  } from "../lib/helpers/display.js";
24
+ import { thoughtEnd, thoughtLog } from "../lib/helpers/logger.js";
24
25
  import {
25
26
  ATOM_DB,
26
27
  dirNameStr,
@@ -397,6 +398,7 @@ if (!args.projectName) {
397
398
  args.projectName = basename(resolve(filePath));
398
399
  }
399
400
  }
401
+ thoughtLog(`Let's try to generate a CycloneDX BOM for the path '${filePath}'`);
400
402
  if (
401
403
  filePath.includes(" ") ||
402
404
  filePath.includes("\r") ||
@@ -412,6 +414,9 @@ if (
412
414
  // Support for obom/cbom aliases
413
415
  if (process.argv[1].includes("obom") && !args.type) {
414
416
  args.type = "os";
417
+ thoughtLog(
418
+ "Ok, the user wants to generate an Operations Bill-of-Materials (OBOM).",
419
+ );
415
420
  }
416
421
 
417
422
  /**
@@ -428,14 +433,28 @@ const options = Object.assign({}, args, {
428
433
  ? resolve(join(filePath, args.output))
429
434
  : args.output,
430
435
  });
431
-
436
+ // Filter duplicate types. Eg: -t gradle -t gradle
437
+ if (options.projectType && Array.isArray(options.projectType)) {
438
+ options.projectType = Array.from(new Set(options.projectType));
439
+ }
440
+ if (!options.projectType) {
441
+ thoughtLog(
442
+ "Ok, the user wants me to identify all the project types and generate a consolidated BOM document.",
443
+ );
444
+ }
432
445
  if (process.argv[1].includes("cbom")) {
446
+ thoughtLog(
447
+ "Ok, the user wants to generate Cryptographic Bill-of-Materials (CBOM).",
448
+ );
433
449
  options.includeCrypto = true;
434
450
  options.evidence = true;
435
451
  options.specVersion = 1.6;
436
452
  options.deep = true;
437
453
  }
438
454
  if (process.argv[1].includes("cdxgen-secure")) {
455
+ thoughtLog(
456
+ "Ok, the user wants cdxgen to run in secure mode by default. Let's try and use the permissions api.",
457
+ );
439
458
  console.log(
440
459
  "NOTE: Secure mode only restricts cdxgen from performing certain activities such as package installation. It does not provide security guarantees in the presence of malicious code.",
441
460
  );
@@ -446,6 +465,9 @@ if (options.standard) {
446
465
  options.specVersion = 1.6;
447
466
  }
448
467
  if (options.includeFormulation) {
468
+ thoughtLog(
469
+ "Wait, the user wants to include formulation information. Let's warn about accidentally disclosing sensitive data via the BOM files.",
470
+ );
449
471
  console.log(
450
472
  "NOTE: Formulation section could include sensitive data such as emails and secrets.\nPlease review the generated SBOM before distribution.\n",
451
473
  );
@@ -456,6 +478,13 @@ if (options.includeFormulation) {
456
478
  * @param {object} options CLI options
457
479
  */
458
480
  const applyAdvancedOptions = (options) => {
481
+ if (options?.profile !== "generic") {
482
+ thoughtLog(`BOM profile to use is '${options.profile}'.`);
483
+ } else {
484
+ thoughtLog(
485
+ "The user hasn't specified a profile. Should I suggest one to optimize the BOM for a specific use case or persona 🤔?",
486
+ );
487
+ }
459
488
  switch (options.profile) {
460
489
  case "appsec":
461
490
  options.deep = true;
@@ -508,6 +537,11 @@ const applyAdvancedOptions = (options) => {
508
537
  default:
509
538
  break;
510
539
  }
540
+ if (options.lifecycle) {
541
+ thoughtLog(
542
+ `BOM must be generated for the lifecycle '${options.lifecycle}'.`,
543
+ );
544
+ }
511
545
  switch (options.lifecycle) {
512
546
  case "pre-build":
513
547
  options.installDeps = false;
@@ -728,7 +762,9 @@ const checkPermissions = (filePath, options) => {
728
762
  options.usagesSlicesFile = `${options.projectName}-usages.json`;
729
763
  }
730
764
  prepareEnv(filePath, options);
765
+ thoughtLog("Getting ready to generate the BOM ⚡️.");
731
766
  let bomNSData = (await createBom(filePath, options)) || {};
767
+ thoughtLog("Tweaking the generated BOM data. Nearly there.");
732
768
  // Add extra metadata and annotations with post processing
733
769
  bomNSData = postProcess(bomNSData, options);
734
770
  if (
@@ -748,6 +784,13 @@ const checkPermissions = (filePath, options) => {
748
784
  } else {
749
785
  jsonPayload = JSON.stringify(bomNSData.bomJson, null, null);
750
786
  fs.writeFileSync(jsonFile, jsonPayload);
787
+ if (jsonFile.endsWith("bom.json")) {
788
+ thoughtLog(
789
+ `Let's save the file to "${jsonFile}". Should I suggest the '.cdx.json' file extension for better semantics?`,
790
+ );
791
+ } else {
792
+ thoughtLog(`Let's save the file to "${jsonFile}".`);
793
+ }
751
794
  }
752
795
  if (
753
796
  jsonPayload &&
@@ -843,6 +886,7 @@ const checkPermissions = (filePath, options) => {
843
886
  jsonFile,
844
887
  JSON.stringify(bomJsonUnsignedObj, null, null),
845
888
  );
889
+ thoughtLog(`Signing the BOM file "${jsonFile}".`);
846
890
  if (publicKeyFile) {
847
891
  // Verifying this signature
848
892
  const signatureVerification = jws.verify(
@@ -929,10 +973,13 @@ const checkPermissions = (filePath, options) => {
929
973
  }
930
974
  // Perform automatic validation
931
975
  if (options.validate) {
976
+ thoughtLog("Wait, let's check the generated BOM file for any issues.");
932
977
  if (!validateBom(bomNSData.bomJson)) {
933
978
  process.exit(1);
934
979
  }
980
+ thoughtLog("BOM file looks valid. Thank you for using cdxgen!");
935
981
  }
982
+ thoughtEnd();
936
983
  // Automatically submit the bom data
937
984
  // biome-ignore lint/suspicious/noDoubleEquals: yargs passes true for empty values
938
985
  if (options.serverUrl && options.serverUrl != true && options.apiKey) {
package/lib/cli/index.js CHANGED
@@ -30,6 +30,8 @@ import {
30
30
  gitTreeHashes,
31
31
  listFiles,
32
32
  } from "../helpers/envcontext.js";
33
+ import { thoughtLog } from "../helpers/logger.js";
34
+
33
35
  import {
34
36
  CARGO_CMD,
35
37
  CLJ_CMD,
@@ -1344,11 +1346,22 @@ export async function createJavaBom(path, options) {
1344
1346
  `${options.multiProject ? "**/" : ""}pom.xml`,
1345
1347
  options,
1346
1348
  );
1349
+ // gradle
1350
+ const gradleFiles = getAllFiles(
1351
+ path,
1352
+ `${options.multiProject ? "**/" : ""}build.gradle*`,
1353
+ options,
1354
+ );
1347
1355
  let bomJsonFiles = [];
1348
1356
  if (
1349
1357
  pomFiles?.length &&
1350
1358
  isPackageManagerAllowed("maven", ["bazel", "sbt", "gradle"], options)
1351
1359
  ) {
1360
+ if (gradleFiles.length) {
1361
+ thoughtLog(
1362
+ `Is this a Gradle project? I recommend invoking cdxgen with the "-t gradle" option if you're encountering build errors.`,
1363
+ );
1364
+ }
1352
1365
  if (!isQuarkus) {
1353
1366
  // Quarkus projects require special treatment. To detect quarkus, we parse the first 3 maven file to look for a hit
1354
1367
  for (const pf of pomFiles.slice(0, 3)) {
@@ -1367,6 +1380,9 @@ export async function createJavaBom(path, options) {
1367
1380
  let result = undefined;
1368
1381
  let mvnArgs;
1369
1382
  if (isQuarkus) {
1383
+ thoughtLog(
1384
+ "This appears to be a quarkus project. Let's use the right maven plugin.",
1385
+ );
1370
1386
  // disable analytics. See: https://quarkus.io/usage/
1371
1387
  mvnArgs = [
1372
1388
  "-fn",
@@ -1438,6 +1454,7 @@ export async function createJavaBom(path, options) {
1438
1454
  }
1439
1455
  // Use the cyclonedx maven plugin if there is no preference for maven deps tree
1440
1456
  if (!useMavenDepsTree) {
1457
+ thoughtLog("The user wants me to use the cyclonedx-maven plugin.");
1441
1458
  console.log(
1442
1459
  `Executing '${mavenCmd} ${mvnArgs.join(" ")}' in`,
1443
1460
  basePath,
@@ -1488,6 +1505,9 @@ export async function createJavaBom(path, options) {
1488
1505
  // For the first pom alone, we need to execute first in non-recursive mode to capture
1489
1506
  // the parent component. Then, we execute all of them in recursive mode
1490
1507
  if (f === firstPom) {
1508
+ thoughtLog(
1509
+ "What is the parent component here? Let's use maven command to find out.",
1510
+ );
1491
1511
  result = spawnSync(
1492
1512
  "mvn",
1493
1513
  ["dependency:tree", "-N", `-DoutputFile=${tempMvnParentTree}`],
@@ -1510,10 +1530,22 @@ export async function createJavaBom(path, options) {
1510
1530
  tmpParentComponent.type = "application";
1511
1531
  parentComponent = tmpParentComponent;
1512
1532
  parentComponent.components = [];
1533
+ if (parentComponent.name) {
1534
+ thoughtLog(
1535
+ `Parent component is called ${parentComponent.name}!`,
1536
+ );
1537
+ }
1513
1538
  }
1514
1539
  }
1515
1540
  }
1516
- console.log(`Executing 'mvn ${mvnTreeArgs.join(" ")}' in ${basePath}`);
1541
+ thoughtLog(
1542
+ `**MAVEN**: Let's use Maven to collect packages from ${basePath}.`,
1543
+ );
1544
+ if (DEBUG_MODE) {
1545
+ console.log(
1546
+ `Executing 'mvn ${mvnTreeArgs.join(" ")}' in ${basePath}`,
1547
+ );
1548
+ }
1517
1549
  // Prefer the built-in maven
1518
1550
  result = spawnSync(
1519
1551
  PREFER_MAVEN_DEPS_TREE ? "mvn" : mavenCmd,
@@ -1577,6 +1609,9 @@ export async function createJavaBom(path, options) {
1577
1609
  console.log(
1578
1610
  "\nFalling back to parsing pom.xml files. Only direct dependencies would get included!",
1579
1611
  );
1612
+ thoughtLog(
1613
+ "**MAVEN**: There appear to be build errors, so the SBOM will be incomplete.",
1614
+ );
1580
1615
  const dlist = parsePom(f);
1581
1616
  if (dlist?.length) {
1582
1617
  pkgList = pkgList.concat(dlist);
@@ -1693,19 +1728,17 @@ export async function createJavaBom(path, options) {
1693
1728
  }
1694
1729
  }
1695
1730
  if (possible_misses) {
1696
- if (!DEBUG_MODE) {
1731
+ if (gradleFiles.length) {
1732
+ console.log(
1733
+ "Is this a gradle project? Try running cdxgen with `-t gradle`.",
1734
+ );
1735
+ } else if (!DEBUG_MODE) {
1697
1736
  console.warn(
1698
1737
  "Multiple errors occurred while building this project with maven. The SBOM is therefore incomplete!",
1699
1738
  );
1700
1739
  }
1701
1740
  }
1702
1741
  }
1703
- // gradle
1704
- const gradleFiles = getAllFiles(
1705
- path,
1706
- `${options.multiProject ? "**/" : ""}build.gradle*`,
1707
- options,
1708
- );
1709
1742
  const allProjects = [];
1710
1743
  const allProjectsAddedPurls = [];
1711
1744
  const rootDependsOn = new Set();
@@ -1923,9 +1956,14 @@ export async function createJavaBom(path, options) {
1923
1956
  "from this gradle project. De-duping this list ...",
1924
1957
  );
1925
1958
  } else {
1926
- console.log(
1927
- "No packages found. Set the environment variable 'CDXGEN_DEBUG_MODE=debug' to troubleshoot any gradle related errors.",
1959
+ thoughtLog(
1960
+ "**GRADLE:** SBOM is incomplete. I recommend troubleshooting the issue to improve the BOM precision.",
1928
1961
  );
1962
+ if (!DEBUG_MODE) {
1963
+ console.log(
1964
+ "No packages found. Set the environment variable 'CDXGEN_DEBUG_MODE=debug' to troubleshoot any gradle related errors.",
1965
+ );
1966
+ }
1929
1967
  options.failOnError && process.exit(1);
1930
1968
  }
1931
1969
  // Should we attempt to resolve class names
@@ -2367,16 +2405,14 @@ export async function createNodejsBom(path, options) {
2367
2405
  `${options.multiProject ? "**/" : ""}package.json`,
2368
2406
  options,
2369
2407
  );
2370
- const yarnLockFile = getAllFiles(path, "yarn.lock", options);
2371
- const pnpmLockFile = getAllFiles(path, "pnpm-lock.yaml", options);
2372
2408
  const npmInstallCount = Number.parseInt(process.env.NPM_INSTALL_COUNT) || 2;
2373
2409
  // Automatic npm install logic.
2374
2410
  // Only perform npm install for smaller projects (< 2 package.json) without the correct number of lock files
2375
2411
  if (
2376
2412
  (pkgJsonLockFiles?.length === 0 ||
2377
2413
  pkgJsonLockFiles?.length < pkgJsonFiles?.length) &&
2378
- yarnLockFile?.length === 0 &&
2379
- pnpmLockFile?.length === 0 &&
2414
+ yarnLockFiles?.length === 0 &&
2415
+ pnpmLockFiles?.length === 0 &&
2380
2416
  pkgJsonFiles?.length <= npmInstallCount &&
2381
2417
  options.installDeps
2382
2418
  ) {
@@ -3317,6 +3353,9 @@ export async function createPythonBom(path, options) {
3317
3353
  }
3318
3354
  // Fallback to parsing manually
3319
3355
  if (!pkgList.length || !frozen) {
3356
+ thoughtLog(
3357
+ `Manually parsing ${f}. The result would include only direct dependencies.`,
3358
+ );
3320
3359
  if (DEBUG_MODE) {
3321
3360
  console.log(
3322
3361
  `Manually parsing ${f}. The result would include only direct dependencies.`,
@@ -4005,10 +4044,12 @@ export async function createRustBom(path, options) {
4005
4044
  }
4006
4045
  }
4007
4046
  // After running cargo check, .d files would get created
4008
- const makeDFiles = getAllFiles(path, "target/**/*.d", options);
4009
4047
  let pkgFilesMap = {};
4010
- for (const dfile of makeDFiles) {
4011
- pkgFilesMap = { ...pkgFilesMap, ...parseMakeDFile(dfile) };
4048
+ if (options.deep || ["build", "post-build"].includes(options.lifecycle)) {
4049
+ const makeDFiles = getAllFiles(path, "target/**/*.d", options);
4050
+ for (const dfile of makeDFiles) {
4051
+ pkgFilesMap = { ...pkgFilesMap, ...parseMakeDFile(dfile) };
4052
+ }
4012
4053
  }
4013
4054
  const cargoLockFiles = getAllFiles(
4014
4055
  path,
@@ -6205,7 +6246,16 @@ export async function createMultiXBom(pathList, options) {
6205
6246
  );
6206
6247
  if (DEBUG_MODE) {
6207
6248
  console.log(
6208
- `Found ${osPackages.length} OS packages at ${options.allLayersExplodedDir}`,
6249
+ `**OS**: Found ${osPackages.length} OS packages at ${options.allLayersExplodedDir}`,
6250
+ );
6251
+ }
6252
+ if (osPackages.length) {
6253
+ thoughtLog(
6254
+ `I found ${osPackages.length} OS packages at ${options.allLayersExplodedDir}`,
6255
+ );
6256
+ } else {
6257
+ thoughtLog(
6258
+ `I couldn't find any OS packages at ${options.allLayersExplodedDir}. Perhaps the binary plugin wasn't available, or the architecture is unsupported.`,
6209
6259
  );
6210
6260
  }
6211
6261
  if (allTypes?.length) {
@@ -6230,6 +6280,11 @@ export async function createMultiXBom(pathList, options) {
6230
6280
  if (DEBUG_MODE) {
6231
6281
  console.log(`Found ${bomData.bomJson.components.length} OS components`);
6232
6282
  }
6283
+ if (bomData.bomJson.components.length) {
6284
+ thoughtLog(
6285
+ `I found ${bomData.bomJson.components.length} OS packages 😎.`,
6286
+ );
6287
+ }
6233
6288
  components = components.concat(bomData.bomJson.components);
6234
6289
  }
6235
6290
  }
@@ -6237,10 +6292,19 @@ export async function createMultiXBom(pathList, options) {
6237
6292
  if (DEBUG_MODE) {
6238
6293
  console.log("Scanning", path);
6239
6294
  }
6295
+ if (pathList.length > 2) {
6296
+ thoughtLog(`Let's thoroughly check the path ${path}.`);
6297
+ }
6240
6298
  // Node.js
6241
6299
  if (hasAnyProjectType(["oci", "js"], options)) {
6300
+ thoughtLog(
6301
+ "**JS**: Now looking for JavaScript projects (npm, yarn, pnpm) and files.",
6302
+ );
6242
6303
  bomData = await createNodejsBom(path, options);
6243
6304
  if (bomData?.bomJson?.components?.length) {
6305
+ thoughtLog(
6306
+ `I found ${bomData.bomJson.components.length} npm packages. Let's keep looking.`,
6307
+ );
6244
6308
  if (DEBUG_MODE) {
6245
6309
  console.log(
6246
6310
  `Found ${bomData.bomJson.components.length} npm packages at ${path}`,
@@ -6268,8 +6332,14 @@ export async function createMultiXBom(pathList, options) {
6268
6332
  }
6269
6333
  // Java
6270
6334
  if (hasAnyProjectType(["oci", "java"], options)) {
6335
+ thoughtLog(
6336
+ "**JAVA**: Looking for Java projects (e.g., Maven, Gradle, SBT). I hope all configurations—from Java version to individual build settings—are correctly aligned.",
6337
+ );
6271
6338
  bomData = await createJavaBom(path, options);
6272
6339
  if (bomData?.bomJson?.components?.length) {
6340
+ thoughtLog(
6341
+ `I found ${bomData.bomJson.components.length} java packages.`,
6342
+ );
6273
6343
  if (DEBUG_MODE) {
6274
6344
  console.log(
6275
6345
  `Found ${bomData.bomJson.components.length} java packages at ${path}`,
@@ -6291,6 +6361,9 @@ export async function createMultiXBom(pathList, options) {
6291
6361
  if (bomData.parentComponent.components?.length) {
6292
6362
  let bomSubComponents = bomData.parentComponent.components;
6293
6363
  if (["true", "1"].includes(process.env.GRADLE_RESOLVE_FROM_NODE)) {
6364
+ thoughtLog(
6365
+ "Wait, the user wants me to resolve gradle projects from npm.",
6366
+ );
6294
6367
  const allRefs = components.map((c) => c["bom-ref"]);
6295
6368
  const duplicateComponents = bomSubComponents.filter((c) =>
6296
6369
  allRefs.includes(c["bom-ref"]),
@@ -6309,8 +6382,19 @@ export async function createMultiXBom(pathList, options) {
6309
6382
  }
6310
6383
  }
6311
6384
  if (hasAnyProjectType(["oci", "py"], options)) {
6385
+ thoughtLog(
6386
+ "**PYTHON**: Looking for Python projects with package managers such as pip, poetry, uv, etc. Wish me good luck!",
6387
+ );
6388
+ if (process.env?.CDXGEN_IN_CONTAINER !== "true") {
6389
+ thoughtLog(
6390
+ "I'm running in a non-container environment. Let's hope the correct build tools are available ✌️.",
6391
+ );
6392
+ }
6312
6393
  bomData = await createPythonBom(path, options);
6313
6394
  if (bomData?.bomJson?.components?.length) {
6395
+ thoughtLog(
6396
+ `I found ${bomData.bomJson.components.length} python packages.`,
6397
+ );
6314
6398
  if (DEBUG_MODE) {
6315
6399
  console.log(
6316
6400
  `Found ${bomData.bomJson.components.length} python packages at ${path}`,
@@ -6330,8 +6414,12 @@ export async function createMultiXBom(pathList, options) {
6330
6414
  }
6331
6415
  }
6332
6416
  if (hasAnyProjectType(["oci", "go"], options)) {
6417
+ thoughtLog(
6418
+ "**GO**: Looking for go projects. I need to be cautious about purl namespaces and potential failures with the 'go list' command.",
6419
+ );
6333
6420
  bomData = await createGoBom(path, options);
6334
6421
  if (bomData?.bomJson?.components?.length) {
6422
+ thoughtLog(`I found ${bomData.bomJson.components.length} go packages.`);
6335
6423
  if (DEBUG_MODE) {
6336
6424
  console.log(
6337
6425
  `Found ${bomData.bomJson.components.length} go packages at ${path}`,
@@ -6351,8 +6439,14 @@ export async function createMultiXBom(pathList, options) {
6351
6439
  }
6352
6440
  }
6353
6441
  if (hasAnyProjectType(["oci", "rust"], options)) {
6442
+ thoughtLog(
6443
+ "**RUST**: Let's search for Cargo/Rust projects. Should I warn the user that we don't support Cargo 'features' and native dependencies, which may lead to both false positives and false negatives? 🤔?",
6444
+ );
6354
6445
  bomData = await createRustBom(path, options);
6355
6446
  if (bomData?.bomJson?.components?.length) {
6447
+ thoughtLog(
6448
+ `I found ${bomData.bomJson.components.length} rust packages.`,
6449
+ );
6356
6450
  if (DEBUG_MODE) {
6357
6451
  console.log(
6358
6452
  `Found ${bomData.bomJson.components.length} rust packages at ${path}`,
@@ -6379,8 +6473,14 @@ export async function createMultiXBom(pathList, options) {
6379
6473
  }
6380
6474
  }
6381
6475
  if (hasAnyProjectType(["oci", "php"], options)) {
6476
+ thoughtLog(
6477
+ "**PHP**: About to search for Composer-based projects. I hope lock files are available; otherwise, the 'composer install' command might fail for various reasons.",
6478
+ );
6382
6479
  bomData = createPHPBom(path, options);
6383
6480
  if (bomData?.bomJson?.components?.length) {
6481
+ thoughtLog(
6482
+ `I found ${bomData.bomJson.components.length} php packages.`,
6483
+ );
6384
6484
  if (DEBUG_MODE) {
6385
6485
  console.log(
6386
6486
  `Found ${bomData.bomJson.components.length} php packages at ${path}`,
@@ -6407,8 +6507,14 @@ export async function createMultiXBom(pathList, options) {
6407
6507
  }
6408
6508
  }
6409
6509
  if (hasAnyProjectType(["oci", "ruby"], options)) {
6510
+ thoughtLog(
6511
+ "**RUBY**: Are there any Ruby projects in this path? There's only one way to know.",
6512
+ );
6410
6513
  bomData = await createRubyBom(path, options);
6411
6514
  if (bomData?.bomJson?.components?.length) {
6515
+ thoughtLog(
6516
+ `We got ${bomData.bomJson.components.length} ruby packages.`,
6517
+ );
6412
6518
  if (DEBUG_MODE) {
6413
6519
  console.log(
6414
6520
  `Found ${bomData.bomJson.components.length} ruby packages at ${path}`,
@@ -6436,8 +6542,12 @@ export async function createMultiXBom(pathList, options) {
6436
6542
  }
6437
6543
  }
6438
6544
  if (hasAnyProjectType(["oci", "csharp"], options)) {
6545
+ thoughtLog("**CSHARP**: What about csharp and fsharp projects?");
6439
6546
  bomData = await createCsharpBom(path, options);
6440
6547
  if (bomData?.bomJson?.components?.length) {
6548
+ thoughtLog(
6549
+ `There are ${bomData.bomJson.components.length} csharp packages.`,
6550
+ );
6441
6551
  if (DEBUG_MODE) {
6442
6552
  console.log(
6443
6553
  `Found ${bomData.bomJson.components.length} csharp packages at ${path}`,
@@ -6464,8 +6574,14 @@ export async function createMultiXBom(pathList, options) {
6464
6574
  }
6465
6575
  }
6466
6576
  if (hasAnyProjectType(["oci", "dart"], options)) {
6577
+ thoughtLog(
6578
+ "**DART**: Looking for Dart projects. These are rare ones. Should I inform the user that they can pass the types argument via the command-line to speed things up?",
6579
+ );
6467
6580
  bomData = await createDartBom(path, options);
6468
6581
  if (bomData?.bomJson?.components?.length) {
6582
+ thoughtLog(
6583
+ `I found ${bomData.bomJson.components.length} pub packages.`,
6584
+ );
6469
6585
  if (DEBUG_MODE) {
6470
6586
  console.log(
6471
6587
  `Found ${bomData.bomJson.components.length} pub packages at ${path}`,
@@ -6485,8 +6601,14 @@ export async function createMultiXBom(pathList, options) {
6485
6601
  }
6486
6602
  }
6487
6603
  if (hasAnyProjectType(["oci", "haskell"], options)) {
6604
+ thoughtLog(
6605
+ "**HASKELL**: Looking for Haskell projects. They're rarely encountered.",
6606
+ );
6488
6607
  bomData = createHaskellBom(path, options);
6489
6608
  if (bomData?.bomJson?.components?.length) {
6609
+ thoughtLog(
6610
+ `I found ${bomData.bomJson.components.length} hackage packages.`,
6611
+ );
6490
6612
  if (DEBUG_MODE) {
6491
6613
  console.log(
6492
6614
  `Found ${bomData.bomJson.components.length} hackage packages at ${path}`,
@@ -6506,8 +6628,14 @@ export async function createMultiXBom(pathList, options) {
6506
6628
  }
6507
6629
  }
6508
6630
  if (hasAnyProjectType(["oci", "elixir"], options)) {
6631
+ thoughtLog(
6632
+ "**ELIXIR**: Looking for Elixir projects—they're quite rare as well.",
6633
+ );
6509
6634
  bomData = createElixirBom(path, options);
6510
6635
  if (bomData?.bomJson?.components?.length) {
6636
+ thoughtLog(
6637
+ `I found ${bomData.bomJson.components.length} mix packages.`,
6638
+ );
6511
6639
  if (DEBUG_MODE) {
6512
6640
  console.log(
6513
6641
  `Found ${bomData.bomJson.components.length} mix packages at ${path}`,
@@ -6527,8 +6655,14 @@ export async function createMultiXBom(pathList, options) {
6527
6655
  }
6528
6656
  }
6529
6657
  if (hasAnyProjectType(["oci", "c"], options)) {
6658
+ thoughtLog(
6659
+ "**C/C++**: Looking for C/C++ projects. Should I warn the user that the generated SBOM might have low accuracy and contain errors?",
6660
+ );
6530
6661
  bomData = createCppBom(path, options);
6531
6662
  if (bomData?.bomJson?.components?.length) {
6663
+ thoughtLog(
6664
+ `I found ${bomData.bomJson.components.length} cpp packages.`,
6665
+ );
6532
6666
  if (DEBUG_MODE) {
6533
6667
  console.log(
6534
6668
  `Found ${bomData.bomJson.components.length} cpp packages at ${path}`,
@@ -6548,8 +6682,14 @@ export async function createMultiXBom(pathList, options) {
6548
6682
  }
6549
6683
  }
6550
6684
  if (hasAnyProjectType(["oci", "clojure"], options)) {
6685
+ thoughtLog(
6686
+ "**CLOJURE**: Looking for Clojure projects. Should I warn the user that the purl namespace 'clojars' isn't widely supported by tools like Dependency-Track?",
6687
+ );
6551
6688
  bomData = createClojureBom(path, options);
6552
6689
  if (bomData?.bomJson?.components?.length) {
6690
+ thoughtLog(
6691
+ `I found ${bomData.bomJson.components.length} clojure packages.`,
6692
+ );
6553
6693
  if (DEBUG_MODE) {
6554
6694
  console.log(
6555
6695
  `Found ${bomData.bomJson.components.length} clojure packages at ${path}`,
@@ -6569,8 +6709,12 @@ export async function createMultiXBom(pathList, options) {
6569
6709
  }
6570
6710
  }
6571
6711
  if (hasAnyProjectType(["oci", "github"], options)) {
6712
+ thoughtLog("**GITHUB**: Looking for any github packages and workflows.");
6572
6713
  bomData = createGitHubBom(path, options);
6573
6714
  if (bomData?.bomJson?.components?.length) {
6715
+ thoughtLog(
6716
+ `I found ${bomData.bomJson.components.length} github action packages as well. Should I convert these to formulation instead 🤔`,
6717
+ );
6574
6718
  if (DEBUG_MODE) {
6575
6719
  console.log(
6576
6720
  `Found ${bomData.bomJson.components.length} GitHub action packages at ${path}`,
@@ -6590,8 +6734,14 @@ export async function createMultiXBom(pathList, options) {
6590
6734
  }
6591
6735
  }
6592
6736
  if (hasAnyProjectType(["oci", "cloudbuild"], options)) {
6737
+ thoughtLog(
6738
+ "**CLOUDBUILD**: Let's check for CloudBuild configuration files that include package dependencies.",
6739
+ );
6593
6740
  bomData = createCloudBuildBom(path, options);
6594
6741
  if (bomData?.bomJson?.components?.length) {
6742
+ thoughtLog(
6743
+ `I found ${bomData.bomJson.components.length} cloudbuild packages.`,
6744
+ );
6595
6745
  if (DEBUG_MODE) {
6596
6746
  console.log(
6597
6747
  `Found ${bomData.bomJson.components.length} CloudBuild configuration at ${path}`,
@@ -6611,8 +6761,14 @@ export async function createMultiXBom(pathList, options) {
6611
6761
  }
6612
6762
  }
6613
6763
  if (hasAnyProjectType(["oci", "swift"], options)) {
6764
+ thoughtLog(
6765
+ "**SWIFT**: Now checking for Swift projects. We don't support CocoaPods, Objective-C, or pure Xcode projects, so the SBOM will be incomplete.",
6766
+ );
6614
6767
  bomData = await createSwiftBom(path, options);
6615
6768
  if (bomData?.bomJson?.components?.length) {
6769
+ thoughtLog(
6770
+ `I found ${bomData.bomJson.components.length} swift packages here.`,
6771
+ );
6616
6772
  if (DEBUG_MODE) {
6617
6773
  console.log(
6618
6774
  `Found ${bomData.bomJson.components.length} Swift packages at ${path}`,
@@ -6632,8 +6788,14 @@ export async function createMultiXBom(pathList, options) {
6632
6788
  }
6633
6789
  }
6634
6790
  if (hasAnyProjectType(["oci", "jar", "war", "ear"], options)) {
6791
+ thoughtLog(
6792
+ "**JAR**: Let's check for any bundled jar/war/ear files to improve the SBOM accuracy.",
6793
+ );
6635
6794
  bomData = await createJarBom(path, options);
6636
6795
  if (bomData?.bomJson?.components?.length) {
6796
+ thoughtLog(
6797
+ `I found ${bomData.bomJson.components.length} jar packages as well.`,
6798
+ );
6637
6799
  if (DEBUG_MODE) {
6638
6800
  console.log(
6639
6801
  `Found ${bomData.bomJson.components.length} jar packages at ${path}`,
@@ -6654,8 +6816,14 @@ export async function createMultiXBom(pathList, options) {
6654
6816
  }
6655
6817
  // Collect any crypto keys
6656
6818
  if (options.specVersion >= 1.6 && options.includeCrypto) {
6819
+ thoughtLog(
6820
+ "**CBOM**: Wait, the user wants me to look for cryptographic assets. Let's check thoroughly.",
6821
+ );
6657
6822
  bomData = await createCryptoCertsBom(path, options);
6658
6823
  if (bomData?.bomJson?.components?.length) {
6824
+ thoughtLog(
6825
+ `I found ${bomData.bomJson.components.length} crypto assets.`,
6826
+ );
6659
6827
  if (DEBUG_MODE) {
6660
6828
  console.log(
6661
6829
  `Found ${bomData.bomJson.components.length} crypto assets at ${path}`,
@@ -6693,6 +6861,7 @@ export async function createMultiXBom(pathList, options) {
6693
6861
  }
6694
6862
  // Retain the components of parent component
6695
6863
  if (parentSubComponents.length) {
6864
+ thoughtLog("**METADATA**: Tweaking the parent component hierarchy.");
6696
6865
  if (!parentComponent || !Object.keys(parentComponent).length) {
6697
6866
  parentComponent = parentSubComponents[0];
6698
6867
  }
@@ -7196,9 +7365,17 @@ export async function createBom(path, options) {
7196
7365
  projectType = ["java"];
7197
7366
  }
7198
7367
  if (projectType.length > 1) {
7368
+ thoughtLog(
7369
+ `The user has specified multiple project types: projectType.join(", "). Let's focus on the types one at a time.`,
7370
+ );
7199
7371
  console.log("Generate BOM for project types:", projectType.join(", "));
7200
7372
  return await createMultiXBom(path, options);
7201
7373
  }
7374
+ if (projectType.length === 1) {
7375
+ thoughtLog(
7376
+ `The user wants me to focus on a single type, '${projectType}'. Could there be an issue with auto-detection, or might they use another tool like cyclonedx-cli to merge all the generated BOMs later?`,
7377
+ );
7378
+ }
7202
7379
  // Use the project type alias to return any singular BOM
7203
7380
  if (PROJECT_TYPE_ALIASES["java"].includes(projectType[0])) {
7204
7381
  return await createJavaBom(path, options);