@cyclonedx/cdxgen 9.9.6 → 9.9.8

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
@@ -27,7 +27,7 @@ Most SBOM tools are like barcode scanners. They can scan a few package manifest
27
27
  | Go | binary, go.mod, go.sum, Gopkg.lock | Yes except binary | Yes |
28
28
  | Ruby | Gemfile.lock, gemspec | Only for Gemfile.lock | |
29
29
  | Rust | binary, Cargo.toml, Cargo.lock | Only for Cargo.lock | |
30
- | .Net | .csproj, packages.config, project.assets.json [3], packages.lock.json, .nupkg, paket.lock | Only for project.assets.json, packages.lock.json, paket.lock | |
30
+ | .Net | .csproj, .vbproj, .fsproj, packages.config, project.assets.json [3], packages.lock.json, .nupkg, paket.lock | Only for project.assets.json, packages.lock.json, paket.lock | |
31
31
  | Dart | pubspec.lock, pubspec.yaml | Only for pubspec.lock | |
32
32
  | Haskell | cabal.project.freeze | Yes | |
33
33
  | Elixir | mix.lock | Yes | |
@@ -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
 
package/binary.js CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  import { join, dirname, basename } from "node:path";
10
10
  import { spawnSync } from "node:child_process";
11
11
  import { PackageURL } from "packageurl-js";
12
- import { DEBUG_MODE, findLicenseId } from "./utils.js";
12
+ import { DEBUG_MODE, TIMEOUT_MS, findLicenseId } from "./utils.js";
13
13
 
14
14
  import { fileURLToPath } from "node:url";
15
15
 
@@ -24,7 +24,7 @@ const isWin = _platform() === "win32";
24
24
  let platform = _platform();
25
25
  let extn = "";
26
26
  let pluginsBinSuffix = "";
