@cyclonedx/cdxgen 11.1.0 → 11.1.2

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
@@ -519,6 +519,10 @@ pnpm run lint
519
519
  pnpm test
520
520
  ```
521
521
 
522
+ ## Sponsors
523
+
524
+ <img src="./docs/_media/LevoLogo-LightBg.jpg" width="200" height="auto">
525
+
522
526
  <!-- LINK LABELS -->
523
527
  <!-- Badges -->
524
528
 
package/bin/cdxgen.js CHANGED
@@ -167,6 +167,7 @@ const args = yargs(hideBin(process.argv))
167
167
  })
168
168
  .option("install-deps", {
169
169
  type: "boolean",
170
+ default: true,
170
171
  description:
171
172
  "Install dependencies automatically for some projects. Defaults to true but disabled for containers and oci scans. Use --no-install-deps to disable this feature.",
172
173
  })
@@ -506,7 +507,6 @@ const applyAdvancedOptions = (options) => {
506
507
  options.installDeps = true;
507
508
  break;
508
509
  default:
509
- options.installDeps = true;
510
510
  break;
511
511
  }
512
512
  // When the user specifies source-code-analysis as a technique, then enable deep and evidence mode.
package/lib/cli/index.js CHANGED
@@ -135,6 +135,7 @@ import {
135
135
  parsePkgJson,
136
136
  parsePkgLock,
137
137
  parsePnpmLock,
138
+ parsePnpmWorkspace,
138
139
  parsePom,
139
140
  parsePrivadoFile,
140
141
  parsePubLockData,
@@ -2310,6 +2311,11 @@ export async function createNodejsBom(path, options) {
2310
2311
  `${options.multiProject ? "**/" : ""}pnpm-lock.yaml`,
2311
2312
  options,
2312
2313
  );
2314
+ const pnpmWorkspaceFiles = getAllFiles(
2315
+ path,
2316
+ `${options.multiProject ? "**/" : ""}pnpm-workspace.yaml`,
2317
+ options,
2318
+ );
2313
2319
  const minJsFiles = getAllFiles(
2314
2320
  path,
2315
2321
  `${options.multiProject ? "**/" : ""}*min.js`,
@@ -2479,6 +2485,67 @@ export async function createNodejsBom(path, options) {
2479
2485
  isPackageManagerAllowed("pnpm", ["npm", "yarn", "rush"], options)
2480
2486
  ) {
2481
2487
  manifestFiles = manifestFiles.concat(pnpmLockFiles);
2488
+ const workspacePackages = [];
2489
+ const workspaceSrcFiles = {};
2490
+ const workspaceDirectDeps = {};
2491
+ const depsWorkspaceRefs = {};
2492
+ let workspaceCatalogs = {};
2493
+ let workspaceWarningShown = false;
2494
+ // Is this a pnpm workspace?
2495
+ for (const f of pnpmWorkspaceFiles) {
2496
+ if (DEBUG_MODE) {
2497
+ console.log(`Parsing workspace definition ${f}`);
2498
+ }
2499
+ const workspaceObj = parsePnpmWorkspace(f);
2500
+ if (workspaceObj?.packages) {
2501
+ // We need the precise purl for all workspace packages and their direct dependencies
2502
+ for (const awp of workspaceObj.packages) {
2503
+ const wpkgJsonFiles = getAllFiles(awp, "**/package.json", options);
2504
+ if (!wpkgJsonFiles?.length) {
2505
+ if (!workspaceWarningShown) {
2506
+ workspaceWarningShown = true;
2507
+ console.log(
2508
+ `Unable to find any package.json files belonging to the workspace '${awp}' referred in ${f}. To improve SBOM precision, run cdxgen from the directory containing the complete source code.`,
2509
+ );
2510
+ }
2511
+ continue;
2512
+ }
2513
+ for (const apj of wpkgJsonFiles) {
2514
+ const pkgData = JSON.parse(readFileSync(apj, "utf-8"));
2515
+ if (pkgData?.name) {
2516
+ let workspaceRef = `pkg:npm/${pkgData.name}`;
2517
+ if (pkgData?.version) {
2518
+ workspaceRef = `${workspaceRef}@${pkgData.version}`;
2519
+ }
2520
+ // Track all workspace purls
2521
+ workspacePackages.push(workspaceRef);
2522
+ workspaceSrcFiles[workspaceRef] = apj;
2523
+ // Track the direct dependencies of each workspace and workspace refs for each direct deps.
2524
+ const allDeps = {
2525
+ ...(pkgData.dependencies || {}),
2526
+ ...(pkgData.devDependencies || {}),
2527
+ ...(pkgData.peerDependencies || {}),
2528
+ };
2529
+ for (const adep of Object.keys(allDeps)) {
2530
+ if (!workspaceDirectDeps[workspaceRef]) {
2531
+ workspaceDirectDeps[workspaceRef] = new Set();
2532
+ }
2533
+ const apkgRef = `pkg:npm/${adep}`;
2534
+ workspaceDirectDeps[workspaceRef].add(apkgRef);
2535
+ if (!depsWorkspaceRefs[apkgRef]) {
2536
+ depsWorkspaceRefs[apkgRef] = [];
2537
+ }
2538
+ depsWorkspaceRefs[apkgRef].push(workspaceRef);
2539
+ }
2540
+ }
2541
+ }
2542
+ }
2543
+ }
2544
+ workspaceCatalogs = {
2545
+ ...workspaceCatalogs,
2546
+ ...(workspaceObj.catalogs || {}),
2547
+ };
2548
+ }
2482
2549
  for (const f of pnpmLockFiles) {
2483
2550
  if (DEBUG_MODE) {
2484
2551
  console.log(`Parsing ${f}`);
@@ -2527,7 +2594,15 @@ export async function createNodejsBom(path, options) {
2527
2594
  }
2528
2595
  }
2529
2596
  // Parse the pnpm file
2530
- const parsedList = await parsePnpmLock(f, parentComponent);
2597
+ const parsedList = await parsePnpmLock(
2598
+ f,
2599
+ parentComponent,
2600
+ workspacePackages,
2601
+ workspaceSrcFiles,
2602
+ workspaceCatalogs,
2603
+ workspaceDirectDeps,
2604
+ depsWorkspaceRefs,
2605
+ );
2531
2606
  const dlist = parsedList.pkgList;
2532
2607
  if (dlist?.length) {
2533
2608
  pkgList = pkgList.concat(dlist);
@@ -5911,7 +5986,11 @@ export function trimComponents(components) {
5911
5986
  const keyCache = {};
5912
5987
  const filteredComponents = [];
5913
5988
  for (const comp of components) {
5914
- const key = comp.purl || comp["bom-ref"] || comp.name + comp.version;
5989
+ const key = (
5990
+ comp.purl ||
5991
+ comp["bom-ref"] ||
5992
+ comp.name + comp.version
5993
+ ).toLowerCase();
5915
5994
  if (!keyCache[key]) {
5916
5995
  keyCache[key] = comp;
5917
5996
  } else {
@@ -1017,10 +1017,7 @@ export function isFilterableType(language, userDefinedTypesMap, typeFullName) {
1017
1017
  return true;
1018
1018
  }
1019
1019
  }
1020
- if (userDefinedTypesMap[typeFullName]) {
1021
- return true;
1022
- }
1023
- return false;
1020
+ return !!userDefinedTypesMap[typeFullName];
1024
1021
  }
1025
1022
 
1026
1023
  /**
@@ -23,6 +23,7 @@ import path, {
23
23
  extname,
24
24
  join,
25
25
  resolve,
26
+ relative,
26
27
  sep as _sep,
27
28
  } from "node:path";
28
29
  import process from "node:process";
@@ -975,12 +976,12 @@ export async function parsePkgJson(pkgJsonFile, simple = false) {
975
976
  try {
976
977
  const pkgData = JSON.parse(readFileSync(pkgJsonFile, "utf8"));
977
978
  const pkgIdentifier = parsePackageJsonName(pkgData.name);
978
- const name = pkgIdentifier.fullName || pkgData.name;
979
+ let name = pkgIdentifier.fullName || pkgData.name;
979
980
  if (DEBUG_MODE && !name && !pkgJsonFile.includes("node_modules")) {
981
+ name = dirname(pkgJsonFile);
980
982
  console.log(
981
- `${pkgJsonFile} doesn't contain the package name. Consider using the 'npm init' command to create a valid package.json file for this project.`,
983
+ `${pkgJsonFile} doesn't contain the package name. Consider using the 'npm init' command to create a valid package.json file for this project. Assuming the name as '${name}'.`,
982
984
  );
