@cyclonedx/cdxgen 8.3.2 → 8.4.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
@@ -298,6 +298,7 @@ cdxgen shiftleft/scan-slim -o /tmp/bom.json -t docker
298
298
  You can also pass the .tar file of a container image.
299
299
 
300
300
  ```shell
301
+ docker pull shiftleft/scan-slim
301
302
  docker save -o /tmp/slim.tar shiftleft/scan-slim
302
303
  podman save -q --format oci-archive -o /tmp/slim.tar shiftleft/scan-slim
303
304
  cdxgen /tmp/slim.tar -o /tmp/bom.json -t docker
package/bin/cdxgen CHANGED
@@ -128,7 +128,6 @@ let options = {
128
128
  dev: true,
129
129
  projectType: args.type,
130
130
  multiProject: args.recurse,
131
- depth: 3,
132
131
  output: args.output,
133
132
  resolveClass: args.resolveClass,
134
133
  installDeps: true,
package/docker.js CHANGED
@@ -423,9 +423,15 @@ const extractTar = async (fullImageName, dir) => {
423
423
  C: dir,
424
424
  portable: true,
425
425
  onwarn: () => {},
426
- filter: (path) => {
426
+ filter: (path, entry) => {
427
427
  // Some files are known to cause issues with extract
428
- if (path.includes("cacerts") || path.includes("ssl/certs")) {
428
+ if (
429
+ path.includes("cacerts") ||
430
+ path.includes("ssl/certs") ||
431
+ path.includes("etc/") ||
432
+ path.includes("logs/") ||
433
+ ["CharacterDevice"].includes(entry.type)
434
+ ) {
429
435
  return false;
430
436
  }
431
437
  return true;
@@ -434,12 +440,14 @@ const extractTar = async (fullImageName, dir) => {
434
440
  );
435
441
  return true;
436
442
  } catch (err) {
437
- console.log(
438
- "Error during extraction. Please file this bug to the cdxgen repo. https://github.com/CycloneDX/cdxgen/issues"
439
- );
440
- console.log("------------");
441
- console.log(err);
442
- console.log("------------");
443
+ if (err.code !== "TAR_BAD_ARCHIVE") {
444
+ console.log(
445
+ `Error while extracting image ${fullImageName} to ${dir}. Please file this bug to the cdxgen repo. https://github.com/CycloneDX/cdxgen/issues`
446
+ );
447
+ console.log("------------");
448
+ console.log(err);
449
+ console.log("------------");
450
+ }
443
451
  return false;
444
452
  }
445
453
  };
