@cyclonedx/cdxgen 9.11.6 → 10.0.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 CHANGED
@@ -130,8 +130,7 @@ import { createBom, submitBom } from "npm:@cyclonedx/cdxgen@^9.0.1";
130
130
  ```text
131
131
  $ cdxgen -h
132
132
  Options:
133
- -o, --output Output file for bom.xml or bom.json. Default bom.
134
- json
133
+ -o, --output Output file. Default bom.json
135
134
  -t, --type Project type
136
135
  -r, --recurse Recurse mode suitable for mono-repos. Defaults to
137
136
  true. Pass --no-recurse to disable.
@@ -188,6 +187,8 @@ Options:
188
187
  c.
189
188
  [choices: "appsec", "research", "operational", "threat-modeling", "license-com
190
189
  pliance", "generic"] [default: "generic"]
190
+ --include-formulation Generate formulation section using git metadata.
191
+ [boolean] [default: false]
191
192
  --auto-compositions Automatically set compositions when the BOM was f
192
193
  iltered. Defaults to true
193
194
  [boolean] [default: true]
@@ -383,7 +384,7 @@ cdxgen can retain the dependency tree under the `dependencies` attribute for a s
383
384
  | SBOM_SIGN_ALGORITHM | Signature algorithm. Some valid values are RS256, RS384, RS512, PS256, PS384, PS512, ES256 etc |
384
385
  | SBOM_SIGN_PRIVATE_KEY | Private key to use for signing |
385
386
  | SBOM_SIGN_PUBLIC_KEY | Optional. Public key to include in the SBOM signature |
386
- | CDX_MAVEN_PLUGIN | CycloneDX Maven plugin to use. Default "org.cyclonedx:cyclonedx-maven-plugin:2.7.10" |
387
+ | CDX_MAVEN_PLUGIN | CycloneDX Maven plugin to use. Default "org.cyclonedx:cyclonedx-maven-plugin:2.7.11" |
387
388
  | CDX_MAVEN_GOAL | CycloneDX Maven plugin goal to use. Default makeAggregateBom. Other options: makeBom, makePackageBom |
388
389
  | CDX_MAVEN_INCLUDE_TEST_SCOPE | Whether test scoped dependencies should be included from Maven projects, Default: true |
389
390
  | ASTGEN_IGNORE_DIRS | Comma separated list of directories to ignore while analyzing using babel. The environment variable is also used by atom and astgen. |
@@ -510,7 +511,7 @@ Permission to modify and redistribute is granted under the terms of the Apache 2
510
511
 
511
512
  ## Integration as library
512
513
 
513
- cdxgen is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c) and could be imported and used with both deno and Node.js >= 16
514
+ cdxgen is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c) and could be imported and used with both deno and Node.js >= 20
514
515
 
515
516
  Minimal example:
516
517
 
@@ -522,7 +523,7 @@ See the [Deno Readme](./contrib/deno/README.md) for detailed instructions.
522
523
 
523
524
  ```javascript
524
525
  import { createBom, submitBom } from "@cyclonedx/cdxgen";
525
- // bomNSData would contain bomJson, bomXml
526
+ // bomNSData would contain bomJson
526
527
  const bomNSData = await createBom(filePath, options);
527
528
  // Submission to dependency track server
528
529
  const dbody = await submitBom(args, bomNSData.bomJson);
package/analyzer.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { parse } from "@babel/parser";
2
2
  import traverse from "@babel/traverse";
3
3
  import { join } from "node:path";
4
+ import process from "node:process";
4
5
  import { readdirSync, lstatSync, readFileSync } from "node:fs";
5
6
  import { basename, resolve, isAbsolute, relative } from "node:path";
6
7
 
package/bin/cdxgen.js CHANGED
@@ -7,7 +7,7 @@ import { tmpdir } from "node:os";
7
7
  import { basename, dirname, join, resolve } from "node:path";
8
8
  import jws from "jws";
9
9
  import crypto from "node:crypto";
10
- import { fileURLToPath } from "node:url";
10
+ import { fileURLToPath, URL } from "node:url";
11
11
  import globalAgent from "global-agent";
12
12
  import process from "node:process";