983
- return pkgList;
984
985
  }
985
986
  const group = pkgIdentifier.scope || "";
986
987
  const purl = new PackageURL(
@@ -1967,6 +1968,59 @@ function _markTreeOptional(
1967
1968
  }
1968
1969
  }
1969
1970
 
1971
+ function _setTreeWorkspaceRef(
1972
+ dependenciesMap,
1973
+ depref,
1974
+ pkgRefMap,
1975
+ wref,
1976
+ wsrcFile,
1977
+ depsWorkspaceRefs,
1978
+ ) {
1979
+ for (const dref of dependenciesMap[depref] || []) {
1980
+ const addedMap = {};
1981
+ const depPkg = pkgRefMap[dref];
1982
+ if (!depPkg) {
1983
+ continue;
1984
+ }
1985
+ const wsprops = depPkg.properties.filter(
1986
+ (p) => p.name === "internal:workspaceRef",
1987
+ );
1988
+ if (wsprops.length) {
1989
+ continue;
1990
+ }
1991
+ depPkg.properties = depPkg.properties || [];
1992
+ for (const prop of depPkg.properties) {
1993
+ addedMap[prop.value] = true;
1994
+ }
1995
+ if (!addedMap[wref]) {
1996
+ depPkg.properties.push({
1997
+ name: "internal:workspaceRef",
1998
+ value: wref,
1999
+ });
2000
+ addedMap[wref] = true;
2001
+ }
2002
+ if (wsrcFile && !addedMap[wsrcFile]) {
2003
+ depPkg.properties.push({
2004
+ name: "internal:workspaceSrcFile",
2005
+ value: wsrcFile,
2006
+ });
2007
+ addedMap[wsrcFile] = true;
2008
+ }
2009
+ depsWorkspaceRefs[dref] = depsWorkspaceRefs[dref] || [];
2010
+ depsWorkspaceRefs[dref] = depsWorkspaceRefs[dref].concat(
2011
+ dependenciesMap[depref] || [],
2012
+ );
2013
+ _setTreeWorkspaceRef(
2014
+ dependenciesMap,
2015
+ dref,
2016
+ pkgRefMap,
2017
+ wref,
2018
+ wsrcFile,
2019
+ depsWorkspaceRefs,
2020
+ );
2021
+ }
2022
+ }
2023
+
1970
2024
  async function getVersionNumPnpm(depPkg, relativePath) {
1971
2025
  let version = depPkg;
1972
2026
  if (typeof version === "object" && depPkg.version) {
@@ -2003,13 +2057,48 @@ async function getVersionNumPnpm(depPkg, relativePath) {
2003
2057
  return version;
2004
2058
  }
2005
2059
 
2060
+ /**
2061
+ * Parse pnpm workspace file
2062
+ *
2063
+ * @param {string} workspaceFile pnpm-workspace.yaml
2064
+ * @returns {object} Object containing packages and catalogs
2065
+ */
2066
+ export function parsePnpmWorkspace(workspaceFile) {
2067
+ const workspaceData = readFileSync(workspaceFile, "utf-8");
2068
+ const yamlObj = _load(workspaceData);
2069
+ if (!yamlObj) {
2070
+ return {};
2071
+ }
2072
+ const packages = (yamlObj.packages || [])
2073
+ .filter((n) => !/^(!|\.|__)/.test(n))
2074
+ .map((n) => n.replaceAll("/**", "").replaceAll("/*", ""));
2075
+ const catalogs = yamlObj.catalog || {};
2076
+ return {
2077
+ packages,
2078
+ catalogs,
2079
+ };
2080
+ }
2081
+
2006
2082
  /**
2007
2083
  * Parse nodejs pnpm lock file
2008
2084
  *
2009
2085
  * @param {string} pnpmLock pnpm-lock.yaml file
2010
- * @param {object} parentComponent parent component
2086
+ * @param {Object} parentComponent parent component
2087
+ * @param {Array[String]} workspacePackages Workspace packages
2088
+ * @param {Object} workspaceSrcFiles Workspace package.json files
2089
+ * @param {Object} workspaceCatalogs Workspace catalogs
2090
+ * @param {Object} workspaceDirectDeps Direct dependencies of each workspace
2091
+ * @param {Object} depsWorkspaceRefs Workspace references for each dependency
2011
2092
  */
2012
- export async function parsePnpmLock(pnpmLock, parentComponent = null) {
2093
+ export async function parsePnpmLock(
2094
+ pnpmLock,
2095
+ parentComponent = null,
2096
+ workspacePackages = [],
2097
+ workspaceSrcFiles = {},
2098
+ _workspaceCatalogs = {},
2099
+ _workspaceDirectDeps = {},
2100
+ depsWorkspaceRefs = {},
2101
+ ) {
2013
2102
  let pkgList = [];
2014
2103
  const dependenciesList = [];
2015
2104
  // For lockfile >= 9, we need to track dev and optional packages manually
@@ -2022,6 +2111,16 @@ export async function parsePnpmLock(pnpmLock, parentComponent = null) {
2022
2111
  let lockfileVersion = 0;
2023
2112
  const parentSubComponents = [];
2024
2113
  const srcFilesMap = {};
2114
+ const workspacePackageNames = {};
2115
+ const pkgRefMap = {};
2116
+ // Track references to packages that are directly installed from github.com
2117
+ const gitPkgRefs = {};
2118
+ // pnpm could refer to packages from git sources
2119
+ const githubServerHost = process.env.CDXGEN_GIT_HOST || "github.com";
2120
+ // Convert workspace package names to an object to help with the lookup
2121
+ for (const w of workspacePackages || []) {
2122
+ workspacePackageNames[w] = true;
2123
+ }
2025
2124
  if (parentComponent?.name) {
2026
2125
  ppurl =
2027
2126
  parentComponent.purl ||
@@ -2061,6 +2160,10 @@ export async function parsePnpmLock(pnpmLock, parentComponent = null) {
2061
2160
  lockfileVersion >= 6
2062
2161
  ? yamlObj.importers["."]?.optionalDependencies || {}
2063
2162
  : {};
2163
+ const rootPeerDeps =
2164
+ lockfileVersion >= 6
2165
+ ? yamlObj.importers["."]?.peerDependencies || {}
2166
+ : {};
2064
2167
  const ddeplist = new Set();
2065
2168
  // Find the root optional dependencies
2066
2169
  for (const rdk of Object.keys(rootDevDeps)) {
@@ -2075,7 +2178,7 @@ export async function parsePnpmLock(pnpmLock, parentComponent = null) {
2075
2178
  ).toString();
2076
2179
  possibleOptionalDeps[decodeURIComponent(dpurl)] = true;
2077
2180
  }
2078
- for (const rdk of Object.keys(rootOptionalDeps)) {
2181
+ for (const rdk of Object.keys({ ...rootOptionalDeps, ...rootPeerDeps })) {
2079
2182
  const version = await getVersionNumPnpm(rootOptionalDeps[rdk]);
2080
2183
  const dpurl = new PackageURL(
2081
2184
  "npm",
@@ -2117,6 +2220,8 @@ export async function parsePnpmLock(pnpmLock, parentComponent = null) {
2117
2220
  const componentOptionalDeps =
2118
2221
  yamlObj?.importers[importedComponentName]["optionalDependencies"] ||
2119
2222
  {};
2223
+ const componentPeerDeps =
2224
+ yamlObj?.importers[importedComponentName]["peerDependencies"] || {};
2120
2225
  let compPurl = undefined;
2121
2226
  let pkgSrcFile = undefined;
2122
2227
  let fallbackMode = true;
@@ -2136,14 +2241,39 @@ export async function parsePnpmLock(pnpmLock, parentComponent = null) {
2136
2241
  const compRef = decodeURIComponent(compPurl);
2137
2242
  // Add this package to the root dependency list and parent component
2138
2243
  ddeplist.add(compRef);
2139
- parentSubComponents.push({
2244
+ const psObj = {
2140
2245
  group: importedComponentObj[0]?.group,
2141
2246
  name: importedComponentObj[0]?.name,
2142
2247
  version,
2143
2248
  type: "application",
2144
2249
  purl: compPurl,
2145
2250
  "bom-ref": compRef,
2146
- });
2251
+ };
2252
+ const purlNoVersion = new PackageURL(
2253
+ "npm",
2254
+ importedComponentObj[0]?.group,
2255
+ importedComponentObj[0]?.name,
2256
+ version,
2257
+ ).toString();
2258
+ const matchRef =
2259
+ workspacePackageNames[decodeURIComponent(purlNoVersion)] ||
2260
+ workspacePackageNames[compRef];
2261
+ const matchSrcFile =
2262
+ workspaceSrcFiles[decodeURIComponent(purlNoVersion)] ||
2263
+ workspaceSrcFiles[compRef];
2264
+ if (matchRef || matchSrcFile) {
2265
+ psObj.properties = [
2266
+ { name: "internal:is_workspace", value: "true" },
2267
+ ];
2268
+ }
2269
+ if (matchSrcFile) {
2270
+ psObj.properties.push({ name: "SrcFile", value: matchSrcFile });
2271
+ psObj.properties.push({
2272
+ name: "internal:virtual_path",
2273
+ value: relative(dirname(pnpmLock), dirname(matchSrcFile)),
2274
+ });
2275
+ }
2276
+ parentSubComponents.push(psObj);
2147
2277
  fallbackMode = false;
2148
2278
  }
2149
2279
  }
@@ -2167,20 +2297,37 @@ export async function parsePnpmLock(pnpmLock, parentComponent = null) {
2167
2297
  // Find the component optional dependencies
2168
2298
  const comDepList = new Set();
2169
2299
  for (const cdk of Object.keys(componentDeps)) {
2300
+ let name = cdk;
2301
+ let group = "";
2302
+ let version;
2170
2303
  const versionObj = componentDeps[cdk];
2171
- const version = await getVersionNumPnpm(
2172
- versionObj,
2173
- importedComponentName,
2174
- );
2304
+ if (versionObj?.version?.startsWith(githubServerHost)) {
2305
+ const parts = versionObj.version.split("/");
2306
+ version = parts.pop();
2307
+ name = parts.pop();
2308
+ group = parts.pop();
2309
+ if (group === githubServerHost) {
2310
+ group = "";
2311
+ } else {
2312
+ group = `@${group}`;
2313
+ }
2314
+ gitPkgRefs[versionObj.version] = { group, name, version };
2315
+ } else {
2316
+ version = await getVersionNumPnpm(
2317
+ versionObj,
2318
+ importedComponentName,
2319
+ );
2320
+ }
2175
2321
  const dpurl = new PackageURL(
2176
2322
  "npm",
2177
- "",
2178
- cdk,
2323
+ group,
2324
+ name,
2179
2325
  version,
2180
2326
  null,
2181
2327
  null,
2182
2328
  ).toString();
2183
2329
  const depRef = decodeURIComponent(dpurl);
2330
+ // This is a definite dependency of this component
2184
2331
  comDepList.add(depRef);
2185
2332
  possibleOptionalDeps[depRef] = false;
2186
2333
  // Track the package.json files
@@ -2191,10 +2338,6 @@ export async function parsePnpmLock(pnpmLock, parentComponent = null) {
2191
2338
  srcFilesMap[depRef].push(pkgSrcFile);
2192
2339
  }
2193
2340
  }
2194
- dependenciesList.push({
2195
- ref: decodeURIComponent(compPurl),
2196
- dependsOn: [...comDepList].sort(),
2197
- });
2198
2341
  for (const cdk of Object.keys(componentDevDeps)) {
2199
2342
  const version = await getVersionNumPnpm(componentDevDeps[cdk]);
2200
2343
  const dpurl = new PackageURL(
@@ -2205,9 +2348,15 @@ export async function parsePnpmLock(pnpmLock, parentComponent = null) {
2205
2348
  null,
2206
2349
  null,
2207
2350
  ).toString();
2208
- possibleOptionalDeps[decodeURIComponent(dpurl)] = true;
2209
- }
2210
- for (const cdk of Object.keys(componentOptionalDeps)) {
2351
+ const devDpRef = decodeURIComponent(dpurl);
2352
+ possibleOptionalDeps[devDpRef] = true;
2353
+ // This is also a dependency of this component
2354
+ comDepList.add(devDpRef);
2355
+ }
2356
+ for (const cdk of Object.keys({
2357
+ ...componentOptionalDeps,
2358
+ ...componentPeerDeps,
2359
+ })) {
2211
2360
  const version = await getVersionNumPnpm(componentOptionalDeps[cdk]);
2212
2361
  const dpurl = new PackageURL(
2213
2362
  "npm",
@@ -2219,6 +2368,10 @@ export async function parsePnpmLock(pnpmLock, parentComponent = null) {
2219
2368
  ).toString();
2220
2369
  possibleOptionalDeps[decodeURIComponent(dpurl)] = true;
2221
2370
  }
2371
+ dependenciesList.push({
2372
+ ref: decodeURIComponent(compPurl),
2373
+ dependsOn: [...comDepList].sort(),
2374
+ });
2222
2375
  }
2223
2376
  dependenciesList.push({
2224
2377
  ref: decodeURIComponent(ppurl),
@@ -2356,12 +2509,28 @@ export async function parsePnpmLock(pnpmLock, parentComponent = null) {
2356
2509
  }
2357
2510
  // Let's have some warnings till we fully support pnpm 8
2358
2511
  if (!name) {
2359
- console.warn(
2360
- `Unable to extract name and version for string ${pkgKeys[k]}`,
2361
- parts,
2362
- fullName,
2363
- );
2364
- continue;
2512
+ if (gitPkgRefs[fullName]) {
2513
+ name = gitPkgRefs[fullName].name;
2514
+ group = gitPkgRefs[fullName].group;
2515
+ version = gitPkgRefs[fullName].version;
2516
+ } else if (parts?.length >= 3 && parts[0] === githubServerHost) {
2517
+ version = parts[parts.length - 1];
2518
+ name = parts[parts.length - 2];
2519
+ group = parts.length === 4 ? `@${parts[parts.length - 3]}` : "";
2520
+ gitPkgRefs[fullName] = {
2521
+ group,
2522
+ name,
2523
+ version,
2524
+ purl: new PackageURL("npm", group, name, version).toString(),
2525
+ };
2526
+ } else {
2527
+ console.warn(
2528
+ `Unable to extract name and version for string ${pkgKeys[k]}`,
2529
+ parts,
2530
+ fullName,
2531
+ );
2532
+ continue;
2533
+ }
2365
2534
  }
2366
2535
  if (name.indexOf("file:") !== 0) {
2367
2536
  const purlString = new PackageURL(
@@ -2384,7 +2553,7 @@ export async function parsePnpmLock(pnpmLock, parentComponent = null) {
2384
2553
  if (dpkgName.endsWith("-cjs")) {
2385
2554
  const tmpB = vers.split("@");
2386
2555
  if (tmpB.length > 1) {
2387
- dpkgName = tmpB[0];
2556
+ dpkgName = tmpB[0].replace(/^\//, "");
2388
2557
  vers = tmpB[1];
2389
2558
  }
2390
2559
  }
@@ -2394,7 +2563,9 @@ export async function parsePnpmLock(pnpmLock, parentComponent = null) {
2394
2563
  // With overrides version could be like this: @nolyfill/side-channel@1.0.29
2395
2564
  if (vers.includes("@")) {
2396
2565
  const overrideVersion = vers.split("@").pop();
2397
- dpkgName = vers.replace(`@${overrideVersion}`, "");
2566
+ dpkgName = vers
2567
+ .replace(`@${overrideVersion}`, "")
2568
+ .replace(/^\//, "");
2398
2569
  vers = overrideVersion;
2399
2570
  }
2400
2571
  const dpurlString = new PackageURL(
@@ -2423,6 +2594,7 @@ export async function parsePnpmLock(pnpmLock, parentComponent = null) {
2423
2594
  if (!dependenciesMap[bomRef]) {
2424
2595
  dependenciesMap[bomRef] = [];
2425
2596
  }
2597
+
2426
2598
  dependenciesMap[bomRef] = dependenciesMap[bomRef].concat(deplist);
2427
2599
  const properties = [
2428
2600
  {
@@ -2450,12 +2622,75 @@ export async function parsePnpmLock(pnpmLock, parentComponent = null) {
2450
2622
  });
2451
2623
  }
2452
2624
  }
2453
- pkgList.push({
2625
+ const purlNoVersion = new PackageURL("npm", group, name).toString();
2626
+ let packageType = "library";
2627
+ const theBomRef = decodeURIComponent(purlString);
2628
+ if (
2629
+ workspacePackageNames[decodeURIComponent(purlNoVersion)] ||
2630
+ workspacePackageNames[theBomRef]
2631
+ ) {
2632
+ properties.push({
2633
+ name: "internal:is_workspace",
2634
+ value: "true",
2635
+ });
2636
+ packageType = "application";
2637
+ const wsSrcFile =
2638
+ workspaceSrcFiles[decodeURIComponent(purlNoVersion)] ||
2639
+ workspaceSrcFiles[theBomRef];
2640
+ if (wsSrcFile) {
2641
+ properties.push({
2642
+ name: "internal:virtual_path",
2643
+ value: relative(dirname(pnpmLock), dirname(wsSrcFile)),
2644
+ });
2645
+ }
2646
+ }
2647
+ // Capture all the workspaces that directly depend on this package and their source file
2648
+ for (const wref of Array.from(
2649
+ depsWorkspaceRefs[purlNoVersion] ||
2650
+ depsWorkspaceRefs[purlString] ||
2651
+ [],
2652
+ )) {
2653
+ // This cycle shouldn't happen, but we can't be sure
2654
+ if (wref === purlString) {
2655
+ continue;
2656
+ }
2657
+ properties.push({
2658
+ name: "internal:workspaceRef",
2659
+ value: wref,
2660
+ });
2661
+ if (workspaceSrcFiles[wref]) {
2662
+ properties.push({
2663
+ name: "internal:workspaceSrcFile",
2664
+ value: workspaceSrcFiles[wref],
2665
+ });
2666
+ }
2667
+ // Add workspaceRef to the dependent components as well
2668
+ for (const dref of dependenciesMap[theBomRef]) {
2669
+ if (!depsWorkspaceRefs[dref]) {
2670
+ depsWorkspaceRefs[dref] = [];
2671
+ }
2672
+ if (!depsWorkspaceRefs[dref].includes(wref)) {
2673
+ depsWorkspaceRefs[dref].push(wref);
2674
+ }
2675
+ if (dependenciesMap[dref]) {
2676
+ for (const l2ref of dependenciesMap[dref]) {
2677
+ if (!depsWorkspaceRefs[l2ref]) {
2678
+ depsWorkspaceRefs[l2ref] = [];
2679
+ }
2680
+ if (!depsWorkspaceRefs[l2ref].includes(wref)) {
2681
+ depsWorkspaceRefs[l2ref].push(wref);
2682
+ }
2683
+ }
2684
+ }
2685
+ }
2686
+ }
2687
+ const thePkg = {
2454
2688
  group: group,
2455
2689
  name: name,
2456
2690
  version: version,
2457
2691
  purl: purlString,
2458
- "bom-ref": decodeURIComponent(purlString),
2692
+ "bom-ref": theBomRef,
2693
+ type: packageType,
2459
2694
  scope,
2460
2695
  _integrity: integrity,
2461
2696
  properties,
@@ -2472,7 +2707,12 @@ export async function parsePnpmLock(pnpmLock, parentComponent = null) {
2472
2707
  ],
2473
2708
  },
2474
2709
  },
2475
- });
2710
+ };
2711
+ // Don't add internal workspace packages to the components list
2712
+ if (thePkg.type !== "application") {
2713
+ pkgList.push(thePkg);
2714
+ }
2715
+ pkgRefMap[thePkg["bom-ref"]] = thePkg;
2476
2716
  }
2477
2717
  }
2478
2718
  }
@@ -2524,6 +2764,55 @@ export async function parsePnpmLock(pnpmLock, parentComponent = null) {
2524
2764
  if (requiredDependencies[apkg["bom-ref"]]) {
2525
2765
  apkg.scope = undefined;
2526
2766
  }
2767
+ // There are no workspaces so exit early
2768
+ if (!Object.keys(workspacePackageNames).length) {
2769
+ continue;
2770
+ }
2771
+ const purlNoVersion = decodeURIComponent(
2772
+ new PackageURL("npm", apkg.group, apkg.name).toString(),
2773
+ );
2774
+ const wsRefs =
2775
+ depsWorkspaceRefs[apkg["bom-ref"]] || depsWorkspaceRefs[purlNoVersion];
2776
+ // There is a workspace reference
2777
+ if (wsRefs?.length) {
2778
+ const wsprops = apkg.properties.filter(
2779
+ (p) => p.name === "internal:workspaceRef",
2780
+ );
2781
+ // workspace properties are already set.
2782
+ if (wsprops.length) {
2783
+ continue;
2784
+ }
2785
+ for (const wref of wsRefs) {
2786
+ // Such a cycle should never happen, but we can't sure
2787
+ if (wref === apkg["bom-ref"]) {
2788
+ continue;
2789
+ }
2790
+ apkg.properties.push({
2791
+ name: "internal:workspaceRef",
2792
+ value: wref,
2793
+ });
2794
+ const purlObj = PackageURL.fromString(apkg.purl);
2795
+ purlObj.version = undefined;
2796
+ const wrefNoVersion = decodeURIComponent(purlObj.toString());
2797
+ const wsrcFile =
2798
+ workspaceSrcFiles[wref] || workspaceSrcFiles[wrefNoVersion];
2799
+ if (wsrcFile) {
2800
+ apkg.properties.push({
2801
+ name: "internal:workspaceSrcFile",
2802
+ value: wsrcFile,
2803
+ });
2804
+ }
2805
+ // Repeat for the children
2806
+ _setTreeWorkspaceRef(
2807
+ dependenciesMap,
2808
+ apkg["bom-ref"],
2809
+ pkgRefMap,
2810
+ wref,
2811
+ wsrcFile,
2812
+ depsWorkspaceRefs,
2813
+ );
2814
+ }
2815
+ }
2527
2816
  }
2528
2817
 
2529
2818
  if (Object.keys(dependenciesMap).length) {
@@ -4449,6 +4738,7 @@ export async function parsePyLockData(lockData, lockFile, pyProjectFile) {
4449
4738
  const dependenciesList = [];
4450
4739
  const depsMap = {};
4451
4740
  const existingPkgMap = {};
4741
+ const pkgBomRefMap = {};
4452
4742
  let directDepsKeys = {};
4453
4743
  let groupDepsKeys = {};
4454
4744
  let parentComponent;
@@ -4503,6 +4793,20 @@ export async function parsePyLockData(lockData, lockFile, pyProjectFile) {
4503
4793
  // Nested workspace is not supported
4504
4794
  const wcompMap = parsePyProjectTomlFile(awpyproj);
4505
4795
  if (wcompMap?.parentComponent) {
4796
+ wcompMap.parentComponent.properties =
4797
+ wcompMap.parentComponent.properties || [];
4798
+ wcompMap.parentComponent.properties.push({
4799
+ name: "internal:is_workspace",
4800
+ value: "true",
4801
+ });
4802
+ wcompMap.parentComponent.properties.push({
4803
+ name: "SrcFile",
4804
+ value: awpyproj,
4805
+ });
4806
+ wcompMap.parentComponent.properties.push({
4807
+ name: "internal:virtual_path",
4808
+ value: relative(dirname(lockFile), dirname(awpyproj)),
4809
+ });
4506
4810
  workspaceComponentMap[wcompMap.parentComponent.name] =
4507
4811
  wcompMap.parentComponent;
4508
4812
  workspacePyProjMap[wcompMap.parentComponent.name] = awpyproj;
@@ -4703,7 +5007,12 @@ export async function parsePyLockData(lockData, lockFile, pyProjectFile) {
4703
5007
  }
4704
5008
  // This would help the lookup
4705
5009
  existingPkgMap[pkg.name.toLowerCase()] = pkg["bom-ref"];
4706
- pkgList.push(pkg);
5010
+ pkgBomRefMap[pkg["bom-ref"]] = pkg;
5011
+ // Do not repeat workspace components again under components
5012
+ // This will reduce false positives, when a downstream tool attempts to analyze all components
5013
+ if (pkg.type !== "application") {
5014
+ pkgList.push(pkg);
5015
+ }
4707
5016
  if (!depsMap[pkg["bom-ref"]]) {
4708
5017
  depsMap[pkg["bom-ref"]] = new Set();
4709
5018
  }
@@ -4716,34 +5025,138 @@ export async function parsePyLockData(lockData, lockFile, pyProjectFile) {
4716
5025
  depsMap[pkgParentRef].add(pkg["bom-ref"]);
4717
5026
  }
4718
5027
  }
4719
- if (apkg.dependencies) {
5028
+ let optionalDependencies = [];
5029
+ let devDependencies = [];
5030
+ if (apkg["dev-dependencies"]) {
5031
+ for (const agroup of Object.keys(apkg["dev-dependencies"])) {
5032
+ devDependencies = devDependencies.concat(
5033
+ apkg["dev-dependencies"][agroup],
5034
+ );
5035
+ }
5036
+ }
5037
+ if (apkg["optional-dependencies"]) {
5038
+ for (const agroup of Object.keys(apkg["optional-dependencies"])) {
5039
+ optionalDependencies = optionalDependencies.concat(
5040
+ apkg["optional-dependencies"][agroup],
5041
+ );
5042
+ }
5043
+ }
5044
+ if (
5045
+ apkg.dependencies ||
5046
+ devDependencies.length ||
5047
+ optionalDependencies.length
5048
+ ) {
4720
5049
  if (Array.isArray(apkg.dependencies)) {
4721
5050
  // pdm.lock files
4722
- for (const apkgDep of apkg.dependencies) {
5051
+ let allDeps = apkg.dependencies;
5052
+ allDeps = allDeps.concat(devDependencies);
5053
+ allDeps = allDeps.concat(optionalDependencies);
5054
+ for (const apkgDep of allDeps) {
4723
5055
  // Example: "msgpack>=0.5.2"
4724
5056
  const nameStr =
4725
5057
  apkgDep.name || apkgDep.split(/(==|<=|~=|>=)/)[0].split(" ")[0];
4726
5058
  depsMap[pkg["bom-ref"]].add(existingPkgMap[nameStr] || nameStr);
5059
+ // Propagate the workspace properties to the child components
5060
+ if (
5061
+ existingPkgMap[nameStr] &&
5062
+ pkgBomRefMap[existingPkgMap[nameStr]]
5063
+ ) {
5064
+ const dependentPkg = pkgBomRefMap[existingPkgMap[nameStr]];
5065
+ dependentPkg.properties = dependentPkg.properties || [];
5066
+ const addedValue = {};
5067
+ // Is the parent a workspace
5068
+ if (workspaceComponentMap[pkg.name]) {
5069
+ dependentPkg.properties.push({
5070
+ name: "internal:workspaceRef",
5071
+ value: pkg["bom-ref"],
5072
+ });
5073
+ dependentPkg.properties.push({
5074
+ name: "internal:workspaceSrcFile",
5075
+ value: workspaceRefPyProjMap[pkg["bom-ref"]],
5076
+ });
5077
+ addedValue[pkg["bom-ref"]] = true;
5078
+ }
5079
+ for (const pprop of pkg.properties) {
5080
+ if (
5081
+ pprop.name.startsWith("internal:workspace") &&
5082
+ !addedValue[pprop.value]
5083
+ ) {
5084
+ dependentPkg.properties.push(pprop);
5085
+ addedValue[pprop.value] = true;
5086
+ }
5087
+ }
5088
+ }
4727
5089
  }
4728
- } else if (Object.keys(apkg.dependencies).length) {
5090
+ } else if (pkg.dependencies && Object.keys(apkg.dependencies).length) {
4729
5091
  for (const apkgDep of Object.keys(apkg.dependencies)) {
4730
5092
  depsMap[pkg["bom-ref"]].add(existingPkgMap[apkgDep] || apkgDep);
4731
5093
  }
4732
5094
  }
4733
5095
  }
4734
5096
  }
4735
- pkgList = await getPyMetadata(pkgList, false);
4736
5097
  for (const key of Object.keys(depsMap)) {
4737
5098
  const dependsOnList = new Set();
5099
+ const parentPkg = pkgBomRefMap[key];
4738
5100
  for (const adep of Array.from(depsMap[key])) {
5101
+ let depRef;
4739
5102
  if (adep.startsWith("pkg:")) {
4740
- dependsOnList.add(adep);
5103
+ depRef = adep;
4741
5104
  } else if (existingPkgMap[adep]) {
4742
- dependsOnList.add(existingPkgMap[adep]);
5105
+ depRef = existingPkgMap[adep];
4743
5106
  } else if (existingPkgMap[`py${adep}`]) {
4744
- dependsOnList.add(existingPkgMap[`py${adep}`]);
5107
+ depRef = existingPkgMap[`py${adep}`];
4745
5108
  } else if (existingPkgMap[adep.replace(/-/g, "_")]) {
4746
- dependsOnList.add(existingPkgMap[adep.replace(/-/g, "_")]);
5109
+ depRef = existingPkgMap[adep.replace(/-/g, "_")];
5110
+ }
5111
+ if (depRef) {
5112
+ dependsOnList.add(depRef);
5113
+ // We need to propagate the workspace properties from the parent
5114
+ const dependentPkg = pkgBomRefMap[depRef];
5115
+ dependentPkg.properties = dependentPkg.properties || [];
5116
+ const addedValue = {};
5117
+ for (const p of dependentPkg.properties) {
5118
+ if (p.name.startsWith("internal:workspace")) {
5119
+ addedValue[p.value] = true;
5120
+ }
5121
+ }
5122
+ for (const pprop of parentPkg.properties) {
5123
+ if (
5124
+ pprop.name.startsWith("internal:workspace") &&
5125
+ !addedValue[pprop.value]
5126
+ ) {
5127
+ dependentPkg.properties.push(pprop);
5128
+ addedValue[pprop.value] = true;
5129
+ } else if (pprop.name === "internal:is_workspace") {
5130
+ dependentPkg.properties.push({
5131
+ name: "internal:workspaceRef",
5132
+ value: parentPkg["bom-ref"],
5133
+ });
5134
+ dependentPkg.properties.push({
5135
+ name: "internal:workspaceSrcFile",
5136
+ value: workspaceRefPyProjMap[parentPkg["bom-ref"]],
5137
+ });
5138
+ addedValue[parentPkg["bom-ref"]] = true;
5139
+ addedValue[workspaceRefPyProjMap[parentPkg["bom-ref"]]] = true;
5140
+ const childDeps = depsMap[dependentPkg["bom-ref"]];
5141
+ for (const childRef of childDeps) {
5142
+ if (!childRef.startsWith("pkg:")) {
5143
+ continue;
5144
+ }
5145
+ const childPkg = pkgBomRefMap[childRef];
5146
+ if (childPkg) {
5147
+ childPkg.properties = childPkg.properties || [];
5148
+ childPkg.properties.push({
5149
+ name: "internal:workspaceRef",
5150
+ value: parentPkg["bom-ref"],
5151
+ });
5152
+ childPkg.properties.push({
5153
+ name: "internal:workspaceSrcFile",
5154
+ value: workspaceRefPyProjMap[parentPkg["bom-ref"]],
5155
+ });
5156
+ }
5157
+ }
5158
+ }
5159
+ }
4747
5160
  }
4748
5161
  }
4749
5162
  dependenciesList.push({
@@ -4751,6 +5164,7 @@ export async function parsePyLockData(lockData, lockFile, pyProjectFile) {
4751
5164
  dependsOn: [...dependsOnList].sort(),
4752
5165
  });
4753
5166
  }
5167
+ pkgList = await getPyMetadata(pkgList, false);
4754
5168
  return {
4755
5169
  parentComponent,
4756
5170
  pkgList,
@@ -9114,17 +9528,43 @@ export function parseCsProjAssetsData(csProjData, assetsJsonFile) {
9114
9528
  continue;
9115
9529
  }
9116
9530
  const targetNameVersion = `${nameOperatorVersion.name}/${nameOperatorVersion.version}`;
9117
-
9118
- // skip if the dep is not in the targets for whatever reason
9531
+ let nameToUse = nameOperatorVersion.name;
9532
+ // Due to the difference in casing, we might arrive this case where a simple lookup doesn't succeed.
9533
+ // Instead of skipping, let's work harder to find a match.
9119
9534
  if (!csProjData.targets[frameworkTarget][targetNameVersion]) {
9120
- continue;
9535
+ let matchFound = false;
9536
+ for (const fkeys of Object.keys(
9537
+ csProjData.targets[frameworkTarget],
9538
+ )) {
9539
+ const tmpParts = fkeys.split("/");
9540
+ const tname = tmpParts[0];
9541
+ const tversion = tmpParts[1];
9542
+ if (
9543
+ tname.toLowerCase() === nameOperatorVersion.name.toLowerCase() &&
9544
+ tversion === nameOperatorVersion.version
9545
+ ) {
9546
+ nameToUse = tname;
9547
+ matchFound = true;
9548
+ break;
9549
+ }
9550
+ }
9551
+ if (!matchFound) {
9552
+ if (DEBUG_MODE) {
9553
+ console.log(
9554
+ "Unable to match",
9555
+ dependencyName,
9556
+ "with a target name. The dependency tree will be imprecise.",
9557
+ );
9558
+ }
9559
+ continue;
9560
+ }
9121
9561
  }
9122
9562
 
9123
9563
  const dpurl = decodeURIComponent(
9124
9564
  new PackageURL(
9125
9565
  "nuget",
9126
9566
  "",
9127
- nameOperatorVersion.name,
9567
+ nameToUse,
9128
9568
  nameOperatorVersion.version,
9129
9569
  null,
9130
9570
  null,
@@ -76,6 +76,7 @@ import {
76
76
  parsePkgJson,
77
77
  parsePkgLock,
78
78
  parsePnpmLock,
79
+ parsePnpmWorkspace,
79
80
  parsePom,
80
81
  parsePrivadoFile,
81
82
  parsePubLockData,
@@ -3479,6 +3480,12 @@ test("parseSetupPyFile", async () => {
3479
3480
  ]);
3480
3481
  });
3481
3482
 
3483
+ test("parsePnpmWorkspace", async () => {
3484
+ const wobj = parsePnpmWorkspace("./test/data/pnpm_locks/pnpm-workspace.yaml");
3485
+ expect(wobj.packages.length).toEqual(31);
3486
+ expect(Object.keys(wobj.catalogs).length).toEqual(217);
3487
+ });
3488
+
3482
3489
  test("parsePnpmLock", async () => {
3483
3490
  let parsedList = await parsePnpmLock("./test/pnpm-lock.yaml");
3484
3491
  expect(parsedList.pkgList.length).toEqual(1706);
@@ -3491,6 +3498,7 @@ test("parsePnpmLock", async () => {
3491
3498
  "bom-ref": "pkg:npm/@babel/code-frame@7.10.1",
3492
3499
  purl: "pkg:npm/%40babel/code-frame@7.10.1",
3493
3500
  scope: undefined,
3501
+ type: "library",
3494
3502
  version: "7.10.1",
3495
3503
  properties: [
3496
3504
  {
@@ -3523,6 +3531,7 @@ test("parsePnpmLock", async () => {
3523
3531
  "bom-ref": "pkg:npm/@babel/code-frame@7.16.7",
3524
3532
  purl: "pkg:npm/%40babel/code-frame@7.16.7",
3525
3533
  scope: "optional",
3534
+ type: "library",
3526
3535
  version: "7.16.7",
3527
3536
  properties: [
3528
3537
  {
@@ -3554,6 +3563,7 @@ test("parsePnpmLock", async () => {
3554
3563
  "bom-ref": "pkg:npm/ansi-regex@2.1.1",
3555
3564
  purl: "pkg:npm/ansi-regex@2.1.1",
3556
3565
  scope: undefined,
3566
+ type: "library",
3557
3567
  _integrity: "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
3558
3568
  properties: [{ name: "SrcFile", value: "./test/data/pnpm-lock2.yaml" }],
3559
3569
  evidence: {
@@ -3590,6 +3600,7 @@ test("parsePnpmLock", async () => {
3590
3600
  "bom-ref": "pkg:npm/@nodelib/fs.scandir@2.1.5",
3591
3601
  purl: "pkg:npm/%40nodelib/fs.scandir@2.1.5",
3592
3602
  scope: undefined,
3603
+ type: "library",
3593
3604
  _integrity:
3594
3605
  "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
3595
3606
  properties: [{ name: "SrcFile", value: "./test/data/pnpm-lock3.yaml" }],
@@ -3625,6 +3636,7 @@ test("parsePnpmLock", async () => {
3625
3636
  "bom-ref": "pkg:npm/@babel/code-frame@7.18.6",
3626
3637
  purl: "pkg:npm/%40babel/code-frame@7.18.6",
3627
3638
  scope: "optional",
3639
+ type: "library",
3628
3640
  _integrity:
3629
3641
  "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==",
3630
3642
  properties: [{ name: "SrcFile", value: "./test/data/pnpm-lock6.yaml" }],
@@ -3649,6 +3661,7 @@ test("parsePnpmLock", async () => {
3649
3661
  "bom-ref": "pkg:npm/yargs@17.7.1",
3650
3662
  purl: "pkg:npm/yargs@17.7.1",
3651
3663
  scope: "optional",
3664
+ type: "library",
3652
3665
  _integrity:
3653
3666
  "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==",
3654
3667
  properties: [{ name: "SrcFile", value: "./test/data/pnpm-lock6.yaml" }],
@@ -3676,6 +3689,7 @@ test("parsePnpmLock", async () => {
3676
3689
  "bom-ref": "pkg:npm/@babel/code-frame@7.18.6",
3677
3690
  purl: "pkg:npm/%40babel/code-frame@7.18.6",
3678
3691
  scope: "optional",
3692
+ type: "library",
3679
3693
  _integrity:
3680
3694
  "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==",
3681
3695
  properties: [{ name: "SrcFile", value: "./test/data/pnpm-lock6a.yaml" }],
@@ -3723,9 +3737,9 @@ test("parsePnpmLock", async () => {
3723
3737
  obj["ref"] === "pkg:npm/rush/my-toolchain@latest#tools/my-toolchain",
3724
3738
  );
3725
3739
  expect(mainRootDependency["dependsOn"].length).toEqual(0);
3726
- expect(myAppRootDependency["dependsOn"].length).toEqual(2);
3727
- expect(myControlsRootDependency["dependsOn"].length).toEqual(0);
3728
- expect(myToolChainRootDependency["dependsOn"].length).toEqual(1);
3740
+ expect(myAppRootDependency["dependsOn"].length).toEqual(4);
3741
+ expect(myControlsRootDependency["dependsOn"].length).toEqual(2);
3742
+ expect(myToolChainRootDependency["dependsOn"].length).toEqual(4);
3729
3743
 
3730
3744
  parsedList = await parsePnpmLock("./test/data/pnpm-lock9a.yaml", {
3731
3745
  name: "pnpm9",
@@ -3757,6 +3771,7 @@ test("parsePnpmLock", async () => {
3757
3771
  version: "2.3.0",
3758
3772
  purl: "pkg:npm/%40ampproject/remapping@2.3.0",
3759
3773
  "bom-ref": "pkg:npm/@ampproject/remapping@2.3.0",
3774
+ type: "library",
3760
3775
  _integrity:
3761
3776
  "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
3762
3777
  properties: [{ name: "SrcFile", value: "./pnpm-lock.yaml" }],
@@ -1,11 +1,11 @@
1
1
  import { readFileSync } from "node:fs";
2
- import { dirname, join } from "node:path";
2
+ import { join } from "node:path";
3
3
  import Ajv from "ajv";
4
4
  import addFormats from "ajv-formats";
5
5
  import { PackageURL } from "packageurl-js";
6
6
  import { DEBUG_MODE, dirNameStr, isPartialTree } from "./utils.js";
7
7
 
8
- import { URL, fileURLToPath } from "node:url";
8
+ import { URL } from "node:url";
9
9
  let url = import.meta.url;
10
10
  if (!url.startsWith("file://")) {
11
11
  url = new URL(`file://${import.meta.url}`).toString();
@@ -58,7 +58,10 @@ export const validateBom = (bomJson) => {
58
58
  }
59
59
  // Deep validation tests
60
60
  return (
61
- validateMetadata(bomJson) && validatePurls(bomJson) && validateRefs(bomJson)
61
+ validateMetadata(bomJson) &&
62
+ validatePurls(bomJson) &&
63
+ validateRefs(bomJson) &&
64
+ validateProps(bomJson)
62
65
  );
63
66
  };
64
67
 
@@ -266,3 +269,61 @@ export const validateRefs = (bomJson) => {
266
269
  }
267
270
  return true;
268
271
  };
272
+
273
+ /**
274
+ * Validate the component properties
275
+ *
276
+ * @param {object} bomJson Bom json object
277
+ */
278
+ export function validateProps(bomJson) {
279
+ const errorList = [];
280
+ const warningsList = [];
281
+ let isWorkspaceMode = false;
282
+ if (bomJson?.components) {
283
+ for (const comp of bomJson.components) {
284
+ if (!["library", "framework"].includes(comp.type)) {
285
+ continue;
286
+ }
287
+ if (!comp.properties) {
288
+ warningsList.push(`${comp["bom-ref"]} lacks properties.`);
289
+ } else {
290
+ let srcFilePropFound = false;
291
+ let workspacePropFound = false;
292
+ for (const p of comp.properties) {
293
+ if (p.name === "SrcFile") {
294
+ srcFilePropFound = true;
295
+ }
296
+ if (p.name === "internal:workspaceRef") {
297
+ isWorkspaceMode = true;
298
+ workspacePropFound = true;
299
+ }
300
+ }
301
+ if (
302
+ isWorkspaceMode &&
303
+ !workspacePropFound &&
304
+ !srcFilePropFound &&
305
+ comp?.scope !== "optional"
306
+ ) {
307
+ warningsList.push(
308
+ `${comp["bom-ref"]} lacks workspace-related properties.`,
309
+ );
310
+ }
311
+ if (!srcFilePropFound) {
312
+ warningsList.push(`${comp["bom-ref"]} lacks SrcFile property.`);
313
+ }
314
+ }
315
+ if (!comp.evidence) {
316
+ warningsList.push(`${comp["bom-ref"]} lacks evidence.`);
317
+ }
318
+ }
319
+ }
320
+ if (DEBUG_MODE && warningsList.length !== 0) {
321
+ console.log("===== WARNINGS =====");
322
+ console.log(warningsList);
323
+ }
324
+ if (errorList.length !== 0) {
325
+ console.log(errorList);
326
+ return false;
327
+ }
328
+ return true;
329
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyclonedx/cdxgen",
3
- "version": "11.1.0",
3
+ "version": "11.1.2",
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>",
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../lib/cli/index.js"],"names":[],"mappings":"AAoxBA;;;;;;;;GAQG;AACH,gFAFW,MAAM,SAchB;AAuXD;;;;;;;GAOG;AACH,mCALW,MAAM,qBAiEhB;AAED;;;;;GAKG;AACH,uCAHW,MAAM;;;;EAKhB;AAED;;;;;GAKG;AACH,sCAHW,MAAM;;;;EAkBhB;AAED;;;;;GAKG;AACH,oCAHW,MAAM,8BAs7BhB;AAED;;;;;GAKG;AACH,sCAHW,MAAM,8BA0kBhB;AAED;;;;;;;;;;GAUG;AACH,+DAsEC;AAED;;;;;GAKG;AACH,sCAHW,MAAM,8BA+dhB;AAED;;;;;GAKG;AACH,kCAHW,MAAM,8BA+YhB;AAED;;;;;GAKG;AACH,oCAHW,MAAM,8BAqIhB;AAED;;;;;GAKG;AACH,oCAHW,MAAM,8BAkEhB;AAED;;;;;GAKG;AACH,mCAHW,MAAM,qBA+KhB;AAED;;;;;GAKG;AACH,uCAHW,MAAM,qBAsHhB;AAED;;;;;GAKG;AACH,uCAHW,MAAM,qBA2BhB;AAED;;;;;GAKG;AACH,sCAHW,MAAM,qBA2BhB;AAED;;;;;GAKG;AACH,sCAHW,MAAM,qBA2BhB;AAED;;;;;GAKG;AACH,0CAHW,MAAM,qBAuBhB;AAED;;;;;GAKG;AACH,mCAHW,MAAM,8BAqDhB;AAED;;;;;GAKG;AACH,uCAHW,MAAM,8BA4ChB;AAED;;;;;GAKG;AACH,oCAHW,MAAM,qBA2BhB;AAED;;;;;GAKG;AACH,qCAHW,MAAM,8BA6FhB;AAED;;;;;GAKG;AACH,iDAHW,MAAM,qBAmUhB;AAED;;;;;GAKG;AACH,mCAHW,MAAM,qBAiJhB;AAED;;;;;GAKG;AACH,oCAHW,MAAM,8BAqNhB;AAED;;;;;GAKG;AACH,sCAHW,MAAM,8BAkahB;AAED;;;;;GAKG;AACH,2CAHW,MAAM;;;;;;;;;;;;;;;;;;;;GAoChB;AAED;;;;;;;;KA+DC;AAED;;;;;;GAMG;AACH,yDAqFC;AAED;;;;;;;;;GASG;AACH,2GA6BC;AAED;;;;;GAKG;AACH,0CAHW,MAAM,EAAE,8BA2iBlB;AAED;;;;;GAKG;AACH,iCAHW,MAAM,8BAgUhB;AAED;;;;;GAKG;AACH,gCAHW,MAAM,qBAiPhB;AAED;;;;;;GAMG;AACH,wDAFY,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,SAAS,CAAC,CAwHxE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../lib/cli/index.js"],"names":[],"mappings":"AAqxBA;;;;;;;;GAQG;AACH,gFAFW,MAAM,SAchB;AAuXD;;;;;;;GAOG;AACH,mCALW,MAAM,qBAiEhB;AAED;;;;;GAKG;AACH,uCAHW,MAAM;;;;EAKhB;AAED;;;;;GAKG;AACH,sCAHW,MAAM;;;;EAkBhB;AAED;;;;;GAKG;AACH,oCAHW,MAAM,8BAs7BhB;AAED;;;;;GAKG;AACH,sCAHW,MAAM,8BAopBhB;AAED;;;;;;;;;;GAUG;AACH,+DAsEC;AAED;;;;;GAKG;AACH,sCAHW,MAAM,8BA+dhB;AAED;;;;;GAKG;AACH,kCAHW,MAAM,8BA+YhB;AAED;;;;;GAKG;AACH,oCAHW,MAAM,8BAqIhB;AAED;;;;;GAKG;AACH,oCAHW,MAAM,8BAkEhB;AAED;;;;;GAKG;AACH,mCAHW,MAAM,qBA+KhB;AAED;;;;;GAKG;AACH,uCAHW,MAAM,qBAsHhB;AAED;;;;;GAKG;AACH,uCAHW,MAAM,qBA2BhB;AAED;;;;;GAKG;AACH,sCAHW,MAAM,qBA2BhB;AAED;;;;;GAKG;AACH,sCAHW,MAAM,qBA2BhB;AAED;;;;;GAKG;AACH,0CAHW,MAAM,qBAuBhB;AAED;;;;;GAKG;AACH,mCAHW,MAAM,8BAqDhB;AAED;;;;;GAKG;AACH,uCAHW,MAAM,8BA4ChB;AAED;;;;;GAKG;AACH,oCAHW,MAAM,qBA2BhB;AAED;;;;;GAKG;AACH,qCAHW,MAAM,8BA6FhB;AAED;;;;;GAKG;AACH,iDAHW,MAAM,qBAmUhB;AAED;;;;;GAKG;AACH,mCAHW,MAAM,qBAiJhB;AAED;;;;;GAKG;AACH,oCAHW,MAAM,8BAqNhB;AAED;;;;;GAKG;AACH,sCAHW,MAAM,8BAkahB;AAED;;;;;GAKG;AACH,2CAHW,MAAM;;;;;;;;;;;;;;;;;;;;GAoChB;AAED;;;;;;;;KA+DC;AAED;;;;;;GAMG;AACH,yDAyFC;AAED;;;;;;;;;GASG;AACH,2GA6BC;AAED;;;;;GAKG;AACH,0CAHW,MAAM,EAAE,8BA2iBlB;AAED;;;;;GAKG;AACH,iCAHW,MAAM,8BAgUhB;AAED;;;;;GAKG;AACH,gCAHW,MAAM,qBAiPhB;AAED;;;;;;GAMG;AACH,wDAFY,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,SAAS,CAAC,CAwHxE"}
@@ -147,13 +147,25 @@ export function parseYarnLock(yarnLockFile: string): Promise<{
147
147
  * @param {string} swFile shrinkwrap-deps.json file
148
148
  */
149
149
  export function parseNodeShrinkwrap(swFile: string): Promise<any[]>;
150
+ /**
151
+ * Parse pnpm workspace file
152
+ *
153
+ * @param {string} workspaceFile pnpm-workspace.yaml
154
+ * @returns {object} Object containing packages and catalogs
155
+ */
156
+ export function parsePnpmWorkspace(workspaceFile: string): object;
150
157
  /**
151
158
  * Parse nodejs pnpm lock file
152
159
  *
153
160
  * @param {string} pnpmLock pnpm-lock.yaml file
154
- * @param {object} parentComponent parent component
155
- */
156
- export function parsePnpmLock(pnpmLock: string, parentComponent?: object): Promise<{
161
+ * @param {Object} parentComponent parent component
162
+ * @param {Array[String]} workspacePackages Workspace packages
163
+ * @param {Object} workspaceSrcFiles Workspace package.json files
164
+ * @param {Object} workspaceCatalogs Workspace catalogs
165
+ * @param {Object} workspaceDirectDeps Direct dependencies of each workspace
166
+ * @param {Object} depsWorkspaceRefs Workspace references for each dependency
167
+ */
168
+ export function parsePnpmLock(pnpmLock: string, parentComponent?: any, workspacePackages?: any, workspaceSrcFiles?: any, _workspaceCatalogs?: {}, _workspaceDirectDeps?: {}, depsWorkspaceRefs?: any): Promise<{
157
169
  pkgList?: undefined;
158
170
  dependenciesList?: undefined;
159
171
  parentSubComponents?: undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../lib/helpers/utils.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../lib/helpers/utils.js"],"names":[],"mappings":"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"}
@@ -1,3 +1,9 @@
1
+ /**
2
+ * Validate the component properties
3
+ *
4
+ * @param {object} bomJson Bom json object
5
+ */
6
+ export function validateProps(bomJson: object): boolean;
1
7
  export function validateBom(bomJson: object): boolean;
2
8
  export function validateMetadata(bomJson: object): boolean;
3
9
  export function validatePurls(bomJson: object): boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../../lib/helpers/validator.js"],"names":[],"mappings":"AAmBO,qCAFI,MAAM,WA6ChB;AAOM,0CAFI,MAAM,WAwDhB;AAOM,uCAFI,MAAM,WAgEhB;AA6BM,sCAFI,MAAM,WAgDhB"}
1
+ {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../../lib/helpers/validator.js"],"names":[],"mappings":"AAgRA;;;;GAIG;AACH,uCAFW,MAAM,WAqDhB;AArTM,qCAFI,MAAM,WAgDhB;AAOM,0CAFI,MAAM,WAwDhB;AAOM,uCAFI,MAAM,WAgEhB;AA6BM,sCAFI,MAAM,WAgDhB"}