@cyclonedx/cdxgen 9.9.5 → 9.9.7

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
@@ -51,6 +51,7 @@ Most SBOM tools are like barcode scanners. They can scan a few package manifest
51
51
  | Docker compose | docker-compose\*.yml. Images would also be scanned. | N/A | |
52
52
  | Dockerfile | `*Dockerfile*` Images would also be scanned. | N/A | |
53
53
  | Containerfile | `*Containerfile*`. Images would also be scanned. | N/A | |
54
+ | Bitbucket Pipelines | `bitbucket-pipelines.yml` images and pipes would also be scanned. | N/A | |
54
55
  | Google CloudBuild configuration | cloudbuild.yaml | N/A | |
55
56
  | OpenAPI | openapi\*.json, openapi\*.yaml | N/A | |
56
57
 
@@ -86,10 +87,10 @@ For go, `go mod why` command is used to identify required packages. For php, com
86
87
  ## Installing
87
88
 
88
89
  ```shell
89
- sudo npm install -g @cyclonedx/cdxgen
90
+ npm install -g @cyclonedx/cdxgen
90
91
 
91
92
  # For CycloneDX 1.4 compatibility use version 8.6.0 or pass the argument `--spec-version 1.4`
92
- sudo npm install -g @cyclonedx/cdxgen@8.6.0
93
+ npm install -g @cyclonedx/cdxgen@8.6.0
93
94
  ```
94
95
 