13
13
  import {
@@ -56,7 +56,7 @@ const args = yargs(hideBin(process.argv))
56
56
  .env("CDXGEN")
57
57
  .option("output", {
58
58
  alias: "o",
59
- description: "Output file for bom.xml or bom.json. Default bom.json",
59
+ description: "Output file. Default bom.json",
60
60
  default: "bom.json"
61
61
  })
62
62
  .option("evinse-output", {
@@ -231,6 +231,17 @@ const args = yargs(hideBin(process.argv))
231
231
  default: "bom.cdx",
232
232
  hidden: true
233
233
  })
234
+ .option("include-formulation", {
235
+ type: "boolean",
236
+ default: false,
237
+ description: "Generate formulation section using git metadata."
238
+ })
239
+ .option("include-crypto", {
240
+ type: "boolean",
241
+ default: false,
242
+ description: "Include crypto libraries found under formulation.",
243
+ hidden: true
244
+ })
234
245
  .completion("completion", "Generate bash/zsh completion")
235
246
  .array("filter")
236
247
  .array("only")
@@ -295,7 +306,7 @@ const applyProfile = (options) => {
295
306
  case "research":
296
307
  options.deep = true;
297
308
  options.evidence = true;
298
- process.env.CDX_MAVEN_INCLUDE_TEST_SCOPE = true;
309
+ process.env.CDX_MAVEN_INCLUDE_TEST_SCOPE = "true";
299
310
  process.env.ASTGEN_IGNORE_DIRS = "";
300
311
  process.env.ASTGEN_IGNORE_FILE_PATTERN = "";
301
312
  break;
@@ -305,7 +316,7 @@ const applyProfile = (options) => {
305
316
  case "threat-modeling": // unused
306
317
  break;
307
318
  case "license-compliance":
308
- process.env.FETCH_LICENSE = true;
319
+ process.env.FETCH_LICENSE = "true";
309
320
  break;
310
321
  default:
311
322
  break;
@@ -382,162 +393,149 @@ const checkPermissions = (filePath) => {
382
393
  options.output &&
383
394
  (typeof options.output === "string" || options.output instanceof String)
384
395
  ) {
385
- if (bomNSData.bomXmlFiles) {
386
- console.log("BOM files produced:", bomNSData.bomXmlFiles);
387
- } else {
388
- const jsonFile = options.output.replace(".xml", ".json");
389
- // Create bom json file
390
- if (!options.output.endsWith(".xml") && bomNSData.bomJson) {
391
- let jsonPayload = undefined;
392
- if (
393
- typeof bomNSData.bomJson === "string" ||
394
- bomNSData.bomJson instanceof String
395
- ) {
396
- fs.writeFileSync(jsonFile, bomNSData.bomJson);
397
- jsonPayload = bomNSData.bomJson;
398
- } else {
399
- jsonPayload = JSON.stringify(bomNSData.bomJson, null, 2);
400
- fs.writeFileSync(jsonFile, jsonPayload);
396
+ const jsonFile = options.output;
397
+ // Create bom json file
398
+ if (bomNSData.bomJson) {
399
+ let jsonPayload = undefined;
400
+ if (
401
+ typeof bomNSData.bomJson === "string" ||
402
+ bomNSData.bomJson instanceof String
403
+ ) {
404
+ fs.writeFileSync(jsonFile, bomNSData.bomJson);
405
+ jsonPayload = bomNSData.bomJson;
406
+ } else {
407
+ jsonPayload = JSON.stringify(bomNSData.bomJson, null, 2);
408
+ fs.writeFileSync(jsonFile, jsonPayload);
409
+ }
410
+ if (
411
+ jsonPayload &&
412
+ (options.generateKeyAndSign ||
413
+ (process.env.SBOM_SIGN_ALGORITHM &&
414
+ process.env.SBOM_SIGN_ALGORITHM !== "none" &&
415
+ process.env.SBOM_SIGN_PRIVATE_KEY &&
416
+ fs.existsSync(process.env.SBOM_SIGN_PRIVATE_KEY)))
417
+ ) {
418
+ let alg = process.env.SBOM_SIGN_ALGORITHM || "RS512";
419
+ if (alg.includes("none")) {
420
+ alg = "RS512";
401
421
  }
402
- if (
403
- jsonPayload &&
404
- (options.generateKeyAndSign ||
405
- (process.env.SBOM_SIGN_ALGORITHM &&
406
- process.env.SBOM_SIGN_ALGORITHM !== "none" &&
407
- process.env.SBOM_SIGN_PRIVATE_KEY &&
408
- fs.existsSync(process.env.SBOM_SIGN_PRIVATE_KEY)))
409
- ) {
410
- let alg = process.env.SBOM_SIGN_ALGORITHM || "RS512";
411
- if (alg.includes("none")) {
412
- alg = "RS512";
413
- }
414
- let privateKeyToUse = undefined;
415
- let jwkPublicKey = undefined;
416
- let publicKeyFile = undefined;
417
- if (options.generateKeyAndSign) {
418
- const jdirName = dirname(jsonFile);
419
- publicKeyFile = join(jdirName, "public.key");
420
- const privateKeyFile = join(jdirName, "private.key");
421
- const { privateKey, publicKey } = crypto.generateKeyPairSync(
422
- "rsa",
423
- {
424
- modulusLength: 4096,
425
- publicKeyEncoding: {
426
- type: "spki",
427
- format: "pem"
428
- },
429
- privateKeyEncoding: {
430
- type: "pkcs8",
431
- format: "pem"
432
- }
433
- }
434
- );
435
- fs.writeFileSync(publicKeyFile, publicKey);
436
- fs.writeFileSync(privateKeyFile, privateKey);
437
- console.log(
438
- "Created public/private key pairs for testing purposes",
439
- publicKeyFile,
440
- privateKeyFile
441
- );
442
- privateKeyToUse = privateKey;
422
+ let privateKeyToUse = undefined;
423
+ let jwkPublicKey = undefined;
424
+ let publicKeyFile = undefined;
425
+ if (options.generateKeyAndSign) {
426
+ const jdirName = dirname(jsonFile);
427
+ publicKeyFile = join(jdirName, "public.key");
428
+ const privateKeyFile = join(jdirName, "private.key");
429
+ const { privateKey, publicKey } = crypto.generateKeyPairSync("rsa", {
430
+ modulusLength: 4096,
431
+ publicKeyEncoding: {
432
+ type: "spki",
433
+ format: "pem"
434
+ },
435
+ privateKeyEncoding: {
436
+ type: "pkcs8",
437
+ format: "pem"
438
+ }
439
+ });
440
+ fs.writeFileSync(publicKeyFile, publicKey);
441
+ fs.writeFileSync(privateKeyFile, privateKey);
442
+ console.log(
443
+ "Created public/private key pairs for testing purposes",
444
+ publicKeyFile,
445
+ privateKeyFile
446
+ );
447
+ privateKeyToUse = privateKey;
448
+ jwkPublicKey = crypto
449
+ .createPublicKey(publicKey)
450
+ .export({ format: "jwk" });
451
+ } else {
452
+ privateKeyToUse = fs.readFileSync(
453
+ process.env.SBOM_SIGN_PRIVATE_KEY,
454
+ "utf8"
455
+ );
456
+ if (
457
+ process.env.SBOM_SIGN_PUBLIC_KEY &&
458
+ fs.existsSync(process.env.SBOM_SIGN_PUBLIC_KEY)
459
+ ) {
443
460
  jwkPublicKey = crypto
444
- .createPublicKey(publicKey)
461
+ .createPublicKey(
462
+ fs.readFileSync(process.env.SBOM_SIGN_PUBLIC_KEY, "utf8")
463
+ )
445
464
  .export({ format: "jwk" });
446
- } else {
447
- privateKeyToUse = fs.readFileSync(
448
- process.env.SBOM_SIGN_PRIVATE_KEY,
449
- "utf8"
450
- );
451
- if (
452
- process.env.SBOM_SIGN_PUBLIC_KEY &&
453
- fs.existsSync(process.env.SBOM_SIGN_PUBLIC_KEY)
454
- ) {
455
- jwkPublicKey = crypto
456
- .createPublicKey(
457
- fs.readFileSync(process.env.SBOM_SIGN_PUBLIC_KEY, "utf8")
458
- )
459
- .export({ format: "jwk" });
460
- }
461
465
  }
462
- try {
463
- // Sign the individual components
464
- // Let's leave the services unsigned for now since it might require additional cleansing
465
- const bomJsonUnsignedObj = JSON.parse(jsonPayload);
466
- for (const comp of bomJsonUnsignedObj.components) {
467
- const compSignature = jws.sign({
468
- header: { alg },
469
- payload: comp,
470
- privateKey: privateKeyToUse
471
- });
472
- const compSignatureBlock = {
473
- algorithm: alg,
474
- value: compSignature
475
- };
476
- if (jwkPublicKey) {
477
- compSignatureBlock.publicKey = jwkPublicKey;
478
- }
479
- comp.signature = compSignatureBlock;
480
- }
481
- const signature = jws.sign({
466
+ }
467
+ try {
468
+ // Sign the individual components
469
+ // Let's leave the services unsigned for now since it might require additional cleansing
470
+ const bomJsonUnsignedObj = JSON.parse(jsonPayload);
471
+ for (const comp of bomJsonUnsignedObj.components) {
472
+ const compSignature = jws.sign({
482
473
  header: { alg },
483
- payload: JSON.stringify(bomJsonUnsignedObj, null, 2),
474
+ payload: comp,
484
475
  privateKey: privateKeyToUse
485
476
  });
486
- if (signature) {
487
- const signatureBlock = {
488
- algorithm: alg,
489
- value: signature
490
- };
491
- if (jwkPublicKey) {
492
- signatureBlock.publicKey = jwkPublicKey;
493
- }
494
- bomJsonUnsignedObj.signature = signatureBlock;
495
- fs.writeFileSync(
496
- jsonFile,
497
- JSON.stringify(bomJsonUnsignedObj, null, 2)
477
+ const compSignatureBlock = {
478
+ algorithm: alg,
479
+ value: compSignature
480
+ };
481
+ if (jwkPublicKey) {
482
+ compSignatureBlock.publicKey = jwkPublicKey;
483
+ }
484
+ comp.signature = compSignatureBlock;
485
+ }
486
+ const signature = jws.sign({
487
+ header: { alg },
488
+ payload: JSON.stringify(bomJsonUnsignedObj, null, 2),
489
+ privateKey: privateKeyToUse
490
+ });
491
+ if (signature) {
492
+ const signatureBlock = {
493
+ algorithm: alg,
494
+ value: signature
495
+ };
496
+ if (jwkPublicKey) {
497
+ signatureBlock.publicKey = jwkPublicKey;
498
+ }
499
+ bomJsonUnsignedObj.signature = signatureBlock;
500
+ fs.writeFileSync(
501
+ jsonFile,
502
+ JSON.stringify(bomJsonUnsignedObj, null, 2)
503
+ );
504
+ if (publicKeyFile) {
505
+ // Verifying this signature
506
+ const signatureVerification = jws.verify(
507
+ signature,
508
+ alg,
509
+ fs.readFileSync(publicKeyFile, "utf8")
498
510
  );
499
- if (publicKeyFile) {
500
- // Verifying this signature
501
- const signatureVerification = jws.verify(
502
- signature,
503
- alg,
504
- fs.readFileSync(publicKeyFile, "utf8")
511
+ if (signatureVerification) {
512
+ console.log(
513
+ "SBOM signature is verifiable with the public key and the algorithm",
514
+ publicKeyFile,
515
+ alg
516
+ );
517
+ } else {
518
+ console.log("SBOM signature verification was unsuccessful");
519
+ console.log(
520
+ "Check if the public key was exported in PEM format"
505
521
  );
506
- if (signatureVerification) {
507
- console.log(
508
- "SBOM signature is verifiable with the public key and the algorithm",
509
- publicKeyFile,
510
- alg
511
- );
512
- } else {
513
- console.log("SBOM signature verification was unsuccessful");
514
- console.log(
515
- "Check if the public key was exported in PEM format"
516
- );
517
- }
518
522
  }
519
523
  }
520
- } catch (ex) {
521
- console.log("SBOM signing was unsuccessful", ex);
522
- console.log("Check if the private key was exported in PEM format");
523
524
  }
525
+ } catch (ex) {
526
+ console.log("SBOM signing was unsuccessful", ex);
527
+ console.log("Check if the private key was exported in PEM format");
524
528
  }
525
529
  }
526
- // Create bom xml file
527
- if (options.output.endsWith(".xml") && bomNSData.bomXml) {
528
- fs.writeFileSync(options.output, bomNSData.bomXml);
529
- }
530
- //
531
- if (bomNSData.nsMapping && Object.keys(bomNSData.nsMapping).length) {
532
- const nsFile = jsonFile + ".map";
533
- fs.writeFileSync(nsFile, JSON.stringify(bomNSData.nsMapping));
534
- }
530
+ }
531
+ // bom ns mapping
532
+ if (bomNSData.nsMapping && Object.keys(bomNSData.nsMapping).length) {
533
+ const nsFile = jsonFile + ".map";
534
+ fs.writeFileSync(nsFile, JSON.stringify(bomNSData.nsMapping));
535
535
  }
536
536
  } else if (!options.print) {
537
537
  if (bomNSData.bomJson) {
538
538
  console.log(JSON.stringify(bomNSData.bomJson, null, 2));
539
- } else if (bomNSData.bomXml) {
540
- console.log(Buffer.from(bomNSData.bomXml).toString());
541
539
  } else {
542
540
  console.log("Unable to produce BOM for", filePath);
543
541
  console.log("Try running the command with -t <type> or -r argument");
package/bin/repl.js CHANGED
@@ -155,7 +155,7 @@ cdxgenRepl.defineCommand("search", {
155
155
  searchStr = `components[group ~> /${searchStr}/i or name ~> /${searchStr}/i or description ~> /${searchStr}/i or publisher ~> /${searchStr}/i or purl ~> /${searchStr}/i]`;
156
156
  }
157
157
  const expression = jsonata(searchStr);
158
- let components = await expression.evaluate(sbom);
158
+ const components = await expression.evaluate(sbom);
159
159
  if (!components) {
160
160
  console.log("No results found!");
161
161
  } else {
@@ -187,7 +187,7 @@ cdxgenRepl.defineCommand("sort", {
187
187
  sortStr = `components^(${sortStr})`;
188
188
  }
189
189
  const expression = jsonata(sortStr);
190
- let components = await expression.evaluate(sbom);
190
+ const components = await expression.evaluate(sbom);
191
191
  if (!components) {
192
192
  console.log("No results found!");
193
193
  } else {
@@ -354,14 +354,14 @@ cdxgenRepl.defineCommand("occurrences", {
354
354
  });
355
355
  cdxgenRepl.defineCommand("discord", {
356
356
  help: "display the discord invite link for support",
357
- async action() {
357
+ action() {
358
358
  console.log("Head to https://discord.gg/pF4BYWEJcS for support");
359
359
  this.displayPrompt();
360
360
  }
361
361
  });
362
362
  cdxgenRepl.defineCommand("sponsor", {
363
363
  help: "display the sponsorship link to fund this project",
364
- async action() {
364
+ action() {
365
365
  console.log(
366
366
  "Hey, thanks a lot for considering! https://github.com/sponsors/prabhu"
367
367
  );
@@ -434,7 +434,7 @@ cdxgenRepl.defineCommand("osinfocategories", {
434
434
  const expression = jsonata(
435
435
  '$distinct(components.properties[name="cdx:osquery:category"].value)'
436
436
  );
437
- let catgories = await expression.evaluate(sbom);
437
+ const catgories = await expression.evaluate(sbom);
438
438
  if (!catgories) {
439
439
  console.log(
440
440
  "Unable to retrieve the os info categories. Only OBOMs generated by cdxgen are supported by this tool."
package/bin/verify.js CHANGED
@@ -5,7 +5,7 @@ import { hideBin } from "yargs/helpers";
5
5
  import fs from "node:fs";
6
6
  import jws from "jws";
7
7
  import process from "node:process";
8
- import { fileURLToPath } from "node:url";
8
+ import { fileURLToPath, URL } from "node:url";
9
9
  import { dirname, join } from "node:path";
10
10
 
11
11
  let url = import.meta.url;
package/binary.js CHANGED
@@ -1,4 +1,6 @@
1
1
  import { platform as _platform, arch as _arch, tmpdir, homedir } from "node:os";
2
+ import process from "node:process";
3
+ import { Buffer } from "node:buffer";
2
4
  import {
3
5
  existsSync,
4
6
  mkdirSync,
@@ -11,7 +13,7 @@ import { spawnSync } from "node:child_process";
11
13
  import { PackageURL } from "packageurl-js";
12
14
  import { DEBUG_MODE, TIMEOUT_MS, findLicenseId } from "./utils.js";
13
15
 
14
- import { fileURLToPath } from "node:url";
16
+ import { fileURLToPath, URL } from "node:url";
15
17
 
16
18
  let url = import.meta.url;
17
19
  if (!url.startsWith("file://")) {
@@ -108,16 +110,18 @@ if (!CDXGEN_PLUGINS_DIR) {
108
110
  }
109
111
  }
110
112
  }
111
- const globalPlugins = join(
112
- globalNodePath,
113
- "@cyclonedx",
114
- "cdxgen-plugins-bin" + pluginsBinSuffix,
115
- "plugins"
116
- );
117
- if (existsSync(globalPlugins)) {
118
- CDXGEN_PLUGINS_DIR = globalPlugins;
119
- if (DEBUG_MODE) {
120
- console.log("Found global plugins", CDXGEN_PLUGINS_DIR);
113
+ if (globalNodePath) {
114
+ const globalPlugins = join(
115
+ globalNodePath,
116
+ "@cyclonedx",
117
+ "cdxgen-plugins-bin" + pluginsBinSuffix,
118
+ "plugins"
119
+ );
120
+ if (existsSync(globalPlugins)) {
121
+ CDXGEN_PLUGINS_DIR = globalPlugins;
122
+ if (DEBUG_MODE) {
123
+ console.log("Found global plugins", CDXGEN_PLUGINS_DIR);
124
+ }
121
125
  }
122
126
  }
123
127
  }
@@ -398,7 +402,7 @@ export const getOSPackages = (src) => {
398
402
  }
399
403
  let distro_codename = osReleaseData["VERSION_CODENAME"] || "";
400
404
  let distro_id = osReleaseData["ID"] || "";
401
- let distro_id_like = osReleaseData["ID_LIKE"] || "";
405
+ const distro_id_like = osReleaseData["ID_LIKE"] || "";
402
406
  let purl_type = "rpm";
403
407
  switch (distro_id) {
404
408
  case "debian":
@@ -464,6 +468,7 @@ export const getOSPackages = (src) => {
464
468
  comp.group = group;
465
469
  purlObj.namespace = group;
466
470
  }
471
+ purlObj.qualifiers = purlObj.qualifiers || {};
467
472
  if (distro_id && distro_id.length) {
468
473
  purlObj.qualifiers["distro"] = distro_id;
469
474
  }
@@ -647,6 +652,7 @@ const retrieveDependencies = (tmpDependencies, origBomRef, comp) => {
647
652
  const tmpPurl = PackageURL.fromString(d.replace("none", compPurl.type));
648
653
  tmpPurl.type = compPurl.type;
649
654
  tmpPurl.namespace = compPurl.namespace;
655
+ tmpPurl.qualifiers = tmpPurl.qualifiers || {};
650
656
  if (compPurl.qualifiers) {
651
657
  if (compPurl.qualifiers.distro_name) {
652
658
  tmpPurl.qualifiers.distro_name = compPurl.qualifiers.distro_name;
@@ -682,7 +688,7 @@ export const executeOsQuery = (query) => {
682
688
  timeout: 60 * 1000
683
689
  });
684
690
  if (result.status !== 0 || result.error) {
685
- if (DEBUG_MODE && result.error) {
691
+ if (DEBUG_MODE && result.stderr) {
686
692
  console.error(result.stdout, result.stderr);
687
693
  }
688
694
  }
package/cbomutils.js ADDED
@@ -0,0 +1,39 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { convertOSQueryResults, dirNameStr } from "./utils.js";
3
+ import { executeOsQuery } from "./binary.js";
4
+ import { join } from "node:path";
5
+ const cbomosDbQueries = JSON.parse(
6
+ readFileSync(join(dirNameStr, "data", "cbomosdb-queries.json"), "utf-8")
7
+ );
8
+
9
+ /**
10
+ * Method to collect crypto and ssl libraries from the OS.
11
+ *
12
+ * @param {Object} options
13
+ * @returns osPkgsList Array of OS crypto packages
14
+ */
15
+ export const collectOSCryptoLibs = (options) => {
16
+ let osPkgsList = [];
17
+ for (const queryCategory of Object.keys(cbomosDbQueries)) {
18
+ const queryObj = cbomosDbQueries[queryCategory];
19
+ const results = executeOsQuery(queryObj.query);
20
+ const dlist = convertOSQueryResults(
21
+ queryCategory,
22
+ queryObj,
23
+ results,
24
+ false
25
+ );
26
+ if (dlist && dlist.length) {
27
+ osPkgsList = osPkgsList.concat(dlist);
28
+ // Should we downgrade from cryptographic-asset to data for < 1.6 spec
29
+ if (options && options.specVersion && options.specVersion < 1.6) {
30
+ for (const apkg of osPkgsList) {
31
+ if (apkg.type === "cryptographic-asset") {
32
+ apkg.type = "data";
33
+ }
34
+ }
35
+ }
36
+ }
37
+ }
38
+ return osPkgsList;
39
+ };
@@ -0,0 +1,8 @@
1
+ import { expect, test } from "@jest/globals";
2
+
3
+ import { collectOSCryptoLibs } from "./cbomutils.js";
4
+
5
+ test("cbom utils tests", () => {
6
+ const cryptoLibs = collectOSCryptoLibs();
7
+ expect(cryptoLibs).toBeDefined();
8
+ });
package/data/README.md CHANGED
@@ -7,6 +7,7 @@ Contents of data directory and their purpose.
7
7
  | bom-1.4.schema.json | CycloneDX 1.4 jsonschema for validation |
8
8
  | bom-1.5.schema.json | CycloneDX 1.5 jsonschema for validation |
9
9
  | cosdb-queries.json | osquery useful for identifying OS packages for C |
10
+ | cbomosdb-queries.json | osquery for identifying ssl packages in OS |
10
11
  | jsf-0.82.schema.json | jsonschema for validation |
11
12
  | known-licenses.json | Hard coded list to correct any license id. Not maintained. |
12
13
  | lic-mapping.json | Hard coded list to match a license id based on name |
@@ -0,0 +1,68 @@
1
+ {
2
+ "deb_packages": {
3
+ "query": "select * from deb_packages where name like '%ssl%' OR name like '%crypto%';",
4
+ "description": "Retrieves all the installed DEB packages in the target Linux system.",
5
+ "purlType": "deb",
6
+ "componentType": "library"
7
+ },
8
+ "portage_packages": {
9
+ "query": "select * from portage_packages where package like '%ssl%' OR package like '%crypto%';",
10
+ "description": "Retrieves all the installed packages on the target Linux system.",
11
+ "purlType": "ebuild",
12
+ "componentType": "library"
13
+ },
14
+ "rpm_packages": {
15
+ "query": "select * from rpm_packages where name like '%ssl%' OR name like '%crypto%';",
16
+ "description": "Retrieves all the installed RPM packages in the target Linux system.",
17
+ "purlType": "rpm",
18
+ "componentType": "library"
19
+ },
20
+ "python_packages": {
21
+ "query": "select * from python_packages where name like '%ssl%' OR name like '%crypto%';",
22
+ "description": "Python packages installed on system.",
23
+ "purlType": "pypi",
24
+ "componentType": "library"
25
+ },
26
+ "windows_programs": {
27
+ "query": "select * from programs where name like '%ssl%' OR name like '%crypto%';",
28
+ "description": "Retrieves the list of products as they are installed by Windows Installer in the target Windows system.",
29
+ "purlType": "swid",
30
+ "componentType": "application"
31
+ },
32
+ "homebrew_packages": {
33
+ "query": "SELECT * FROM homebrew_packages where name like '%ssl%' OR name like '%crypto%';",
34
+ "description": "List all homebrew_packages.",
35
+ "purlType": "swid",
36
+ "componentType": "library"
37
+ },
38
+ "authorized_keys": {
39
+ "query": "SELECT * FROM authorized_keys;",
40
+ "description": "List of authorized keys.",
41
+ "purlType": "generic",
42
+ "componentType": "cryptographic-asset"
43
+ },
44
+ "certificates": {
45
+ "query": "SELECT * FROM certificates;",
46
+ "description": "List of certificates.",
47
+ "purlType": "generic",
48
+ "componentType": "cryptographic-asset"
49
+ },
50
+ "keychain_items": {
51
+ "query": "SELECT * FROM keychain_items;",
52
+ "description": "Generic details about keychain items.",
53
+ "purlType": "generic",
54
+ "componentType": "data"
55
+ },
56
+ "kernel_keys": {
57
+ "query": "SELECT * FROM kernel_keys;",
58
+ "description": "List of security data, authentication keys and encryption keys.",
59
+ "purlType": "generic",
60
+ "componentType": "cryptographic-asset"
61
+ },
62
+ "yum_sources": {
63
+ "query": "SELECT * FROM yum_sources;",
64
+ "description": "Current list of Yum repositories or software channels.",
65
+ "purlType": "generic",
66
+ "componentType": "data"
67
+ }
68
+ }