@cyclonedx/cdxgen 8.4.11 → 8.4.12

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.
Files changed (4) hide show
  1. package/index.js +43 -9
  2. package/package.json +1 -1
  3. package/utils.js +56 -16
  4. package/utils.test.js +28 -15
package/index.js CHANGED
@@ -4594,13 +4594,47 @@ exports.submitBom = async (args, bomContents) => {
4594
4594
  projectVersion
4595
4595
  );
4596
4596
  }
4597
- return await got(serverUrl, {
4598
- method: "POST",
4599
- headers: {
4600
- "X-Api-Key": args.apiKey,
4601
- "Content-Type": "application/json"
4602
- },
4603
- json: bomPayload,
4604
- responseType: "json"
4605
- }).json();
4597
+ try {
4598
+ return await got(serverUrl, {
4599
+ method: "PUT",
4600
+ headers: {
4601
+ "X-Api-Key": args.apiKey,
4602
+ "Content-Type": "application/json"
4603
+ },
4604
+ json: bomPayload,
4605
+ responseType: "json"
4606
+ }).json();
4607
+ } catch (error) {
4608
+ if (error.response.statusCode === 401) {
4609
+ // Unauthorized
4610
+ console.log(
4611
+ "Received Unauthorized error. Check the API key used is valid and has necessary permissions to create projects and upload bom."
4612
+ );
4613
+ } else if (error.response.statusCode === 405) {
4614
+ // Method not allowed errors
4615
+ try {
4616
+ return await got(serverUrl, {
4617
+ method: "POST",
4618
+ headers: {
4619
+ "X-Api-Key": args.apiKey,
4620
+ "Content-Type": "application/json"
4621
+ },
4622
+ json: {
4623
+ project: args.projectId,
4624
+ projectName: args.projectName,
4625
+ projectVersion: projectVersion,
4626
+ autoCreate: "true",
4627
+ bom: Buffer.from(bomContents).toString()
4628
+ },
4629
+ responseType: "json"
4630
+ }).json();
4631
+ } catch (error) {
4632
+ console.log("Unable to submit the SBoM to the Dependency-Track server");
4633
+ console.log(error);
4634
+ }
4635
+ } else {
4636
+ console.log("Unable to submit the SBoM to the Dependency-Track server");
4637
+ console.log(error);
4638
+ }
4639
+ }
4606
4640
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyclonedx/cdxgen",
3
- "version": "8.4.11",
3
+ "version": "8.4.12",
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
@@ -1218,8 +1218,11 @@ const parseGradleDep = function (
1218
1218
  let last_level = 0;
1219
1219
  let last_purl = `pkg:maven/${rootProjectName}@${rootProjectVersion}?type=jar`;
1220
1220
  const first_purl = last_purl;
1221
+ let last_project_purl = first_purl;
1221
1222
  const level_trees = {};
1222
1223
  level_trees[last_purl] = [];
1224
+ let scope = undefined;
1225
+ let profileName = undefined;
1223
1226
  if (retMap && retMap.projects) {
1224
1227
  const subDependsOn = [];
1225
1228
  for (const sd of retMap.projects) {
@@ -1242,16 +1245,34 @@ const parseGradleDep = function (
1242
1245
  const depRegex =
1243
1246
  /^.*?--- +(?<group>[^\s:]+):(?<name>[^\s:]+)(?::(?:{strictly [[]?)?(?<versionspecified>[^,\s:}]+))?(?:})?(?:[^->]* +-> +(?<versionoverride>[^\s:]+))?/gm;
1244
1247
  for (const rline of rawOutput.split("\n")) {
1245
- if (last_level !== 1) {
1246
- if (
1247
- !rline ||
1248
- rline.trim() === "" ||
1249
- rline.startsWith("+--- ") ||
1250
- rline.startsWith("\\--- ")
1251
- ) {
1252
- last_level = 1;
1253
- last_purl = first_purl;
1254
- stack = [last_purl];
1248
+ if (!rline) {
1249
+ continue;
1250
+ }
1251
+ if (
1252
+ rline.trim() === "" ||
1253
+ rline.startsWith("+--- ") ||
1254
+ rline.startsWith("\\--- ")
1255
+ ) {
1256
+ last_level = 1;
1257
+ if (rline.startsWith("+--- project :")) {
1258
+ let tmpProj = rline.split("+--- project :");
1259
+ last_project_purl = `pkg:maven/${tmpProj[1].trim()}@${rootProjectVersion}?type=jar`;
1260
+ stack = [last_project_purl];
1261
+ last_purl = last_project_purl;
1262
+ } else {
1263
+ last_project_purl = first_purl;
1264
+ last_purl = last_project_purl;
1265
+ stack = [first_purl];
1266
+ }
1267
+ }
1268
+ if (rline.includes(" - ")) {
1269
+ profileName = rline.split(" - ")[0];
1270
+ if (profileName.toLowerCase().includes("test")) {
1271
+ scope = "optional";
1272
+ } else if (profileName.toLowerCase().includes("runtime")) {
1273
+ scope = "required";
1274
+ } else {
1275
+ scope = undefined;
1255
1276
  }
1256
1277
  }
1257
1278
  while ((match = depRegex.exec(rline))) {
@@ -1273,21 +1294,38 @@ const parseGradleDep = function (
1273
1294
  // Filter duplicates
1274
1295
  if (!deps_keys_cache[purlString]) {
1275
1296
  deps_keys_cache[purlString] = true;
1276
- deps.push({
1297
+ const adep = {
1277
1298
  group,
1278
1299
  name: name,
1279
1300
  version: version,
1280
1301
  qualifiers: { type: "jar" }
1281
- });
1302
+ };
1303
+ if (scope) {
1304
+ adep["scope"] = scope;
1305
+ }
1306
+ if (profileName) {
1307
+ adep.properties = [
1308
+ {
1309
+ name: "GradleProfileName",
1310
+ value: profileName
1311
+ }
1312
+ ];
1313
+ }
1314
+ deps.push(adep);
1282
1315
  }
1283
1316
  if (!level_trees[purlString]) {
1284
1317
  level_trees[purlString] = [];
1285
1318
  }
1286
- if (level == 0 || last_purl === "") {
1319
+ if (level == 0) {
1320
+ stack = [first_purl];
1321
+ stack.push(purlString);
1322
+ } else if (last_purl === "") {
1287
1323
  stack.push(purlString);
1288
1324
  } else if (level > last_level) {
1289
1325
  const cnodes = level_trees[last_purl] || [];
1290
- cnodes.push(purlString);
1326
+ if (!cnodes.includes(purlString)) {
1327
+ cnodes.push(purlString);
1328
+ }
1291
1329
  level_trees[last_purl] = cnodes;
1292
1330
  if (stack[stack.length - 1] !== purlString) {
1293
1331
  stack.push(purlString);
@@ -1297,9 +1335,11 @@ const parseGradleDep = function (
1297
1335
  stack.pop();
1298
1336
  }
1299
1337
  const last_stack =
1300
- stack.length > 0 ? stack[stack.length - 1] : first_purl;
1338
+ stack.length > 0 ? stack[stack.length - 1] : last_project_purl;
1301
1339
  const cnodes = level_trees[last_stack] || [];
1302
- cnodes.push(purlString);
1340
+ if (!cnodes.includes(purlString)) {
1341
+ cnodes.push(purlString);
1342
+ }
1303
1343
  level_trees[last_stack] = cnodes;
1304
1344
  stack.push(purlString);
1305
1345
  }
package/utils.test.js CHANGED
@@ -98,7 +98,14 @@ test("parse gradle dependencies", () => {
98
98
  qualifiers: {
99
99
  type: "jar"
100
100
  },
101
- version: "1.0.2"
101
+ scope: "optional",
102
+ version: "1.0.2",
103
+ properties: [
104
+ {
105
+ name: "GradleProfileName",
106
+ value: "androidTestImplementation"
107
+ }
108
+ ]
102
109
  });
103
110
  expect(parsedList.pkgList[104]).toEqual({
104
111
  group: "androidx.print",
@@ -106,15 +113,14 @@ test("parse gradle dependencies", () => {
106
113
  qualifiers: {
107
114
  type: "jar"
108
115
  },
109
- version: "1.0.0"
110
- });
111
- expect(parsedList.pkgList[105]).toEqual({
112
- group: "androidx.core",
113
- name: "core",
114
- qualifiers: {
115
- type: "jar"
116
- },
117
- version: "1.7.0"
116
+ version: "1.0.0",
117
+ scope: "optional",
118
+ properties: [
119
+ {
120
+ name: "GradleProfileName",
121
+ value: "releaseUnitTestRuntimeClasspath"
122
+ }
123
+ ]
118
124
  });
119
125
  parsedList = utils.parseGradleDep(
120
126
  fs.readFileSync("./test/data/gradle-out1.dep", { encoding: "utf-8" })
@@ -125,7 +131,13 @@ test("parse gradle dependencies", () => {
125
131
  group: "org.springframework.boot",
126
132
  name: "spring-boot-starter-web",
127
133
  version: "2.2.0.RELEASE",
128
- qualifiers: { type: "jar" }
134
+ qualifiers: { type: "jar" },
135
+ properties: [
136
+ {
137
+ name: "GradleProfileName",
138
+ value: "compileClasspath"
139
+ }
140
+ ]
129
141
  });
130
142
 
131
143
  parsedList = utils.parseGradleDep(
@@ -210,17 +222,17 @@ test("parse gradle dependencies", () => {
210
222
  fs.readFileSync("./test/data/gradle-out-249.dep", { encoding: "utf-8" })
211
223
  );
212
224
  expect(parsedList.pkgList.length).toEqual(21);
213
- expect(parsedList.dependenciesList.length).toEqual(21);
225
+ expect(parsedList.dependenciesList.length).toEqual(22);
214
226
  parsedList = utils.parseGradleDep(
215
227
  fs.readFileSync("./test/data/gradle-service.out", { encoding: "utf-8" })
216
228
  );
217
229
  expect(parsedList.pkgList.length).toEqual(35);
218
- expect(parsedList.dependenciesList.length).toEqual(35);
230
+ expect(parsedList.dependenciesList.length).toEqual(36);
219
231
  parsedList = utils.parseGradleDep(
220
232
  fs.readFileSync("./test/data/gradle-s.out", { encoding: "utf-8" })
221
233
  );
222
234
  expect(parsedList.pkgList.length).toEqual(28);
223
- expect(parsedList.dependenciesList.length).toEqual(28);
235
+ expect(parsedList.dependenciesList.length).toEqual(29);
224
236
  parsedList = utils.parseGradleDep(
225
237
  fs.readFileSync("./test/data/gradle-core.out", { encoding: "utf-8" })
226
238
  );
@@ -1022,8 +1034,8 @@ test("get repo license", async () => {
1022
1034
  url: "https://github.com/ugorji/go/blob/master/LICENSE"
1023
1035
  });
1024
1036
  });
1025
- */
1026
1037
  test("get go pkg license", async () => {
1038
+ jest.setTimeout(120000);
1027
1039
  let license = await utils.getGoPkgLicense({
1028
1040
  group: "github.com/Azure/azure-amqp-common-go",
1029
1041
  name: "v2"
@@ -1057,6 +1069,7 @@ test("get go pkg license", async () => {
1057
1069
  }
1058
1070
  ]);
1059
1071
  });
1072
+ */
1060
1073
 
1061
1074
  test("get licenses", () => {
1062
1075
  let licenses = utils.getLicenses({ license: "MIT" });