@cyclonedx/cdxgen 9.11.2 → 9.11.3

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
@@ -345,7 +345,7 @@ cdxgen can retain the dependency tree under the `dependencies` attribute for a s
345
345
  - Gradle
346
346
  - Scala SBT
347
347
  - Python (requirements.txt, setup.py, pyproject.toml, poetry.lock)
348
- - .NET (project.assets.json, paket.lock)
348
+ - .NET (packages.lock.json, project.assets.json, paket.lock)
349
349
  - Go (go.mod)
350
350
  - PHP (composer.lock)
351
351
 
package/index.js CHANGED
@@ -4357,16 +4357,41 @@ export const createCsharpBom = async (
4357
4357
  }
4358
4358
  } else if (pkgLockFiles.length) {
4359
4359
  manifestFiles = manifestFiles.concat(pkgLockFiles);
4360
+ let parentDependsOn = [];
4360
4361
  // packages.lock.json from nuget
4361
4362
  for (const af of pkgLockFiles) {
4362
4363
  if (DEBUG_MODE) {
4363
4364
  console.log(`Parsing ${af}`);
4364
4365
  }
4365
4366
  pkgData = readFileSync(af, { encoding: "utf-8" });
4366
- const dlist = await parseCsPkgLockData(pkgData);
4367
+ let results = await parseCsPkgLockData(pkgData, af);
4368
+ let deps = results["dependenciesList"];
4369
+ let dlist = results["pkgList"];
4370
+ let rootList = results["rootList"];
4367
4371
  if (dlist && dlist.length) {
4368
4372
  pkgList = pkgList.concat(dlist);
4369
4373
  }
4374
+ if (deps && deps.length) {
4375
+ dependencies = dependencies.concat(deps);
4376
+ }
4377
+ if (!parentComponent) {
4378
+ parentComponent = createDefaultParentComponent(
4379
+ path,
4380
+ options.type,
4381
+ options
4382
+ );
4383
+ }
4384
+ // Keep track of the direct dependencies so that we can construct one complete
4385
+ // list after processing all lock files
4386
+ if (rootList && rootList.length) {
4387
+ parentDependsOn = parentDependsOn.concat(rootList);
4388
+ }
4389
+ }
4390
+ if (parentDependsOn.length) {
4391
+ dependencies.splice(0, 0, {
4392
+ ref: parentComponent["bom-ref"],
4393
+ dependsOn: parentDependsOn.map((p) => p["bom-ref"])
4394
+ });
4370
4395
  }
4371
4396
  } else if (pkgConfigFiles.length) {
4372
4397
  manifestFiles = manifestFiles.concat(pkgConfigFiles);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyclonedx/cdxgen",
3
- "version": "9.11.2",
3
+ "version": "9.11.3",
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,9 +55,9 @@
55
55
  "url": "https://github.com/cyclonedx/cdxgen/issues"
56
56
  },
57
57
  "dependencies": {
58
- "@babel/parser": "^7.23.6",
59
- "@babel/traverse": "^7.23.7",
60
- "@npmcli/arborist": "7.2.2",
58
+ "@babel/parser": "^7.23.9",
59
+ "@babel/traverse": "^7.23.9",
60
+ "@npmcli/arborist": "7.3.1",
61
61
  "ajv": "^8.12.0",
62
62
  "ajv-formats": "^2.1.1",
63
63
  "cheerio": "^1.0.0-rc.12",
package/utils.js CHANGED
@@ -5577,28 +5577,95 @@ export const parseCsProjAssetsData = async function (
5577
5577
  };
5578
5578
  };
5579
5579
 
