@cyclonedx/cdxgen 10.0.4 → 10.0.6

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/docker.js CHANGED
@@ -426,7 +426,14 @@ export const parseImageName = (fullImageName) => {
426
426
  return nameObj;
427
427
  }
428
428
  // ensure it's lowercased
429
- fullImageName = fullImageName.toLowerCase();
429
+ fullImageName = fullImageName.toLowerCase().trim();
430
+
431
+ // Extract platform
432
+ if (fullImageName.startsWith("--platform=")) {
433
+ const tmpName = fullImageName.replace("--platform=", "").split(" ");
434
+ nameObj.platform = tmpName[0];
435
+ fullImageName = tmpName[1];
436
+ }
430
437
 
431
438
  // Extract registry name
432
439
  if (
@@ -1183,3 +1190,31 @@ export const getCredsFromHelper = (exeSuffix, serverAddress) => {
1183
1190
  }
1184
1191
  return undefined;
1185
1192
  };
1193
+
1194
+ export const addSkippedSrcFiles = (skippedImageSrcs, components) => {
1195
+ for (const skippedImage of skippedImageSrcs) {
1196
+ for (const co of components) {
1197
+ let srcFileValues = [];
1198
+ let srcImageValue;
1199
+ co.properties.forEach(function (property) {
1200
+ if (property.name === "oci:SrcImage") {
1201
+ srcImageValue = property.value;
1202
+ }
1203
+
1204
+ if (property.name === "SrcFile") {
1205
+ srcFileValues.push(property.value);
1206
+ }
1207
+ });
1208
+
1209
+ if (
1210
+ srcImageValue === skippedImage.image &&
1211
+ !srcFileValues.includes(skippedImage.src)
1212
+ ) {
1213
+ co.properties = co.properties.concat({
1214
+ name: "SrcFile",
1215
+ value: skippedImage.src
1216
+ });
1217
+ }
1218
+ }
1219
+ }
1220
+ };
package/docker.test.js CHANGED
@@ -4,9 +4,10 @@ import {
4
4
  getImage,
5
5
  removeImage,
6
6
  exportImage,
7
- isWin
7
+ isWin,
8
+ addSkippedSrcFiles
8
9
  } from "./docker.js";
9
- import { expect, test } from "@jest/globals";
10
+ import { expect, test, describe, beforeEach } from "@jest/globals";
10
11
 