package/index.js CHANGED
@@ -536,11 +536,11 @@ function addComponent(
536
536
  pkg.purl ||
537
537
  new PackageURL(
538
538
  ptype,
539
- encodeURIComponent(group),
540
- encodeURIComponent(name),
539
+ utils.encodeForPurl(group),
540
+ utils.encodeForPurl(name),
541
541
  version,
542
542
  pkg.qualifiers,
543
- pkg.subpath
543
+ utils.encodeForPurl(pkg.subpath)
544
544
  );
545
545
  let purlString = purl.toString();
546
546
  purlString = decodeURIComponent(purlString);
@@ -1006,6 +1006,12 @@ const createJavaBom = async (path, options) => {
1006
1006
  }
1007
1007
  for (let f of pomFiles) {
1008
1008
  const basePath = pathLib.dirname(f);
1009
+ const settingsXml = pathLib.join(basePath, "settings.xml");
1010
+ if (fs.existsSync(settingsXml)) {
1011
+ console.log(
1012
+ `maven settings.xml found in ${basePath}. Please set the MVN_ARGS environment variable based on the full mvn build command used for this project.\nExample: MVN_ARGS='--settings ${settingsXml}'`
1013
+ );
1014
+ }
1009
1015
  let mavenCmd = utils.getMavenCommand(basePath, path);
1010
1016
  // Should we attempt to resolve class names
1011
1017
  if (options.resolveClass) {
@@ -2221,7 +2227,7 @@ const createGoBom = async (path, options) => {
2221
2227
  "list",
2222
2228
  "-deps",
2223
2229
  "-f",
2224
- "'{{with .Module}}{{.Path}} {{.Version}}{{end}}'",
2230
+ "'{{with .Module}}{{.Path}} {{.Version}} {{.Indirect}} {{.GoMod}} {{.GoVersion}}{{end}}'",
2225
2231
  "./..."
2226
2232
  ],
2227
2233
  { cwd: basePath, encoding: "utf-8", timeout: TIMEOUT_MS }
@@ -2256,7 +2262,11 @@ const createGoBom = async (path, options) => {
2256
2262
  if (circuitBreak) {
2257
2263
  break;
2258
2264
  }
2259
- let pkgFullName = `${apkg.group}/${apkg.name}`;
2265
+ let pkgFullName = `${apkg.name}`;
2266
+ if (apkg.scope === "required") {
2267
+ allImports[pkgFullName] = true;
2268
+ continue;
2269
+ }
2260
2270
  if (DEBUG_MODE) {
2261
2271
  console.log(`go mod why -m -vendor ${pkgFullName}`);
2262
2272
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyclonedx/cdxgen",
3
- "version": "8.3.2",
3
+ "version": "8.4.0",
4
4
  "description": "Creates CycloneDX Software Bill-of-Materials (SBOM) from source or container image",
5
5
  "homepage": "http://github.com/cyclonedx/cdxgen",
6
6
  "author": "Prabhu Subramanian <prabhu@appthreat.com>",
package/utils.js CHANGED
@@ -2104,34 +2104,24 @@ const parseGoModData = async function (goModData, gosumMap) {
2104
2104
 
2105
2105
  if (!isModReplacement) {
2106
2106
  // Add group, name and version component properties for required modules
2107
- let group = path.dirname(tmpA[0]);
2108
- const name = path.basename(tmpA[0]);
2109
- if (group === ".") {
2110
- group = name;
2111
- }
2112
2107
  const version = tmpA[1];
2113
- let gosumHash = gosumMap[`${group}/${name}/${version}`];
2108
+ let gosumHash = gosumMap[`${tmpA[0]}/${version}`];
2114
2109
  // The hash for this version was not found in go.sum, so skip as it is most likely being replaced.
2115
2110
  if (gosumHash === undefined) {
2116
2111
  continue;
2117
2112
  }
2118
- let component = await getGoPkgComponent(group, name, version, gosumHash);
2113
+ let component = await getGoPkgComponent("", tmpA[0], version, gosumHash);
2119
2114
  pkgComponentsList.push(component);
2120
2115
  } else {
2121
2116
  // Add group, name and version component properties for replacement modules
2122
- let group = path.dirname(tmpA[2]);
2123
- const name = path.basename(tmpA[2]);
2124
- if (group === ".") {
2125
- group = name;
2126
- }
2127
2117
  const version = tmpA[3];
2128
2118
 
2129
- let gosumHash = gosumMap[`${group}/${name}/${version}`];
2119
+ let gosumHash = gosumMap[`${tmpA[2]}/${version}`];
2130
2120
  // The hash for this version was not found in go.sum, so skip.
2131
2121
  if (gosumHash === undefined) {
2132
2122
  continue;
2133
2123
  }
2134
- let component = await getGoPkgComponent(group, name, version, gosumHash);
2124
+ let component = await getGoPkgComponent("", tmpA[2], version, gosumHash);
2135
2125
  pkgComponentsList.push(component);
2136
2126
  }
2137
2127
  }
@@ -2154,24 +2144,35 @@ const parseGoListDep = async function (rawOutput, gosumMap) {
2154
2144
  const pkgs = rawOutput.split("\n");
2155
2145
  for (let l of pkgs) {
2156
2146
  const verArr = l.trim().replace(new RegExp("[\"']", "g"), "").split(" ");
2157
- if (verArr && verArr.length === 2) {
2147
+
2148
+ if (verArr && verArr.length === 5) {
2158
2149
  const key = verArr[0] + "-" + verArr[1];
2159
2150
  // Filter duplicates
2160
2151
  if (!keys_cache[key]) {
2161
2152
  keys_cache[key] = key;
2162
- let group = path.dirname(verArr[0]);
2163
- const name = path.basename(verArr[0]);
2164
2153
  const version = verArr[1];
2165
- if (group === ".") {
2166
- group = name;
2167
- }
2168
- let gosumHash = gosumMap[`${group}/${name}/${version}`];
2154
+ let gosumHash = gosumMap[`${verArr[0]}/${version}`];
2169
2155
  let component = await getGoPkgComponent(
2170
- group,
2171
- name,
2156
+ "",
2157
+ verArr[0],
2172
2158
  version,
2173
2159
  gosumHash
2174
2160
  );
2161
+ if (verArr[2] === "false") {
2162
+ component.scope = "required";
2163
+ } else if (verArr[2] === "true") {
2164
+ component.scope = "optional";
2165
+ }
2166
+ component.properties = [
2167
+ {
2168
+ name: "SrcGoMod",
2169
+ value: verArr[3] || ""
2170
+ },
2171
+ {
2172
+ name: "ModuleGoVersion",
2173
+ value: verArr[4] || ""
2174
+ }
2175
+ ];
2175
2176
  deps.push(component);
2176
2177
  }
2177
2178
  }
@@ -2212,27 +2213,23 @@ const parseGosumData = async function (gosumData) {
2212
2213
  // look for lines containing go.mod
2213
2214
  if (l.indexOf("go.mod") > -1) {
2214
2215
  const tmpA = l.split(" ");
2215
- let group = path.dirname(tmpA[0]);
2216
- const name = path.basename(tmpA[0]);
2217
- if (group === ".") {
2218
- group = name;
2219
- }
2216
+ const name = tmpA[0];
2220
2217
  const version = tmpA[1].replace("/go.mod", "");
2221
2218
  const hash = tmpA[tmpA.length - 1].replace("h1:", "sha256-");
2222
2219
  let license = undefined;
2223
2220
  if (process.env.FETCH_LICENSE) {
2224
2221
  if (DEBUG_MODE) {
2225
2222
  console.log(
2226
- `About to fetch go package license information for ${group}:${name}`
2223
+ `About to fetch go package license information for ${name}`
2227
2224
  );
2228
2225
  }
2229
2226
  license = await getGoPkgLicense({
2230
- group: group,
2227
+ group: "",
2231
2228
  name: name
2232
2229
  });
2233
2230
  }
2234
2231
  pkgList.push({
2235
- group: group,
2232
+ group: "",
2236
2233
  name: name,
2237
2234
  version: version,
2238
2235
  _integrity: hash,
@@ -2271,11 +2268,8 @@ const parseGopkgData = async function (gopkgData) {
2271
2268
  pkg._integrity = "sha256-" + toBase64(digestStr);
2272
2269
  break;
2273
2270
  case "name":
2274
- pkg.group = path.dirname(value);
2275
- pkg.name = path.basename(value);
2276
- if (pkg.group === ".") {
2277
- pkg.group = pkg.name;
2278
- }
2271
+ pkg.group = "";
2272
+ pkg.name = value;
2279
2273
  if (process.env.FETCH_LICENSE) {
2280
2274
  pkg.license = await getGoPkgLicense({
2281
2275
  group: pkg.group,
@@ -2312,16 +2306,12 @@ const parseGoVersionData = async function (buildInfoData) {
2312
2306
  if (!tmpA || tmpA.length < 3) {
2313
2307
  continue;
2314
2308
  }
2315
- let group = path.dirname(tmpA[1].trim());
2316
- const name = path.basename(tmpA[1].trim());
2317
- if (group === ".") {
2318
- group = name;
2319
- }
2309
+ const name = tmpA[1].trim();
2320
2310
  let hash = "";
2321
2311
  if (tmpA.length == 4) {
2322
2312
  hash = tmpA[tmpA.length - 1].replace("h1:", "sha256-");
2323
2313
  }
2324
- let component = await getGoPkgComponent(group, name, tmpA[2].trim(), hash);
2314
+ let component = await getGoPkgComponent("", name, tmpA[2].trim(), hash);
2325
2315
  pkgList.push(component);
2326
2316
  }
2327
2317
  return pkgList;
@@ -2917,9 +2907,7 @@ const parseContainerSpecData = async function (dcData) {
2917
2907
  try {
2918
2908
  yamlObj = yaml.load(dcData);
2919
2909
  } catch (err) {
2920
- if (DEBUG_MODE) {
2921
- console.log(err);
2922
- }
2910
+ // ignore errors
2923
2911
  }
2924
2912
  if (!yamlObj) {
2925
2913
  continue;
@@ -4188,6 +4176,13 @@ const parseJarManifest = function (jarMetadata) {
4188
4176
  };
4189
4177
  exports.parseJarManifest = parseJarManifest;
4190
4178
 
4179
+ const encodeForPurl = (s) => {
4180
+ return s
4181
+ ? encodeURIComponent(s).replace(/%3A/g, ":").replace(/%2F/g, "/")
4182
+ : s;
4183
+ };
4184
+ exports.encodeForPurl = encodeForPurl;
4185
+
4191
4186
  /**
4192
4187
  * Method to extract a war or ear file
4193
4188
  *
@@ -4272,7 +4267,8 @@ const extractJarArchive = function (jarFile, tempDir) {
4272
4267
  jarMetadata["Implementation-Vendor-Id"] ||
4273
4268
  jarMetadata["Bundle-SymbolicName"] ||
4274
4269
  jarMetadata["Bundle-Vendor"] ||
4275
- jarMetadata["Automatic-Module-Name"];
4270
+ jarMetadata["Automatic-Module-Name"] ||
4271
+ "";
4276
4272
  let name = "";
4277
4273
  if (
4278
4274
  jarMetadata["Bundle-Name"] &&
@@ -4338,8 +4334,8 @@ const extractJarArchive = function (jarFile, tempDir) {
4338
4334
  }
4339
4335
  if (name && version) {
4340
4336
  pkgList.push({
4341
- group: group === "." ? "" : encodeURIComponent(group) || "",
4342
- name: name ? encodeURIComponent(name) : "",
4337
+ group: group === "." ? "" : encodeForPurl(group || "") || "",
4338
+ name: name ? encodeForPurl(name) : "",
4343
4339
  version,
4344
4340
  properties: [
4345
4341
  {
package/utils.test.js CHANGED
@@ -385,29 +385,29 @@ test("parseGoModData", async () => {
385
385
  );
386
386
  expect(dep_list.length).toEqual(4);
387
387
  expect(dep_list[0]).toEqual({
388
- group: "github.com/aws",
389
- name: "aws-sdk-go",
388
+ group: "",
389
+ name: "github.com/aws/aws-sdk-go",
390
390
  license: undefined,
391
391
  version: "v1.38.47",
392
392
  _integrity: "sha256-fake-sha-for-aws-go-sdk="
393
393
  });
394
394
  expect(dep_list[1]).toEqual({
395
- group: "github.com/spf13",
396
- name: "cobra",
395
+ group: "",
396
+ name: "github.com/spf13/cobra",
397
397
  license: undefined,
398
398
  version: "v1.0.0",
399
399
  _integrity: "sha256-/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE="
400
400
  });
401
401
  expect(dep_list[2]).toEqual({
402
- group: "google.golang.org",
403
- name: "grpc",
402
+ group: "",
403
+ name: "google.golang.org/grpc",
404
404
  license: undefined,
405
405
  version: "v1.21.0",
406
406
  _integrity: "sha256-oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM="
407
407
  });
408
408
  expect(dep_list[3]).toEqual({
409
- group: "github.com/spf13",
410
- name: "viper",
409
+ group: "",
410
+ name: "github.com/spf13/viper",
411
411
  license: undefined,
412
412
  version: "v1.0.2",
413
413
  _integrity: "sha256-A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM="
@@ -426,29 +426,29 @@ test("parseGoSumData", async () => {
426
426
  );
427
427
  expect(dep_list.length).toEqual(4);
428
428
  expect(dep_list[0]).toEqual({
429
- group: "google.golang.org",
430
- name: "grpc",
429
+ group: "",
430
+ name: "google.golang.org/grpc",
431
431
  license: undefined,
432
432
  version: "v1.21.0",
433
433
  _integrity: "sha256-oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM="
434
434
  });
435
435
  expect(dep_list[1]).toEqual({
436
- group: "github.com/spf13",
437
- name: "cobra",
436
+ group: "",
437
+ name: "github.com/spf13/cobra",
438
438
  license: undefined,
439
439
  version: "v1.0.0",
440
440
  _integrity: "sha256-/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE="
441
441
  });
442
442
  expect(dep_list[2]).toEqual({
443
- group: "github.com/spf13",
444
- name: "viper",
443
+ group: "",
444
+ name: "github.com/spf13/viper",
445
445
  license: undefined,
446
446
  version: "v1.0.2",
447
447
  _integrity: "sha256-A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM="
448
448
  });
449
449
  expect(dep_list[3]).toEqual({
450
- group: "github.com/stretchr",
451
- name: "testify",
450
+ group: "",
451
+ name: "github.com/stretchr/testify",
452
452
  license: undefined,
453
453
  version: "v1.6.1",
454
454
  _integrity: "sha256-6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg="
@@ -463,11 +463,22 @@ test("parse go list dependencies", async () => {
463
463
  fs.readFileSync("./test/data/golist-dep.txt", { encoding: "utf-8" }),
464
464
  {}
465
465
  );
466
- expect(dep_list.length).toEqual(8);
466
+ expect(dep_list.length).toEqual(4);
467
467
  expect(dep_list[0]).toEqual({
468
- group: "github.com/badoux",
469
- name: "checkmail",
470
- version: "v0.0.0-20181210160741-9661bd69e9ad"
468
+ group: "",
469
+ name: "github.com/gorilla/mux",
470
+ version: "v1.7.4",
471
+ _integrity: undefined,
472
+ license: undefined,
473
+ scope: "required",
474
+ properties: [
475
+ {
476
+ name: "SrcGoMod",
477
+ value:
478
+ "/home/almalinux/go/pkg/mod/cache/download/github.com/gorilla/mux/@v/v1.7.4.mod"
479
+ },
480
+ { name: "ModuleGoVersion", value: "1.12" }
481
+ ]
471
482
  });
472
483
  });
473
484
 
@@ -491,8 +502,8 @@ test("parseGopkgData", async () => {
491
502
  );
492
503
  expect(dep_list.length).toEqual(36);
493
504
  expect(dep_list[0]).toEqual({
494
- group: "cloud.google.com",
495
- name: "go",
505
+ group: "",
506
+ name: "cloud.google.com/go",
496
507
  version: "v0.39.0",
497
508
  _integrity: "sha256-LKUyprxlVmM0QAS6ECQ20pAxAY6rI2JHZ42x2JeGJ78="
498
509
  });
@@ -508,8 +519,8 @@ test("parse go version data", async () => {
508
519
  );
509
520
  expect(dep_list.length).toEqual(125);
510
521
  expect(dep_list[0]).toEqual({
511
- group: "github.com/ShiftLeftSecurity",
512
- name: "atlassian-connect-go",
522
+ group: "",
523
+ name: "github.com/ShiftLeftSecurity/atlassian-connect-go",
513
524
  version: "v0.0.2",
514
525
  _integrity: "",
515
526
  license: undefined
@@ -520,8 +531,8 @@ test("parse go version data", async () => {
520
531
  );
521
532
  expect(dep_list.length).toEqual(149);
522
533
  expect(dep_list[0]).toEqual({
523
- group: "cloud.google.com",
524
- name: "go",
534
+ group: "",
535
+ name: "cloud.google.com/go",
525
536
  version: "v0.79.0",
526
537
  _integrity: "sha256-oqqswrt4x6b9OGBnNqdssxBl1xf0rSUNjU2BR4BZar0=",
527
538
  license: undefined