95
96
  If you are a [Homebrew](https://brew.sh/) user, you can also install [cdxgen](https://formulae.brew.sh/formula/cdxgen) via:
@@ -327,7 +328,7 @@ This would create a bom.json.map file with the jar - class name mapping. Refer t
327
328
 
328
329
  ## Resolving licenses
329
330
 
330
- cdxgen can automatically query public registries such as maven, npm, or nuget to resolve the package licenses. This is a time-consuming operation and is disabled by default. To enable, set the environment variable `FETCH_LICENSE` to `true`, as shown.
331
+ cdxgen can automatically query public registries such as maven, npm, or nuget to resolve the package licenses. This is a time-consuming operation and is disabled by default. To enable, set the environment variable `FETCH_LICENSE` to `true`, as shown. Ensure that `GITHUB_TOKEN` is set or provided by [built-in GITHUB_TOKEN in GitHub Actions](https://docs.github.com/en/rest/overview/rate-limits-for-the-rest-api#primary-rate-limit-for-github_token-in-github-actions), otherwise rate limiting might prevent license resolving.
331
332
 
332
333
  ```bash
333
334
  export FETCH_LICENSE=true
@@ -141,6 +141,25 @@
141
141
  "pkg:cargo/nickel",
142
142
  "pkg:cargo/yew",
143
143
  "pkg:cargo/azul",
144
- "pkg:cargo/conrod"
144
+ "pkg:cargo/conrod",
145
+ "pkg:generic/Aws",
146
+ "pkg:generic/Azure",
147
+ "pkg:generic/google",
148
+ "pkg:generic/CivetServer",
149
+ "pkg:generic/civetweb",
150
+ "pkg:generic/cpprest",
151
+ "pkg:generic/QCoreApplication",
152
+ "pkg:generic/drogon",
153
+ "pkg:generic/wfrest",
154
+ "pkg:generic/http",
155
+ "pkg:generic/fio",
156
+ "pkg:generic/onion",
157
+ "pkg:generic/lwan",
158
+ "pkg:generic/oatpp",
159
+ "pkg:generic/QDjango",
160
+ "pkg:generic/userver",
161
+ "pkg:generic/Wt/",
162
+ "pkg:generic/klone",
163
+ "pkg:generic/kcgi"
145
164
  ]
146
165
  }
@@ -1,31 +1,82 @@
1
1
  [
2
- { "license": "Apache-2.0", "group": "cloud.google.com", "name": "go" },
3
- { "license": "Apache-2.0", "group": "cloud.google.com/go", "name": "*" },
4
- { "license": "Apache-2.0", "group": "cuelang.org", "name": "go" },
5
- { "license": "MIT", "group": "pack.ag", "name": "amqp" },
6
- { "license": "Apache-2.0", "group": "google.golang.org", "name": "*" },
7
- { "license": "BSD-3-Clause", "group": "golang.org/x", "name": "*" },
8
2
  {
9
- "license": "BSD-3-Clause",
10
- "group": "dmitri.shuralyov.com/gpu",
11
- "name": "*"
3
+ "packageNamespace": "*",
4
+ "knownLicenses": [{ "license": "MIT", "urlIncludes": "mit-license" }]
12
5
  },
13
- { "license": "Apache-2.0", "group": "contrib.go.opencensus.io", "name": "*" },
14
- { "license": "Apache-2.0", "group": "git.apache.org", "name": "*" },
15
- { "license": "Apache-2.0", "group": ".", "name": "go.opencensus.io" },
16
- { "license": "MIT", "group": "sigs.k8s.io", "name": "*" },
17
- { "license": "BSD-3-Clause", "group": "rsc.io", "name": "*" },
18
- { "license": "Apache-2.0", "group": "openpitrix.io", "name": "*" },
19
- { "license": "BSD-3-Clause", "group": "modernc.org", "name": "*" },
20
- { "license": "Apache-2.0", "group": "kubesphere.io", "name": "*" },
21
- { "license": "Apache-2.0", "group": "k8s.io", "name": "*" },
22
- { "license": "Apache-2.0", "group": "istio.io", "name": "*" },
23
- { "license": "MIT", "group": "honnef.co/go", "name": "*" },
24
- { "license": "Apache-2.0", "group": ".", "name": "gotest.tools" },
25
- { "license": "Apache-2.0", "group": "gopkg.in", "name": "*" },
26
- { "license": "Apache-2.0", "group": "code.cloudfoundry.org", "name": "*" },
27
- { "license": "BSD-3-Clause", "group": "gonum.org/v1", "name": "*" },
28
- { "license": "Apache-2.0", "group": "gomodules.xyz/jsonpatch", "name": "*" },
29
- { "license": "MIT", "group": "go.uber.org", "name": "*" },
30
- { "license": "MIT", "group": "go.etcd.io", "name": "*" }
6
+ {
7
+ "packageNamespace": "pkg:golang/",
8
+ "knownLicenses": [
9
+ { "license": "Apache-2.0", "group": "cloud.google.com", "name": "go" },
10
+ { "license": "Apache-2.0", "group": "cloud.google.com/go", "name": "*" },
11
+ { "license": "Apache-2.0", "group": "cuelang.org", "name": "go" },
12
+ { "license": "MIT", "group": "pack.ag", "name": "amqp" },
13
+ { "license": "Apache-2.0", "group": "google.golang.org", "name": "*" },
14
+ { "license": "BSD-3-Clause", "group": "golang.org/x", "name": "*" },
15
+ {
16
+ "license": "BSD-3-Clause",
17
+ "group": "dmitri.shuralyov.com/gpu",
18
+ "name": "*"
19
+ },
20
+ {
21
+ "license": "Apache-2.0",
22
+ "group": "contrib.go.opencensus.io",
23
+ "name": "*"
24
+ },
25
+ { "license": "Apache-2.0", "group": "git.apache.org", "name": "*" },
26
+ { "license": "Apache-2.0", "group": ".", "name": "go.opencensus.io" },
27
+ { "license": "MIT", "group": "sigs.k8s.io", "name": "*" },
28
+ { "license": "BSD-3-Clause", "group": "rsc.io", "name": "*" },
29
+ { "license": "Apache-2.0", "group": "openpitrix.io", "name": "*" },
30
+ { "license": "BSD-3-Clause", "group": "modernc.org", "name": "*" },
31
+ { "license": "Apache-2.0", "group": "kubesphere.io", "name": "*" },
32
+ { "license": "Apache-2.0", "group": "k8s.io", "name": "*" },
33
+ { "license": "Apache-2.0", "group": "istio.io", "name": "*" },
34
+ { "license": "MIT", "group": "honnef.co/go", "name": "*" },
35
+ { "license": "Apache-2.0", "group": ".", "name": "gotest.tools" },
36
+ { "license": "Apache-2.0", "group": "gopkg.in", "name": "*" },
37
+ {
38
+ "license": "Apache-2.0",
39
+ "group": "code.cloudfoundry.org",
40
+ "name": "*"
41
+ },
42
+ { "license": "BSD-3-Clause", "group": "gonum.org/v1", "name": "*" },
43
+ {
44
+ "license": "Apache-2.0",
45
+ "group": "gomodules.xyz/jsonpatch",
46
+ "name": "*"
47
+ },
48
+ { "license": "MIT", "group": "go.uber.org", "name": "*" },
49
+ { "license": "MIT", "group": "go.etcd.io", "name": "*" }
50
+ ]
51
+ },
52
+ {
53
+ "packageNamespace": "pkg:nuget/",
54
+ "knownLicenses": [
55
+ {
56
+ "license": "MIT",
57
+ "urlIncludes": "//github.com/dotnet/standard/",
58
+ "licenseEvidence": "https://github.com/dotnet/standard/blob/release/3.0/LICENSE.TXT"
59
+ },
60
+ {
61
+ "license": "MIT",
62
+ "urlIncludes": "//github.com/dotnet/corefx/",
63
+ "licenseEvidence": "https://github.com/dotnet/corefx/blob/release/2.0.0/LICENSE.TXT"
64
+ },
65
+ {
66
+ "license": "MIT",
67
+ "urlIncludes": "//github.com/dotnet/core-setup/",
68
+ "licenseEvidence": "https://github.com/dotnet/core-setup/blob/release/2.0.0/LICENSE.TXT"
69
+ },
70
+ {
71
+ "licenseName": ".NET Library License",
72
+ "urlEndswith": "?LinkId=329770",
73
+ "licenseEvidence": "https://go.microsoft.com/fwlink/?LinkId=329770"
74
+ },
75
+ {
76
+ "licenseName": ".NET Library License",
77
+ "urlEndswith": "dotnet_library_license.htm",
78
+ "licenseEvidence": "https://dotnet.microsoft.com/en-us/dotnet_library_license.htm"
79
+ }
80
+ ]
81
+ }
31
82
  ]
package/docker.js CHANGED
@@ -416,11 +416,16 @@ export const parseImageName = (fullImageName) => {
416
416
  repo: "",
417
417
  tag: "",
418
418
  digest: "",
419
- platform: ""
419
+ platform: "",
420
+ group: "",
421
+ name: ""
420
422
  };
421
423
  if (!fullImageName) {
422
424
  return nameObj;
423
425
  }
426
+ // ensure it's lowercased
427
+ fullImageName = fullImageName.toLowerCase();
428
+
424
429
  // Extract registry name
425
430
  if (
426
431
  fullImageName.includes("/") &&
@@ -437,6 +442,7 @@ export const parseImageName = (fullImageName) => {
437
442
  fullImageName = fullImageName.replace(tmpA[0] + "/", "");
438
443
  }
439
444
  }
445
+
440
446
  // Extract digest name
441
447
  if (fullImageName.includes("@sha256:")) {
442
448
  const tmpA = fullImageName.split("@sha256:");
@@ -445,6 +451,7 @@ export const parseImageName = (fullImageName) => {
445
451
  fullImageName = fullImageName.replace("@sha256:" + nameObj.digest, "");
446
452
  }
447
453
  }
454
+
448
455
  // Extract tag name
449
456
  if (fullImageName.includes(":")) {
450
457
  const tmpA = fullImageName.split(":");
@@ -453,11 +460,20 @@ export const parseImageName = (fullImageName) => {
453
460
  fullImageName = fullImageName.replace(":" + nameObj.tag, "");
454
461
  }
455
462
  }
456
- if (fullImageName && fullImageName.startsWith("library/")) {
457
- fullImageName = fullImageName.replace("library/", "");
458
- }
463
+
459
464
  // The left over string is the repo name
460
465
  nameObj.repo = fullImageName;
466
+ nameObj.name = fullImageName;
467
+
468
+ // extract group name
469
+ if (fullImageName.includes("/")) {
470
+ const tmpA = fullImageName.split("/");
471
+ if (tmpA.length > 1) {
472
+ nameObj.name = tmpA[tmpA.length - 1];
473
+ nameObj.group = fullImageName.replace("/" + tmpA[tmpA.length - 1], "");
474
+ }
475
+ }
476
+
461
477
  return nameObj;
462
478
  };
463
479
 
package/docker.test.js CHANGED
@@ -24,35 +24,54 @@ test("parseImageName tests", () => {
24
24
  repo: "debian",
25
25
  tag: "",
26
26
  digest: "",
27
- platform: ""
27
+ platform: "",
28
+ group: "",
29
+ name: "debian"
28
30
  });
29
31
  expect(parseImageName("debian:latest")).toEqual({
30
32
  registry: "",
31
33
  repo: "debian",
32
34
  tag: "latest",
33
35
  digest: "",
34
- platform: ""
36
+ platform: "",
37
+ group: "",
38
+ name: "debian"
39
+ });
40
+ expect(parseImageName("library/debian:latest")).toEqual({
41
+ registry: "",
42
+ repo: "library/debian",
43
+ tag: "latest",
44
+ digest: "",
45
+ platform: "",
46
+ group: "library",
47
+ name: "debian"
35
48
  });
36
49
  expect(parseImageName("shiftleft/scan:v1.15.6")).toEqual({
37
50
  registry: "",
38
51
  repo: "shiftleft/scan",
39
52
  tag: "v1.15.6",
40
53
  digest: "",
41
- platform: ""
54
+ platform: "",
55
+ group: "shiftleft",
56
+ name: "scan"
42
57
  });
43
58
  expect(parseImageName("localhost:5000/shiftleft/scan:v1.15.6")).toEqual({
44
59
  registry: "localhost:5000",
45
60
  repo: "shiftleft/scan",
46
61
  tag: "v1.15.6",
47
62
  digest: "",
48
- platform: ""
63
+ platform: "",
64
+ group: "shiftleft",
65
+ name: "scan"
49
66
  });
50
67
  expect(parseImageName("localhost:5000/shiftleft/scan")).toEqual({
51
68
  registry: "localhost:5000",
52
69
  repo: "shiftleft/scan",
53
70
  tag: "",
54
71
  digest: "",
55
- platform: ""
72
+ platform: "",
73
+ group: "shiftleft",
74
+ name: "scan"
56
75
  });
57
76
  expect(
58
77
  parseImageName("foocorp.jfrog.io/docker/library/eclipse-temurin:latest")
@@ -61,7 +80,9 @@ test("parseImageName tests", () => {
61
80
  repo: "docker/library/eclipse-temurin",
62
81
  tag: "latest",
63
82
  digest: "",
64
- platform: ""
83
+ platform: "",
84
+ group: "docker/library",
85
+ name: "eclipse-temurin"
65
86
  });
66
87
  expect(
67
88
  parseImageName(
@@ -72,7 +93,9 @@ test("parseImageName tests", () => {
72
93
  repo: "shiftleft/scan-java",
73
94
  tag: "",
74
95
  digest: "5d008306a7c5d09ba0161a3408fa3839dc2c9dd991ffb68adecc1040399fe9e1",
75
- platform: ""
96
+ platform: "",
97
+ group: "shiftleft",
98
+ name: "scan-java"
76
99
  });
77
100
  }, 120000);
78
101
 
package/evinser.js CHANGED
@@ -322,6 +322,29 @@ export const analyzeProject = async (dbObjMap, options) => {
322
322
  // Load any existing purl-location information from the sbom.
323
323
  // For eg: cdxgen populates this information for javascript projects
324
324
  let { purlLocationMap, purlImportsMap } = initFromSbom(components);
325
+ // Do reachables first so that usages slicing can reuse the atom file
326
+ if (options.withReachables) {
327
+ if (
328
+ options.reachablesSlicesFile &&
329
+ fs.existsSync(options.reachablesSlicesFile)
330
+ ) {
331
+ reachablesSlicesFile = options.reachablesSlicesFile;
332
+ reachablesSlice = JSON.parse(
333
+ fs.readFileSync(options.reachablesSlicesFile, "utf-8")
334
+ );
335
+ } else {
336
+ retMap = createSlice(language, dirPath, "reachables", options);
337
+ if (retMap && retMap.slicesFile && fs.existsSync(retMap.slicesFile)) {
338
+ reachablesSlicesFile = retMap.slicesFile;
339
+ reachablesSlice = JSON.parse(
340
+ fs.readFileSync(retMap.slicesFile, "utf-8")
341
+ );
342
+ }
343
+ }
344
+ }
345
+ if (reachablesSlice && Object.keys(reachablesSlice).length) {
346
+ dataFlowFrames = await collectReachableFrames(language, reachablesSlice);
347
+ }
325
348
  // Reuse existing usages slices
326
349
  if (options.usagesSlicesFile && fs.existsSync(options.usagesSlicesFile)) {
327
350
  usageSlice = JSON.parse(fs.readFileSync(options.usagesSlicesFile, "utf-8"));
@@ -374,28 +397,6 @@ export const analyzeProject = async (dbObjMap, options) => {
374
397
  purlImportsMap
375
398
  );
376
399
  }
377
- if (options.withReachables) {
378
- if (
379
- options.reachablesSlicesFile &&
380
- fs.existsSync(options.reachablesSlicesFile)
381
- ) {
382
- reachablesSlicesFile = options.reachablesSlicesFile;
383
- reachablesSlice = JSON.parse(
384
- fs.readFileSync(options.reachablesSlicesFile, "utf-8")
385
- );
386
- } else {
387
- retMap = createSlice(language, dirPath, "reachables", options);
388
- if (retMap && retMap.slicesFile && fs.existsSync(retMap.slicesFile)) {
389
- reachablesSlicesFile = retMap.slicesFile;
390
- reachablesSlice = JSON.parse(
391
- fs.readFileSync(retMap.slicesFile, "utf-8")
392
- );
393
- }
394
- }
395
- }
396
- if (reachablesSlice && Object.keys(reachablesSlice).length) {
397
- dataFlowFrames = await collectReachableFrames(language, reachablesSlice);
398
- }
399
400
  return {
400
401
  atomFile: retMap.atomFile,
401
402
  usagesSlicesFile,
@@ -776,15 +777,19 @@ export const detectServicesFromUDT = (
776
777
  servicesMap
777
778
  ) => {
778
779
  if (
779
- ["python", "py"].includes(language) &&
780
+ ["python", "py", "c", "cpp", "c++"].includes(language) &&
780
781
  userDefinedTypes &&
781
782
  userDefinedTypes.length
782
783
  ) {
783
784
  for (const audt of userDefinedTypes) {
784
785
  if (
785
- audt.name.includes("route") ||
786
- audt.name.includes("path") ||
787
- audt.name.includes("url")
786
+ audt.name.toLowerCase().includes("route") ||
787
+ audt.name.toLowerCase().includes("path") ||
788
+ audt.name.toLowerCase().includes("url") ||
789
+ audt.name.toLowerCase().includes("registerhandler") ||
790
+ audt.name.toLowerCase().includes("endpoint") ||
791
+ audt.name.toLowerCase().includes("api") ||
792
+ audt.name.toLowerCase().includes("add_method")
788
793
  ) {
789
794
  const fields = audt.fields || [];
790
795
  if (
@@ -875,14 +880,11 @@ export const extractEndpoints = (language, code) => {
875
880
  );
876
881
  }
877
882
  break;
878
- case "py":
879
- case "python":
883
+ default:
880
884
  endpoints = (code.match(/['"](.*?)['"]/gi) || [])
881
885
  .map((v) => v.replace(/["']/g, "").replace("\n", ""))
882
886
  .filter((v) => v.length > 2);
883
887
  break;
884
- default:
885
- break;
886
888
  }
887
889
  return endpoints;
888
890
  };
@@ -910,6 +912,7 @@ export const createEvinseFile = (sliceArtefacts, options) => {
910
912
  const components = bomJson.components || [];
911
913
  let occEvidencePresent = false;
912
914
  let csEvidencePresent = false;
915
+ let servicesPresent = false;
913
916
  for (const comp of components) {
914
917
  if (!comp.purl) {
915
918
  continue;
@@ -957,6 +960,7 @@ export const createEvinseFile = (sliceArtefacts, options) => {
957
960
  }
958
961
  // Add to existing services
959
962
  bomJson.services = (bomJson.services || []).concat(services);
963
+ servicesPresent = true;
960
964
  }
961
965
  if (options.annotate) {
962
966
  if (!bomJson.annotations) {
@@ -993,7 +997,7 @@ export const createEvinseFile = (sliceArtefacts, options) => {
993
997
  bomJson.metadata.timestamp = new Date().toISOString();
994
998
  delete bomJson.signature;
995
999
  fs.writeFileSync(evinseOutFile, JSON.stringify(bomJson, null, 2));
996
- if (occEvidencePresent || csEvidencePresent) {
1000
+ if (occEvidencePresent || csEvidencePresent || servicesPresent) {
997
1001
  console.log(evinseOutFile, "created successfully.");
998
1002
  } else {
999
1003
  console.log(
package/index.js CHANGED
@@ -105,7 +105,9 @@ import {
105
105
  MAX_BUFFER,
106
106
  getNugetMetadata,
107
107
  frameworksList,
108
- parseContainerFile
108
+ parseContainerFile,
109
+ parseBitbucketPipelinesFile,
110
+ getPyMetadata
109
111
  } from "./utils.js";
110
112
  import { spawnSync } from "node:child_process";
111
113
  import { fileURLToPath } from "node:url";
@@ -2574,6 +2576,9 @@ export const createPythonBom = async (path, options) => {
2574
2576
  if (tempDir && tempDir.startsWith(tmpdir()) && rmSync) {
2575
2577
  rmSync(tempDir, { recursive: true, force: true });
2576
2578
  }
2579
+ if (FETCH_LICENSE) {
2580
+ pkgList = await getPyMetadata(pkgList, false);
2581
+ }
2577
2582
  return buildBomNSData(options, pkgList, "pypi", {
2578
2583
  allImports,
2579
2584
  src: path,
@@ -3148,6 +3153,18 @@ export const createCppBom = (path, options) => {
3148
3153
  retMap.parentComponent.type = "library";
3149
3154
  pkgList.push(retMap.parentComponent);
3150
3155
  }
3156
+ // Retain the dependency tree from cmake
3157
+ if (retMap.dependenciesList) {
3158
+ if (dependencies.length) {
3159
+ dependencies = mergeDependencies(
3160
+ dependencies,
3161
+ retMap.dependenciesList,
3162
+ parentComponent
3163
+ );
3164
+ } else {
3165
+ dependencies = retMap.dependenciesList;
3166
+ }
3167
+ }
3151
3168
  }
3152
3169
  }
3153
3170
  // The need for java >= 17 with atom is causing confusions since there could be C projects
@@ -3719,6 +3736,11 @@ export const createContainerSpecLikeBom = async (path, options) => {
3719
3736
  (options.multiProject ? "**/" : "") + "*Dockerfile*",
3720
3737
  options
3721
3738
  );
3739
+ const bbPipelineFiles = getAllFiles(
3740
+ path,
3741
+ (options.multiProject ? "**/" : "") + "bitbucket-pipelines.yml",
3742
+ options
3743
+ );
3722
3744
  const cfFiles = getAllFiles(
3723
3745
  path,
3724
3746
  (options.multiProject ? "**/" : "") + "*Containerfile*",
@@ -3747,27 +3769,35 @@ export const createContainerSpecLikeBom = async (path, options) => {
3747
3769
  }
3748
3770
  // Privado.ai json files
3749
3771
  const privadoFiles = getAllFiles(path, ".privado/" + "*.json", options);
3750
- // Parse yaml manifest files, dockerfiles or containerfiles
3751
- if (dcFiles.length || dfFiles.length || cfFiles.length) {
3752
- for (const f of [...dcFiles, ...dfFiles, ...cfFiles]) {
3772
+
3773
+ // Parse yaml manifest files, dockerfiles, containerfiles or bitbucket pipeline files
3774
+ if (
3775
+ dcFiles.length ||
3776
+ dfFiles.length ||
3777
+ cfFiles.length ||
3778
+ bbPipelineFiles.length
3779
+ ) {
3780
+ for (const f of [...dcFiles, ...dfFiles, ...cfFiles, ...bbPipelineFiles]) {
3753
3781
  if (DEBUG_MODE) {
3754
3782
  console.log(`Parsing ${f}`);
3755
3783
  }
3756
3784
 
3757
3785
  const dData = readFileSync(f, { encoding: "utf-8" });
3758
- let imglist = [];
3786
+ let imgList = [];
3759
3787
  // parse yaml manifest files
3760
- if (f.endsWith(".yml") || f.endsWith(".yaml")) {
3761
- imglist = parseContainerSpecData(dData);
3788
+ if (f.endsWith("bitbucket-pipelines.yml")) {
3789
+ imgList = parseBitbucketPipelinesFile(dData);
3790
+ } else if (f.endsWith(".yml") || f.endsWith(".yaml")) {
3791
+ imgList = parseContainerSpecData(dData);
3762
3792
  } else {
3763
- imglist = parseContainerFile(dData);
3793
+ imgList = parseContainerFile(dData);
3764
3794
  }
3765
3795
 
3766
- if (imglist && imglist.length) {
3796
+ if (imgList && imgList.length) {
3767
3797
  if (DEBUG_MODE) {
3768
- console.log("Images identified in", f, "are", imglist);
3798
+ console.log("Images identified in", f, "are", imgList);
3769
3799
  }
3770
- for (const img of imglist) {
3800
+ for (const img of imgList) {
3771
3801
  const commonProperties = [
3772
3802
  {
3773
3803
  name: "SrcFile",
@@ -3832,20 +3862,26 @@ export const createContainerSpecLikeBom = async (path, options) => {
3832
3862
  console.log(`Parsing image ${img.image}`);
3833
3863
  }
3834
3864
  const imageObj = parseImageName(img.image);
3865
+
3835
3866
  const pkg = {
3836
- name: imageObj.repo,
3867
+ name: imageObj.name,
3868
+ group: imageObj.group,
3837
3869
  version:
3838
3870
  imageObj.tag ||
3839
3871
  (imageObj.digest ? "sha256:" + imageObj.digest : "latest"),
3840
3872
  qualifiers: {},
3841
- properties: commonProperties
3873
+ properties: commonProperties,
3874
+ type: "container"
3842
3875
  };
3843
3876
  if (imageObj.registry) {
3844
- pkg["qualifiers"]["repository_url"] = imageObj.registry;
3877
+ pkg["qualifiers"]["repository_url"] = img.image;
3845
3878
  }
3846
3879
  if (imageObj.platform) {
3847
3880
  pkg["qualifiers"]["platform"] = imageObj.platform;
3848
3881
  }
3882
+ if (imageObj.tag) {
3883
+ pkg["qualifiers"]["tag"] = imageObj.tag;
3884
+ }
3849
3885
  // Create an entry for the oci image
3850
3886
  const imageBomData = buildBomNSData(options, [pkg], "oci", {
3851
3887
  src: img.image,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyclonedx/cdxgen",
3
- "version": "9.9.5",
3
+ "version": "9.9.7",
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>",
@@ -55,13 +55,13 @@
55
55
  "url": "https://github.com/cyclonedx/cdxgen/issues"
56
56
  },
57
57
  "dependencies": {
58
- "@babel/parser": "^7.23.3",
59
- "@babel/traverse": "^7.23.3",
58
+ "@babel/parser": "^7.23.5",
59
+ "@babel/traverse": "^7.23.5",
60
60
  "@npmcli/arborist": "7.2.0",
61
61
  "ajv": "^8.12.0",
62
62
  "ajv-formats": "^2.1.1",
63
63
  "cheerio": "^1.0.0-rc.12",
64
- "edn-data": "^1.0.0",
64
+ "edn-data": "1.1.1",
65
65
  "find-up": "^6.3.0",
66
66
  "glob": "^10.3.10",
67
67
  "global-agent": "^3.0.0",
@@ -83,7 +83,7 @@
83
83
  "yargs": "^17.7.2"
84
84
  },
85
85
  "optionalDependencies": {
86
- "@appthreat/atom": "1.6.4",
86
+ "@appthreat/atom": "1.7.2",
87
87
  "@cyclonedx/cdxgen-plugins-bin": "^1.4.0",
88
88
  "@cyclonedx/cdxgen-plugins-bin-arm64": "^1.4.0",
89
89
  "@cyclonedx/cdxgen-plugins-bin-ppc64": "^1.4.0",
@@ -91,7 +91,7 @@
91
91
  "compression": "^1.7.4",
92
92
  "connect": "^3.7.0",
93
93
  "jsonata": "^2.0.3",
94
- "sequelize": "^6.35.0",
94
+ "sequelize": "^6.35.1",
95
95
  "sqlite3": "^5.1.6"
96
96
  },
97
97
  "files": [
@@ -102,7 +102,7 @@
102
102
  "devDependencies": {
103
103
  "caxa": "^3.0.1",
104
104
  "docsify-cli": "^4.4.4",
105
- "eslint": "^8.53.0",
105
+ "eslint": "^8.54.0",
106
106
  "eslint-config-prettier": "^9.0.0",
107
107
  "eslint-plugin-prettier": "^5.0.1",
108
108
  "jest": "^29.7.0",
package/server.js CHANGED
@@ -83,7 +83,8 @@ const parseQueryString = (q, body, options = {}) => {
83
83
  "filter",
84
84
  "only",
85
85
  "autoCompositions",
86
- "gitBranch"
86
+ "gitBranch",
87
+ "active"
87
88
  ];
88
89
 
89
90
  for (const param of queryParams) {