11
12
  test("docker connection", async () => {
12
13
  if (!(isWin && process.env.CI === "true")) {
@@ -84,6 +85,19 @@ test("parseImageName tests", () => {
84
85
  group: "docker/library",
85
86
  name: "eclipse-temurin"
86
87
  });
88
+ expect(
89
+ parseImageName(
90
+ "--platform=linux/amd64 foocorp.jfrog.io/docker/library/eclipse-temurin:latest"
91
+ )
92
+ ).toEqual({
93
+ registry: "foocorp.jfrog.io",
94
+ repo: "docker/library/eclipse-temurin",
95
+ tag: "latest",
96
+ digest: "",
97
+ platform: "linux/amd64",
98
+ group: "docker/library",
99
+ name: "eclipse-temurin"
100
+ });
87
101
  expect(
88
102
  parseImageName(
89
103
  "quay.io/shiftleft/scan-java@sha256:5d008306a7c5d09ba0161a3408fa3839dc2c9dd991ffb68adecc1040399fe9e1"
@@ -117,3 +131,72 @@ test("docker getImage", async () => {
117
131
  const imageData = await exportImage("hello-world:latest");
118
132
  expect(imageData);
119
133
  }, 120000);
134
+
135
+ describe("addSkippedSrcFiles tests", () => {
136
+ let testComponents;
137
+
138
+ beforeEach(() => {
139
+ testComponents = [
140
+ {
141
+ name: "node",
142
+ version: "20",
143
+ component: "node:20",
144
+ purl: "pkg:oci/node@20?tag=20",
145
+ type: "container",
146
+ "bom-ref": "pkg:oci/node@20?tag=20",
147
+ properties: [
148
+ {
149
+ name: "SrcFile",
150
+ value: "/some/project/Dockerfile"
151
+ },
152
+ {
153
+ name: "oci:SrcImage",
154
+ value: "node:20"
155
+ }
156
+ ]
157
+ }
158
+ ];
159
+ });
160
+
161
+ test("no matching additional src files", () => {
162
+ addSkippedSrcFiles(
163
+ [
164
+ {
165
+ image: "node:18",
166
+ src: "/some/project/bitbucket-pipeline.yml"
167
+ }
168
+ ],
169
+ testComponents
170
+ );
171
+
172
+ expect(testComponents[0].properties).toHaveLength(2);
173
+ });
174
+
175
+ test("adds additional src files", () => {
176
+ addSkippedSrcFiles(
177
+ [
178
+ {
179
+ image: "node:20",
180
+ src: "/some/project/bitbucket-pipeline.yml"
181
+ }
182
+ ],
183
+ testComponents
184
+ );
185
+
186
+ expect(testComponents[0].properties).toHaveLength(3);
187
+ });
188
+
189
+ test("skips if same src file", () => {
190
+ addSkippedSrcFiles(
191
+ [
192
+ {
193
+ image: "node:20",
194
+ src: "/some/project/Dockerfile"
195
+ }
196
+ ],
197
+ testComponents
198
+ );
199
+
200
+ expect(testComponents[0].properties).toHaveLength(2);
201
+ });
202
+ }, 120000);
package/index.js CHANGED
@@ -139,7 +139,8 @@ import {
139
139
  getPkgPathList,
140
140
  parseImageName,
141
141
  exportArchive,
142
- exportImage
142
+ exportImage,
143
+ addSkippedSrcFiles
143
144
  } from "./docker.js";
144
145
  import {
145
146
  getGoBuildInfo,
@@ -3659,6 +3660,7 @@ export const createContainerSpecLikeBom = async (path, options) => {
3659
3660
  let parentComponent = {};
3660
3661
  let dependencies = [];
3661
3662
  const doneimages = [];
3663
+ const skippedImageSrcs = [];
3662
3664
  const doneservices = [];
3663
3665
  const origProjectType = options.projectType;
3664
3666
  let dcFiles = getAllFiles(
@@ -3789,8 +3791,14 @@ export const createContainerSpecLikeBom = async (path, options) => {
3789
3791
  if (img.image) {
3790
3792
  if (doneimages.includes(img.image)) {
3791
3793
  if (DEBUG_MODE) {
3792
- console.log("Skipping", img.image);
3794
+ console.log(
3795
+ "Skipping image as it's already been processed",
3796
+ img.image
3797
+ );
3793
3798
  }
3799
+
3800
+ skippedImageSrcs.push({ image: img.image, src: f });
3801
+
3794
3802
  continue;
3795
3803
  }
3796
3804
  if (DEBUG_MODE) {
@@ -3809,7 +3817,21 @@ export const createContainerSpecLikeBom = async (path, options) => {
3809
3817
  type: "container"
3810
3818
  };
3811
3819
  if (imageObj.registry) {
3812
- pkg["qualifiers"]["repository_url"] = img.image;
3820
+ // Skip adding repository_url if the registry or repo contains variables.
3821
+ if (
3822
+ imageObj.registry.includes("${") ||
3823
+ imageObj.repo.includes("${")
3824
+ ) {
3825
+ if (DEBUG_MODE) {
3826
+ console.warn(
3827
+ "Skipping adding repository_url qualifier as it contains variables, which are not yet supported",
3828
+ img.image
3829
+ );
3830
+ }
3831
+ } else {
3832
+ pkg["qualifiers"]["repository_url"] =
3833
+ `${imageObj.registry}/${imageObj.repo}`;
3834
+ }
3813
3835
  }
3814
3836
  if (imageObj.platform) {
3815
3837
  pkg["qualifiers"]["platform"] = imageObj.platform;
@@ -3845,6 +3867,9 @@ export const createContainerSpecLikeBom = async (path, options) => {
3845
3867
  } // for img
3846
3868
  }
3847
3869
  } // for
3870
+
3871
+ // Add additional SrcFile property to skipped image components
3872
+ addSkippedSrcFiles(skippedImageSrcs, components);
3848
3873
  } // if
3849
3874
  // Parse openapi files
3850
3875
  if (oapiFiles.length) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyclonedx/cdxgen",
3
- "version": "10.0.4",
3
+ "version": "10.0.6",
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>",