@cyclonedx/cdxgen 9.6.0 → 9.7.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 +7 -8
- package/bin/cdxgen.js +1 -3
- package/bin/evinse.js +0 -0
- package/bin/verify.js +19 -0
- package/binary.js +166 -30
- package/data/queries-win.json +200 -0
- package/data/queries.json +166 -15
- package/display.js +14 -8
- package/docker.js +18 -1
- package/evinser.js +23 -32
- package/index.js +96 -18
- package/package.json +10 -8
- package/utils.js +159 -85
- package/utils.test.js +2 -2
package/index.js
CHANGED
|
@@ -120,12 +120,13 @@ import {
|
|
|
120
120
|
executeOsQuery,
|
|
121
121
|
getOSPackages
|
|
122
122
|
} from "./binary.js";
|
|
123
|
-
const osQueries = JSON.parse(
|
|
124
|
-
readFileSync(join(dirName, "data", "queries.json"))
|
|
125
|
-
);
|
|
126
123
|
|
|
127
124
|
const isWin = _platform() === "win32";
|
|
128
125
|
|
|
126
|
+
const osQueries = !isWin
|
|
127
|
+
? JSON.parse(readFileSync(join(dirName, "data", "queries.json")))
|
|
128
|
+
: JSON.parse(readFileSync(join(dirName, "data", "queries-win.json")));
|
|
129
|
+
|
|
129
130
|
import { table } from "table";
|
|
130
131
|
|
|
131
132
|
// Construct gradle cache directory
|
|
@@ -372,7 +373,16 @@ function addMetadata(parentComponent = {}, format = "xml", options = {}) {
|
|
|
372
373
|
// We cannot use purl or bom-ref here since they would not match
|
|
373
374
|
// purl - could have application on one side and a different type
|
|
374
375
|
// bom-ref could have qualifiers on one side
|
|
375
|
-
|
|
376
|
+
// Ignore components that have the same name as the parent component but with latest as the version.
|
|
377
|
+
// These are default components created based on directory names
|
|
378
|
+
if (
|
|
379
|
+
fullName !== parentFullName &&
|
|
380
|
+
!(
|
|
381
|
+
(comp.name === parentComponent.name ||
|
|
382
|
+
comp.name === parentComponent.name + ":latest") &&
|
|
383
|
+
comp.version === "latest"
|
|
384
|
+
)
|
|
385
|
+
) {
|
|
376
386
|
if (!comp["bom-ref"]) {
|
|
377
387
|
comp["bom-ref"] = `pkg:${comp.type}/${fullName}`;
|
|
378
388
|
}
|
|
@@ -380,6 +390,7 @@ function addMetadata(parentComponent = {}, format = "xml", options = {}) {
|
|
|
380
390
|
}
|
|
381
391
|
}
|
|
382
392
|
} // for
|
|
393
|
+
parentComponent.components = subComponents;
|
|
383
394
|
}
|
|
384
395
|
if (format === "json") {
|
|
385
396
|
metadata.component = parentComponent;
|
|
@@ -650,7 +661,6 @@ function addComponent(
|
|
|
650
661
|
return;
|
|
651
662
|
}
|
|
652
663
|
const licenses = pkg.licenses || getLicenses(pkg, format);
|
|
653
|
-
|
|
654
664
|
const purl =
|
|
655
665
|
pkg.purl ||
|
|
656
666
|
new PackageURL(
|
|
@@ -745,8 +755,22 @@ function addComponent(
|
|
|
745
755
|
* word for it, otherwise, identify the module as a 'library'.
|
|
746
756
|
*/
|
|
747
757
|
function determinePackageType(pkg) {
|
|
748
|
-
|
|
749
|
-
|
|
758
|
+
// Retain the exact component type in certain cases.
|
|
759
|
+
if (
|
|
760
|
+
[
|
|
761
|
+
"application",
|
|
762
|
+
"container",
|
|
763
|
+
"platform",
|
|
764
|
+
"operating-system",
|
|
765
|
+
"device",
|
|
766
|
+
"device-driver",
|
|
767
|
+
"firmware",
|
|
768
|
+
"file",
|
|
769
|
+
"machine-learning-model",
|
|
770
|
+
"data"
|
|
771
|
+
].includes(pkg.type)
|
|
772
|
+
) {
|
|
773
|
+
return pkg.type;
|
|
750
774
|
}
|
|
751
775
|
if (pkg.purl) {
|
|
752
776
|
try {
|
|
@@ -1174,7 +1198,8 @@ export const createJavaBom = async (path, options) => {
|
|
|
1174
1198
|
cwd: basePath,
|
|
1175
1199
|
shell: true,
|
|
1176
1200
|
encoding: "utf-8",
|
|
1177
|
-
timeout: TIMEOUT_MS
|
|
1201
|
+
timeout: TIMEOUT_MS,
|
|
1202
|
+
maxBuffer: 50 * 1024 * 1024
|
|
1178
1203
|
});
|
|
1179
1204
|
// Check if the cyclonedx plugin created the required bom.xml file
|
|
1180
1205
|
// Sometimes the plugin fails silently for complex maven projects
|
|
@@ -2199,10 +2224,13 @@ export const createPythonBom = async (path, options) => {
|
|
|
2199
2224
|
if (pdmLockFiles && pdmLockFiles.length) {
|
|
2200
2225
|
poetryFiles = poetryFiles.concat(pdmLockFiles);
|
|
2201
2226
|
}
|
|
2202
|
-
|
|
2227
|
+
let reqFiles = getAllFiles(
|
|
2203
2228
|
path,
|
|
2204
2229
|
(options.multiProject ? "**/" : "") + "*requirements*.txt"
|
|
2205
2230
|
);
|
|
2231
|
+
reqFiles = reqFiles.filter(
|
|
2232
|
+
(f) => !f.includes(join("mercurial", "helptext", "internals"))
|
|
2233
|
+
);
|
|
2206
2234
|
const reqDirFiles = getAllFiles(
|
|
2207
2235
|
path,
|
|
2208
2236
|
(options.multiProject ? "**/" : "") + "requirements/*.txt"
|
|
@@ -3131,34 +3159,44 @@ export const createCloudBuildBom = (path, options) => {
|
|
|
3131
3159
|
};
|
|
3132
3160
|
|
|
3133
3161
|
/**
|
|
3134
|
-
* Function to create
|
|
3162
|
+
* Function to create obom string for the current OS using osquery
|
|
3135
3163
|
*
|
|
3136
3164
|
* @param path to the project
|
|
3137
3165
|
* @param options Parse options from the cli
|
|
3138
3166
|
*/
|
|
3139
3167
|
export const createOSBom = (path, options) => {
|
|
3140
3168
|
console.warn(
|
|
3141
|
-
"About to generate
|
|
3169
|
+
"About to generate OBoM for the current OS installation. This will take several minutes ..."
|
|
3142
3170
|
);
|
|
3143
3171
|
let pkgList = [];
|
|
3144
3172
|
let bomData = {};
|
|
3173
|
+
let parentComponent = {};
|
|
3145
3174
|
for (const queryCategory of Object.keys(osQueries)) {
|
|
3146
3175
|
const queryObj = osQueries[queryCategory];
|
|
3147
3176
|
const results = executeOsQuery(queryObj.query);
|
|
3148
3177
|
const dlist = convertOSQueryResults(queryCategory, queryObj, results);
|
|
3149
3178
|
if (dlist && dlist.length) {
|
|
3150
|
-
|
|
3179
|
+
if (!Object.keys(parentComponent).length) {
|
|
3180
|
+
parentComponent = dlist.splice(0, 1)[0];
|
|
3181
|
+
}
|
|
3182
|
+
pkgList = pkgList.concat(
|
|
3183
|
+
dlist.sort(function (a, b) {
|
|
3184
|
+
return a.name.localeCompare(b.name);
|
|
3185
|
+
})
|
|
3186
|
+
);
|
|
3151
3187
|
}
|
|
3152
3188
|
} // for
|
|
3153
3189
|
if (pkgList.length) {
|
|
3154
3190
|
bomData = buildBomNSData(options, pkgList, "", {
|
|
3155
3191
|
src: "",
|
|
3156
|
-
filename: ""
|
|
3192
|
+
filename: "",
|
|
3193
|
+
parentComponent
|
|
3157
3194
|
});
|
|
3158
3195
|
}
|
|
3159
3196
|
options.bomData = bomData;
|
|
3160
3197
|
options.multiProject = true;
|
|
3161
3198
|
options.installDeps = false;
|
|
3199
|
+
options.parentComponent = parentComponent;
|
|
3162
3200
|
// Force the project type to os
|
|
3163
3201
|
options.projectType = "os";
|
|
3164
3202
|
options.lastWorkingDir = undefined;
|
|
@@ -3910,7 +3948,7 @@ export const mergeDependencies = (
|
|
|
3910
3948
|
for (const akey of Object.keys(deps_map)) {
|
|
3911
3949
|
retlist.push({
|
|
3912
3950
|
ref: akey,
|
|
3913
|
-
dependsOn: Array.from(deps_map[akey])
|
|
3951
|
+
dependsOn: Array.from(deps_map[akey]).sort()
|
|
3914
3952
|
});
|
|
3915
3953
|
}
|
|
3916
3954
|
return retlist;
|
|
@@ -4003,7 +4041,7 @@ export const createMultiXBom = async (pathList, options) => {
|
|
|
4003
4041
|
["docker", "oci", "container"].includes(options.projectType) &&
|
|
4004
4042
|
options.allLayersExplodedDir
|
|
4005
4043
|
) {
|
|
4006
|
-
const { osPackages, allTypes } = getOSPackages(
|
|
4044
|
+
const { osPackages, dependenciesList, allTypes } = getOSPackages(
|
|
4007
4045
|
options.allLayersExplodedDir
|
|
4008
4046
|
);
|
|
4009
4047
|
if (DEBUG_MODE) {
|
|
@@ -4018,6 +4056,17 @@ export const createMultiXBom = async (pathList, options) => {
|
|
|
4018
4056
|
componentsXmls = componentsXmls.concat(
|
|
4019
4057
|
listComponents(options, {}, osPackages, "", "xml")
|
|
4020
4058
|
);
|
|
4059
|
+
if (dependenciesList && dependenciesList.length) {
|
|
4060
|
+
dependencies = dependencies.concat(dependenciesList);
|
|
4061
|
+
}
|
|
4062
|
+
if (parentComponent && Object.keys(parentComponent).length) {
|
|
4063
|
+
// Make the parent oci image depend on all os components
|
|
4064
|
+
const parentDependsOn = new Set(osPackages.map((p) => p["bom-ref"]));
|
|
4065
|
+
dependencies.splice(0, 0, {
|
|
4066
|
+
ref: parentComponent["bom-ref"],
|
|
4067
|
+
dependsOn: Array.from(parentDependsOn).sort()
|
|
4068
|
+
});
|
|
4069
|
+
}
|
|
4021
4070
|
}
|
|
4022
4071
|
if (options.projectType === "os" && options.bomData) {
|
|
4023
4072
|
bomData = options.bomData;
|
|
@@ -4409,7 +4458,12 @@ export const createMultiXBom = async (pathList, options) => {
|
|
|
4409
4458
|
// Jar scanning is enabled by default
|
|
4410
4459
|
// See #330
|
|
4411
4460
|
bomData = createJarBom(path, options);
|
|
4412
|
-
if (
|
|
4461
|
+
if (
|
|
4462
|
+
bomData &&
|
|
4463
|
+
bomData.bomJson &&
|
|
4464
|
+
bomData.bomJson.components &&
|
|
4465
|
+
bomData.bomJson.components.length
|
|
4466
|
+
) {
|
|
4413
4467
|
if (DEBUG_MODE) {
|
|
4414
4468
|
console.log(
|
|
4415
4469
|
`Found ${bomData.bomJson.components.length} jar packages at ${path}`
|
|
@@ -4430,7 +4484,12 @@ export const createMultiXBom = async (pathList, options) => {
|
|
|
4430
4484
|
} // for
|
|
4431
4485
|
if (options.lastWorkingDir && options.lastWorkingDir !== "") {
|
|
4432
4486
|
bomData = createJarBom(options.lastWorkingDir, options);
|
|
4433
|
-
if (
|
|
4487
|
+
if (
|
|
4488
|
+
bomData &&
|
|
4489
|
+
bomData.bomJson &&
|
|
4490
|
+
bomData.bomJson.components &&
|
|
4491
|
+
bomData.bomJson.components.length
|
|
4492
|
+
) {
|
|
4434
4493
|
if (DEBUG_MODE) {
|
|
4435
4494
|
console.log(
|
|
4436
4495
|
`Found ${bomData.bomJson.components.length} jar packages at ${options.lastWorkingDir}`
|
|
@@ -4462,7 +4521,8 @@ export const createMultiXBom = async (pathList, options) => {
|
|
|
4462
4521
|
parentComponent.components = trimComponents(parentSubComponents, "json");
|
|
4463
4522
|
if (
|
|
4464
4523
|
parentComponent.components.length == 1 &&
|
|
4465
|
-
parentComponent.components[0].name == parentComponent.name
|
|
4524
|
+
parentComponent.components[0].name == parentComponent.name &&
|
|
4525
|
+
!parentComponent.purl.startsWith("pkg:container")
|
|
4466
4526
|
) {
|
|
4467
4527
|
parentComponent = parentComponent.components[0];
|
|
4468
4528
|
delete parentComponent.components;
|
|
@@ -4818,8 +4878,26 @@ export const createBom = async (path, options) => {
|
|
|
4818
4878
|
purl: "pkg:oci/" + inspectData.RepoDigests[0],
|
|
4819
4879
|
_integrity: inspectData.RepoDigests[0].replace("sha256:", "sha256-")
|
|
4820
4880
|
};
|
|
4881
|
+
options.parentComponent["bom-ref"] = options.parentComponent.purl;
|
|
4821
4882
|
}
|
|
4883
|
+
} else if (inspectData.Id) {
|
|
4884
|
+
options.parentComponent = {
|
|
4885
|
+
name: inspectData.RepoDigests[0].split("@")[0],
|
|
4886
|
+
version: inspectData.RepoDigests[0]
|
|
4887
|
+
.split("@")[1]
|
|
4888
|
+
.replace("sha256:", ""),
|
|
4889
|
+
type: "container",
|
|
4890
|
+
purl: "pkg:oci/" + inspectData.RepoDigests[0],
|
|
4891
|
+
_integrity: inspectData.RepoDigests[0].replace("sha256:", "sha256-")
|
|
4892
|
+
};
|
|
4893
|
+
options.parentComponent["bom-ref"] = options.parentComponent.purl;
|
|
4822
4894
|
}
|
|
4895
|
+
} else {
|
|
4896
|
+
options.parentComponent = createDefaultParentComponent(
|
|
4897
|
+
path,
|
|
4898
|
+
"container",
|
|
4899
|
+
options
|
|
4900
|
+
);
|
|
4823
4901
|
}
|
|
4824
4902
|
// Pass the entire export data about the image layers
|
|
4825
4903
|
options.exportData = exportData;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cyclonedx/cdxgen",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.7.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>",
|
|
@@ -53,8 +53,8 @@
|
|
|
53
53
|
"url": "https://github.com/cyclonedx/cdxgen/issues"
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
|
-
"@babel/parser": "^7.22.
|
|
57
|
-
"@babel/traverse": "^7.22.
|
|
56
|
+
"@babel/parser": "^7.22.11",
|
|
57
|
+
"@babel/traverse": "^7.22.11",
|
|
58
58
|
"ajv": "^8.12.0",
|
|
59
59
|
"ajv-formats": "^2.1.1",
|
|
60
60
|
"cheerio": "^1.0.0-rc.12",
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"node-stream-zip": "^1.15.0",
|
|
69
69
|
"packageurl-js": "^1.0.2",
|
|
70
70
|
"prettify-xml": "^1.2.0",
|
|
71
|
-
"properties-reader": "^2.
|
|
71
|
+
"properties-reader": "^2.3.0",
|
|
72
72
|
"semver": "^7.5.3",
|
|
73
73
|
"ssri": "^10.0.4",
|
|
74
74
|
"table": "^6.8.1",
|
|
@@ -80,7 +80,9 @@
|
|
|
80
80
|
},
|
|
81
81
|
"optionalDependencies": {
|
|
82
82
|
"@appthreat/atom": "^1.1.4",
|
|
83
|
-
"@cyclonedx/cdxgen-plugins-bin": "^1.
|
|
83
|
+
"@cyclonedx/cdxgen-plugins-bin": "^1.4.0",
|
|
84
|
+
"@cyclonedx/cdxgen-plugins-bin-arm64": "^1.4.0",
|
|
85
|
+
"@cyclonedx/cdxgen-plugins-bin-ppc64": "^1.4.0",
|
|
84
86
|
"body-parser": "^1.20.2",
|
|
85
87
|
"compression": "^1.7.4",
|
|
86
88
|
"connect": "^3.7.0",
|
|
@@ -95,8 +97,8 @@
|
|
|
95
97
|
],
|
|
96
98
|
"devDependencies": {
|
|
97
99
|
"caxa": "^3.0.1",
|
|
98
|
-
"eslint": "^8.
|
|
99
|
-
"jest": "^29.
|
|
100
|
-
"prettier": "3.0.
|
|
100
|
+
"eslint": "^8.48.0",
|
|
101
|
+
"jest": "^29.6.4",
|
|
102
|
+
"prettier": "3.0.2"
|
|
101
103
|
}
|
|
102
104
|
}
|
package/utils.js
CHANGED
|
@@ -329,21 +329,21 @@ export const getNpmMetadata = async function (pkgList) {
|
|
|
329
329
|
const _getDepPkgList = async function (
|
|
330
330
|
pkgLockFile,
|
|
331
331
|
pkgList,
|
|
332
|
-
dependenciesList,
|
|
333
332
|
depKeys,
|
|
334
|
-
pkg
|
|
333
|
+
pkg,
|
|
334
|
+
versionCache
|
|
335
335
|
) {
|
|
336
|
-
const pkgDependencies =
|
|
337
|
-
pkg.
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
const versionCache = {};
|
|
336
|
+
const pkgDependencies = {
|
|
337
|
+
...(pkg.packages || {}),
|
|
338
|
+
...(pkg.dependencies || {})
|
|
339
|
+
};
|
|
341
340
|
if (pkg.packages) {
|
|
342
341
|
for (const k in pkg.packages) {
|
|
343
342
|
if (k === "") {
|
|
344
343
|
continue;
|
|
345
344
|
}
|
|
346
345
|
const pl = pkg.packages[k];
|
|
346
|
+
versionCache[k] = pl.version;
|
|
347
347
|
versionCache[k.replaceAll("node_modules/", "")] = pl.version;
|
|
348
348
|
}
|
|
349
349
|
}
|
|
@@ -355,7 +355,13 @@ const _getDepPkgList = async function (
|
|
|
355
355
|
continue;
|
|
356
356
|
}
|
|
357
357
|
const name = k;
|
|
358
|
-
|
|
358
|
+
let version = pkgDependencies[name].version;
|
|
359
|
+
if (!version && versionCache[k]) {
|
|
360
|
+
version = versionCache[k];
|
|
361
|
+
}
|
|
362
|
+
if (!version && pkgDependencies["node_modules/" + name]) {
|
|
363
|
+
version = pkgDependencies["node_modules/" + name].version;
|
|
364
|
+
}
|
|
359
365
|
const purl = new PackageURL(
|
|
360
366
|
"npm",
|
|
361
367
|
"",
|
|
@@ -415,32 +421,20 @@ const _getDepPkgList = async function (
|
|
|
415
421
|
const deppurlString = decodeURIComponent(deppurl.toString());
|
|
416
422
|
deplist.push(deppurlString);
|
|
417
423
|
}
|
|
418
|
-
|
|
419
|
-
dependenciesList.push({
|
|
420
|
-
ref: purlString,
|
|
421
|
-
dependsOn: deplist
|
|
422
|
-
});
|
|
423
|
-
depKeys[purlString] = true;
|
|
424
|
-
}
|
|
424
|
+
depKeys[purlString] = (depKeys[purlString] || []).concat(deplist);
|
|
425
425
|
if (pkg.lockfileVersion && pkg.lockfileVersion >= 3) {
|
|
426
426
|
// Do not recurse for lock file v3 and above
|
|
427
427
|
} else {
|
|
428
428
|
await _getDepPkgList(
|
|
429
429
|
pkgLockFile,
|
|
430
430
|
pkgList,
|
|
431
|
-
dependenciesList,
|
|
432
431
|
depKeys,
|
|
433
|
-
pkgDependencies[name]
|
|
432
|
+
pkgDependencies[name],
|
|
433
|
+
versionCache
|
|
434
434
|
);
|
|
435
435
|
}
|
|
436
|
-
} else {
|
|
437
|
-
|
|
438
|
-
dependenciesList.push({
|
|
439
|
-
ref: purlString,
|
|
440
|
-
dependsOn: []
|
|
441
|
-
});
|
|
442
|
-
depKeys[purlString] = true;
|
|
443
|
-
}
|
|
436
|
+
} else if (!depKeys[purlString]) {
|
|
437
|
+
depKeys[purlString] = [];
|
|
444
438
|
}
|
|
445
439
|
}
|
|
446
440
|
}
|
|
@@ -519,6 +513,7 @@ export const parsePkgLock = async (pkgLockFile, options = {}) => {
|
|
|
519
513
|
const dependenciesList = [];
|
|
520
514
|
const depKeys = {};
|
|
521
515
|
let rootPkg = {};
|
|
516
|
+
const versionCache = {};
|
|
522
517
|
if (!options) {
|
|
523
518
|
options = {};
|
|
524
519
|
}
|
|
@@ -612,11 +607,17 @@ export const parsePkgLock = async (pkgLockFile, options = {}) => {
|
|
|
612
607
|
pkgList = await _getDepPkgList(
|
|
613
608
|
pkgLockFile,
|
|
614
609
|
pkgList,
|
|
615
|
-
dependenciesList,
|
|
616
610
|
depKeys,
|
|
617
|
-
lockData
|
|
611
|
+
lockData,
|
|
612
|
+
versionCache
|
|
618
613
|
);
|
|
619
614
|
}
|
|
615
|
+
for (const dk of Object.keys(depKeys)) {
|
|
616
|
+
dependenciesList.push({
|
|
617
|
+
ref: dk,
|
|
618
|
+
dependsOn: depKeys[dk] || []
|
|
619
|
+
});
|
|
620
|
+
}
|
|
620
621
|
if (fetchLicenses && pkgList && pkgList.length) {
|
|
621
622
|
if (DEBUG_MODE) {
|
|
622
623
|
console.log(
|
|
@@ -2007,7 +2008,8 @@ export const guessLicenseId = function (content) {
|
|
|
2007
2008
|
* @param {Array} pkgList Package list
|
|
2008
2009
|
*/
|
|
2009
2010
|
export const getMvnMetadata = async function (pkgList) {
|
|
2010
|
-
const MAVEN_CENTRAL_URL =
|
|
2011
|
+
const MAVEN_CENTRAL_URL =
|
|
2012
|
+
process.env.MAVEN_CENTRAL_URL || "https://repo1.maven.org/maven2/";
|
|
2011
2013
|
const ANDROID_MAVEN = "https://maven.google.com/";
|
|
2012
2014
|
const cdepList = [];
|
|
2013
2015
|
if (!pkgList || !pkgList.length) {
|
|
@@ -3285,14 +3287,15 @@ export const getCratesMetadata = async function (pkgList) {
|
|
|
3285
3287
|
* @param {Array} pkgList Package list
|
|
3286
3288
|
*/
|
|
3287
3289
|
export const getDartMetadata = async function (pkgList) {
|
|
3288
|
-
const PUB_DEV_URL = "https://pub.dev
|
|
3290
|
+
const PUB_DEV_URL = process.env.PUB_DEV_URL || "https://pub.dev";
|
|
3291
|
+
const PUB_PACKAGES_URL = PUB_DEV_URL + "/api/packages/";
|
|
3289
3292
|
const cdepList = [];
|
|
3290
3293
|
for (const p of pkgList) {
|
|
3291
3294
|
try {
|
|
3292
3295
|
if (DEBUG_MODE) {
|
|
3293
|
-
console.log(`Querying
|
|
3296
|
+
console.log(`Querying ${PUB_DEV_URL} for ${p.name}`);
|
|
3294
3297
|
}
|
|
3295
|
-
const res = await cdxgenAgent.get(
|
|
3298
|
+
const res = await cdxgenAgent.get(PUB_PACKAGES_URL + p.name, {
|
|
3296
3299
|
responseType: "json",
|
|
3297
3300
|
headers: {
|
|
3298
3301
|
Accept: "application/vnd.pub.v2+json"
|
|
@@ -3310,7 +3313,7 @@ export const getDartMetadata = async function (pkgList) {
|
|
|
3310
3313
|
if (pubspec.homepage) {
|
|
3311
3314
|
p.homepage = { url: pubspec.homepage };
|
|
3312
3315
|
}
|
|
3313
|
-
p.license =
|
|
3316
|
+
p.license = `${PUB_DEV_URL}/packages/${p.name}/license`;
|
|
3314
3317
|
cdepList.push(p);
|
|
3315
3318
|
break;
|
|
3316
3319
|
}
|
|
@@ -4764,49 +4767,99 @@ export const convertOSQueryResults = function (
|
|
|
4764
4767
|
const pkgList = [];
|
|
4765
4768
|
if (results && results.length) {
|
|
4766
4769
|
for (const res of results) {
|
|
4767
|
-
|
|
4768
|
-
|
|
4769
|
-
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
|
|
4773
|
-
|
|
4774
|
-
|
|
4775
|
-
|
|
4776
|
-
|
|
4777
|
-
|
|
4778
|
-
|
|
4779
|
-
|
|
4780
|
-
|
|
4781
|
-
|
|
4782
|
-
|
|
4783
|
-
|
|
4784
|
-
|
|
4785
|
-
|
|
4786
|
-
|
|
4787
|
-
|
|
4788
|
-
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
|
|
4792
|
-
|
|
4793
|
-
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
|
|
4797
|
-
|
|
4798
|
-
|
|
4799
|
-
|
|
4800
|
-
|
|
4801
|
-
|
|
4802
|
-
|
|
4803
|
-
|
|
4804
|
-
|
|
4805
|
-
|
|
4806
|
-
|
|
4807
|
-
|
|
4808
|
-
|
|
4770
|
+
const version =
|
|
4771
|
+
res.version ||
|
|
4772
|
+
res.hotfix_id ||
|
|
4773
|
+
res.hardware_version ||
|
|
4774
|
+
res.port ||
|
|
4775
|
+
res.pid ||
|
|
4776
|
+
res.subject_key_id ||
|
|
4777
|
+
res.interface ||
|
|
4778
|
+
res.instance_id;
|
|
4779
|
+
let name =
|
|
4780
|
+
res.name ||
|
|
4781
|
+
res.device_id ||
|
|
4782
|
+
res.hotfix_id ||
|
|
4783
|
+
res.uuid ||
|
|
4784
|
+
res.serial ||
|
|
4785
|
+
res.pid ||
|
|
4786
|
+
res.address ||
|
|
4787
|
+
res.ami_id ||
|
|
4788
|
+
res.interface ||
|
|
4789
|
+
res.client_app_id;
|
|
4790
|
+
let group = "";
|
|
4791
|
+
const subpath = res.path || res.admindir || res.source;
|
|
4792
|
+
let publisher =
|
|
4793
|
+
res.publisher ||
|
|
4794
|
+
res.maintainer ||
|
|
4795
|
+
res.creator ||
|
|
4796
|
+
res.manufacturer ||
|
|
4797
|
+
res.provider ||
|
|
4798
|
+
"";
|
|
4799
|
+
if (publisher === "null") {
|
|
4800
|
+
publisher = "";
|
|
4801
|
+
}
|
|
4802
|
+
let scope = undefined;
|
|
4803
|
+
const compScope = res.priority;
|
|
4804
|
+
if (["required", "optional", "excluded"].includes(compScope)) {
|
|
4805
|
+
scope = compScope;
|
|
4806
|
+
}
|
|
4807
|
+
const description =
|
|
4808
|
+
res.description ||
|
|
4809
|
+
res.summary ||
|
|
4810
|
+
res.arguments ||
|
|
4811
|
+
res.device ||
|
|
4812
|
+
res.codename ||
|
|
4813
|
+
res.section ||
|
|
4814
|
+
res.status ||
|
|
4815
|
+
res.identifier ||
|
|
4816
|
+
res.components ||
|
|
4817
|
+
"";
|
|
4818
|
+
// Re-use the name from query obj
|
|
4819
|
+
if (!name && results.length === 1 && queryObj.name) {
|
|
4820
|
+
name = queryObj.name;
|
|
4821
|
+
}
|
|
4822
|
+
let qualifiers = undefined;
|
|
4823
|
+
if (res.identifying_number && res.identifying_number.length) {
|
|
4824
|
+
qualifiers = {
|
|
4825
|
+
tag_id: res.identifying_number.replace("{", "").replace("}", "")
|
|
4826
|
+
};
|
|
4827
|
+
}
|
|
4828
|
+
if (name) {
|
|
4829
|
+
name = name.replace(/ /g, "+").replace(/[:%]/g, "-");
|
|
4830
|
+
group = group.replace(/ /g, "+").replace(/[:%]/g, "-");
|
|
4831
|
+
const purl = new PackageURL(
|
|
4832
|
+
queryObj.purlType || "swid",
|
|
4833
|
+
group,
|
|
4834
|
+
name,
|
|
4835
|
+
version || "",
|
|
4836
|
+
qualifiers,
|
|
4837
|
+
subpath
|
|
4838
|
+
).toString();
|
|
4839
|
+
const apkg = {
|
|
4840
|
+
name,
|
|
4841
|
+
group,
|
|
4842
|
+
version: version || "",
|
|
4843
|
+
description,
|
|
4844
|
+
publisher,
|
|
4845
|
+
"bom-ref": decodeURIComponent(purl),
|
|
4846
|
+
purl,
|
|
4847
|
+
scope,
|
|
4848
|
+
type: queryObj.componentType
|
|
4849
|
+
};
|
|
4850
|
+
const props = [{ name: "cdx:osquery:category", value: queryCategory }];
|
|
4851
|
+
for (const k of Object.keys(res).filter(
|
|
4852
|
+
(p) => !["name", "version", "description", "publisher"].includes(p)
|
|
4853
|
+
)) {
|
|
4854
|
+
if (res[k] && res[k] !== "null") {
|
|
4855
|
+
props.push({
|
|
4856
|
+
name: k,
|
|
4857
|
+
value: res[k]
|
|
4858
|
+
});
|
|
4859
|
+
}
|
|
4809
4860
|
}
|
|
4861
|
+
apkg.properties = props;
|
|
4862
|
+
pkgList.push(apkg);
|
|
4810
4863
|
}
|
|
4811
4864
|
}
|
|
4812
4865
|
}
|
|
@@ -5783,27 +5836,37 @@ export const executeAtom = (src, args) => {
|
|
|
5783
5836
|
}
|
|
5784
5837
|
const freeMemoryGB = Math.floor(freemem() / 1024 / 1024 / 1024);
|
|
5785
5838
|
if (DEBUG_MODE) {
|
|
5786
|
-
console.log("
|
|
5839
|
+
console.log("Executing", ATOM_BIN, args.join(" "));
|
|
5787
5840
|
}
|
|
5788
5841
|
const env = {
|
|
5789
5842
|
...process.env,
|
|
5790
5843
|
JAVA_OPTS: `-Xms${freeMemoryGB}G -Xmx${freeMemoryGB}G`
|
|
5791
5844
|
};
|
|
5845
|
+
env.PATH = `${env.PATH}${_delimiter}${join(
|
|
5846
|
+
dirNameStr,
|
|
5847
|
+
"node_modules",
|
|
5848
|
+
".bin"
|
|
5849
|
+
)}`;
|
|
5792
5850
|
const result = spawnSync(ATOM_BIN, args, {
|
|
5793
5851
|
cwd,
|
|
5794
5852
|
encoding: "utf-8",
|
|
5795
5853
|
timeout: TIMEOUT_MS,
|
|
5796
5854
|
env
|
|
5797
5855
|
});
|
|
5798
|
-
if (
|
|
5799
|
-
|
|
5800
|
-
|
|
5801
|
-
|
|
5802
|
-
|
|
5803
|
-
|
|
5804
|
-
|
|
5805
|
-
|
|
5806
|
-
|
|
5856
|
+
if (result.stderr) {
|
|
5857
|
+
if (
|
|
5858
|
+
result.stderr.includes(
|
|
5859
|
+
"has been compiled by a more recent version of the Java Runtime"
|
|
5860
|
+
)
|
|
5861
|
+
) {
|
|
5862
|
+
console.log(
|
|
5863
|
+
"Atom requires Java 17 or above. Please install a suitable version and re-run cdxgen to improve the SBoM accuracy.\nAlternatively, use the cdxgen container image."
|
|
5864
|
+
);
|
|
5865
|
+
} else if (result.stderr.includes("astgen")) {
|
|
5866
|
+
console.warn(
|
|
5867
|
+
"WARN: Unable to locate astgen command. Install atom globally using sudo npm install -g @appthreat/atom to resolve this issue."
|
|
5868
|
+
);
|
|
5869
|
+
}
|
|
5807
5870
|
}
|
|
5808
5871
|
if (DEBUG_MODE) {
|
|
5809
5872
|
if (result.stdout) {
|
|
@@ -5813,7 +5876,7 @@ export const executeAtom = (src, args) => {
|
|
|
5813
5876
|
console.log(result.stderr);
|
|
5814
5877
|
}
|
|
5815
5878
|
}
|
|
5816
|
-
return
|
|
5879
|
+
return !result.error;
|
|
5817
5880
|
};
|
|
5818
5881
|
|
|
5819
5882
|
/**
|
|
@@ -6232,3 +6295,14 @@ export const addEvidenceForImports = (pkgList, allImports) => {
|
|
|
6232
6295
|
}
|
|
6233
6296
|
return pkgList;
|
|
6234
6297
|
};
|
|
6298
|
+
|
|
6299
|
+
export const componentSorter = (a, b) => {
|
|
6300
|
+
if (a && b) {
|
|
6301
|
+
for (const k of ["bom-ref", "purl", "name"]) {
|
|
6302
|
+
if (a[k] && b[k]) {
|
|
6303
|
+
return a[k].localeCompare(b[k]);
|
|
6304
|
+
}
|
|
6305
|
+
}
|
|
6306
|
+
}
|
|
6307
|
+
return a.localeCompare(b);
|
|
6308
|
+
};
|
package/utils.test.js
CHANGED
|
@@ -1358,8 +1358,8 @@ test("parsePkgLock", async () => {
|
|
|
1358
1358
|
});
|
|
1359
1359
|
parsedList = await parsePkgLock("./test/data/package-lock-v2.json");
|
|
1360
1360
|
deps = parsedList.pkgList;
|
|
1361
|
-
expect(deps.length).toEqual(
|
|
1362
|
-
expect(parsedList.dependenciesList.length).toEqual(
|
|
1361
|
+
expect(deps.length).toEqual(5433);
|
|
1362
|
+
expect(parsedList.dependenciesList.length).toEqual(1616);
|
|
1363
1363
|
expect(deps[0]).toEqual({
|
|
1364
1364
|
"bom-ref": "pkg:npm/flink-dashboard@2.0.0",
|
|
1365
1365
|
group: "",
|