5580
- export const parseCsPkgLockData = async function (csLockData) {
5580
+ export const parseCsPkgLockData = async function (csLockData, pkgLockFile) {
5581
5581
  const pkgList = [];
5582
+ const dependenciesList = [];
5583
+ const rootList = [];
5582
5584
  let pkg = null;
5583
5585
  if (!csLockData) {
5584
- return pkgList;
5586
+ return {
5587
+ pkgList,
5588
+ dependenciesList,
5589
+ rootList
5590
+ };
5585
5591
  }
5586
5592
  const assetData = JSON.parse(csLockData);
5587
5593
  if (!assetData || !assetData.dependencies) {
5588
- return pkgList;
5594
+ return {
5595
+ pkgList,
5596
+ dependenciesList,
5597
+ rootList
5598
+ };
5589
5599
  }
5590
5600
  for (const aversion of Object.keys(assetData.dependencies)) {
5591
5601
  for (const alib of Object.keys(assetData.dependencies[aversion])) {
5592
5602
  const libData = assetData.dependencies[aversion][alib];
5603
+ const purl = new PackageURL(
5604
+ "nuget",
5605
+ "",
5606
+ alib,
5607
+ libData.resolved,
5608
+ null,
5609
+ null
5610
+ ).toString();
5593
5611
  pkg = {
5594
5612
  group: "",
5595
5613
  name: alib,
5596
- version: libData.resolved
5614
+ version: libData.resolved,
5615
+ purl,
5616
+ "bom-ref": decodeURIComponent(purl),
5617
+ _integrity: libData.contentHash
5618
+ ? "sha512-" + libData.contentHash
5619
+ : undefined,
5620
+ properties: [
5621
+ {
5622
+ name: "SrcFile",
5623
+ value: pkgLockFile
5624
+ }
5625
+ ],
5626
+ evidence: {
5627
+ identity: {
5628
+ field: "purl",
5629
+ confidence: 1,
5630
+ methods: [
5631
+ {
5632
+ technique: "manifest-analysis",
5633
+ confidence: 1,
5634
+ value: pkgLockFile
5635
+ }
5636
+ ]
5637
+ }
5638
+ }
5597
5639
  };
5598
5640
  pkgList.push(pkg);
5641
+ if (libData.type === "Direct") {
5642
+ rootList.push(pkg);
5643
+ }
5644
+ const dependsOn = [];
5645
+ if (libData.dependencies) {
5646
+ for (const adep of Object.keys(libData.dependencies)) {
5647
+ const adpurl = new PackageURL(
5648
+ "nuget",
5649
+ "",
5650
+ adep,
5651
+ libData.dependencies[adep],
5652
+ null,
5653
+ null
5654
+ ).toString();
5655
+ dependsOn.push(decodeURIComponent(adpurl));
5656
+ }
5657
+ }
5658
+ dependenciesList.push({
5659
+ ref: decodeURIComponent(purl),
5660
+ dependsOn
5661
+ });
5599
5662
  }
5600
5663
  }
5601
- return pkgList;
5664
+ return {
5665
+ pkgList,
5666
+ dependenciesList,
5667
+ rootList
5668
+ };
5602
5669
  };
5603
5670
 
5604
5671
  export const parsePaketLockData = async function (paketLockData, pkgLockFile) {
package/utils.test.js CHANGED
@@ -1333,16 +1333,82 @@ test("parse project.assets.json", async () => {
1333
1333
  });
1334
1334
 
1335
1335
  test("parse packages.lock.json", async () => {
1336
- expect(await parseCsPkgLockData(null)).toEqual([]);
1337
- const dep_list = await parseCsPkgLockData(
1338
- readFileSync("./test/data/packages.lock.json", { encoding: "utf-8" })
1336
+ expect(await parseCsPkgLockData(null)).toEqual({
1337
+ dependenciesList: [],
1338
+ pkgList: [],
1339
+ rootList: []
1340
+ });
1341
+ let dep_list = await parseCsPkgLockData(
1342
+ readFileSync("./test/data/packages.lock.json", { encoding: "utf-8" }),
1343
+ "./test/data/packages.lock.json"
1339
1344
  );
1340
- expect(dep_list.length).toEqual(14);
1341
- expect(dep_list[0]).toEqual({
1345
+ expect(dep_list["pkgList"].length).toEqual(14);
1346
+ expect(dep_list["pkgList"][0]).toEqual({
1342
1347
  group: "",
1343
1348
  name: "Antlr",
1344
- version: "3.5.0.2"
1349
+ version: "3.5.0.2",
1350
+ purl: "pkg:nuget/Antlr@3.5.0.2",
1351
+ "bom-ref": "pkg:nuget/Antlr@3.5.0.2",
1352
+ _integrity:
1353
+ "sha512-CSfrVuDVMx3OrQhT84zed+tOdM1clljyRLWWlQM22fJsmG836RVDGQlE6tzysXh8X8p9UjkHbLr6OqEIVhtdEA==",
1354
+ properties: [{ name: "SrcFile", value: "./test/data/packages.lock.json" }],
1355
+ evidence: {
1356
+ identity: {
1357
+ field: "purl",
1358
+ confidence: 1,
1359
+ methods: [
1360
+ {
1361
+ technique: "manifest-analysis",
1362
+ confidence: 1,
1363
+ value: "./test/data/packages.lock.json"
1364
+ }
1365
+ ]
1366
+ }
1367
+ }
1368
+ });
1369
+ dep_list = await parseCsPkgLockData(
1370
+ readFileSync("./test/data/packages2.lock.json", { encoding: "utf-8" }),
1371
+ "./test/data/packages2.lock.json"
1372
+ );
1373
+ expect(dep_list["pkgList"].length).toEqual(34);
1374
+ expect(dep_list["dependenciesList"].length).toEqual(34);
1375
+ expect(dep_list["pkgList"][0]).toEqual({
1376
+ group: "",
1377
+ name: "McMaster.Extensions.Hosting.CommandLine",
1378
+ version: "4.0.1",
1379
+ purl: "pkg:nuget/McMaster.Extensions.Hosting.CommandLine@4.0.1",
1380
+ "bom-ref": "pkg:nuget/McMaster.Extensions.Hosting.CommandLine@4.0.1",
1381
+ _integrity:
1382
+ "sha512-pZJF/zeXT3OC+3GUNO9ZicpCO9I7wYLmj0E2qPR8CRA6iUs0kGu6SCkmraB1sITx4elcVjMLiZDGMsBVMqaPhg==",
1383
+ properties: [{ name: "SrcFile", value: "./test/data/packages2.lock.json" }],
1384
+ evidence: {
1385
+ identity: {
1386
+ field: "purl",
1387
+ confidence: 1,
1388
+ methods: [
1389
+ {
1390
+ technique: "manifest-analysis",
1391
+ confidence: 1,
1392
+ value: "./test/data/packages2.lock.json"
1393
+ }
1394
+ ]
1395
+ }
1396
+ }
1345
1397
  });
1398
+ expect(dep_list["dependenciesList"][0]).toEqual({
1399
+ ref: "pkg:nuget/McMaster.Extensions.Hosting.CommandLine@4.0.1",
1400
+ dependsOn: [
1401
+ "pkg:nuget/McMaster.Extensions.CommandLineUtils@4.0.1",
1402
+ "pkg:nuget/Microsoft.Extensions.Hosting.Abstractions@6.0.0",
1403
+ "pkg:nuget/Microsoft.Extensions.Logging.Abstractions@6.0.0"
1404
+ ]
1405
+ });
1406
+ dep_list = await parseCsPkgLockData(
1407
+ readFileSync("./test/data/packages3.lock.json", { encoding: "utf-8" }),
1408
+ "./test/data/packages3.lock.json"
1409
+ );
1410
+ expect(dep_list["pkgList"].length).toEqual(15);
1411
+ expect(dep_list["dependenciesList"].length).toEqual(15);
1346
1412
  });
1347
1413
 
1348
1414
  test("parse paket.lock", async () => {