@cyclonedx/cdxgen 9.0.1 → 9.1.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 +64 -25
- package/analyzer.js +1 -1
- package/bin/cdxgen.js +18 -24
- package/binary.js +7 -7
- package/data/bom-1.5.schema.json +3660 -0
- package/data/jsf-0.82.schema.json +211 -0
- package/data/pypi-pkg-aliases.json +84 -77
- package/data/spdx.schema.json +621 -0
- package/display.js +102 -0
- package/display.test.js +10 -0
- package/docker.js +12 -24
- package/docker.test.js +1 -1
- package/index.js +316 -300
- package/package.json +5 -3
- package/piptree.js +136 -0
- package/server.js +2 -2
- package/utils.js +500 -218
- package/utils.test.js +301 -35
package/utils.js
CHANGED
|
@@ -48,6 +48,7 @@ import { satisfies, coerce, maxSatisfying, clean, valid } from "semver";
|
|
|
48
48
|
import StreamZip from "node-stream-zip";
|
|
49
49
|
import { parseEDNString } from "edn-data";
|
|
50
50
|
import { PackageURL } from "packageurl-js";
|
|
51
|
+
import { getTreeWithPlugin } from "./piptree.js";
|
|
51
52
|
|
|
52
53
|
const selfPJson = JSON.parse(readFileSync(join(dirName, "package.json")));
|
|
53
54
|
const _version = selfPJson.version;
|
|
@@ -195,7 +196,7 @@ export function getLicenses(pkg, format = "xml") {
|
|
|
195
196
|
* the text to the license text object and stop.
|
|
196
197
|
*/
|
|
197
198
|
export function addLicenseText(pkg, l, licenseContent, format = "xml") {
|
|
198
|
-
|
|
199
|
+
const licenseFilenames = [
|
|
199
200
|
"LICENSE",
|
|
200
201
|
"License",
|
|
201
202
|
"license",
|
|
@@ -206,7 +207,7 @@ export function addLicenseText(pkg, l, licenseContent, format = "xml") {
|
|
|
206
207
|
"Notice",
|
|
207
208
|
"notice"
|
|
208
209
|
];
|
|
209
|
-
|
|
210
|
+
const licenseContentTypes = {
|
|
210
211
|
"text/plain": "",
|
|
211
212
|
"text/txt": ".txt",
|
|
212
213
|
"text/markdown": ".md",
|
|
@@ -219,7 +220,7 @@ export function addLicenseText(pkg, l, licenseContent, format = "xml") {
|
|
|
219
220
|
for (const [licenseContentType, fileExtension] of Object.entries(
|
|
220
221
|
licenseContentTypes
|
|
221
222
|
)) {
|
|
222
|
-
|
|
223
|
+
const licenseFilepath = `${pkg.realPath}/${licenseFilename}${licenseName}${fileExtension}`;
|
|
223
224
|
if (existsSync(licenseFilepath)) {
|
|
224
225
|
licenseContent.text = readLicenseText(
|
|
225
226
|
licenseFilepath,
|
|
@@ -242,16 +243,16 @@ export function readLicenseText(
|
|
|
242
243
|
licenseContentType,
|
|
243
244
|
format = "xml"
|
|
244
245
|
) {
|
|
245
|
-
|
|
246
|
+
const licenseText = readFileSync(licenseFilepath, "utf8");
|
|
246
247
|
if (licenseText) {
|
|
247
248
|
if (format === "xml") {
|
|
248
|
-
|
|
249
|
+
const licenseContentText = { "#cdata": licenseText };
|
|
249
250
|
if (licenseContentType !== "text/plain") {
|
|
250
251
|
licenseContentText["@content-type"] = licenseContentType;
|
|
251
252
|
}
|
|
252
253
|
return licenseContentText;
|
|
253
254
|
} else {
|
|
254
|
-
|
|
255
|
+
const licenseContentText = { content: licenseText };
|
|
255
256
|
if (licenseContentType !== "text/plain") {
|
|
256
257
|
licenseContentText["contentType"] = licenseContentType;
|
|
257
258
|
}
|
|
@@ -315,7 +316,7 @@ const _getDepPkgList = async function (
|
|
|
315
316
|
depKeys,
|
|
316
317
|
pkg
|
|
317
318
|
) {
|
|
318
|
-
|
|
319
|
+
const pkgDependencies =
|
|
319
320
|
pkg.lockfileVersion && pkg.lockfileVersion >= 3
|
|
320
321
|
? pkg.packages
|
|
321
322
|
: pkg.dependencies;
|
|
@@ -326,7 +327,7 @@ const _getDepPkgList = async function (
|
|
|
326
327
|
if (k === "") {
|
|
327
328
|
continue;
|
|
328
329
|
}
|
|
329
|
-
|
|
330
|
+
const name = k;
|
|
330
331
|
const version = pkgDependencies[name].version;
|
|
331
332
|
const purl = new PackageURL(
|
|
332
333
|
"npm",
|
|
@@ -337,7 +338,7 @@ const _getDepPkgList = async function (
|
|
|
337
338
|
null
|
|
338
339
|
);
|
|
339
340
|
const purlString = decodeURIComponent(purl.toString());
|
|
340
|
-
|
|
341
|
+
const scope = pkgDependencies[name].dev === true ? "optional" : undefined;
|
|
341
342
|
const apkg = {
|
|
342
343
|
name: name.replace("node_modules/", ""),
|
|
343
344
|
version,
|
|
@@ -348,7 +349,20 @@ const _getDepPkgList = async function (
|
|
|
348
349
|
name: "SrcFile",
|
|
349
350
|
value: pkgLockFile
|
|
350
351
|
}
|
|
351
|
-
]
|
|
352
|
+
],
|
|
353
|
+
evidence: {
|
|
354
|
+
identity: {
|
|
355
|
+
field: "purl",
|
|
356
|
+
confidence: 1,
|
|
357
|
+
methods: [
|
|
358
|
+
{
|
|
359
|
+
technique: "manifest-analysis",
|
|
360
|
+
confidence: 1,
|
|
361
|
+
value: pkgLockFile
|
|
362
|
+
}
|
|
363
|
+
]
|
|
364
|
+
}
|
|
365
|
+
}
|
|
352
366
|
};
|
|
353
367
|
pkgList.push(apkg);
|
|
354
368
|
if (pkgDependencies[name].dependencies) {
|
|
@@ -422,7 +436,20 @@ export const parsePkgJson = async (pkgJsonFile) => {
|
|
|
422
436
|
name: "SrcFile",
|
|
423
437
|
value: pkgJsonFile
|
|
424
438
|
}
|
|
425
|
-
]
|
|
439
|
+
],
|
|
440
|
+
evidence: {
|
|
441
|
+
identity: {
|
|
442
|
+
field: "purl",
|
|
443
|
+
confidence: 1,
|
|
444
|
+
methods: [
|
|
445
|
+
{
|
|
446
|
+
technique: "manifest-analysis",
|
|
447
|
+
confidence: 1,
|
|
448
|
+
value: pkgJsonFile
|
|
449
|
+
}
|
|
450
|
+
]
|
|
451
|
+
}
|
|
452
|
+
}
|
|
426
453
|
});
|
|
427
454
|
} catch (err) {
|
|
428
455
|
// continue regardless of error
|
|
@@ -446,8 +473,8 @@ export const parsePkgJson = async (pkgJsonFile) => {
|
|
|
446
473
|
*/
|
|
447
474
|
export const parsePkgLock = async (pkgLockFile) => {
|
|
448
475
|
let pkgList = [];
|
|
449
|
-
|
|
450
|
-
|
|
476
|
+
const dependenciesList = [];
|
|
477
|
+
const depKeys = {};
|
|
451
478
|
let rootPkg = {};
|
|
452
479
|
if (existsSync(pkgLockFile)) {
|
|
453
480
|
const lockData = JSON.parse(readFileSync(pkgLockFile, "utf8"));
|
|
@@ -652,7 +679,20 @@ export const parseYarnLock = async function (yarnLockFile) {
|
|
|
652
679
|
name: "SrcFile",
|
|
653
680
|
value: yarnLockFile
|
|
654
681
|
}
|
|
655
|
-
]
|
|
682
|
+
],
|
|
683
|
+
evidence: {
|
|
684
|
+
identity: {
|
|
685
|
+
field: "purl",
|
|
686
|
+
confidence: 1,
|
|
687
|
+
methods: [
|
|
688
|
+
{
|
|
689
|
+
technique: "manifest-analysis",
|
|
690
|
+
confidence: 1,
|
|
691
|
+
value: yarnLockFile
|
|
692
|
+
}
|
|
693
|
+
]
|
|
694
|
+
}
|
|
695
|
+
}
|
|
656
696
|
});
|
|
657
697
|
// Reset all the variables
|
|
658
698
|
group = "";
|
|
@@ -766,7 +806,7 @@ export const parseNodeShrinkwrap = async function (swFile) {
|
|
|
766
806
|
if (existsSync(swFile)) {
|
|
767
807
|
const lockData = JSON.parse(readFileSync(swFile, "utf8"));
|
|
768
808
|
const pkgKeys = Object.keys(lockData);
|
|
769
|
-
for (
|
|
809
|
+
for (const k in pkgKeys) {
|
|
770
810
|
const fullName = pkgKeys[k];
|
|
771
811
|
const integrity = lockData[fullName];
|
|
772
812
|
const parts = fullName.split("@");
|
|
@@ -779,7 +819,7 @@ export const parseNodeShrinkwrap = async function (swFile) {
|
|
|
779
819
|
version = parts[1];
|
|
780
820
|
} else if (parts.length === 3) {
|
|
781
821
|
if (parts[0] === "") {
|
|
782
|
-
|
|
822
|
+
const gnameparts = parts[1].split("/");
|
|
783
823
|
group = gnameparts[0];
|
|
784
824
|
name = gnameparts[1];
|
|
785
825
|
} else {
|
|
@@ -798,7 +838,20 @@ export const parseNodeShrinkwrap = async function (swFile) {
|
|
|
798
838
|
name: "SrcFile",
|
|
799
839
|
value: swFile
|
|
800
840
|
}
|
|
801
|
-
]
|
|
841
|
+
],
|
|
842
|
+
evidence: {
|
|
843
|
+
identity: {
|
|
844
|
+
field: "purl",
|
|
845
|
+
confidence: 1,
|
|
846
|
+
methods: [
|
|
847
|
+
{
|
|
848
|
+
technique: "manifest-analysis",
|
|
849
|
+
confidence: 1,
|
|
850
|
+
value: swFile
|
|
851
|
+
}
|
|
852
|
+
]
|
|
853
|
+
}
|
|
854
|
+
}
|
|
802
855
|
});
|
|
803
856
|
}
|
|
804
857
|
}
|
|
@@ -874,7 +927,7 @@ export const parsePnpmLock = async function (pnpmLock, parentComponent = null) {
|
|
|
874
927
|
}
|
|
875
928
|
const packages = yamlObj.packages;
|
|
876
929
|
const pkgKeys = Object.keys(packages);
|
|
877
|
-
for (
|
|
930
|
+
for (const k in pkgKeys) {
|
|
878
931
|
// Eg: @babel/code-frame/7.10.1
|
|
879
932
|
// In lockfileVersion 6, /@babel/code-frame@7.18.6
|
|
880
933
|
let fullName = pkgKeys[k].replace("/@", "@");
|
|
@@ -885,7 +938,7 @@ export const parsePnpmLock = async function (pnpmLock, parentComponent = null) {
|
|
|
885
938
|
const parts = fullName.split("/");
|
|
886
939
|
const integrity = packages[pkgKeys[k]].resolution.integrity;
|
|
887
940
|
const deps = packages[pkgKeys[k]].dependencies || [];
|
|
888
|
-
|
|
941
|
+
const scope = packages[pkgKeys[k]].dev === true ? "optional" : undefined;
|
|
889
942
|
if (parts && parts.length) {
|
|
890
943
|
let name = "";
|
|
891
944
|
let version = "";
|
|
@@ -952,7 +1005,20 @@ export const parsePnpmLock = async function (pnpmLock, parentComponent = null) {
|
|
|
952
1005
|
name: "SrcFile",
|
|
953
1006
|
value: pnpmLock
|
|
954
1007
|
}
|
|
955
|
-
]
|
|
1008
|
+
],
|
|
1009
|
+
evidence: {
|
|
1010
|
+
identity: {
|
|
1011
|
+
field: "purl",
|
|
1012
|
+
confidence: 1,
|
|
1013
|
+
methods: [
|
|
1014
|
+
{
|
|
1015
|
+
technique: "manifest-analysis",
|
|
1016
|
+
confidence: 1,
|
|
1017
|
+
value: pnpmLock
|
|
1018
|
+
}
|
|
1019
|
+
]
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
956
1022
|
});
|
|
957
1023
|
}
|
|
958
1024
|
}
|
|
@@ -998,7 +1064,20 @@ export const parseBowerJson = async (bowerJsonFile) => {
|
|
|
998
1064
|
name: "SrcFile",
|
|
999
1065
|
value: bowerJsonFile
|
|
1000
1066
|
}
|
|
1001
|
-
]
|
|
1067
|
+
],
|
|
1068
|
+
evidence: {
|
|
1069
|
+
identity: {
|
|
1070
|
+
field: "purl",
|
|
1071
|
+
confidence: 1,
|
|
1072
|
+
methods: [
|
|
1073
|
+
{
|
|
1074
|
+
technique: "manifest-analysis",
|
|
1075
|
+
confidence: 1,
|
|
1076
|
+
value: bowerJsonFile
|
|
1077
|
+
}
|
|
1078
|
+
]
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1002
1081
|
});
|
|
1003
1082
|
} catch (err) {
|
|
1004
1083
|
// continue regardless of error
|
|
@@ -1049,7 +1128,7 @@ export const parseMinJs = async (minJsFile) => {
|
|
|
1049
1128
|
: pkgNameVer.split(" ");
|
|
1050
1129
|
if (tmpB && tmpB.length > 1) {
|
|
1051
1130
|
// Fix #223 - lowercase parsed package name
|
|
1052
|
-
|
|
1131
|
+
const name = tmpB[0].replace(/ /g, "-").trim().toLowerCase();
|
|
1053
1132
|
if (
|
|
1054
1133
|
["copyright", "author", "licensed"].includes(name.toLowerCase())
|
|
1055
1134
|
) {
|
|
@@ -1066,7 +1145,20 @@ export const parseMinJs = async (minJsFile) => {
|
|
|
1066
1145
|
name: "SrcFile",
|
|
1067
1146
|
value: minJsFile
|
|
1068
1147
|
}
|
|
1069
|
-
]
|
|
1148
|
+
],
|
|
1149
|
+
evidence: {
|
|
1150
|
+
identity: {
|
|
1151
|
+
field: "purl",
|
|
1152
|
+
confidence: 0.25,
|
|
1153
|
+
methods: [
|
|
1154
|
+
{
|
|
1155
|
+
technique: "filename",
|
|
1156
|
+
confidence: 0.25,
|
|
1157
|
+
value: minJsFile
|
|
1158
|
+
}
|
|
1159
|
+
]
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1070
1162
|
});
|
|
1071
1163
|
}
|
|
1072
1164
|
return;
|
|
@@ -1111,7 +1203,7 @@ export const parsePom = function (pomFile) {
|
|
|
1111
1203
|
} else if (dependencies && !Array.isArray(dependencies)) {
|
|
1112
1204
|
dependencies = [dependencies];
|
|
1113
1205
|
}
|
|
1114
|
-
for (
|
|
1206
|
+
for (const adep of dependencies) {
|
|
1115
1207
|
const version = adep.version;
|
|
1116
1208
|
let versionStr = undefined;
|
|
1117
1209
|
if (version && version._ && version._.indexOf("$") == -1) {
|
|
@@ -1127,7 +1219,20 @@ export const parsePom = function (pomFile) {
|
|
|
1127
1219
|
name: "SrcFile",
|
|
1128
1220
|
value: pomFile
|
|
1129
1221
|
}
|
|
1130
|
-
]
|
|
1222
|
+
],
|
|
1223
|
+
evidence: {
|
|
1224
|
+
identity: {
|
|
1225
|
+
field: "purl",
|
|
1226
|
+
confidence: 1,
|
|
1227
|
+
methods: [
|
|
1228
|
+
{
|
|
1229
|
+
technique: "manifest-analysis",
|
|
1230
|
+
confidence: 1,
|
|
1231
|
+
value: pomFile
|
|
1232
|
+
}
|
|
1233
|
+
]
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1131
1236
|
});
|
|
1132
1237
|
}
|
|
1133
1238
|
}
|
|
@@ -1150,7 +1255,7 @@ export const parseMavenTree = function (rawOutput) {
|
|
|
1150
1255
|
const tmpA = rawOutput.split("\n");
|
|
1151
1256
|
let last_level = 0;
|
|
1152
1257
|
let last_purl = "";
|
|
1153
|
-
|
|
1258
|
+
const stack = [];
|
|
1154
1259
|
tmpA.forEach((l) => {
|
|
1155
1260
|
if (!includeMavenTestScope && l.trim().endsWith(":test")) {
|
|
1156
1261
|
return;
|
|
@@ -1314,7 +1419,7 @@ export const parseGradleDep = function (
|
|
|
1314
1419
|
) {
|
|
1315
1420
|
last_level = 1;
|
|
1316
1421
|
if (rline.startsWith("+--- project :")) {
|
|
1317
|
-
|
|
1422
|
+
const tmpProj = rline.split("+--- project :");
|
|
1318
1423
|
last_project_purl = `pkg:maven/${tmpProj[1].trim()}@${rootProjectVersion}?type=jar`;
|
|
1319
1424
|
stack = [last_project_purl];
|
|
1320
1425
|
last_purl = last_project_purl;
|
|
@@ -1481,17 +1586,17 @@ export const parseLeinDep = function (rawOutput) {
|
|
|
1481
1586
|
|
|
1482
1587
|
export const parseLeinMap = function (node, keys_cache, deps) {
|
|
1483
1588
|
if (node["map"]) {
|
|
1484
|
-
for (
|
|
1589
|
+
for (const n of node["map"]) {
|
|
1485
1590
|
if (n.length === 2) {
|
|
1486
1591
|
const rootNode = n[0];
|
|
1487
|
-
|
|
1488
|
-
|
|
1592
|
+
const psym = rootNode[0].sym;
|
|
1593
|
+
const version = rootNode[1];
|
|
1489
1594
|
let group = dirname(psym);
|
|
1490
1595
|
if (group === ".") {
|
|
1491
1596
|
group = "";
|
|
1492
1597
|
}
|
|
1493
|
-
|
|
1494
|
-
|
|
1598
|
+
const name = basename(psym);
|
|
1599
|
+
const cacheKey = group + "-" + name + "-" + version;
|
|
1495
1600
|
if (!keys_cache[cacheKey]) {
|
|
1496
1601
|
keys_cache[cacheKey] = true;
|
|
1497
1602
|
deps.push({ group, name, version });
|
|
@@ -1524,7 +1629,7 @@ export const parseGradleProjects = function (rawOutput) {
|
|
|
1524
1629
|
} else if (l.includes("--- Project")) {
|
|
1525
1630
|
const tmpB = l.split("Project ");
|
|
1526
1631
|
if (tmpB && tmpB.length > 1) {
|
|
1527
|
-
|
|
1632
|
+
const projName = tmpB[1].split(" ")[0].replace(/'/g, "");
|
|
1528
1633
|
// Include all projects including test projects
|
|
1529
1634
|
if (projName.startsWith(":")) {
|
|
1530
1635
|
projects.add(projName);
|
|
@@ -1533,7 +1638,7 @@ export const parseGradleProjects = function (rawOutput) {
|
|
|
1533
1638
|
} else if (l.includes("--- project ")) {
|
|
1534
1639
|
const tmpB = l.split("--- project ");
|
|
1535
1640
|
if (tmpB && tmpB.length > 1) {
|
|
1536
|
-
|
|
1641
|
+
const projName = tmpB[1];
|
|
1537
1642
|
if (projName.startsWith(":")) {
|
|
1538
1643
|
projects.add(projName);
|
|
1539
1644
|
}
|
|
@@ -1554,7 +1659,7 @@ export const parseGradleProjects = function (rawOutput) {
|
|
|
1554
1659
|
*/
|
|
1555
1660
|
export const parseGradleProperties = function (rawOutput) {
|
|
1556
1661
|
let rootProject = "root";
|
|
1557
|
-
|
|
1662
|
+
const projects = new Set();
|
|
1558
1663
|
const metadata = { group: "", version: "latest", properties: [] };
|
|
1559
1664
|
if (typeof rawOutput === "string") {
|
|
1560
1665
|
const tmpA = rawOutput.split("\n");
|
|
@@ -1616,11 +1721,7 @@ export const executeGradleProperties = function (dir, rootPath, subProject) {
|
|
|
1616
1721
|
"plain",
|
|
1617
1722
|
"--build-cache"
|
|
1618
1723
|
];
|
|
1619
|
-
|
|
1620
|
-
if (process.env.GRADLE_ARGS) {
|
|
1621
|
-
const addArgs = process.env.GRADLE_ARGS.split(" ");
|
|
1622
|
-
gradlePropertiesArgs = gradlePropertiesArgs.concat(addArgs);
|
|
1623
|
-
}
|
|
1724
|
+
const gradleCmd = getGradleCommand(dir, rootPath);
|
|
1624
1725
|
console.log(
|
|
1625
1726
|
"Executing",
|
|
1626
1727
|
gradleCmd,
|
|
@@ -1764,7 +1865,7 @@ export const parseKVDep = function (rawOutput) {
|
|
|
1764
1865
|
* @param {string} name License full name
|
|
1765
1866
|
*/
|
|
1766
1867
|
export const findLicenseId = function (name) {
|
|
1767
|
-
for (
|
|
1868
|
+
for (const l of licenseMapping) {
|
|
1768
1869
|
if (l.names.includes(name)) {
|
|
1769
1870
|
return l.exp;
|
|
1770
1871
|
}
|
|
@@ -1781,8 +1882,8 @@ export const findLicenseId = function (name) {
|
|
|
1781
1882
|
*/
|
|
1782
1883
|
export const guessLicenseId = function (content) {
|
|
1783
1884
|
content = content.replace(/\n/g, " ");
|
|
1784
|
-
for (
|
|
1785
|
-
for (
|
|
1885
|
+
for (const l of licenseMapping) {
|
|
1886
|
+
for (const j in l.names) {
|
|
1786
1887
|
if (content.toUpperCase().indexOf(l.names[j].toUpperCase()) > -1) {
|
|
1787
1888
|
return l.exp;
|
|
1788
1889
|
}
|
|
@@ -1817,7 +1918,7 @@ export const getMvnMetadata = async function (pkgList) {
|
|
|
1817
1918
|
if (p.group.indexOf("android") !== -1) {
|
|
1818
1919
|
urlPrefix = ANDROID_MAVEN;
|
|
1819
1920
|
}
|
|
1820
|
-
|
|
1921
|
+
const groupPart = p.group.replace(/\./g, "/");
|
|
1821
1922
|
// Querying maven requires a valid group name
|
|
1822
1923
|
if (!groupPart || groupPart === "") {
|
|
1823
1924
|
cdepList.push(p);
|
|
@@ -1900,7 +2001,7 @@ export const parsePyRequiresDist = function (dist_string) {
|
|
|
1900
2001
|
name = tmpA[0];
|
|
1901
2002
|
} else if (tmpA.length > 1) {
|
|
1902
2003
|
name = tmpA[0];
|
|
1903
|
-
|
|
2004
|
+
const tmpVersion = tmpA[1];
|
|
1904
2005
|
version = tmpVersion.split(",")[0].replace(/[();=&glt><]/g, "");
|
|
1905
2006
|
}
|
|
1906
2007
|
return {
|
|
@@ -1919,7 +2020,7 @@ export const guessPypiMatchingVersion = (versionsList, versionSpecifiers) => {
|
|
|
1919
2020
|
versionSpecifiers = versionSpecifiers.replace(/,/g, " ").split(";")[0];
|
|
1920
2021
|
// Iterate in the reverse order
|
|
1921
2022
|
for (let i = versionsList.length - 1; i > 0; i--) {
|
|
1922
|
-
|
|
2023
|
+
const rv = versionsList[i];
|
|
1923
2024
|
if (satisfies(coerce(rv), versionSpecifiers, true)) {
|
|
1924
2025
|
return rv;
|
|
1925
2026
|
}
|
|
@@ -1939,7 +2040,7 @@ export const getPyMetadata = async function (pkgList, fetchDepsInfo) {
|
|
|
1939
2040
|
return pkgList;
|
|
1940
2041
|
}
|
|
1941
2042
|
const PYPI_URL = "https://pypi.org/pypi/";
|
|
1942
|
-
|
|
2043
|
+
const cdepList = [];
|
|
1943
2044
|
for (const p of pkgList) {
|
|
1944
2045
|
if (!p || !p.name) {
|
|
1945
2046
|
continue;
|
|
@@ -1973,7 +2074,7 @@ export const getPyMetadata = async function (pkgList, fetchDepsInfo) {
|
|
|
1973
2074
|
p.description = body.info.summary;
|
|
1974
2075
|
p.license = findLicenseId(body.info.license);
|
|
1975
2076
|
if (body.info.home_page) {
|
|
1976
|
-
if (body.info.home_page.
|
|
2077
|
+
if (body.info.home_page.includes("git")) {
|
|
1977
2078
|
p.repository = { url: body.info.home_page };
|
|
1978
2079
|
} else {
|
|
1979
2080
|
p.homepage = { url: body.info.home_page };
|
|
@@ -2003,11 +2104,39 @@ export const getPyMetadata = async function (pkgList, fetchDepsInfo) {
|
|
|
2003
2104
|
Object.keys(body.releases || {}),
|
|
2004
2105
|
versionSpecifiers
|
|
2005
2106
|
);
|
|
2107
|
+
// Indicate the confidence with our guess
|
|
2108
|
+
p.evidence = {
|
|
2109
|
+
identity: {
|
|
2110
|
+
field: "version",
|
|
2111
|
+
confidence: 0.75,
|
|
2112
|
+
methods: [
|
|
2113
|
+
{
|
|
2114
|
+
technique: "manifest-analysis",
|
|
2115
|
+
confidence: 0.75,
|
|
2116
|
+
value: `Version specifiers: ${versionSpecifiers}`
|
|
2117
|
+
}
|
|
2118
|
+
]
|
|
2119
|
+
}
|
|
2120
|
+
};
|
|
2006
2121
|
}
|
|
2007
2122
|
// If we have reached here, it means we have not solved the version
|
|
2008
2123
|
// So assume latest
|
|
2009
2124
|
if (!p.version) {
|
|
2010
2125
|
p.version = body.info.version;
|
|
2126
|
+
// Indicate the low confidence
|
|
2127
|
+
p.evidence = {
|
|
2128
|
+
identity: {
|
|
2129
|
+
field: "version",
|
|
2130
|
+
confidence: 0.5,
|
|
2131
|
+
methods: [
|
|
2132
|
+
{
|
|
2133
|
+
technique: "source-code-analysis",
|
|
2134
|
+
confidence: 0.5,
|
|
2135
|
+
value: `PyPI package: ${p.name}`
|
|
2136
|
+
}
|
|
2137
|
+
]
|
|
2138
|
+
}
|
|
2139
|
+
};
|
|
2011
2140
|
}
|
|
2012
2141
|
} else if (p.version !== body.info.version) {
|
|
2013
2142
|
if (!p.properties) {
|
|
@@ -2044,16 +2173,21 @@ export const getPyMetadata = async function (pkgList, fetchDepsInfo) {
|
|
|
2044
2173
|
);
|
|
2045
2174
|
}
|
|
2046
2175
|
p.version = "latest";
|
|
2176
|
+
// Indicate the low confidence
|
|
2177
|
+
p.evidence = {
|
|
2178
|
+
identity: {
|
|
2179
|
+
field: "version",
|
|
2180
|
+
confidence: 0,
|
|
2181
|
+
methods: [
|
|
2182
|
+
{
|
|
2183
|
+
technique: "source-code-analysis",
|
|
2184
|
+
confidence: 0,
|
|
2185
|
+
value: `Module ${p.name}`
|
|
2186
|
+
}
|
|
2187
|
+
]
|
|
2188
|
+
}
|
|
2189
|
+
};
|
|
2047
2190
|
}
|
|
2048
|
-
// Add a property to let the downstream tools know about this assumption
|
|
2049
|
-
// FIXME: Do this correctly with 1.5
|
|
2050
|
-
if (!p.properties) {
|
|
2051
|
-
p.properties = [];
|
|
2052
|
-
}
|
|
2053
|
-
p.properties.push({
|
|
2054
|
-
name: "cdx:pypi:pedigree",
|
|
2055
|
-
value: "unknown"
|
|
2056
|
-
});
|
|
2057
2191
|
cdepList.push(p);
|
|
2058
2192
|
}
|
|
2059
2193
|
}
|
|
@@ -2099,7 +2233,7 @@ export const parsePiplockData = async function (lockData) {
|
|
|
2099
2233
|
Object.keys(depBlock).forEach((p) => {
|
|
2100
2234
|
const pkg = depBlock[p];
|
|
2101
2235
|
if (Object.prototype.hasOwnProperty.call(pkg, "version")) {
|
|
2102
|
-
|
|
2236
|
+
const versionStr = pkg.version.replace("==", "");
|
|
2103
2237
|
pkgList.push({ name: p, version: versionStr });
|
|
2104
2238
|
}
|
|
2105
2239
|
});
|
|
@@ -2184,7 +2318,7 @@ export async function parseReqFile(reqData, fetchDepsInfo) {
|
|
|
2184
2318
|
versionStr = null;
|
|
2185
2319
|
}
|
|
2186
2320
|
if (!tmpA[0].includes("=") && !tmpA[0].trim().includes(" ")) {
|
|
2187
|
-
|
|
2321
|
+
const name = tmpA[0].trim().replace(";", "");
|
|
2188
2322
|
if (!PYTHON_STD_MODULES.includes(name)) {
|
|
2189
2323
|
pkgList.push({
|
|
2190
2324
|
name,
|
|
@@ -2194,8 +2328,8 @@ export async function parseReqFile(reqData, fetchDepsInfo) {
|
|
|
2194
2328
|
}
|
|
2195
2329
|
}
|
|
2196
2330
|
} else if (l.includes("<") && l.includes(">")) {
|
|
2197
|
-
|
|
2198
|
-
|
|
2331
|
+
const tmpA = l.split(">");
|
|
2332
|
+
const name = tmpA[0].trim().replace(";", "");
|
|
2199
2333
|
const versionSpecifiers = l.replace(name, "");
|
|
2200
2334
|
if (!PYTHON_STD_MODULES.includes(name)) {
|
|
2201
2335
|
pkgList.push({
|
|
@@ -2216,7 +2350,7 @@ export async function parseReqFile(reqData, fetchDepsInfo) {
|
|
|
2216
2350
|
tmpA = tmpA.split("#")[0];
|
|
2217
2351
|
}
|
|
2218
2352
|
if (!tmpA[0].trim().includes(" ")) {
|
|
2219
|
-
|
|
2353
|
+
const name = tmpA[0].trim().replace(";", "");
|
|
2220
2354
|
const versionSpecifiers = l.replace(name, "");
|
|
2221
2355
|
if (!PYTHON_STD_MODULES.includes(name)) {
|
|
2222
2356
|
pkgList.push({
|
|
@@ -2237,9 +2371,9 @@ export async function parseReqFile(reqData, fetchDepsInfo) {
|
|
|
2237
2371
|
l = l.split("#")[0];
|
|
2238
2372
|
}
|
|
2239
2373
|
l = l.trim();
|
|
2240
|
-
|
|
2374
|
+
const tmpA = l.split(/(<|>)/);
|
|
2241
2375
|
if (tmpA && tmpA.length === 3) {
|
|
2242
|
-
|
|
2376
|
+
const name = tmpA[0].trim().replace(";", "");
|
|
2243
2377
|
const versionSpecifiers = l.replace(name, "");
|
|
2244
2378
|
if (!PYTHON_STD_MODULES.includes(name)) {
|
|
2245
2379
|
pkgList.push({
|
|
@@ -2255,7 +2389,7 @@ export async function parseReqFile(reqData, fetchDepsInfo) {
|
|
|
2255
2389
|
});
|
|
2256
2390
|
}
|
|
2257
2391
|
} else if (!l.includes(" ")) {
|
|
2258
|
-
|
|
2392
|
+
const name = l.replace(";", "");
|
|
2259
2393
|
const versionSpecifiers = l.replace(name, "");
|
|
2260
2394
|
if (!PYTHON_STD_MODULES.includes(name)) {
|
|
2261
2395
|
pkgList.push({
|
|
@@ -2286,6 +2420,7 @@ export async function parseReqFile(reqData, fetchDepsInfo) {
|
|
|
2286
2420
|
*/
|
|
2287
2421
|
export const getPyModules = async (src, epkgList) => {
|
|
2288
2422
|
const allImports = {};
|
|
2423
|
+
const dependenciesList = [];
|
|
2289
2424
|
const modList = findAppModules(src, "python");
|
|
2290
2425
|
const pyDefaultModules = new Set(PYTHON_STD_MODULES);
|
|
2291
2426
|
const filteredModList = modList.filter(
|
|
@@ -2323,7 +2458,13 @@ export const getPyModules = async (src, epkgList) => {
|
|
|
2323
2458
|
pkgList = pkgList.filter((p) => !pkgMaps.includes(p.name));
|
|
2324
2459
|
}
|
|
2325
2460
|
pkgList = await getPyMetadata(pkgList, true);
|
|
2326
|
-
|
|
2461
|
+
for (const p of pkgList) {
|
|
2462
|
+
dependenciesList.push({
|
|
2463
|
+
ref: `pkg:pypi/${p.name}@${p.version}`.toLowerCase(),
|
|
2464
|
+
dependsOn: []
|
|
2465
|
+
});
|
|
2466
|
+
}
|
|
2467
|
+
return { allImports, pkgList, dependenciesList };
|
|
2327
2468
|
};
|
|
2328
2469
|
|
|
2329
2470
|
/**
|
|
@@ -2429,7 +2570,7 @@ export const getRepoLicense = async function (repoUrl, repoMetadata) {
|
|
|
2429
2570
|
const group = repoMetadata.group;
|
|
2430
2571
|
const name = repoMetadata.name;
|
|
2431
2572
|
if (group && name) {
|
|
2432
|
-
for (
|
|
2573
|
+
for (const akLic of knownLicenses) {
|
|
2433
2574
|
if (akLic.group === "." && akLic.name === name) {
|
|
2434
2575
|
return akLic.license;
|
|
2435
2576
|
} else if (
|
|
@@ -2471,7 +2612,7 @@ export const getGoPkgLicense = async function (repoMetadata) {
|
|
|
2471
2612
|
}
|
|
2472
2613
|
const licenseIds = licenses.split(", ");
|
|
2473
2614
|
const licList = [];
|
|
2474
|
-
for (
|
|
2615
|
+
for (const id of licenseIds) {
|
|
2475
2616
|
const alicense = {
|
|
2476
2617
|
id: id
|
|
2477
2618
|
};
|
|
@@ -2554,23 +2695,33 @@ export const parseGoModData = async function (goModData, gosumMap) {
|
|
|
2554
2695
|
if (!isModReplacement) {
|
|
2555
2696
|
// Add group, name and version component properties for required modules
|
|
2556
2697
|
const version = tmpA[1];
|
|
2557
|
-
|
|
2698
|
+
const gosumHash = gosumMap[`${tmpA[0]}/${version}`];
|
|
2558
2699
|
// The hash for this version was not found in go.sum, so skip as it is most likely being replaced.
|
|
2559
2700
|
if (gosumHash === undefined) {
|
|
2560
2701
|
continue;
|
|
2561
2702
|
}
|
|
2562
|
-
|
|
2703
|
+
const component = await getGoPkgComponent(
|
|
2704
|
+
"",
|
|
2705
|
+
tmpA[0],
|
|
2706
|
+
version,
|
|
2707
|
+
gosumHash
|
|
2708
|
+
);
|
|
2563
2709
|
pkgComponentsList.push(component);
|
|
2564
2710
|
} else {
|
|
2565
2711
|
// Add group, name and version component properties for replacement modules
|
|
2566
2712
|
const version = tmpA[3];
|
|
2567
2713
|
|
|
2568
|
-
|
|
2714
|
+
const gosumHash = gosumMap[`${tmpA[2]}/${version}`];
|
|
2569
2715
|
// The hash for this version was not found in go.sum, so skip.
|
|
2570
2716
|
if (gosumHash === undefined) {
|
|
2571
2717
|
continue;
|
|
2572
2718
|
}
|
|
2573
|
-
|
|
2719
|
+
const component = await getGoPkgComponent(
|
|
2720
|
+
"",
|
|
2721
|
+
tmpA[2],
|
|
2722
|
+
version,
|
|
2723
|
+
gosumHash
|
|
2724
|
+
);
|
|
2574
2725
|
pkgComponentsList.push(component);
|
|
2575
2726
|
}
|
|
2576
2727
|
}
|
|
@@ -2590,7 +2741,7 @@ export const parseGoListDep = async function (rawOutput, gosumMap) {
|
|
|
2590
2741
|
const deps = [];
|
|
2591
2742
|
const keys_cache = {};
|
|
2592
2743
|
const pkgs = rawOutput.split("\n");
|
|
2593
|
-
for (
|
|
2744
|
+
for (const l of pkgs) {
|
|
2594
2745
|
const verArr = l.trim().replace(new RegExp("[\"']", "g"), "").split(" ");
|
|
2595
2746
|
|
|
2596
2747
|
if (verArr && verArr.length === 5) {
|
|
@@ -2599,8 +2750,8 @@ export const parseGoListDep = async function (rawOutput, gosumMap) {
|
|
|
2599
2750
|
if (!keys_cache[key]) {
|
|
2600
2751
|
keys_cache[key] = key;
|
|
2601
2752
|
const version = verArr[1];
|
|
2602
|
-
|
|
2603
|
-
|
|
2753
|
+
const gosumHash = gosumMap[`${verArr[0]}/${version}`];
|
|
2754
|
+
const component = await getGoPkgComponent(
|
|
2604
2755
|
"",
|
|
2605
2756
|
verArr[0],
|
|
2606
2757
|
version,
|
|
@@ -2655,7 +2806,7 @@ export const parseGosumData = async function (gosumData) {
|
|
|
2655
2806
|
return pkgList;
|
|
2656
2807
|
}
|
|
2657
2808
|
const pkgs = gosumData.split("\n");
|
|
2658
|
-
for (
|
|
2809
|
+
for (const l of pkgs) {
|
|
2659
2810
|
// look for lines containing go.mod
|
|
2660
2811
|
if (l.indexOf("go.mod") > -1) {
|
|
2661
2812
|
const tmpA = l.split(" ");
|
|
@@ -2693,7 +2844,7 @@ export const parseGopkgData = async function (gopkgData) {
|
|
|
2693
2844
|
}
|
|
2694
2845
|
let pkg = null;
|
|
2695
2846
|
const pkgs = gopkgData.split("\n");
|
|
2696
|
-
for (
|
|
2847
|
+
for (const l of pkgs) {
|
|
2697
2848
|
let key = null;
|
|
2698
2849
|
let value = null;
|
|
2699
2850
|
if (l.indexOf("[[projects]]") > -1) {
|
|
@@ -2741,7 +2892,7 @@ export const parseGoVersionData = async function (buildInfoData) {
|
|
|
2741
2892
|
return pkgList;
|
|
2742
2893
|
}
|
|
2743
2894
|
const pkgs = buildInfoData.split("\n");
|
|
2744
|
-
for (
|
|
2895
|
+
for (const i in pkgs) {
|
|
2745
2896
|
const l = pkgs[i].trim().replace(/\t/g, " ");
|
|
2746
2897
|
if (!l.startsWith("dep")) {
|
|
2747
2898
|
continue;
|
|
@@ -2755,7 +2906,7 @@ export const parseGoVersionData = async function (buildInfoData) {
|
|
|
2755
2906
|
if (tmpA.length == 4) {
|
|
2756
2907
|
hash = tmpA[tmpA.length - 1].replace("h1:", "sha256-");
|
|
2757
2908
|
}
|
|
2758
|
-
|
|
2909
|
+
const component = await getGoPkgComponent("", name, tmpA[2].trim(), hash);
|
|
2759
2910
|
pkgList.push(component);
|
|
2760
2911
|
}
|
|
2761
2912
|
return pkgList;
|
|
@@ -2958,7 +3109,7 @@ export const getDartMetadata = async function (pkgList) {
|
|
|
2958
3109
|
});
|
|
2959
3110
|
if (res && res.body) {
|
|
2960
3111
|
const versions = res.body.versions;
|
|
2961
|
-
for (
|
|
3112
|
+
for (const v of versions) {
|
|
2962
3113
|
if (p.version === v.version) {
|
|
2963
3114
|
const pubspec = v.pubspec;
|
|
2964
3115
|
p.description = pubspec.description;
|
|
@@ -2982,7 +3133,7 @@ export const getDartMetadata = async function (pkgList) {
|
|
|
2982
3133
|
};
|
|
2983
3134
|
|
|
2984
3135
|
export const parseCargoTomlData = async function (cargoData) {
|
|
2985
|
-
|
|
3136
|
+
const pkgList = [];
|
|
2986
3137
|
if (!cargoData) {
|
|
2987
3138
|
return pkgList;
|
|
2988
3139
|
}
|
|
@@ -3031,7 +3182,7 @@ export const parseCargoTomlData = async function (cargoData) {
|
|
|
3031
3182
|
pkgList.push(pkg);
|
|
3032
3183
|
}
|
|
3033
3184
|
pkg = undefined;
|
|
3034
|
-
|
|
3185
|
+
const tmpA = l.split(" = ");
|
|
3035
3186
|
let tmpB = undefined;
|
|
3036
3187
|
let name = tmpA[0];
|
|
3037
3188
|
let version = undefined;
|
|
@@ -3179,7 +3330,7 @@ export const parsePubLockData = async function (pubLockData) {
|
|
|
3179
3330
|
}
|
|
3180
3331
|
};
|
|
3181
3332
|
|
|
3182
|
-
export const parsePubYamlData =
|
|
3333
|
+
export const parsePubYamlData = function (pubYamlData) {
|
|
3183
3334
|
const pkgList = [];
|
|
3184
3335
|
let yamlObj = undefined;
|
|
3185
3336
|
try {
|
|
@@ -3199,7 +3350,7 @@ export const parsePubYamlData = async function (pubYamlData) {
|
|
|
3199
3350
|
return pkgList;
|
|
3200
3351
|
};
|
|
3201
3352
|
|
|
3202
|
-
export const parseHelmYamlData =
|
|
3353
|
+
export const parseHelmYamlData = function (helmData) {
|
|
3203
3354
|
const pkgList = [];
|
|
3204
3355
|
let yamlObj = undefined;
|
|
3205
3356
|
try {
|
|
@@ -3211,7 +3362,7 @@ export const parseHelmYamlData = async function (helmData) {
|
|
|
3211
3362
|
return pkgList;
|
|
3212
3363
|
}
|
|
3213
3364
|
if (yamlObj.name && yamlObj.version) {
|
|
3214
|
-
|
|
3365
|
+
const pkg = {
|
|
3215
3366
|
name: yamlObj.name,
|
|
3216
3367
|
description: yamlObj.description || "",
|
|
3217
3368
|
version: yamlObj.version
|
|
@@ -3223,7 +3374,7 @@ export const parseHelmYamlData = async function (helmData) {
|
|
|
3223
3374
|
}
|
|
3224
3375
|
if (yamlObj.dependencies) {
|
|
3225
3376
|
for (const hd of yamlObj.dependencies) {
|
|
3226
|
-
|
|
3377
|
+
const pkg = {
|
|
3227
3378
|
name: hd.name,
|
|
3228
3379
|
version: hd.version // This could have * so not precise
|
|
3229
3380
|
};
|
|
@@ -3238,7 +3389,7 @@ export const parseHelmYamlData = async function (helmData) {
|
|
|
3238
3389
|
for (const key of Object.keys(yamlObj.entries[he])) {
|
|
3239
3390
|
const hd = yamlObj.entries[he][key];
|
|
3240
3391
|
if (hd.name && hd.version) {
|
|
3241
|
-
|
|
3392
|
+
const pkg = {
|
|
3242
3393
|
name: hd.name,
|
|
3243
3394
|
version: hd.version,
|
|
3244
3395
|
description: hd.description || ""
|
|
@@ -3327,7 +3478,7 @@ export const recurseImageNameLookup = (keyValueObj, pkgList, imgList) => {
|
|
|
3327
3478
|
return imgList;
|
|
3328
3479
|
};
|
|
3329
3480
|
|
|
3330
|
-
export const parseContainerSpecData =
|
|
3481
|
+
export const parseContainerSpecData = function (dcData) {
|
|
3331
3482
|
const pkgList = [];
|
|
3332
3483
|
const imgList = [];
|
|
3333
3484
|
if (!dcData.includes("image") && !dcData.includes("kind")) {
|
|
@@ -3397,7 +3548,7 @@ export const parseContainerSpecData = async function (dcData) {
|
|
|
3397
3548
|
export const identifyFlow = function (processingObj) {
|
|
3398
3549
|
let flow = "unknown";
|
|
3399
3550
|
if (processingObj.sinkId) {
|
|
3400
|
-
|
|
3551
|
+
const sinkId = processingObj.sinkId.toLowerCase();
|
|
3401
3552
|
if (sinkId.endsWith("write")) {
|
|
3402
3553
|
flow = "inbound";
|
|
3403
3554
|
} else if (sinkId.endsWith("read")) {
|
|
@@ -3427,7 +3578,7 @@ export const parsePrivadoFile = function (f) {
|
|
|
3427
3578
|
return servlist;
|
|
3428
3579
|
}
|
|
3429
3580
|
const jsonData = JSON.parse(pData);
|
|
3430
|
-
|
|
3581
|
+
const aservice = {
|
|
3431
3582
|
"x-trust-boundary": false,
|
|
3432
3583
|
properties: [],
|
|
3433
3584
|
data: [],
|
|
@@ -3472,9 +3623,9 @@ export const parsePrivadoFile = function (f) {
|
|
|
3472
3623
|
// Find endpoints
|
|
3473
3624
|
if (jsonData.collections) {
|
|
3474
3625
|
const endpoints = [];
|
|
3475
|
-
for (
|
|
3476
|
-
for (
|
|
3477
|
-
for (
|
|
3626
|
+
for (const c of jsonData.collections) {
|
|
3627
|
+
for (const occ of c.collections) {
|
|
3628
|
+
for (const e of occ.occurrences) {
|
|
3478
3629
|
if (e.endPoint) {
|
|
3479
3630
|
endpoints.push(e.endPoint);
|
|
3480
3631
|
}
|
|
@@ -3485,7 +3636,7 @@ export const parsePrivadoFile = function (f) {
|
|
|
3485
3636
|
}
|
|
3486
3637
|
// Capture violations
|
|
3487
3638
|
if (jsonData.violations) {
|
|
3488
|
-
for (
|
|
3639
|
+
for (const v of jsonData.violations) {
|
|
3489
3640
|
aservice.properties.push({
|
|
3490
3641
|
name: "privado_violations",
|
|
3491
3642
|
value: v.policyId
|
|
@@ -3505,7 +3656,7 @@ export const parsePrivadoFile = function (f) {
|
|
|
3505
3656
|
return servlist;
|
|
3506
3657
|
};
|
|
3507
3658
|
|
|
3508
|
-
export const parseOpenapiSpecData =
|
|
3659
|
+
export const parseOpenapiSpecData = function (oaData) {
|
|
3509
3660
|
const servlist = [];
|
|
3510
3661
|
if (!oaData) {
|
|
3511
3662
|
return servlist;
|
|
@@ -3555,7 +3706,7 @@ export const parseOpenapiSpecData = async function (oaData) {
|
|
|
3555
3706
|
return servlist;
|
|
3556
3707
|
};
|
|
3557
3708
|
|
|
3558
|
-
export const parseCabalData =
|
|
3709
|
+
export const parseCabalData = function (cabalData) {
|
|
3559
3710
|
const pkgList = [];
|
|
3560
3711
|
if (!cabalData) {
|
|
3561
3712
|
return pkgList;
|
|
@@ -3582,7 +3733,7 @@ export const parseCabalData = async function (cabalData) {
|
|
|
3582
3733
|
return pkgList;
|
|
3583
3734
|
};
|
|
3584
3735
|
|
|
3585
|
-
export const parseMixLockData =
|
|
3736
|
+
export const parseMixLockData = function (mixData) {
|
|
3586
3737
|
const pkgList = [];
|
|
3587
3738
|
if (!mixData) {
|
|
3588
3739
|
return pkgList;
|
|
@@ -3608,7 +3759,7 @@ export const parseMixLockData = async function (mixData) {
|
|
|
3608
3759
|
return pkgList;
|
|
3609
3760
|
};
|
|
3610
3761
|
|
|
3611
|
-
export const parseGitHubWorkflowData =
|
|
3762
|
+
export const parseGitHubWorkflowData = function (ghwData) {
|
|
3612
3763
|
const pkgList = [];
|
|
3613
3764
|
const keys_cache = {};
|
|
3614
3765
|
if (!ghwData) {
|
|
@@ -3650,7 +3801,7 @@ export const parseGitHubWorkflowData = async function (ghwData) {
|
|
|
3650
3801
|
return pkgList;
|
|
3651
3802
|
};
|
|
3652
3803
|
|
|
3653
|
-
export const parseCloudBuildData =
|
|
3804
|
+
export const parseCloudBuildData = function (cbwData) {
|
|
3654
3805
|
const pkgList = [];
|
|
3655
3806
|
const keys_cache = {};
|
|
3656
3807
|
if (!cbwData) {
|
|
@@ -3666,7 +3817,7 @@ export const parseCloudBuildData = async function (cbwData) {
|
|
|
3666
3817
|
const tmpA = step.name.split(":");
|
|
3667
3818
|
if (tmpA.length === 2) {
|
|
3668
3819
|
let group = dirname(tmpA[0]);
|
|
3669
|
-
|
|
3820
|
+
const name = basename(tmpA[0]);
|
|
3670
3821
|
if (group === ".") {
|
|
3671
3822
|
group = "";
|
|
3672
3823
|
}
|
|
@@ -3687,7 +3838,7 @@ export const parseCloudBuildData = async function (cbwData) {
|
|
|
3687
3838
|
return pkgList;
|
|
3688
3839
|
};
|
|
3689
3840
|
|
|
3690
|
-
export const parseConanLockData =
|
|
3841
|
+
export const parseConanLockData = function (conanLockData) {
|
|
3691
3842
|
const pkgList = [];
|
|
3692
3843
|
if (!conanLockData) {
|
|
3693
3844
|
return pkgList;
|
|
@@ -3697,7 +3848,7 @@ export const parseConanLockData = async function (conanLockData) {
|
|
|
3697
3848
|
return pkgList;
|
|
3698
3849
|
}
|
|
3699
3850
|
const nodes = graphLock.graph_lock.nodes;
|
|
3700
|
-
for (
|
|
3851
|
+
for (const nk of Object.keys(nodes)) {
|
|
3701
3852
|
if (nodes[nk].ref) {
|
|
3702
3853
|
const tmpA = nodes[nk].ref.split("/");
|
|
3703
3854
|
if (tmpA.length === 2) {
|
|
@@ -3708,7 +3859,7 @@ export const parseConanLockData = async function (conanLockData) {
|
|
|
3708
3859
|
return pkgList;
|
|
3709
3860
|
};
|
|
3710
3861
|
|
|
3711
|
-
export const parseConanData =
|
|
3862
|
+
export const parseConanData = function (conanData) {
|
|
3712
3863
|
const pkgList = [];
|
|
3713
3864
|
if (!conanData) {
|
|
3714
3865
|
return pkgList;
|
|
@@ -3737,7 +3888,7 @@ export const parseLeiningenData = function (leinData) {
|
|
|
3737
3888
|
leinData = "(defproject" + tmpArr[1];
|
|
3738
3889
|
}
|
|
3739
3890
|
const ednData = parseEDNString(leinData);
|
|
3740
|
-
for (
|
|
3891
|
+
for (const k of Object.keys(ednData)) {
|
|
3741
3892
|
if (k === "list") {
|
|
3742
3893
|
ednData[k].forEach((jk) => {
|
|
3743
3894
|
if (Array.isArray(jk)) {
|
|
@@ -3768,7 +3919,7 @@ export const parseEdnData = function (rawEdnData) {
|
|
|
3768
3919
|
}
|
|
3769
3920
|
const ednData = parseEDNString(rawEdnData);
|
|
3770
3921
|
const pkgCache = {};
|
|
3771
|
-
for (
|
|
3922
|
+
for (const k of Object.keys(ednData)) {
|
|
3772
3923
|
if (k === "map") {
|
|
3773
3924
|
ednData[k].forEach((jk) => {
|
|
3774
3925
|
if (Array.isArray(jk)) {
|
|
@@ -3815,7 +3966,7 @@ export const parseEdnData = function (rawEdnData) {
|
|
|
3815
3966
|
|
|
3816
3967
|
export const parseNupkg = async function (nupkgFile) {
|
|
3817
3968
|
const pkgList = [];
|
|
3818
|
-
|
|
3969
|
+
const pkg = { group: "" };
|
|
3819
3970
|
let nuspecData = await readZipEntry(nupkgFile, ".nuspec");
|
|
3820
3971
|
// Remove byte order mark
|
|
3821
3972
|
if (nuspecData.charCodeAt(0) === 0xfeff) {
|
|
@@ -3850,6 +4001,19 @@ export const parseNupkg = async function (nupkgFile) {
|
|
|
3850
4001
|
value: nupkgFile
|
|
3851
4002
|
}
|
|
3852
4003
|
];
|
|
4004
|
+
pkg.evidence = {
|
|
4005
|
+
identity: {
|
|
4006
|
+
field: "purl",
|
|
4007
|
+
confidence: 1,
|
|
4008
|
+
methods: [
|
|
4009
|
+
{
|
|
4010
|
+
technique: "binary-analysis",
|
|
4011
|
+
confidence: 1,
|
|
4012
|
+
value: nupkgFile
|
|
4013
|
+
}
|
|
4014
|
+
]
|
|
4015
|
+
}
|
|
4016
|
+
};
|
|
3853
4017
|
pkgList.push(pkg);
|
|
3854
4018
|
if (fetchLicenses) {
|
|
3855
4019
|
return await getNugetMetadata(pkgList);
|
|
@@ -3875,9 +4039,9 @@ export const parseCsPkgData = async function (pkgData) {
|
|
|
3875
4039
|
return pkgList;
|
|
3876
4040
|
}
|
|
3877
4041
|
packages = packages[0].package;
|
|
3878
|
-
for (
|
|
4042
|
+
for (const i in packages) {
|
|
3879
4043
|
const p = packages[i].$;
|
|
3880
|
-
|
|
4044
|
+
const pkg = { group: "" };
|
|
3881
4045
|
pkg.name = p.id;
|
|
3882
4046
|
pkg.version = p.version;
|
|
3883
4047
|
pkgList.push(pkg);
|
|
@@ -3907,12 +4071,12 @@ export const parseCsProjData = async function (csProjData) {
|
|
|
3907
4071
|
}
|
|
3908
4072
|
const project = projects[0];
|
|
3909
4073
|
if (project.ItemGroup && project.ItemGroup.length) {
|
|
3910
|
-
for (
|
|
4074
|
+
for (const i in project.ItemGroup) {
|
|
3911
4075
|
const item = project.ItemGroup[i];
|
|
3912
4076
|
// .net core use PackageReference
|
|
3913
|
-
for (
|
|
4077
|
+
for (const j in item.PackageReference) {
|
|
3914
4078
|
const pref = item.PackageReference[j].$;
|
|
3915
|
-
|
|
4079
|
+
const pkg = { group: "" };
|
|
3916
4080
|
if (!pref.Include || pref.Include.includes(".csproj")) {
|
|
3917
4081
|
continue;
|
|
3918
4082
|
}
|
|
@@ -3921,9 +4085,9 @@ export const parseCsProjData = async function (csProjData) {
|
|
|
3921
4085
|
pkgList.push(pkg);
|
|
3922
4086
|
}
|
|
3923
4087
|
// .net framework use Reference
|
|
3924
|
-
for (
|
|
4088
|
+
for (const j in item.Reference) {
|
|
3925
4089
|
const pref = item.Reference[j].$;
|
|
3926
|
-
|
|
4090
|
+
const pkg = { group: "" };
|
|
3927
4091
|
if (!pref.Include || pref.Include.includes(".csproj")) {
|
|
3928
4092
|
continue;
|
|
3929
4093
|
}
|
|
@@ -3953,7 +4117,7 @@ export const parseCsProjAssetsData = async function (csProjData) {
|
|
|
3953
4117
|
if (!assetData || !assetData.libraries) {
|
|
3954
4118
|
return pkgList;
|
|
3955
4119
|
}
|
|
3956
|
-
for (
|
|
4120
|
+
for (const alib of Object.keys(assetData.libraries)) {
|
|
3957
4121
|
// Skip os runtime packages
|
|
3958
4122
|
if (alib.startsWith("runtime")) {
|
|
3959
4123
|
continue;
|
|
@@ -3992,8 +4156,8 @@ export const parseCsPkgLockData = async function (csLockData) {
|
|
|
3992
4156
|
if (!assetData || !assetData.dependencies) {
|
|
3993
4157
|
return pkgList;
|
|
3994
4158
|
}
|
|
3995
|
-
for (
|
|
3996
|
-
for (
|
|
4159
|
+
for (const aversion of Object.keys(assetData.dependencies)) {
|
|
4160
|
+
for (const alib of Object.keys(assetData.dependencies[aversion])) {
|
|
3997
4161
|
const libData = assetData.dependencies[aversion][alib];
|
|
3998
4162
|
pkg = {
|
|
3999
4163
|
group: "",
|
|
@@ -4135,15 +4299,15 @@ export const parseComposerLock = function (pkgLockFile) {
|
|
|
4135
4299
|
return [];
|
|
4136
4300
|
}
|
|
4137
4301
|
if (lockData) {
|
|
4138
|
-
|
|
4302
|
+
const packages = {};
|
|
4139
4303
|
if (lockData["packages"]) {
|
|
4140
4304
|
packages["required"] = lockData["packages"];
|
|
4141
4305
|
}
|
|
4142
4306
|
if (lockData["packages-dev"]) {
|
|
4143
4307
|
packages["optional"] = lockData["packages-dev"];
|
|
4144
4308
|
}
|
|
4145
|
-
for (
|
|
4146
|
-
for (
|
|
4309
|
+
for (const compScope in packages) {
|
|
4310
|
+
for (const i in packages[compScope]) {
|
|
4147
4311
|
const pkg = packages[compScope][i];
|
|
4148
4312
|
// Be extra cautious. Potential fix for #236
|
|
4149
4313
|
if (!pkg || !pkg.name || !pkg.version) {
|
|
@@ -4153,7 +4317,7 @@ export const parseComposerLock = function (pkgLockFile) {
|
|
|
4153
4317
|
if (group === ".") {
|
|
4154
4318
|
group = "";
|
|
4155
4319
|
}
|
|
4156
|
-
|
|
4320
|
+
const name = basename(pkg.name);
|
|
4157
4321
|
pkgList.push({
|
|
4158
4322
|
group: group,
|
|
4159
4323
|
name: name,
|
|
@@ -4171,7 +4335,20 @@ export const parseComposerLock = function (pkgLockFile) {
|
|
|
4171
4335
|
name: "SrcFile",
|
|
4172
4336
|
value: pkgLockFile
|
|
4173
4337
|
}
|
|
4174
|
-
]
|
|
4338
|
+
],
|
|
4339
|
+
evidence: {
|
|
4340
|
+
identity: {
|
|
4341
|
+
field: "purl",
|
|
4342
|
+
confidence: 1,
|
|
4343
|
+
methods: [
|
|
4344
|
+
{
|
|
4345
|
+
technique: "manifest-analysis",
|
|
4346
|
+
confidence: 1,
|
|
4347
|
+
value: pkgLockFile
|
|
4348
|
+
}
|
|
4349
|
+
]
|
|
4350
|
+
}
|
|
4351
|
+
}
|
|
4175
4352
|
});
|
|
4176
4353
|
}
|
|
4177
4354
|
}
|
|
@@ -4190,7 +4367,7 @@ export const parseSbtLock = function (pkgLockFile) {
|
|
|
4190
4367
|
if (existsSync(pkgLockFile)) {
|
|
4191
4368
|
const lockData = JSON.parse(readFileSync(pkgLockFile, "utf8"));
|
|
4192
4369
|
if (lockData && lockData.dependencies) {
|
|
4193
|
-
for (
|
|
4370
|
+
for (const pkg of lockData.dependencies) {
|
|
4194
4371
|
const artifacts = pkg.artifacts || undefined;
|
|
4195
4372
|
let integrity = "";
|
|
4196
4373
|
if (artifacts && artifacts.length) {
|
|
@@ -4215,7 +4392,20 @@ export const parseSbtLock = function (pkgLockFile) {
|
|
|
4215
4392
|
name: "SrcFile",
|
|
4216
4393
|
value: pkgLockFile
|
|
4217
4394
|
}
|
|
4218
|
-
]
|
|
4395
|
+
],
|
|
4396
|
+
evidence: {
|
|
4397
|
+
identity: {
|
|
4398
|
+
field: "purl",
|
|
4399
|
+
confidence: 1,
|
|
4400
|
+
methods: [
|
|
4401
|
+
{
|
|
4402
|
+
technique: "manifest-analysis",
|
|
4403
|
+
confidence: 1,
|
|
4404
|
+
value: pkgLockFile
|
|
4405
|
+
}
|
|
4406
|
+
]
|
|
4407
|
+
}
|
|
4408
|
+
}
|
|
4219
4409
|
});
|
|
4220
4410
|
}
|
|
4221
4411
|
}
|
|
@@ -4240,15 +4430,15 @@ export const convertOSQueryResults = function (
|
|
|
4240
4430
|
if (res.version) {
|
|
4241
4431
|
const version = res.version;
|
|
4242
4432
|
let name = res.name || res.device_id;
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4433
|
+
const group = "";
|
|
4434
|
+
const subpath = res.path || res.admindir || res.source;
|
|
4435
|
+
const publisher = res.maintainer || res.creator;
|
|
4246
4436
|
let scope = undefined;
|
|
4247
|
-
|
|
4437
|
+
const compScope = res.priority;
|
|
4248
4438
|
if (["required", "optional", "excluded"].includes(compScope)) {
|
|
4249
4439
|
scope = compScope;
|
|
4250
4440
|
}
|
|
4251
|
-
|
|
4441
|
+
const description =
|
|
4252
4442
|
res.description ||
|
|
4253
4443
|
res.arguments ||
|
|
4254
4444
|
res.device ||
|
|
@@ -4293,7 +4483,7 @@ export const _swiftDepPkgList = (
|
|
|
4293
4483
|
jsonData
|
|
4294
4484
|
) => {
|
|
4295
4485
|
if (jsonData && jsonData.dependencies) {
|
|
4296
|
-
for (
|
|
4486
|
+
for (const adep of jsonData.dependencies) {
|
|
4297
4487
|
const urlOrPath = adep.url || adep.path;
|
|
4298
4488
|
const apkg = {
|
|
4299
4489
|
group: adep.identity || "",
|
|
@@ -4333,7 +4523,7 @@ export const _swiftDepPkgList = (
|
|
|
4333
4523
|
// Handle the immediate dependencies before recursing
|
|
4334
4524
|
if (adep.dependencies && adep.dependencies.length) {
|
|
4335
4525
|
const deplist = [];
|
|
4336
|
-
for (
|
|
4526
|
+
for (const cdep of adep.dependencies) {
|
|
4337
4527
|
const deppurl = new PackageURL(
|
|
4338
4528
|
"swift",
|
|
4339
4529
|
cdep.identity || "",
|
|
@@ -4380,7 +4570,7 @@ export const parseSwiftJsonTree = (rawOutput, pkgFile) => {
|
|
|
4380
4570
|
}
|
|
4381
4571
|
const pkgList = [];
|
|
4382
4572
|
const dependenciesList = [];
|
|
4383
|
-
|
|
4573
|
+
const depKeys = {};
|
|
4384
4574
|
let rootPkg = {};
|
|
4385
4575
|
let jsonData = {};
|
|
4386
4576
|
try {
|
|
@@ -4475,7 +4665,20 @@ export const parseSwiftResolved = (resolvedFile) => {
|
|
|
4475
4665
|
name: "SrcFile",
|
|
4476
4666
|
value: resolvedFile
|
|
4477
4667
|
}
|
|
4478
|
-
]
|
|
4668
|
+
],
|
|
4669
|
+
evidence: {
|
|
4670
|
+
identity: {
|
|
4671
|
+
field: "purl",
|
|
4672
|
+
confidence: 1,
|
|
4673
|
+
methods: [
|
|
4674
|
+
{
|
|
4675
|
+
technique: "manifest-analysis",
|
|
4676
|
+
confidence: 1,
|
|
4677
|
+
value: resolvedFile
|
|
4678
|
+
}
|
|
4679
|
+
]
|
|
4680
|
+
}
|
|
4681
|
+
}
|
|
4479
4682
|
};
|
|
4480
4683
|
const repLocation = adep.location || adep.repositoryURL;
|
|
4481
4684
|
if (repLocation) {
|
|
@@ -4497,7 +4700,7 @@ export const parseSwiftResolved = (resolvedFile) => {
|
|
|
4497
4700
|
* @param {string} basePath Path to the maven project
|
|
4498
4701
|
*/
|
|
4499
4702
|
export const collectMvnDependencies = function (mavenCmd, basePath) {
|
|
4500
|
-
|
|
4703
|
+
const tempDir = mkdtempSync(join(tmpdir(), "mvn-deps-"));
|
|
4501
4704
|
console.log(
|
|
4502
4705
|
`Executing 'mvn dependency:copy-dependencies -DoutputDirectory=${tempDir} -DexcludeTransitive=true -DincludeScope=runtime' in ${basePath}`
|
|
4503
4706
|
);
|
|
@@ -4555,7 +4758,7 @@ export const collectJarNS = function (jarPath) {
|
|
|
4555
4758
|
// Execute jar tvf to get class names
|
|
4556
4759
|
const jarFiles = getAllFiles(jarPath, "**/*.jar");
|
|
4557
4760
|
if (jarFiles && jarFiles.length) {
|
|
4558
|
-
for (
|
|
4761
|
+
for (const jf of jarFiles) {
|
|
4559
4762
|
const jarname = basename(jf);
|
|
4560
4763
|
if (DEBUG_MODE) {
|
|
4561
4764
|
console.log(`Executing 'jar tf ${jf}'`);
|
|
@@ -4659,7 +4862,7 @@ export { _encodeForPurl as encodeForPurl };
|
|
|
4659
4862
|
* @return pkgList Package list
|
|
4660
4863
|
*/
|
|
4661
4864
|
export const extractJarArchive = function (jarFile, tempDir) {
|
|
4662
|
-
|
|
4865
|
+
const pkgList = [];
|
|
4663
4866
|
let jarFiles = [];
|
|
4664
4867
|
const fname = basename(jarFile);
|
|
4665
4868
|
let pomname = undefined;
|
|
@@ -4674,7 +4877,7 @@ export const extractJarArchive = function (jarFile, tempDir) {
|
|
|
4674
4877
|
copyFileSync(jarFile, join(tempDir, fname), constants.COPYFILE_FICLONE);
|
|
4675
4878
|
}
|
|
4676
4879
|
if (jarFile.endsWith(".war") || jarFile.endsWith(".hpi")) {
|
|
4677
|
-
|
|
4880
|
+
const jarResult = spawnSync("jar", ["-xf", join(tempDir, fname)], {
|
|
4678
4881
|
encoding: "utf-8",
|
|
4679
4882
|
cwd: tempDir
|
|
4680
4883
|
});
|
|
@@ -4693,7 +4896,7 @@ export const extractJarArchive = function (jarFile, tempDir) {
|
|
|
4693
4896
|
jarFiles = [join(tempDir, fname)];
|
|
4694
4897
|
}
|
|
4695
4898
|
if (jarFiles && jarFiles.length) {
|
|
4696
|
-
for (
|
|
4899
|
+
for (const jf of jarFiles) {
|
|
4697
4900
|
pomname = jf.replace(".jar", ".pom");
|
|
4698
4901
|
const jarname = basename(jf);
|
|
4699
4902
|
// Ignore test jars
|
|
@@ -4703,7 +4906,7 @@ export const extractJarArchive = function (jarFile, tempDir) {
|
|
|
4703
4906
|
) {
|
|
4704
4907
|
continue;
|
|
4705
4908
|
}
|
|
4706
|
-
|
|
4909
|
+
const manifestDir = join(tempDir, "META-INF");
|
|
4707
4910
|
const manifestFile = join(manifestDir, "MANIFEST.MF");
|
|
4708
4911
|
let jarResult = {
|
|
4709
4912
|
status: 1
|
|
@@ -4732,32 +4935,42 @@ export const extractJarArchive = function (jarFile, tempDir) {
|
|
|
4732
4935
|
jarMetadata["Bundle-Vendor"] ||
|
|
4733
4936
|
jarMetadata["Automatic-Module-Name"] ||
|
|
4734
4937
|
"";
|
|
4938
|
+
let version =
|
|
4939
|
+
jarMetadata["Bundle-Version"] ||
|
|
4940
|
+
jarMetadata["Implementation-Version"] ||
|
|
4941
|
+
jarMetadata["Specification-Version"];
|
|
4942
|
+
if (version && version.includes(" ")) {
|
|
4943
|
+
version = version.split(" ")[0];
|
|
4944
|
+
}
|
|
4735
4945
|
let name = "";
|
|
4946
|
+
// Prefer jar filename to construct name and version
|
|
4947
|
+
if (!name || !version || name === "" || version === "") {
|
|
4948
|
+
const tmpA = jarname.split("-");
|
|
4949
|
+
if (tmpA && tmpA.length > 1) {
|
|
4950
|
+
const lastPart = tmpA[tmpA.length - 1];
|
|
4951
|
+
if (!version || version === "") {
|
|
4952
|
+
version = lastPart.replace(".jar", "");
|
|
4953
|
+
}
|
|
4954
|
+
if (!name || name === "") {
|
|
4955
|
+
name = jarname.replace("-" + lastPart, "") || "";
|
|
4956
|
+
}
|
|
4957
|
+
} else {
|
|
4958
|
+
name = jarname.replace(".jar", "");
|
|
4959
|
+
}
|
|
4960
|
+
}
|
|
4736
4961
|
if (
|
|
4962
|
+
!name.length &&
|
|
4737
4963
|
jarMetadata["Bundle-Name"] &&
|
|
4738
4964
|
!jarMetadata["Bundle-Name"].includes(" ")
|
|
4739
4965
|
) {
|
|
4740
4966
|
name = jarMetadata["Bundle-Name"];
|
|
4741
4967
|
} else if (
|
|
4968
|
+
!name.length &&
|
|
4742
4969
|
jarMetadata["Implementation-Title"] &&
|
|
4743
4970
|
!jarMetadata["Implementation-Title"].includes(" ")
|
|
4744
4971
|
) {
|
|
4745
4972
|
name = jarMetadata["Implementation-Title"];
|
|
4746
4973
|
}
|
|
4747
|
-
let version =
|
|
4748
|
-
jarMetadata["Bundle-Version"] ||
|
|
4749
|
-
jarMetadata["Implementation-Version"] ||
|
|
4750
|
-
jarMetadata["Specification-Version"];
|
|
4751
|
-
if (version && version.includes(" ")) {
|
|
4752
|
-
version = version.split(" ")[0];
|
|
4753
|
-
}
|
|
4754
|
-
if (!name && group) {
|
|
4755
|
-
name = basename(group.replace(/\./g, "/"));
|
|
4756
|
-
if (!group.startsWith("javax")) {
|
|
4757
|
-
group = dirname(group.replace(/\./g, "/"));
|
|
4758
|
-
group = group.replace(/\//g, ".");
|
|
4759
|
-
}
|
|
4760
|
-
}
|
|
4761
4974
|
// Sometimes the group might already contain the name
|
|
4762
4975
|
// Eg: group: org.checkerframework.checker.qual name: checker-qual
|
|
4763
4976
|
if (name && group && !group.startsWith("javax")) {
|
|
@@ -4773,21 +4986,6 @@ export const extractJarArchive = function (jarFile, tempDir) {
|
|
|
4773
4986
|
);
|
|
4774
4987
|
}
|
|
4775
4988
|
}
|
|
4776
|
-
// Fallback to parsing jar filename
|
|
4777
|
-
if (!name || !version || name === "" || version === "") {
|
|
4778
|
-
const tmpA = jarname.split("-");
|
|
4779
|
-
if (tmpA && tmpA.length > 1) {
|
|
4780
|
-
const lastPart = tmpA[tmpA.length - 1];
|
|
4781
|
-
if (!version || version === "") {
|
|
4782
|
-
version = lastPart.replace(".jar", "");
|
|
4783
|
-
}
|
|
4784
|
-
if (!name || name === "") {
|
|
4785
|
-
name = jarname.replace("-" + lastPart, "") || "";
|
|
4786
|
-
}
|
|
4787
|
-
} else {
|
|
4788
|
-
name = jarname.replace(".jar", "");
|
|
4789
|
-
}
|
|
4790
|
-
}
|
|
4791
4989
|
// Patch the group string
|
|
4792
4990
|
for (const aprefix in vendorAliases) {
|
|
4793
4991
|
if (name && name.startsWith(aprefix)) {
|
|
@@ -4796,10 +4994,27 @@ export const extractJarArchive = function (jarFile, tempDir) {
|
|
|
4796
4994
|
}
|
|
4797
4995
|
}
|
|
4798
4996
|
if (name && version) {
|
|
4997
|
+
// If group and name are the same we only need the name
|
|
4998
|
+
if (group == name) {
|
|
4999
|
+
group = "";
|
|
5000
|
+
}
|
|
4799
5001
|
pkgList.push({
|
|
4800
5002
|
group: group === "." ? "" : encodeForPurl(group || "") || "",
|
|
4801
5003
|
name: name ? encodeForPurl(name) : "",
|
|
4802
5004
|
version,
|
|
5005
|
+
evidence: {
|
|
5006
|
+
identity: {
|
|
5007
|
+
field: "purl",
|
|
5008
|
+
confidence: 0.5,
|
|
5009
|
+
methods: [
|
|
5010
|
+
{
|
|
5011
|
+
technique: "filename",
|
|
5012
|
+
confidence: 0.5,
|
|
5013
|
+
value: jarname
|
|
5014
|
+
}
|
|
5015
|
+
]
|
|
5016
|
+
}
|
|
5017
|
+
},
|
|
4803
5018
|
properties: [
|
|
4804
5019
|
{
|
|
4805
5020
|
name: "SrcFile",
|
|
@@ -4841,8 +5056,8 @@ export const extractJarArchive = function (jarFile, tempDir) {
|
|
|
4841
5056
|
export const determineSbtVersion = function (projectPath) {
|
|
4842
5057
|
const buildPropFile = join(projectPath, "project", "build.properties");
|
|
4843
5058
|
if (existsSync(buildPropFile)) {
|
|
4844
|
-
|
|
4845
|
-
|
|
5059
|
+
const properties = propertiesReader(buildPropFile);
|
|
5060
|
+
const property = properties.get("sbt.version");
|
|
4846
5061
|
if (property != null && valid(property)) {
|
|
4847
5062
|
return property;
|
|
4848
5063
|
}
|
|
@@ -4864,7 +5079,7 @@ export const determineSbtVersion = function (projectPath) {
|
|
|
4864
5079
|
*/
|
|
4865
5080
|
export const addPlugin = function (projectPath, plugin) {
|
|
4866
5081
|
const pluginsFile = sbtPluginsPath(projectPath);
|
|
4867
|
-
|
|
5082
|
+
let originalPluginsFile = null;
|
|
4868
5083
|
if (existsSync(pluginsFile)) {
|
|
4869
5084
|
originalPluginsFile = pluginsFile + ".cdxgen";
|
|
4870
5085
|
copyFileSync(pluginsFile, originalPluginsFile, constants.COPYFILE_FICLONE);
|
|
@@ -4997,6 +5212,12 @@ export const getMavenCommand = (srcPath, rootPath) => {
|
|
|
4997
5212
|
let findMavenFile = "mvnw";
|
|
4998
5213
|
if (platform() == "win32") {
|
|
4999
5214
|
findMavenFile = "mvnw.bat";
|
|
5215
|
+
if (
|
|
5216
|
+
!existsSync(join(srcPath, findMavenFile)) &&
|
|
5217
|
+
existsSync(join(srcPath, "mvnw.cmd"))
|
|
5218
|
+
) {
|
|
5219
|
+
findMavenFile = "mvnw.cmd";
|
|
5220
|
+
}
|
|
5000
5221
|
}
|
|
5001
5222
|
|
|
5002
5223
|
if (existsSync(join(srcPath, findMavenFile))) {
|
|
@@ -5071,6 +5292,16 @@ export const executeAtom = (src, args) => {
|
|
|
5071
5292
|
timeout: TIMEOUT_MS,
|
|
5072
5293
|
env
|
|
5073
5294
|
});
|
|
5295
|
+
if (
|
|
5296
|
+
result.stderr &&
|
|
5297
|
+
result.stderr.includes(
|
|
5298
|
+
"has been compiled by a more recent version of the Java Runtime"
|
|
5299
|
+
)
|
|
5300
|
+
) {
|
|
5301
|
+
console.log(
|
|
5302
|
+
"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."
|
|
5303
|
+
);
|
|
5304
|
+
}
|
|
5074
5305
|
if (DEBUG_MODE) {
|
|
5075
5306
|
if (result.stdout) {
|
|
5076
5307
|
console.log(result.stdout);
|
|
@@ -5118,17 +5349,62 @@ export const findAppModules = function (src, language) {
|
|
|
5118
5349
|
return retList;
|
|
5119
5350
|
};
|
|
5120
5351
|
|
|
5352
|
+
const flattenDeps = (
|
|
5353
|
+
dependsOn,
|
|
5354
|
+
dependenciesList,
|
|
5355
|
+
pkgList,
|
|
5356
|
+
reqOrSetupFile,
|
|
5357
|
+
t
|
|
5358
|
+
) => {
|
|
5359
|
+
for (const d of t.dependencies) {
|
|
5360
|
+
const pkgRef = `pkg:pypi/${d.name}@${d.version}`
|
|
5361
|
+
.replace(/_/g, "-")
|
|
5362
|
+
.toLowerCase();
|
|
5363
|
+
dependsOn.push(pkgRef);
|
|
5364
|
+
dependenciesList.push({ ref: pkgRef, dependsOn: [] });
|
|
5365
|
+
pkgList.push({
|
|
5366
|
+
name: d.name,
|
|
5367
|
+
version: d.version,
|
|
5368
|
+
properties: [
|
|
5369
|
+
{
|
|
5370
|
+
name: "SrcFile",
|
|
5371
|
+
value: reqOrSetupFile
|
|
5372
|
+
}
|
|
5373
|
+
],
|
|
5374
|
+
evidence: {
|
|
5375
|
+
identity: {
|
|
5376
|
+
field: "purl",
|
|
5377
|
+
confidence: 1,
|
|
5378
|
+
methods: [
|
|
5379
|
+
{
|
|
5380
|
+
technique: "manifest-analysis",
|
|
5381
|
+
confidence: 1,
|
|
5382
|
+
value: reqOrSetupFile
|
|
5383
|
+
}
|
|
5384
|
+
]
|
|
5385
|
+
}
|
|
5386
|
+
}
|
|
5387
|
+
});
|
|
5388
|
+
// Recurse and flatten
|
|
5389
|
+
if (d.dependencies && d.dependencies) {
|
|
5390
|
+
flattenDeps(dependsOn, dependenciesList, pkgList, reqOrSetupFile, d);
|
|
5391
|
+
}
|
|
5392
|
+
}
|
|
5393
|
+
};
|
|
5394
|
+
|
|
5121
5395
|
/**
|
|
5122
|
-
* Execute pip freeze by creating a virtual env in a temp directory
|
|
5396
|
+
* Execute pip freeze by creating a virtual env in a temp directory and construct the dependency tree
|
|
5123
5397
|
*
|
|
5124
5398
|
* @param {string} basePath Base path
|
|
5125
5399
|
* @param {string} reqOrSetupFile Requirements or setup.py file
|
|
5400
|
+
* @param {string} tempVenvDir Temp venv dir
|
|
5126
5401
|
* @returns List of packages from the virtual env
|
|
5127
5402
|
*/
|
|
5128
|
-
export const
|
|
5129
|
-
|
|
5403
|
+
export const getPipFrozenTree = (basePath, reqOrSetupFile, tempVenvDir) => {
|
|
5404
|
+
const pkgList = [];
|
|
5405
|
+
const rootList = [];
|
|
5406
|
+
const dependenciesList = [];
|
|
5130
5407
|
let result = undefined;
|
|
5131
|
-
const tempDir = mkdtempSync(join(tmpdir(), "cdxgen-venv-"));
|
|
5132
5408
|
const env = {
|
|
5133
5409
|
...process.env
|
|
5134
5410
|
};
|
|
@@ -5138,16 +5414,22 @@ export const executePipFreezeInVenv = async (basePath, reqOrSetupFile) => {
|
|
|
5138
5414
|
* By checking the environment variable "VIRTUAL_ENV" we decide whether to create an env or not
|
|
5139
5415
|
*/
|
|
5140
5416
|
if (!process.env.VIRTUAL_ENV) {
|
|
5141
|
-
result = spawnSync(PYTHON_CMD, ["-m", "venv",
|
|
5417
|
+
result = spawnSync(PYTHON_CMD, ["-m", "venv", tempVenvDir]);
|
|
5142
5418
|
if (result.status !== 0 || result.error) {
|
|
5143
5419
|
if (DEBUG_MODE) {
|
|
5144
|
-
console.log(
|
|
5420
|
+
console.log("Virtual env creation has failed");
|
|
5421
|
+
if (!result.stderr) {
|
|
5422
|
+
console.log(
|
|
5423
|
+
"Ensure the virtualenv package is installed using pip. `python -m pip install virtualenv`"
|
|
5424
|
+
);
|
|
5425
|
+
}
|
|
5145
5426
|
}
|
|
5146
5427
|
} else {
|
|
5147
|
-
env.VIRTUAL_ENV =
|
|
5148
|
-
env.PATH = `${join(
|
|
5149
|
-
|
|
5150
|
-
|
|
5428
|
+
env.VIRTUAL_ENV = tempVenvDir;
|
|
5429
|
+
env.PATH = `${join(
|
|
5430
|
+
tempVenvDir,
|
|
5431
|
+
platform() == "win32" ? "Scripts" : "bin"
|
|
5432
|
+
)}${_delimiter}${process.env.PATH || ""}`;
|
|
5151
5433
|
}
|
|
5152
5434
|
}
|
|
5153
5435
|
/**
|
|
@@ -5156,8 +5438,8 @@ export const executePipFreezeInVenv = async (basePath, reqOrSetupFile) => {
|
|
|
5156
5438
|
* This step is accurate but not reproducible since the resulting list could differ based on various factors
|
|
5157
5439
|
* such as the version of python, pip, os, pypi.org availability (and weather?)
|
|
5158
5440
|
*/
|
|
5159
|
-
if (
|
|
5160
|
-
|
|
5441
|
+
if (tempVenvDir === env.VIRTUAL_ENV && reqOrSetupFile) {
|
|
5442
|
+
const pipInstallArgs = [
|
|
5161
5443
|
"-m",
|
|
5162
5444
|
"pip",
|
|
5163
5445
|
"install",
|
|
@@ -5197,6 +5479,7 @@ export const executePipFreezeInVenv = async (basePath, reqOrSetupFile) => {
|
|
|
5197
5479
|
}
|
|
5198
5480
|
if (!versionRelatedError && DEBUG_MODE) {
|
|
5199
5481
|
console.log("args used:", pipInstallArgs);
|
|
5482
|
+
console.log(result.stdout, result.stderr);
|
|
5200
5483
|
console.log(
|
|
5201
5484
|
"Possible build errors detected. The resulting list in the SBoM would therefore be incomplete.\nTry installing any missing build tools or development libraries to improve the accuracy."
|
|
5202
5485
|
);
|
|
@@ -5215,43 +5498,42 @@ export const executePipFreezeInVenv = async (basePath, reqOrSetupFile) => {
|
|
|
5215
5498
|
console.log("- Check if any git submodules have to be initialized.");
|
|
5216
5499
|
}
|
|
5217
5500
|
}
|
|
5501
|
+
}
|
|
5502
|
+
// Bug #375. Attempt pip freeze on existing and new virtual environments
|
|
5503
|
+
if (env.VIRTUAL_ENV && env.VIRTUAL_ENV.length) {
|
|
5218
5504
|
/**
|
|
5219
5505
|
* At this point, the previous attempt to do a pip install might have failed and we might have an unclean virtual environment with an incomplete list
|
|
5220
5506
|
* The position taken by cdxgen is "Some SBoM is better than no SBoM", so we proceed to collecting the dependencies that got installed with pip freeze
|
|
5221
5507
|
*/
|
|
5222
|
-
|
|
5223
|
-
|
|
5224
|
-
|
|
5225
|
-
|
|
5226
|
-
"-l",
|
|
5227
|
-
"--exclude-editable",
|
|
5228
|
-
"--disable-pip-version-check"
|
|
5229
|
-
];
|
|
5230
|
-
if (
|
|
5231
|
-
!reqOrSetupFile.endsWith("setup.py") &&
|
|
5232
|
-
!reqOrSetupFile.endsWith("pyproject.toml")
|
|
5233
|
-
) {
|
|
5234
|
-
pipFreezeArgs.push("-r");
|
|
5235
|
-
pipFreezeArgs.push(resolve(reqOrSetupFile));
|
|
5508
|
+
if (DEBUG_MODE) {
|
|
5509
|
+
console.log(
|
|
5510
|
+
"About to construct the pip dependency tree. Please wait ..."
|
|
5511
|
+
);
|
|
5236
5512
|
}
|
|
5237
|
-
|
|
5238
|
-
|
|
5239
|
-
|
|
5240
|
-
|
|
5241
|
-
|
|
5242
|
-
}
|
|
5243
|
-
|
|
5244
|
-
|
|
5245
|
-
|
|
5246
|
-
const reqData = Buffer.from(result.stdout).toString();
|
|
5247
|
-
const dlist = await parseReqFile(reqData, false);
|
|
5248
|
-
if (dlist && dlist.length) {
|
|
5249
|
-
pkgList = pkgList.concat(dlist);
|
|
5250
|
-
}
|
|
5251
|
-
} else if (result.status !== 0 || result.error) {
|
|
5252
|
-
if (DEBUG_MODE) {
|
|
5253
|
-
console.log(result.stderr, "args used:", pipFreezeArgs);
|
|
5513
|
+
const tree = getTreeWithPlugin(env, PYTHON_CMD, basePath);
|
|
5514
|
+
if (DEBUG_MODE && !tree.length) {
|
|
5515
|
+
console.log(
|
|
5516
|
+
"Dependency tree generation has failed. Please check for any errors or version incompatibilities reported in the logs."
|
|
5517
|
+
);
|
|
5518
|
+
}
|
|
5519
|
+
for (const t of tree) {
|
|
5520
|
+
if (!t.version.length) {
|
|
5521
|
+
continue;
|
|
5254
5522
|
}
|
|
5523
|
+
pkgList.push({
|
|
5524
|
+
name: t.name.replace(/_/g, "-"),
|
|
5525
|
+
version: t.version
|
|
5526
|
+
});
|
|
5527
|
+
rootList.push({
|
|
5528
|
+
name: t.name.replace(/_/g, "-"),
|
|
5529
|
+
version: t.version
|
|
5530
|
+
});
|
|
5531
|
+
const dependsOn = [];
|
|
5532
|
+
flattenDeps(dependsOn, dependenciesList, pkgList, reqOrSetupFile, t);
|
|
5533
|
+
dependenciesList.push({
|
|
5534
|
+
ref: `pkg:pypi/${t.name}@${t.version}`.replace(/_/g, "-").toLowerCase(),
|
|
5535
|
+
dependsOn
|
|
5536
|
+
});
|
|
5255
5537
|
}
|
|
5256
5538
|
} else {
|
|
5257
5539
|
if (DEBUG_MODE) {
|
|
@@ -5260,11 +5542,11 @@ export const executePipFreezeInVenv = async (basePath, reqOrSetupFile) => {
|
|
|
5260
5542
|
);
|
|
5261
5543
|
}
|
|
5262
5544
|
}
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
|
|
5267
|
-
|
|
5545
|
+
return {
|
|
5546
|
+
pkgList,
|
|
5547
|
+
rootList,
|
|
5548
|
+
dependenciesList
|
|
5549
|
+
};
|
|
5268
5550
|
};
|
|
5269
5551
|
|
|
5270
5552
|
// taken from a very old package https://github.com/keithamus/parse-packagejson-name/blob/master/index.js
|