@cyclonedx/cdxgen 8.4.13 → 8.5.0

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
@@ -53,7 +53,7 @@ NOTE:
53
53
  Footnotes:
54
54
 
55
55
  - [1] - For multi-module application, the BoM file could include components that may not be included in the packaged war or ear file.
56
- - [2] - Pip freeze is automatically performed to improve precision.
56
+ - [2] - Pip freeze is automatically performed to improve precision. Requires virtual environment.
57
57
  - [3] - Perform dotnet or nuget restore to generate project.assets.json. Without this file cdxgen would not include indirect dependencies.
58
58
  - [4] - See section on plugins
59
59
  - [5] - Powered by osquery. See section on plugins
@@ -254,7 +254,7 @@ cdxgen can retain the dependency tree under the `dependencies` attribute for a s
254
254
  | MVN_ARGS | Set to pass additional arguments such as profile or settings to maven |
255
255
  | MAVEN_HOME | Specify maven home |
256
256
  | GRADLE_CACHE_DIR | Specify gradle cache directory. Useful for class name resolving |
257
- | GRADLE_MULTI_PROJECT_MODE | Set this variable for gradle multi-project applications. Do not use this with recurse mode. |
257
+ | GRADLE_MULTI_PROJECT_MODE | Unused. Automatically handled |
258
258
  | GRADLE_ARGS | Set to pass additional arguments such as profile or settings to gradle. Eg: --configuration runtimeClassPath |
259
259
  | GRADLE_HOME | Specify gradle home |
260
260
  | GRADLE_CMD | Set to override gradle command |
package/docker.test.js CHANGED
@@ -1,5 +1,5 @@
1
1
  const dockerLib = require("./docker");
2
- const { jest, expect, test } = require("@jest/globals");
2
+ const { expect, test } = require("@jest/globals");
3
3
 
4
4
  test("docker connection", async () => {
5
5
  const dockerConn = await dockerLib.getConnection();
@@ -58,16 +58,14 @@ test("parseImageName tests", () => {
58
58
  });
59
59
 
60
60
  test("docker getImage", async () => {
61
- jest.setTimeout(120000);
62
61
  const imageData = await dockerLib.getImage("hello-world:latest");
63
62
  if (imageData) {
64
63
  const removeData = await dockerLib.removeImage("hello-world:latest");
65
64
  expect(removeData);
66
65
  }
67
- });
66
+ }, 120000);
68
67
 
