@cyclonedx/cdxgen 8.4.13 → 8.5.1
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 +2 -2
- package/docker.test.js +3 -5
- package/index.js +192 -272
- package/package.json +1 -1
- package/spdx-licenses.json +54 -0
- package/utils.js +159 -36
- package/utils.test.js +119 -47
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 |
|
|
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 {
|
|
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,157 @@ 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
|
+
const parentPurl = decodeURIComponent(
|
|
1182
|
+
new PackageURL(
|
|
1183
|
+
"maven",
|
|
1184
|
+
parentComponent.group || "",
|
|
1185
|
+
parentComponent.name,
|
|
1186
|
+
parentComponent.version,
|
|
1187
|
+
parentComponent.qualifiers,
|
|
1188
|
+
null
|
|
1189
|
+
).toString()
|
|
1190
|
+
);
|
|
1191
|
+
parentComponent["purl"] = parentPurl;
|
|
1192
|
+
parentComponent["bom-ref"] = parentPurl;
|
|
1193
|
+
}
|
|
1194
|
+
// Get the sub-project properties and set the root dependencies
|
|
1195
|
+
if (allProjectsStr && allProjectsStr.length) {
|
|
1196
|
+
for (let spstr of allProjectsStr) {
|
|
1197
|
+
retMap = utils.executeGradleProperties(path, null, spstr);
|
|
1198
|
+
let rootSubProject = retMap.rootProject;
|
|
1199
|
+
if (rootSubProject) {
|
|
1200
|
+
let rspName = rootSubProject.replace(/^:/, "").replace(/:/, "/");
|
|
1201
|
+
const rootSubProjectObj = {
|
|
1202
|
+
name: rspName,
|
|
1203
|
+
type: "application",
|
|
1204
|
+
qualifiers: { type: "jar" },
|
|
1205
|
+
...(retMap.metadata || {})
|
|
1206
|
+
};
|
|
1207
|
+
const rootSubProjectPurl = decodeURIComponent(
|
|
1208
|
+
new PackageURL(
|
|
1209
|
+
"maven",
|
|
1210
|
+
rootSubProjectObj.group || parentComponent.group || "",
|
|
1211
|
+
rootSubProjectObj.name,
|
|
1212
|
+
rootSubProjectObj.version,
|
|
1213
|
+
rootSubProjectObj.qualifiers,
|
|
1214
|
+
null
|
|
1215
|
+
).toString()
|
|
1216
|
+
);
|
|
1217
|
+
rootSubProjectObj["purl"] = rootSubProjectPurl;
|
|
1218
|
+
rootSubProjectObj["bom-ref"] = rootSubProjectPurl;
|
|
1219
|
+
if (!allProjectsAddedPurls.includes(rootSubProjectPurl)) {
|
|
1220
|
+
allProjects.push(rootSubProjectObj);
|
|
1221
|
+
rootDependsOn.push(rootSubProjectPurl);
|
|
1222
|
+
allProjectsAddedPurls.push(rootSubProjectPurl);
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
// Bug #317 fix
|
|
1227
|
+
parentComponent.components = allProjects.flatMap((s) => {
|
|
1228
|
+
delete s.qualifiers;
|
|
1229
|
+
return s;
|
|
1230
|
+
});
|
|
1231
|
+
dependencies.push({
|
|
1232
|
+
ref: parentComponent["bom-ref"],
|
|
1233
|
+
dependsOn: rootDependsOn
|
|
1234
|
+
});
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1161
1237
|
if (gradleFiles && gradleFiles.length && options.installDeps) {
|
|
1162
1238
|
let gradleCmd = utils.getGradleCommand(path, null);
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1239
|
+
if (!allProjects || !allProjects.length) {
|
|
1240
|
+
allProjects.push(parentComponent);
|
|
1241
|
+
}
|
|
1242
|
+
for (let sp of allProjects) {
|
|
1243
|
+
let gradleDepArgs = [
|
|
1244
|
+
sp.name === parentComponent.name
|
|
1245
|
+
? "dependencies"
|
|
1246
|
+
: `:${sp.name}:dependencies`,
|
|
1247
|
+
"-q",
|
|
1248
|
+
"--console",
|
|
1249
|
+
"plain",
|
|
1250
|
+
"--build-cache"
|
|
1251
|
+
];
|
|
1252
|
+
// Support custom GRADLE_ARGS such as --configuration runtimeClassPath
|
|
1171
1253
|
if (process.env.GRADLE_ARGS) {
|
|
1172
1254
|
const addArgs = process.env.GRADLE_ARGS.split(" ");
|
|
1173
|
-
|
|
1255
|
+
gradleDepArgs = gradleDepArgs.concat(addArgs);
|
|
1174
1256
|
}
|
|
1175
1257
|
console.log(
|
|
1176
1258
|
"Executing",
|
|
1177
1259
|
gradleCmd,
|
|
1178
|
-
|
|
1179
|
-
"
|
|
1260
|
+
gradleDepArgs.join(" "),
|
|
1261
|
+
"in",
|
|
1180
1262
|
path
|
|
1181
1263
|
);
|
|
1182
|
-
const
|
|
1264
|
+
const sresult = spawnSync(gradleCmd, gradleDepArgs, {
|
|
1183
1265
|
cwd: path,
|
|
1184
1266
|
encoding: "utf-8",
|
|
1185
1267
|
timeout: TIMEOUT_MS
|
|
1186
1268
|
});
|
|
1187
|
-
if (
|
|
1188
|
-
if (
|
|
1189
|
-
console.error(
|
|
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
|
-
}
|
|
1269
|
+
if (sresult.status !== 0 || sresult.error) {
|
|
1270
|
+
if (options.failOnError || DEBUG_MODE) {
|
|
1271
|
+
console.error(sresult.stdout, sresult.stderr);
|
|
1332
1272
|
}
|
|
1333
|
-
} else {
|
|
1334
|
-
console.error("Gradle unexpectedly didn't return any output");
|
|
1335
1273
|
options.failOnError && process.exit(1);
|
|
1336
1274
|
}
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
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
|
|
1275
|
+
const sstdout = sresult.stdout;
|
|
1276
|
+
if (sstdout) {
|
|
1277
|
+
const cmdOutput = Buffer.from(sstdout).toString();
|
|
1278
|
+
const parsedList = utils.parseGradleDep(
|
|
1279
|
+
cmdOutput,
|
|
1280
|
+
sp.group,
|
|
1281
|
+
sp.name,
|
|
1282
|
+
sp.version
|
|
1357
1283
|
);
|
|
1358
|
-
const
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
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
|
-
}
|
|
1284
|
+
const dlist = parsedList.pkgList;
|
|
1285
|
+
if (parsedList.dependenciesList && parsedList.dependenciesList) {
|
|
1286
|
+
dependencies = mergeDependencies(
|
|
1287
|
+
dependencies,
|
|
1288
|
+
parsedList.dependenciesList
|
|
1289
|
+
);
|
|
1397
1290
|
}
|
|
1398
|
-
|
|
1399
|
-
|
|
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 {
|
|
1291
|
+
if (dlist && dlist.length) {
|
|
1292
|
+
if (DEBUG_MODE) {
|
|
1415
1293
|
console.log(
|
|
1416
|
-
"
|
|
1294
|
+
"Found",
|
|
1295
|
+
dlist.length,
|
|
1296
|
+
"packages in gradle project",
|
|
1297
|
+
sp.name
|
|
1417
1298
|
);
|
|
1418
|
-
options.failOnError && process.exit(1);
|
|
1419
1299
|
}
|
|
1300
|
+
pkgList = pkgList.concat(dlist);
|
|
1420
1301
|
}
|
|
1421
1302
|
}
|
|
1303
|
+
} // for
|
|
1304
|
+
if (pkgList.length) {
|
|
1305
|
+
console.log(
|
|
1306
|
+
"Obtained",
|
|
1307
|
+
pkgList.length,
|
|
1308
|
+
"from this gradle project. De-duping this list ..."
|
|
1309
|
+
);
|
|
1310
|
+
} else {
|
|
1311
|
+
console.log(
|
|
1312
|
+
"No packages found. Set the environment variable 'CDXGEN_DEBUG_MODE=debug' to troubleshoot any gradle related errors."
|
|
1313
|
+
);
|
|
1314
|
+
options.failOnError && process.exit(1);
|
|
1422
1315
|
}
|
|
1316
|
+
|
|
1423
1317
|
pkgList = await utils.getMvnMetadata(pkgList);
|
|
1424
1318
|
// Should we attempt to resolve class names
|
|
1425
1319
|
if (options.resolveClass) {
|
|
@@ -1802,7 +1696,7 @@ const createNodejsBom = async (path, options) => {
|
|
|
1802
1696
|
type: "application"
|
|
1803
1697
|
};
|
|
1804
1698
|
ppurl = new PackageURL(
|
|
1805
|
-
"
|
|
1699
|
+
"npm",
|
|
1806
1700
|
parentComponent.group,
|
|
1807
1701
|
parentComponent.name,
|
|
1808
1702
|
parentComponent.version,
|
|
@@ -1933,7 +1827,7 @@ const createNodejsBom = async (path, options) => {
|
|
|
1933
1827
|
type: "application"
|
|
1934
1828
|
};
|
|
1935
1829
|
ppurl = new PackageURL(
|
|
1936
|
-
"
|
|
1830
|
+
"npm",
|
|
1937
1831
|
parentComponent.group,
|
|
1938
1832
|
parentComponent.name,
|
|
1939
1833
|
parentComponent.version,
|
|
@@ -1961,7 +1855,7 @@ const createNodejsBom = async (path, options) => {
|
|
|
1961
1855
|
// Fixes: 212. Handle case where there are no package.json to determine the parent package
|
|
1962
1856
|
if (Object.keys(parentComponent).length && parentComponent.name) {
|
|
1963
1857
|
const ppurl = new PackageURL(
|
|
1964
|
-
"
|
|
1858
|
+
"npm",
|
|
1965
1859
|
parentComponent.group,
|
|
1966
1860
|
parentComponent.name,
|
|
1967
1861
|
parentComponent.version,
|
|
@@ -2030,7 +1924,7 @@ const createPythonBom = async (path, options) => {
|
|
|
2030
1924
|
);
|
|
2031
1925
|
const reqFiles = utils.getAllFiles(
|
|
2032
1926
|
path,
|
|
2033
|
-
(options.multiProject ? "**/" : "") + "*requirements
|
|
1927
|
+
(options.multiProject ? "**/" : "") + "*requirements*.txt"
|
|
2034
1928
|
);
|
|
2035
1929
|
const reqDirFiles = utils.getAllFiles(
|
|
2036
1930
|
path,
|
|
@@ -2102,7 +1996,7 @@ const createPythonBom = async (path, options) => {
|
|
|
2102
1996
|
}
|
|
2103
1997
|
}
|
|
2104
1998
|
}
|
|
2105
|
-
if (requirementsMode || pipenvMode
|
|
1999
|
+
if (requirementsMode || pipenvMode) {
|
|
2106
2000
|
if (pipenvMode) {
|
|
2107
2001
|
spawnSync("pipenv", ["install"], { cwd: path, encoding: "utf-8" });
|
|
2108
2002
|
const piplockFile = pathLib.join(path, "Pipfile.lock");
|
|
@@ -2119,61 +2013,77 @@ const createPythonBom = async (path, options) => {
|
|
|
2119
2013
|
} else if (requirementsMode) {
|
|
2120
2014
|
metadataFilename = "requirements.txt";
|
|
2121
2015
|
if (reqFiles && reqFiles.length) {
|
|
2016
|
+
let pipWarningShown = false;
|
|
2122
2017
|
for (let f of reqFiles) {
|
|
2123
2018
|
const basePath = pathLib.dirname(f);
|
|
2124
2019
|
let reqData = undefined;
|
|
2125
|
-
|
|
2020
|
+
let frozenMode = false;
|
|
2021
|
+
// Attempt to pip freeze to improve precision. First try in venv mode
|
|
2126
2022
|
if (options.installDeps) {
|
|
2127
|
-
const result = spawnSync(
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2023
|
+
const result = spawnSync(
|
|
2024
|
+
PIP_CMD,
|
|
2025
|
+
["freeze", "-r", f, "-l", "--require-virtualenv"],
|
|
2026
|
+
{
|
|
2027
|
+
cwd: basePath,
|
|
2028
|
+
encoding: "utf-8",
|
|
2029
|
+
timeout: TIMEOUT_MS
|
|
2030
|
+
}
|
|
2031
|
+
);
|
|
2132
2032
|
if (result.status === 0 && result.stdout) {
|
|
2133
2033
|
reqData = Buffer.from(result.stdout).toString();
|
|
2034
|
+
const dlist = await utils.parseReqFile(reqData, false);
|
|
2035
|
+
if (dlist && dlist.length) {
|
|
2036
|
+
pkgList = pkgList.concat(dlist);
|
|
2037
|
+
}
|
|
2038
|
+
frozenMode = true;
|
|
2039
|
+
} else if (result.status !== 0 || result.error) {
|
|
2040
|
+
if (DEBUG_MODE && !pipWarningShown) {
|
|
2041
|
+
pipWarningShown = true;
|
|
2042
|
+
console.log(
|
|
2043
|
+
"NOTE: Setup and activate a python virtual environment for this project prior to invoking cdxgen to improve SBoM accuracy."
|
|
2044
|
+
);
|
|
2045
|
+
}
|
|
2134
2046
|
}
|
|
2135
2047
|
}
|
|
2136
|
-
// Fallback to parsing
|
|
2137
|
-
if (!
|
|
2048
|
+
// Fallback to parsing manually
|
|
2049
|
+
if (!frozenMode) {
|
|
2138
2050
|
if (DEBUG_MODE) {
|
|
2139
2051
|
console.log(
|
|
2140
|
-
`
|
|
2052
|
+
`Manually parsing ${f}. The result would include only direct dependencies.`
|
|
2141
2053
|
);
|
|
2142
2054
|
}
|
|
2143
2055
|
reqData = fs.readFileSync(f, { encoding: "utf-8" });
|
|
2056
|
+
const dlist = await utils.parseReqFile(reqData, true);
|
|
2057
|
+
if (dlist && dlist.length) {
|
|
2058
|
+
pkgList = pkgList.concat(dlist);
|
|
2059
|
+
}
|
|
2144
2060
|
}
|
|
2145
|
-
|
|
2146
|
-
if (dlist && dlist.length) {
|
|
2147
|
-
pkgList = pkgList.concat(dlist);
|
|
2148
|
-
}
|
|
2149
|
-
}
|
|
2061
|
+
} // for
|
|
2150
2062
|
metadataFilename = reqFiles.join(", ");
|
|
2151
2063
|
} else if (reqDirFiles && reqDirFiles.length) {
|
|
2152
2064
|
for (let j in reqDirFiles) {
|
|
2153
2065
|
const f = reqDirFiles[j];
|
|
2154
2066
|
const reqData = fs.readFileSync(f, { encoding: "utf-8" });
|
|
2155
|
-
const dlist = await utils.parseReqFile(reqData);
|
|
2067
|
+
const dlist = await utils.parseReqFile(reqData, false);
|
|
2156
2068
|
if (dlist && dlist.length) {
|
|
2157
2069
|
pkgList = pkgList.concat(dlist);
|
|
2158
2070
|
}
|
|
2159
2071
|
}
|
|
2160
2072
|
metadataFilename = reqDirFiles.join(", ");
|
|
2161
2073
|
}
|
|
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
2074
|
}
|
|
2169
2075
|
}
|
|
2170
|
-
if (pkgList.length) {
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2076
|
+
if (!pkgList.length && setupPyMode) {
|
|
2077
|
+
const setupPyData = fs.readFileSync(setupPy, { encoding: "utf-8" });
|
|
2078
|
+
dlist = await utils.parseSetupPyFile(setupPyData);
|
|
2079
|
+
if (dlist && dlist.length) {
|
|
2080
|
+
pkgList = pkgList.concat(dlist);
|
|
2081
|
+
}
|
|
2175
2082
|
}
|
|
2176
|
-
return {
|
|
2083
|
+
return buildBomNSData(options, pkgList, "pypi", {
|
|
2084
|
+
src: path,
|
|
2085
|
+
filename: metadataFilename
|
|
2086
|
+
});
|
|
2177
2087
|
};
|
|
2178
2088
|
|
|
2179
2089
|
/**
|
|
@@ -3712,7 +3622,12 @@ const createMultiXBom = async (pathList, options) => {
|
|
|
3712
3622
|
console.log("Scanning", path);
|
|
3713
3623
|
}
|
|
3714
3624
|
bomData = await createNodejsBom(path, options);
|
|
3715
|
-
if (
|
|
3625
|
+
if (
|
|
3626
|
+
bomData &&
|
|
3627
|
+
bomData.bomJson &&
|
|
3628
|
+
bomData.bomJson.components &&
|
|
3629
|
+
bomData.bomJson.components.length
|
|
3630
|
+
) {
|
|
3716
3631
|
if (DEBUG_MODE) {
|
|
3717
3632
|
console.log(
|
|
3718
3633
|
`Found ${bomData.bomJson.components.length} npm packages at ${path}`
|
|
@@ -3976,7 +3891,12 @@ const createMultiXBom = async (pathList, options) => {
|
|
|
3976
3891
|
);
|
|
3977
3892
|
}
|
|
3978
3893
|
bomData = await createSwiftBom(path, options);
|
|
3979
|
-
if (
|
|
3894
|
+
if (
|
|
3895
|
+
bomData &&
|
|
3896
|
+
bomData.bomJson &&
|
|
3897
|
+
bomData.bomJson.components &&
|
|
3898
|
+
bomData.bomJson.components.length
|
|
3899
|
+
) {
|
|
3980
3900
|
if (DEBUG_MODE) {
|
|
3981
3901
|
console.log(
|
|
3982
3902
|
`Found ${bomData.bomJson.components.length} Swift packages at ${path}`
|
|
@@ -4088,7 +4008,7 @@ const createXBom = async (path, options) => {
|
|
|
4088
4008
|
const poetryMode = fs.existsSync(pathLib.join(path, "poetry.lock"));
|
|
4089
4009
|
const reqFiles = utils.getAllFiles(
|
|
4090
4010
|
path,
|
|
4091
|
-
(options.multiProject ? "**/" : "") + "*requirements
|
|
4011
|
+
(options.multiProject ? "**/" : "") + "*requirements*.txt"
|
|
4092
4012
|
);
|
|
4093
4013
|
const reqDirFiles = utils.getAllFiles(
|
|
4094
4014
|
path,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cyclonedx/cdxgen",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.5.1",
|
|
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>",
|