27
- if (platform == "win32") {
27
+ if (platform === "win32") {
28
28
  platform = "windows";
29
29
  extn = ".exe";
30
30
  }
@@ -36,6 +36,9 @@ switch (arch) {
36
36
  break;
37
37
  case "x64":
38
38
  arch = "amd64";
39
+ if (platform === "windows") {
40
+ pluginsBinSuffix = "-windows-amd64";
41
+ }
39
42
  break;
40
43
  case "arm64":
41
44
  pluginsBinSuffix = "-arm64";
@@ -165,7 +168,21 @@ if (existsSync(join(CDXGEN_PLUGINS_DIR, "osquery"))) {
165
168
  } else if (process.env.OSQUERY_CMD) {
166
169
  OSQUERY_BIN = process.env.OSQUERY_CMD;
167
170
  }
171
+ let DOSAI_BIN = null;
172
+ if (existsSync(join(CDXGEN_PLUGINS_DIR, "dosai"))) {
173
+ if (platform === "darwin") {
174
+ platform = "osx";
175
+ }
176
+ DOSAI_BIN = join(
177
+ CDXGEN_PLUGINS_DIR,
178
+ "dosai",
179
+ "dosai-" + platform + "-" + arch + extn
180
+ );
181
+ } else if (process.env.DOSAI_CMD) {
182
+ DOSAI_BIN = process.env.DOSAI_CMD;
183
+ }
168
184
 
185
+ // Keep this list updated every year
169
186
  const OS_DISTRO_ALIAS = {
170
187
  "ubuntu-4.10": "warty",
171
188
  "ubuntu-5.04": "hoary",
@@ -692,3 +709,36 @@ export const executeOsQuery = (query) => {
692
709
  }
693
710
  return undefined;
694
711
  };
712
+
713
+ /**
714
+ * Method to execute dosai to create slices for dotnet
715
+ *
716
+ * @param {string} src
717
+ * @param {string} slicesFile
718
+ * @returns boolean
719
+ */
720
+ export const getDotnetSlices = (src, slicesFile) => {
721
+ if (!DOSAI_BIN) {
722
+ return false;
723
+ }
724
+ const args = ["methods", "--path", src, "--o", slicesFile];
725
+ if (DEBUG_MODE) {
726
+ console.log("Executing", DOSAI_BIN, args.join(" "));
727
+ }
728
+ const result = spawnSync(DOSAI_BIN, args, {
729
+ encoding: "utf-8",
730
+ timeout: TIMEOUT_MS,
731
+ cwd: src
732
+ });
733
+ if (result.status !== 0 || result.error) {
734
+ if (DEBUG_MODE && result.error) {
735
+ if (result.stderr) {
736
+ console.error(result.stdout, result.stderr);
737
+ } else {
738
+ console.log("Check if dosai plugin was installed successfully.");
739
+ }
740
+ }
741
+ return false;
742
+ }
743
+ return true;
744
+ };
package/evinser.js CHANGED
@@ -244,7 +244,9 @@ export const createSlice = (
244
244
  args.push(path.resolve(filePath));
245
245
  const result = executeAtom(filePath, args);
246
246
  if (!result || !fs.existsSync(slicesFile)) {
247
- console.warn(`Unable to generate ${sliceType} slice using atom.`);
247
+ console.warn(
248
+ `Unable to generate ${sliceType} slice using atom. Check if this is a supported language.`
249
+ );
248
250
  console.log(
249
251
  "Set the environment variable CDXGEN_DEBUG_MODE=debug to troubleshoot."
250
252
  );
package/index.js CHANGED
@@ -106,7 +106,9 @@ import {
106
106
  getNugetMetadata,
107
107
  frameworksList,
108
108
  parseContainerFile,
109
- parseBitbucketPipelinesFile
109
+ parseBitbucketPipelinesFile,
110
+ getPyMetadata,
111
+ addEvidenceForDotnet
110
112
  } from "./utils.js";
111
113
  import { spawnSync } from "node:child_process";
112
114
  import { fileURLToPath } from "node:url";
@@ -130,7 +132,8 @@ import {
130
132
  getGoBuildInfo,
131
133
  getCargoAuditableInfo,
132
134
  executeOsQuery,
133
- getOSPackages
135
+ getOSPackages,
136
+ getDotnetSlices
134
137
  } from "./binary.js";
135
138
 
136
139
  const isWin = _platform() === "win32";
@@ -2575,6 +2578,9 @@ export const createPythonBom = async (path, options) => {
2575
2578
  if (tempDir && tempDir.startsWith(tmpdir()) && rmSync) {
2576
2579
  rmSync(tempDir, { recursive: true, force: true });
2577
2580
  }
2581
+ if (FETCH_LICENSE) {
2582
+ pkgList = await getPyMetadata(pkgList, false);
2583
+ }
2578
2584
  return buildBomNSData(options, pkgList, "pypi", {
2579
2585
  allImports,
2580
2586
  src: path,
@@ -4198,11 +4204,17 @@ export const createCsharpBom = async (
4198
4204
  let manifestFiles = [];
4199
4205
  let pkgData = undefined;
4200
4206
  let dependencies = [];
4201
- const csProjFiles = getAllFiles(
4207
+ let csProjFiles = getAllFiles(
4202
4208
  path,
4203
4209
  (options.multiProject ? "**/" : "") + "*.csproj",
4204
4210
  options
4205
4211
  );
4212
+ csProjFiles = csProjFiles.concat(
4213
+ getAllFiles(path, (options.multiProject ? "**/" : "") + "*.vbproj", options)
4214
+ );
4215
+ csProjFiles = csProjFiles.concat(
4216
+ getAllFiles(path, (options.multiProject ? "**/" : "") + "*.fsproj", options)
4217
+ );
4206
4218
  const pkgConfigFiles = getAllFiles(
4207
4219
  path,
4208
4220
  (options.multiProject ? "**/" : "") + "packages.config",
@@ -4249,7 +4261,7 @@ export const createCsharpBom = async (
4249
4261
  console.log(`Parsing ${af}`);
4250
4262
  }
4251
4263
  pkgData = readFileSync(af, { encoding: "utf-8" });
4252
- let results = await parseCsProjAssetsData(pkgData);
4264
+ let results = await parseCsProjAssetsData(pkgData, af);
4253
4265
  let deps = results["dependenciesList"];
4254
4266
  let dlist = results["pkgList"];
4255
4267
  if (dlist && dlist.length) {
@@ -4301,7 +4313,7 @@ export const createCsharpBom = async (
4301
4313
  if (csProjData.charCodeAt(0) === 0xfeff) {
4302
4314
  csProjData = csProjData.slice(1);
4303
4315
  }
4304
- const dlist = await parseCsProjData(csProjData);
4316
+ const dlist = await parseCsProjData(csProjData, f);
4305
4317
  if (dlist && dlist.length) {
4306
4318
  pkgList = pkgList.concat(dlist);
4307
4319
  }
@@ -4332,6 +4344,22 @@ export const createCsharpBom = async (
4332
4344
  if (pkgList.length) {
4333
4345
  dependencies = mergeDependencies(dependencies, [], parentComponent);
4334
4346
  pkgList = trimComponents(pkgList, "json");
4347
+ // Perform deep analysis using dosai
4348
+ if (options.deep) {
4349
+ const slicesFile = resolve(
4350
+ options.depsSlicesFile || join(tmpdir(), "dosai.json")
4351
+ );
4352
+ // Create the slices file if it doesn't exist
4353
+ if (!existsSync(slicesFile)) {
4354
+ const sliceResult = getDotnetSlices(resolve(path), resolve(slicesFile));
4355
+ if (!sliceResult && DEBUG_MODE) {
4356
+ console.log(
4357
+ "Slicing with dosai was unsuccessful. Check the errors reported in the logs above."
4358
+ );
4359
+ }
4360
+ }
4361
+ pkgList = addEvidenceForDotnet(pkgList, slicesFile, options);
4362
+ }
4335
4363
  }
4336
4364
  if (FETCH_LICENSE) {
4337
4365
  const retMap = await getNugetMetadata(pkgList, dependencies);
@@ -5113,11 +5141,17 @@ export const createXBom = async (path, options) => {
5113
5141
  }
5114
5142
 
5115
5143
  // .Net
5116
- const csProjFiles = getAllFiles(
5144
+ let csProjFiles = getAllFiles(
5117
5145
  path,
5118
5146
  (options.multiProject ? "**/" : "") + "*.csproj",
5119
5147
  options
5120
5148
  );
5149
+ csProjFiles = csProjFiles.concat(
5150
+ getAllFiles(path, (options.multiProject ? "**/" : "") + "*.vbproj", options)
5151
+ );
5152
+ csProjFiles = csProjFiles.concat(
5153
+ getAllFiles(path, (options.multiProject ? "**/" : "") + "*.fsproj", options)
5154
+ );
5121
5155
  if (csProjFiles.length) {
5122
5156
  return await createCsharpBom(path, options);
5123
5157
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyclonedx/cdxgen",
3
- "version": "9.9.6",
3
+ "version": "9.9.8",
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,17 +55,17 @@
55
55
  "url": "https://github.com/cyclonedx/cdxgen/issues"
56
56
  },
57
57
  "dependencies": {
58
- "@babel/parser": "^7.23.5",
59
- "@babel/traverse": "^7.23.5",
58
+ "@babel/parser": "^7.23.6",
59
+ "@babel/traverse": "^7.23.6",
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
64
  "edn-data": "1.1.1",
65
- "find-up": "^6.3.0",
65
+ "find-up": "6.3.0",
66
66
  "glob": "^10.3.10",
67
67
  "global-agent": "^3.0.0",
68
- "got": "^13.0.0",
68
+ "got": "13.0.0",
69
69
  "iconv-lite": "^0.6.3",
70
70
  "js-yaml": "^4.1.0",
71
71
  "jws": "^4.0.0",
@@ -84,14 +84,15 @@
84
84
  },
85
85
  "optionalDependencies": {
86
86
  "@appthreat/atom": "1.7.2",
87
- "@cyclonedx/cdxgen-plugins-bin": "^1.4.0",
88
- "@cyclonedx/cdxgen-plugins-bin-arm64": "^1.4.0",
89
- "@cyclonedx/cdxgen-plugins-bin-ppc64": "^1.4.0",
87
+ "@cyclonedx/cdxgen-plugins-bin": "^1.5.4",
88
+ "@cyclonedx/cdxgen-plugins-bin-windows-amd64": "^1.5.4",
89
+ "@cyclonedx/cdxgen-plugins-bin-arm64": "^1.5.4",
90
+ "@cyclonedx/cdxgen-plugins-bin-ppc64": "^1.5.4",
90
91
  "body-parser": "^1.20.2",
91
92
  "compression": "^1.7.4",
92
93
  "connect": "^3.7.0",
93
94
  "jsonata": "^2.0.3",
94
- "sequelize": "^6.35.1",
95
+ "sequelize": "^6.35.2",
95
96
  "sqlite3": "^5.1.6"
96
97
  },
97
98
  "files": [
@@ -102,10 +103,10 @@
102
103
  "devDependencies": {
103
104
  "caxa": "^3.0.1",
104
105
  "docsify-cli": "^4.4.4",
105
- "eslint": "^8.54.0",
106
- "eslint-config-prettier": "^9.0.0",
106
+ "eslint": "^8.55.0",
107
+ "eslint-config-prettier": "^9.1.0",
107
108
  "eslint-plugin-prettier": "^5.0.1",
108
109
  "jest": "^29.7.0",
109
- "prettier": "3.1.0"
110
+ "prettier": "3.1.1"
110
111
  }
111
112
  }
package/utils.js CHANGED
@@ -19,8 +19,7 @@ import {
19
19
  readFileSync,
20
20
  rmSync,
21
21
  unlinkSync,
22
- writeFileSync,
23
- readdirSync
22
+ writeFileSync
24
23
  } from "node:fs";
25
24
  import got from "got";
26
25
  import Arborist from "@npmcli/arborist";
@@ -5190,7 +5189,7 @@ export const parseCsPkgData = async function (pkgData) {
5190
5189
  return pkgList;
5191
5190
  };
5192
5191
 
5193
- export const parseCsProjData = async function (csProjData) {
5192
+ export const parseCsProjData = async function (csProjData, projFile) {
5194
5193
  const pkgList = [];
5195
5194
  if (!csProjData) {
5196
5195
  return pkgList;
@@ -5219,6 +5218,27 @@ export const parseCsProjData = async function (csProjData) {
5219
5218
  }
5220
5219
  pkg.name = pref.Include;
5221
5220
  pkg.version = pref.Version;
5221
+ if (projFile) {
5222
+ pkg.properties = [
5223
+ {
5224
+ name: "SrcFile",
5225
+ value: projFile
5226
+ }
5227
+ ];
5228
+ pkg.evidence = {
5229
+ identity: {
5230
+ field: "purl",
5231
+ confidence: 0.7,
5232
+ methods: [
5233
+ {
5234
+ technique: "manifest-analysis",
5235
+ confidence: 0.7,
5236
+ value: projFile
5237
+ }
5238
+ ]
5239
+ }
5240
+ };
5241
+ }
5222
5242
  pkgList.push(pkg);
5223
5243
  }
5224
5244
  // .net framework use Reference
@@ -5233,6 +5253,27 @@ export const parseCsProjData = async function (csProjData) {
5233
5253
  if (incParts.length > 1 && incParts[1].includes("Version")) {
5234
5254
  pkg.version = incParts[1].replace("Version=", "").trim();
5235
5255
  }
5256
+ if (projFile) {
5257
+ pkg.properties = [
5258
+ {
5259
+ name: "SrcFile",
5260
+ value: projFile
5261
+ }
5262
+ ];
5263
+ pkg.evidence = {
5264
+ identity: {
5265
+ field: "purl",
5266
+ confidence: 0.7,
5267
+ methods: [
5268
+ {
5269
+ technique: "manifest-analysis",
5270
+ confidence: 0.7,
5271
+ value: projFile
5272
+ }
5273
+ ]
5274
+ }
5275
+ };
5276
+ }
5236
5277
  pkgList.push(pkg);
5237
5278
  }
5238
5279
  }
@@ -5240,7 +5281,10 @@ export const parseCsProjData = async function (csProjData) {
5240
5281
  return pkgList;
5241
5282
  };
5242
5283
 
5243
- export const parseCsProjAssetsData = async function (csProjData) {
5284
+ export const parseCsProjAssetsData = async function (
5285
+ csProjData,
5286
+ assetsJsonFile
5287
+ ) {
5244
5288
  // extract name, operator, version from .NET package representation
5245
5289
  // like "NLog >= 4.5.0"
5246
5290
  function extractNameOperatorVersion(inputStr) {
@@ -5357,6 +5401,43 @@ export const parseCsProjAssetsData = async function (csProjData) {
5357
5401
  } else if (lib[rootDep].sha256) {
5358
5402
  pkg["_integrity"] = "sha256-" + lib[rootDep].sha256;
5359
5403
  }
5404
+ if (lib[rootDep].files && Array.isArray(lib[rootDep].files)) {
5405
+ const dllFiles = new Set();
5406
+ lib[rootDep].files.forEach((f) => {
5407
+ if (
5408
+ f.endsWith(".dll") ||
5409
+ f.endsWith(".exe") ||
5410
+ f.endsWith(".so")
5411
+ ) {
5412
+ dllFiles.add(basename(f));
5413
+ }
5414
+ });
5415
+ pkg.properties = [
5416
+ {
5417
+ name: "SrcFile",
5418
+ value: assetsJsonFile
5419
+ },
5420
+ {
5421
+ name: "PackageFiles",
5422
+ value: Array.from(dllFiles).join(", ")
5423
+ }
5424
+ ];
5425
+ }
5426
+ }
5427
+ if (assetsJsonFile) {
5428
+ pkg.evidence = {
5429
+ identity: {
5430
+ field: "purl",
5431
+ confidence: 1,
5432
+ methods: [
5433
+ {
5434
+ technique: "manifest-analysis",
5435
+ confidence: 1,
5436
+ value: assetsJsonFile
5437
+ }
5438
+ ]
5439
+ }
5440
+ };
5360
5441
  }
5361
5442
  pkgList.push(pkg);
5362
5443
  pkgNameVersionMap[name + framework] = version;
@@ -6683,30 +6764,13 @@ export const encodeForPurl = (s) => {
6683
6764
  export const getPomPropertiesFromMavenDir = function (mavenDir) {
6684
6765
  let pomProperties = {};
6685
6766
  if (existsSync(mavenDir) && lstatSync(mavenDir).isDirectory()) {
6686
- let mavenDirEntries = readdirSync(mavenDir, { withFileTypes: true });
6687
- mavenDirEntries.forEach((mavenDirEntry) => {
6688
- if (mavenDirEntry.isDirectory()) {
6689
- let groupDirEntries = readdirSync(
6690
- join(mavenDirEntry.path, mavenDirEntry.name),
6691
- { withFileTypes: true }
6692
- );
6693
- groupDirEntries.forEach((groupDirEntry) => {
6694
- if (groupDirEntry.isDirectory()) {
6695
- let pomPropertiesFile = join(
6696
- groupDirEntry.path,
6697
- groupDirEntry.name,
6698
- "pom.properties"
6699
- );
6700
- if (existsSync(pomPropertiesFile)) {
6701
- const pomPropertiesString = readFileSync(pomPropertiesFile, {
6702
- encoding: "utf-8"
6703
- });
6704
- pomProperties = parsePomProperties(pomPropertiesString);
6705
- }
6706
- }
6707
- });
6708
- }
6709
- });
6767
+ const pomPropertiesFiles = getAllFiles(mavenDir, "**/pom.properties");
6768
+ if (pomPropertiesFiles && pomPropertiesFiles.length) {
6769
+ const pomPropertiesString = readFileSync(pomPropertiesFiles[0], {
6770
+ encoding: "utf-8"
6771
+ });
6772
+ pomProperties = parsePomProperties(pomPropertiesString);
6773
+ }
6710
6774
  }
6711
6775
  return pomProperties;
6712
6776
  };
@@ -6845,17 +6909,17 @@ export const extractJarArchive = function (
6845
6909
  if (!name || !version || name === "" || version === "") {
6846
6910
  confidence = 0.5;
6847
6911
  technique = "filename";
6912
+ name = jarname.replace(".jar", "");
6848
6913
  const tmpA = jarname.split("-");
6849
6914
  if (tmpA && tmpA.length > 1) {
6850
6915
  const lastPart = tmpA[tmpA.length - 1];
6851
- if (!version || version === "") {
6852
- version = lastPart.replace(".jar", "");
6853
- }
6854
- if (!name || name === "") {
6916
+ // Bug #768. Check if we have any number before simplifying the name.
6917
+ if (/\d/.test(lastPart)) {
6918
+ if (!version || version === "") {
6919
+ version = lastPart.replace(".jar", "");
6920
+ }
6855
6921
  name = jarname.replace("-" + lastPart, "") || "";
6856
6922
  }
6857
- } else {
6858
- name = jarname.replace(".jar", "");
6859
6923
  }
6860
6924
  }
6861
6925
  if (
@@ -7226,6 +7290,7 @@ export const executeAtom = (src, args) => {
7226
7290
  let cwd =
7227
7291
  existsSync(src) && lstatSync(src).isDirectory() ? src : dirname(src);
7228
7292
  let ATOM_BIN = getAtomCommand();
7293
+ let isSupported = true;
7229
7294
  if (ATOM_BIN.includes(" ")) {
7230
7295
  const tmpA = ATOM_BIN.split(" ");
7231
7296
  if (tmpA && tmpA.length > 1) {
@@ -7278,6 +7343,12 @@ export const executeAtom = (src, args) => {
7278
7343
  );
7279
7344
  }
7280
7345
  }
7346
+ if (result.stdout) {
7347
+ if (result.stdout.includes("No language frontend supported for language")) {
7348
+ console.log("This language is not yet supported by atom.");
7349
+ isSupported = false;
7350
+ }
7351
+ }
7281
7352
  if (DEBUG_MODE) {
7282
7353
  if (result.stdout) {
7283
7354
  console.log(result.stdout);
@@ -7286,7 +7357,7 @@ export const executeAtom = (src, args) => {
7286
7357
  console.log(result.stderr);
7287
7358
  }
7288
7359
  }
7289
- return !result.error;
7360
+ return isSupported && !result.error;
7290
7361
  };
7291
7362
 
7292
7363
  /**
@@ -8754,3 +8825,103 @@ export const getNugetMetadata = async function (
8754
8825
  dependencies: newDependencies
8755
8826
  };
8756
8827
  };
8828
+
8829
+ export const addEvidenceForDotnet = (pkgList, slicesFile) => {
8830
+ // We need two datastructures.
8831
+ // dll to purl mapping from the pkgList
8832
+ // purl to occurrences list using the slicesFile
8833
+ if (!slicesFile || !existsSync(slicesFile)) {
8834
+ return pkgList;
8835
+ }
8836
+ const pkgFilePurlMap = {};
8837
+ const purlLocationMap = {};
8838
+ const purlModulesMap = {};
8839
+ const purlMethodsMap = {};
8840
+ for (const apkg of pkgList) {
8841
+ if (apkg.properties && Array.isArray(apkg.properties)) {
8842
+ apkg.properties
8843
+ .filter((p) => p.name === "PackageFiles")
8844
+ .forEach((aprop) => {
8845
+ if (aprop.value) {
8846
+ const tmpA = aprop.value.split(", ");
8847
+ if (tmpA && tmpA.length) {
8848
+ tmpA.forEach((dllFile) => {
8849
+ pkgFilePurlMap[dllFile] = apkg.purl;
8850
+ });
8851
+ }
8852
+ }
8853
+ });
8854
+ }
8855
+ }
8856
+ const slicesData = JSON.parse(readFileSync(slicesFile, "utf-8"));
8857
+ if (slicesData && Object.keys(slicesData)) {
8858
+ if (slicesData.Dependencies) {
8859
+ for (const adep of slicesData.Dependencies) {
8860
+ if (
8861
+ adep.Module &&
8862
+ adep.Module.endsWith(".dll") &&
8863
+ pkgFilePurlMap[adep.Module]
8864
+ ) {
8865
+ const modPurl = pkgFilePurlMap[adep.Module];
8866
+ if (!purlLocationMap[modPurl]) {
8867
+ purlLocationMap[modPurl] = new Set();
8868
+ }
8869
+ purlLocationMap[modPurl].add(`${adep.Path}#${adep.LineNumber}`);
8870
+ }
8871
+ }
8872
+ }
8873
+ if (slicesData.MethodCalls) {
8874
+ for (const amethodCall of slicesData.MethodCalls) {
8875
+ if (
8876
+ amethodCall.Module &&
8877
+ amethodCall.Module.endsWith(".dll") &&
8878
+ pkgFilePurlMap[amethodCall.Module]
8879
+ ) {
8880
+ const modPurl = pkgFilePurlMap[amethodCall.Module];
8881
+ if (!purlLocationMap[modPurl]) {
8882
+ purlLocationMap[modPurl] = new Set();
8883
+ }
8884
+ if (!purlModulesMap[modPurl]) {
8885
+ purlModulesMap[modPurl] = new Set();
8886
+ }
8887
+ if (!purlMethodsMap[modPurl]) {
8888
+ purlMethodsMap[modPurl] = new Set();
8889
+ }
8890
+ purlLocationMap[modPurl].add(
8891
+ `${amethodCall.Path}#${amethodCall.LineNumber}`
8892
+ );
8893
+ purlModulesMap[modPurl].add(amethodCall.ClassName);
8894
+ purlMethodsMap[modPurl].add(amethodCall.CalledMethod);
8895
+ }
8896
+ }
8897
+ }
8898
+ }
8899
+ if (Object.keys(purlLocationMap).length) {
8900
+ for (const apkg of pkgList) {
8901
+ if (purlLocationMap[apkg.purl]) {
8902
+ const locationOccurrences = Array.from(
8903
+ purlLocationMap[apkg.purl]
8904
+ ).sort();
8905
+ // Add the occurrences evidence
8906
+ apkg.evidence.occurrences = locationOccurrences.map((l) => ({
8907
+ location: l
8908
+ }));
8909
+ }
8910
+ // Add the imported modules to properties
8911
+ if (purlModulesMap[apkg.purl]) {
8912
+ apkg.properties.push({
8913
+ name: "ImportedModules",
8914
+ value: Array.from(purlModulesMap[apkg.purl]).sort().join(", ")
8915
+ });
8916
+ }
8917
+ // Add the called methods to properties
8918
+ if (purlMethodsMap[apkg.purl]) {
8919
+ apkg.properties.push({
8920
+ name: "CalledMethods",
8921
+ value: Array.from(purlMethodsMap[apkg.purl]).sort().join(", ")
8922
+ });
8923
+ }
8924
+ }
8925
+ }
8926
+ return pkgList;
8927
+ };
package/utils.test.js CHANGED
@@ -1272,8 +1272,9 @@ test("parse project.assets.json", async () => {
1272
1272
  dependenciesList: [],
1273
1273
  pkgList: []
1274
1274
  });
1275
- const dep_list = await parseCsProjAssetsData(
1276
- readFileSync("./test/data/project.assets.json", { encoding: "utf-8" })
1275
+ let dep_list = await parseCsProjAssetsData(
1276
+ readFileSync("./test/data/project.assets.json", { encoding: "utf-8" }),
1277
+ "./test/data/project.assets.json"
1277
1278
  );
1278
1279
  expect(dep_list["pkgList"].length).toEqual(302);
1279
1280
  expect(dep_list["pkgList"][0]).toEqual({
@@ -1309,6 +1310,26 @@ test("parse project.assets.json", async () => {
1309
1310
  ],
1310
1311
  ref: "pkg:nuget/Castle.Core.Tests@0.0.0"
1311
1312
  });
1313
+ dep_list = await parseCsProjAssetsData(
1314
+ readFileSync("./test/data/project.assets1.json", { encoding: "utf-8" }),
1315
+ "./test/data/project.assets1.json"
1316
+ );
1317
+ expect(dep_list["pkgList"].length).toEqual(43);
1318
+ expect(dep_list["pkgList"][0]).toEqual({
1319
+ "bom-ref": "pkg:nuget/Podcast.Server@1.0.0",
1320
+ purl: "pkg:nuget/Podcast.Server@1.0.0",
1321
+ group: "",
1322
+ name: "Podcast.Server",
1323
+ type: "application",
1324
+ version: "1.0.0"
1325
+ });
1326
+ /*
1327
+ const pkgList = addEvidenceForDotnet(
1328
+ dep_list.pkgList,
1329
+ "./test/data/dosai-methods.json"
1330
+ );
1331
+ expect(pkgList.length).toEqual(43);
1332
+ */
1312
1333
  });
1313
1334
 
1314
1335
  test("parse packages.lock.json", async () => {
@@ -1725,8 +1746,8 @@ test("parsePkgLock v3", async () => {
1725
1746
  projectName: "cdxgen"
1726
1747
  });
1727
1748
  deps = parsedList.pkgList;
1728
- expect(deps.length).toEqual(1204);
1729
- expect(parsedList.dependenciesList.length).toEqual(1204);
1749
+ expect(deps.length).toEqual(1205);
1750
+ expect(parsedList.dependenciesList.length).toEqual(1205);
1730
1751
  });
1731
1752
 
1732
1753
  test("parseBowerJson", async () => {