69
68
  test("docker getImage", async () => {
70
- jest.setTimeout(120000);
71
69
  const imageData = await dockerLib.exportImage("hello-world:latest");
72
70
  expect(imageData);
73
- });
71
+ }, 120000);
package/index.js CHANGED
@@ -248,6 +248,11 @@ function addMetadata(parentComponent = {}, format = "xml", options = {}) {
248
248
  if (format == "xml" && firstPComp.component) {
249
249
  metadata.component = firstPComp.component;
250
250
  } else {
251
+ // Retain the components of parent component
252
+ // Bug #317 fix
253
+ if (parentComponent && parentComponent.components) {
254
+ firstPComp.components = parentComponent.components;
255
+ }
251
256
  metadata.component = firstPComp;
252
257
  }
253
258
  } else {
@@ -1158,268 +1163,154 @@ const createJavaBom = async (path, options) => {
1158
1163
  path,
1159
1164
  (options.multiProject ? "**/" : "") + "build.gradle*"
1160
1165
  );
1166
+ let allProjects = [];
1167
+ const allProjectsAddedPurls = [];
1168
+ const rootDependsOn = [];
1169
+ // Execute gradle properties
1170
+ if (gradleFiles && gradleFiles.length) {
1171
+ let retMap = utils.executeGradleProperties(path, null, null);
1172
+ const allProjectsStr = retMap.projects || [];
1173
+ let rootProject = retMap.rootProject;
1174
+ if (rootProject) {
1175
+ parentComponent = {
1176
+ name: rootProject,
1177
+ type: "application",
1178
+ qualifiers: { type: "jar" },
1179
+ ...(retMap.metadata || {})
1180
+ };
1181
+ }
1182
+ // Get the sub-project properties and set the root dependencies
1183
+ if (allProjectsStr && allProjectsStr.length) {
1184
+ for (let spstr of allProjectsStr) {
1185
+ retMap = utils.executeGradleProperties(path, null, spstr);
1186
+ let rootSubProject = retMap.rootProject;
1187
+ if (rootSubProject) {
1188
+ let rspName = rootSubProject.replace(/^:/, "").replace(/:/, "/");
1189
+ const rootSubProjectObj = {
1190
+ name: rspName,
1191
+ type: "application",
1192
+ qualifiers: { type: "jar" },
1193
+ ...(retMap.metadata || {})
1194
+ };
1195
+ const rootSubProjectPurl = decodeURIComponent(
1196
+ new PackageURL(
1197
+ "maven",
1198
+ rootSubProjectObj.group || parentComponent.group || "",
1199
+ rootSubProjectObj.name,
1200
+ rootSubProjectObj.version,
1201
+ rootSubProjectObj.qualifiers,
1202
+ null
1203
+ ).toString()
1204
+ );
1205
+ rootSubProjectObj["purl"] = rootSubProjectPurl;
1206
+ rootSubProjectObj["bom-ref"] = rootSubProjectPurl;
1207
+ if (!allProjectsAddedPurls.includes(rootSubProjectPurl)) {
1208
+ allProjects.push(rootSubProjectObj);
1209
+ rootDependsOn.push(rootSubProjectPurl);
1210
+ allProjectsAddedPurls.push(rootSubProjectPurl);
1211
+ }
1212
+ }
1213
+ }
1214
+ // Bug #317 fix
1215
+ parentComponent.components = allProjects.flatMap((s) => {
1216
+ delete s.qualifiers;
1217
+ return s;
1218
+ });
1219
+ dependencies.push({
1220
+ ref: decodeURIComponent(
1221
+ new PackageURL(
1222
+ "maven",
1223
+ parentComponent.group,
1224
+ parentComponent.name,
1225
+ parentComponent.version,
1226
+ parentComponent.qualifiers,
1227
+ null
1228
+ ).toString()
1229
+ ),
1230
+ dependsOn: rootDependsOn
1231
+ });
1232
+ }
1233
+ }
1161
1234
  if (gradleFiles && gradleFiles.length && options.installDeps) {
1162
1235
  let gradleCmd = utils.getGradleCommand(path, null);
1163
- const multiProjectMode = process.env.GRADLE_MULTI_PROJECT_MODE || "";
1164
- // Support for multi-project applications
1165
- // Let's experiment with defaulting to multi-project mode when multiple gradle files gets detected
1166
- if (
1167
- ["true", "1"].includes(multiProjectMode) ||
1168
- (gradleFiles.length > 1 && !["false", "0"].includes(multiProjectMode))
1169
- ) {
1170
- let gradleProjectsArgs = ["projects", "-q", "--console", "plain"];
1236
+ if (!allProjects || !allProjects.length) {
1237
+ allProjects.push(parentComponent);
1238
+ }
1239
+ for (let sp of allProjects) {
1240
+ let gradleDepArgs = [
1241
+ sp.name === parentComponent.name
1242
+ ? "dependencies"
1243
+ : `:${sp.name}:dependencies`,
1244
+ "-q",
1245
+ "--console",
1246
+ "plain",
1247
+ "--build-cache"
1248
+ ];
1249
+ // Support custom GRADLE_ARGS such as --configuration runtimeClassPath
1171
1250
  if (process.env.GRADLE_ARGS) {
1172
1251
  const addArgs = process.env.GRADLE_ARGS.split(" ");
1173
- gradleProjectsArgs = gradleProjectsArgs.concat(addArgs);
1252
+ gradleDepArgs = gradleDepArgs.concat(addArgs);
1174
1253
  }
1175
1254
  console.log(
1176
1255
  "Executing",
1177
1256
  gradleCmd,
1178
- gradleProjectsArgs.join(" "),
1179
- "projects in",
1257
+ gradleDepArgs.join(" "),
1258
+ "in",
1180
1259
  path
1181
1260
  );
1182
- const result = spawnSync(gradleCmd, gradleProjectsArgs, {
1261
+ const sresult = spawnSync(gradleCmd, gradleDepArgs, {
1183
1262
  cwd: path,
1184
1263
  encoding: "utf-8",
1185
1264
  timeout: TIMEOUT_MS
1186
1265
  });
1187
- if (result.status !== 0 || result.error) {
1188
- if (result.stderr) {
1189
- console.error(result.stdout, result.stderr);
1190
- }
1191
- console.log(
1192
- "1. Check if the correct version of java and gradle are installed and available in PATH. For example, some project might require Java 11 with gradle 7.\n cdxgen container image bundles Java 17 with gradle 8 which might be incompatible."
1193
- );
1194
- options.failOnError && process.exit(1);
1195
- }
1196
- const stdout = result.stdout;
1197
- if (stdout) {
1198
- const cmdOutput = Buffer.from(stdout).toString();
1199
- const retMap = utils.parseGradleProjects(cmdOutput);
1200
- const allProjects = retMap.projects || [];
1201
- let rootProject = retMap.rootProject;
1202
- if (rootProject) {
1203
- parentComponent = {
1204
- group: "",
1205
- name: rootProject,
1206
- version: "latest",
1207
- type: "maven",
1208
- qualifiers: { type: "jar" }
1209
- };
1210
- }
1211
- if (!allProjects) {
1212
- console.log(
1213
- "No projects found. Is this a gradle multi-project application?"
1214
- );
1215
- options.failOnError && process.exit(1);
1216
- } else {
1217
- console.log(
1218
- "Found",
1219
- allProjects.length,
1220
- "gradle sub-projects. This might take a while ..."
1221
- );
1222
- // We need the first dependency between the root project and child projects
1223
- // See: #249 and #315
1224
- const rootDependsOn = [];
1225
- for (let sp of allProjects) {
1226
- sp = sp.replace(":", "");
1227
- rootDependsOn.push(
1228
- decodeURIComponent(
1229
- new PackageURL(
1230
- "maven",
1231
- "",
1232
- sp,
1233
- parentComponent.version,
1234
- parentComponent.qualifiers,
1235
- null
1236
- ).toString()
1237
- )
1238
- );
1239
- }
1240
- dependencies.push({
1241
- ref: decodeURIComponent(
1242
- new PackageURL(
1243
- "maven",
1244
- parentComponent.group,
1245
- parentComponent.name,
1246
- parentComponent.version,
1247
- parentComponent.qualifiers,
1248
- null
1249
- ).toString()
1250
- ),
1251
- dependsOn: rootDependsOn
1252
- });
1253
- for (let sp of allProjects) {
1254
- let gradleDepArgs = [
1255
- sp + ":dependencies",
1256
- "-q",
1257
- "--console",
1258
- "plain"
1259
- ];
1260
- // Support custom GRADLE_ARGS such as --configuration runtimeClassPath
1261
- if (process.env.GRADLE_ARGS) {
1262
- const addArgs = process.env.GRADLE_ARGS.split(" ");
1263
- gradleDepArgs = gradleDepArgs.concat(addArgs);
1264
- }
1265
- console.log(
1266
- "Executing",
1267
- gradleCmd,
1268
- gradleDepArgs.join(" "),
1269
- "in",
1270
- path
1271
- );
1272
- const sresult = spawnSync(gradleCmd, gradleDepArgs, {
1273
- cwd: path,
1274
- encoding: "utf-8",
1275
- timeout: TIMEOUT_MS
1276
- });
1277
- if (sresult.status !== 0 || sresult.error) {
1278
- if (options.failOnError || DEBUG_MODE) {
1279
- console.error(sresult.stdout, sresult.stderr);
1280
- }
1281
- options.failOnError && process.exit(1);
1282
- }
1283
- const sstdout = sresult.stdout;
1284
- if (sstdout) {
1285
- sp = sp.replace(":", "");
1286
- const cmdOutput = Buffer.from(sstdout).toString();
1287
- const parsedList = utils.parseGradleDep(cmdOutput, sp);
1288
- const dlist = parsedList.pkgList;
1289
- // Do not overwrite the parentComponent in multi-project mode
1290
- if (!parentComponent || !Object.keys(parentComponent).length) {
1291
- parentComponent = dlist.splice(0, 1)[0];
1292
- }
1293
- if (
1294
- parsedList.dependenciesList &&
1295
- parsedList.dependenciesList
1296
- ) {
1297
- dependencies = mergeDependencies(
1298
- dependencies,
1299
- parsedList.dependenciesList
1300
- );
1301
- }
1302
- if (dlist && dlist.length) {
1303
- if (DEBUG_MODE) {
1304
- console.log(
1305
- "Found",
1306
- dlist.length,
1307
- "packages in gradle project",
1308
- sp
1309
- );
1310
- }
1311
- pkgList = pkgList.concat(dlist);
1312
- } else {
1313
- if (options.failOnError || DEBUG_MODE) {
1314
- console.log("No packages were found in gradle project", sp);
1315
- }
1316
- options.failOnError && process.exit(1);
1317
- }
1318
- }
1319
- }
1320
- if (pkgList.length) {
1321
- console.log(
1322
- "Obtained",
1323
- pkgList.length,
1324
- "from this gradle multi-project. De-duping this list ..."
1325
- );
1326
- } else {
1327
- console.log(
1328
- "No packages found. Unset the environment variable GRADLE_MULTI_PROJECT_MODE and try again."
1329
- );
1330
- options.failOnError && process.exit(1);
1331
- }
1266
+ if (sresult.status !== 0 || sresult.error) {
1267
+ if (options.failOnError || DEBUG_MODE) {
1268
+ console.error(sresult.stdout, sresult.stderr);
1332
1269
  }
1333
- } else {
1334
- console.error("Gradle unexpectedly didn't return any output");
1335
1270
  options.failOnError && process.exit(1);
1336
1271
  }
1337
- } else {
1338
- let gradleDepArgs = ["dependencies", "-q", "--console", "plain"];
1339
- // Support for overriding the gradle task name. Issue# 90
1340
- if (process.env.GRADLE_DEPENDENCY_TASK) {
1341
- gradleDepArgs = process.env.GRADLE_DEPENDENCY_TASK.split(" ");
1342
- } else if (process.env.GRADLE_ARGS) {
1343
- // Support custom GRADLE_ARGS such as --configuration runtimeClassPath
1344
- const addArgs = process.env.GRADLE_ARGS.split(" ");
1345
- gradleDepArgs = gradleDepArgs.concat(addArgs);
1346
- }
1347
- for (let f of gradleFiles) {
1348
- const basePath = pathLib.dirname(f);
1349
- // Fixes #157. Look for wrapper script in the nested directory
1350
- gradleCmd = utils.getGradleCommand(basePath, path);
1351
- console.log(
1352
- "Executing",
1353
- gradleCmd,
1354
- gradleDepArgs.join(" "),
1355
- "in",
1356
- basePath
1272
+ const sstdout = sresult.stdout;
1273
+ if (sstdout) {
1274
+ const cmdOutput = Buffer.from(sstdout).toString();
1275
+ const parsedList = utils.parseGradleDep(
1276
+ cmdOutput,
1277
+ sp.group,
1278
+ sp.name,
1279
+ sp.version
1357
1280
  );
1358
- const result = spawnSync(gradleCmd, gradleDepArgs, {
1359
- cwd: basePath,
1360
- encoding: "utf-8",
1361
- timeout: TIMEOUT_MS
1362
- });
1363
- if (result.status !== 0 || result.error) {
1364
- if (result.stderr) {
1365
- const cmdError = Buffer.from(result.stderr).toString();
1366
- if (
1367
- cmdError.includes(
1368
- "is not part of the build defined by settings file"
1369
- ) ||
1370
- cmdError.includes(
1371
- "was not found in any of the following sources"
1372
- )
1373
- ) {
1374
- console.log(
1375
- "This is a multi-project gradle application. Set the environment variable GRADLE_MULTI_PROJECT_MODE to true to improve SBoM accuracy."
1376
- );
1377
- }
1378
- if (DEBUG_MODE) {
1379
- console.log("-----------------------");
1380
- }
1381
- console.error(result.stdout, result.stderr);
1382
- if (DEBUG_MODE) {
1383
- console.log("-----------------------");
1384
- }
1385
- options.failOnError && process.exit(1);
1386
- }
1387
-
1388
- if (DEBUG_MODE || !result.stderr || options.failOnError) {
1389
- console.log(
1390
- "1. Check if the correct version of java and gradle are installed and available in PATH. For example, some project might require Java 11 with gradle 7.\n cdxgen container image bundles Java 17 with gradle 8 which might be incompatible."
1391
- );
1392
- console.log(
1393
- "2. When using tools such as sdkman, the init script must be invoked to set the PATH variables correctly."
1394
- );
1395
- options.failOnError && process.exit(1);
1396
- }
1281
+ const dlist = parsedList.pkgList;
1282
+ if (parsedList.dependenciesList && parsedList.dependenciesList) {
1283
+ dependencies = mergeDependencies(
1284
+ dependencies,
1285
+ parsedList.dependenciesList
1286
+ );
1397
1287
  }
1398
- const stdout = result.stdout;
1399
- if (stdout) {
1400
- const cmdOutput = Buffer.from(stdout).toString();
1401
- const parsedList = utils.parseGradleDep(cmdOutput);
1402
- const dlist = parsedList.pkgList;
1403
- if (!parentComponent || !Object.keys(parentComponent).length) {
1404
- parentComponent = dlist.splice(0, 1)[0];
1405
- }
1406
- if (parsedList.dependenciesList && parsedList.dependenciesList) {
1407
- dependencies = mergeDependencies(
1408
- dependencies,
1409
- parsedList.dependenciesList
1410
- );
1411
- }
1412
- if (dlist && dlist.length) {
1413
- pkgList = pkgList.concat(dlist);
1414
- } else {
1288
+ if (dlist && dlist.length) {
1289
+ if (DEBUG_MODE) {
1415
1290
  console.log(
1416
- "No packages were detected. If this is a multi-project gradle application set the environment variable GRADLE_MULTI_PROJECT_MODE to true and try again."
1291
+ "Found",
1292
+ dlist.length,
1293
+ "packages in gradle project",
1294
+ sp.name
1417
1295
  );
1418
- options.failOnError && process.exit(1);
1419
1296
  }
1297
+ pkgList = pkgList.concat(dlist);
1420
1298
  }
1421
1299
  }
1300
+ } // for
1301
+ if (pkgList.length) {
1302
+ console.log(
1303
+ "Obtained",
1304
+ pkgList.length,
1305
+ "from this gradle multi-project. De-duping this list ..."
1306
+ );
1307
+ } else {
1308
+ console.log(
1309
+ "No packages found. Set the environment variable 'CDXGEN_DEBUG_MODE=debug' to troubleshoot any gradle related errors."
1310
+ );
1311
+ options.failOnError && process.exit(1);
1422
1312
  }
1313
+
1423
1314
  pkgList = await utils.getMvnMetadata(pkgList);
1424
1315
  // Should we attempt to resolve class names
1425
1316
  if (options.resolveClass) {
@@ -2030,7 +1921,7 @@ const createPythonBom = async (path, options) => {
2030
1921
  );
2031
1922
  const reqFiles = utils.getAllFiles(
2032
1923
  path,
2033
- (options.multiProject ? "**/" : "") + "*requirements.txt"
1924
+ (options.multiProject ? "**/" : "") + "*requirements*.txt"
2034
1925
  );
2035
1926
  const reqDirFiles = utils.getAllFiles(
2036
1927
  path,
@@ -2102,7 +1993,7 @@ const createPythonBom = async (path, options) => {
2102
1993
  }
2103
1994
  }
2104
1995
  }
2105
- if (requirementsMode || pipenvMode || setupPyMode) {
1996
+ if (requirementsMode || pipenvMode) {
2106
1997
  if (pipenvMode) {
2107
1998
  spawnSync("pipenv", ["install"], { cwd: path, encoding: "utf-8" });
2108
1999
  const piplockFile = pathLib.join(path, "Pipfile.lock");
@@ -2119,61 +2010,77 @@ const createPythonBom = async (path, options) => {
2119
2010
  } else if (requirementsMode) {
2120
2011
  metadataFilename = "requirements.txt";
2121
2012
  if (reqFiles && reqFiles.length) {
2013
+ let pipWarningShown = false;
2122
2014
  for (let f of reqFiles) {
2123
2015
  const basePath = pathLib.dirname(f);
2124
2016
  let reqData = undefined;
2125
- // Attempt to pip freeze to improve precision
2017
+ let frozenMode = false;
2018
+ // Attempt to pip freeze to improve precision. First try in venv mode
2126
2019
  if (options.installDeps) {
2127
- const result = spawnSync(PIP_CMD, ["freeze", "-r", f, "-l"], {
2128
- cwd: basePath,
2129
- encoding: "utf-8",
2130
- timeout: TIMEOUT_MS
2131
- });
2020
+ const result = spawnSync(
2021
+ PIP_CMD,
2022
+ ["freeze", "-r", f, "-l", "--require-virtualenv"],
2023
+ {
2024
+ cwd: basePath,
2025
+ encoding: "utf-8",
2026
+ timeout: TIMEOUT_MS
2027
+ }
2028
+ );
2132
2029
  if (result.status === 0 && result.stdout) {
2133
2030
  reqData = Buffer.from(result.stdout).toString();
2031
+ const dlist = await utils.parseReqFile(reqData, false);
2032
+ if (dlist && dlist.length) {
2033
+ pkgList = pkgList.concat(dlist);
2034
+ }
2035
+ frozenMode = true;
2036
+ } else if (result.status !== 0 || result.error) {
2037
+ if (DEBUG_MODE && !pipWarningShown) {
2038
+ pipWarningShown = true;
2039
+ console.log(
2040
+ "NOTE: Setup and activate a python virtual environment for this project prior to invoking cdxgen to improve SBoM accuracy."
2041
+ );
2042
+ }
2134
2043
  }
2135
2044
  }
2136
- // Fallback to parsing requirements file
2137
- if (!reqData) {
2045
+ // Fallback to parsing manually
2046
+ if (!frozenMode) {
2138
2047
  if (DEBUG_MODE) {
2139
2048
  console.log(
2140
- `Falling back to manually parsing ${f}. The result would be incomplete!`
2049
+ `Manually parsing ${f}. The result would include only direct dependencies.`
2141
2050
  );
2142
2051
  }
2143
2052
  reqData = fs.readFileSync(f, { encoding: "utf-8" });
2053
+ const dlist = await utils.parseReqFile(reqData, true);
2054
+ if (dlist && dlist.length) {
2055
+ pkgList = pkgList.concat(dlist);
2056
+ }
2144
2057
  }
2145
- const dlist = await utils.parseReqFile(reqData);
2146
- if (dlist && dlist.length) {
2147
- pkgList = pkgList.concat(dlist);
2148
- }
2149
- }
2058
+ } // for
2150
2059
  metadataFilename = reqFiles.join(", ");
2151
2060
  } else if (reqDirFiles && reqDirFiles.length) {
2152
2061
  for (let j in reqDirFiles) {
2153
2062
  const f = reqDirFiles[j];
2154
2063
  const reqData = fs.readFileSync(f, { encoding: "utf-8" });
2155
- const dlist = await utils.parseReqFile(reqData);
2064
+ const dlist = await utils.parseReqFile(reqData, false);
2156
2065
  if (dlist && dlist.length) {
2157
2066
  pkgList = pkgList.concat(dlist);
2158
2067
  }
2159
2068
  }
2160
2069
  metadataFilename = reqDirFiles.join(", ");
2161
2070
  }
2162
- } else if (setupPyMode) {
2163
- const setupPyData = fs.readFileSync(setupPy, { encoding: "utf-8" });
2164
- dlist = await utils.parseSetupPyFile(setupPyData);
2165
- if (dlist && dlist.length) {
2166
- pkgList = pkgList.concat(dlist);
2167
- }
2168
2071
  }
2169
2072
  }
2170
- if (pkgList.length) {
2171
- return buildBomNSData(options, pkgList, "pypi", {
2172
- src: path,
2173
- filename: metadataFilename
2174
- });
2073
+ if (!pkgList.length && setupPyMode) {
2074
+ const setupPyData = fs.readFileSync(setupPy, { encoding: "utf-8" });
2075
+ dlist = await utils.parseSetupPyFile(setupPyData);
2076
+ if (dlist && dlist.length) {
2077
+ pkgList = pkgList.concat(dlist);
2078
+ }
2175
2079
  }
2176
- return {};
2080
+ return buildBomNSData(options, pkgList, "pypi", {
2081
+ src: path,
2082
+ filename: metadataFilename
2083
+ });
2177
2084
  };
2178
2085
 
2179
2086
  /**
@@ -3712,7 +3619,12 @@ const createMultiXBom = async (pathList, options) => {
3712
3619
  console.log("Scanning", path);
3713
3620
  }
3714
3621
  bomData = await createNodejsBom(path, options);
3715
- if (bomData && bomData.bomJson && bomData.bomJson.components) {
3622
+ if (
3623
+ bomData &&
3624
+ bomData.bomJson &&
3625
+ bomData.bomJson.components &&
3626
+ bomData.bomJson.components.length
3627
+ ) {
3716
3628
  if (DEBUG_MODE) {
3717
3629
  console.log(
3718
3630
  `Found ${bomData.bomJson.components.length} npm packages at ${path}`
@@ -3976,7 +3888,12 @@ const createMultiXBom = async (pathList, options) => {
3976
3888
  );
3977
3889
  }
3978
3890
  bomData = await createSwiftBom(path, options);
3979
- if (bomData && bomData.bomJson && bomData.bomJson.components) {
3891
+ if (
3892
+ bomData &&
3893
+ bomData.bomJson &&
3894
+ bomData.bomJson.components &&
3895
+ bomData.bomJson.components.length
3896
+ ) {
3980
3897
  if (DEBUG_MODE) {
3981
3898
  console.log(
3982
3899
  `Found ${bomData.bomJson.components.length} Swift packages at ${path}`
@@ -4088,7 +4005,7 @@ const createXBom = async (path, options) => {
4088
4005
  const poetryMode = fs.existsSync(pathLib.join(path, "poetry.lock"));
4089
4006
  const reqFiles = utils.getAllFiles(
4090
4007
  path,
4091
- (options.multiProject ? "**/" : "") + "*requirements.txt"
4008
+ (options.multiProject ? "**/" : "") + "*requirements*.txt"
4092
4009
  );
4093
4010
  const reqDirFiles = utils.getAllFiles(
4094
4011
  path,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyclonedx/cdxgen",
3
- "version": "8.4.13",
3
+ "version": "8.5.0",
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>",