@cyclonedx/cdxgen 9.8.6 → 9.8.8
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 +17 -8
- package/analyzer.js +3 -3
- package/bin/cdxgen.js +3 -3
- package/bin/repl.js +20 -20
- package/binary.js +1 -1
- package/docker.js +1 -1
- package/index.js +186 -76
- package/package.json +9 -9
- package/server.js +7 -3
- package/utils.js +342 -71
- package/utils.test.js +90 -18
package/index.js
CHANGED
|
@@ -60,6 +60,7 @@ import {
|
|
|
60
60
|
parseGoVersionData,
|
|
61
61
|
parseGosumData,
|
|
62
62
|
parseGoListDep,
|
|
63
|
+
parseGoModGraph,
|
|
63
64
|
parseGoModWhy,
|
|
64
65
|
parseGoModData,
|
|
65
66
|
parseGopkgData,
|
|
@@ -92,6 +93,7 @@ import {
|
|
|
92
93
|
parseCsPkgLockData,
|
|
93
94
|
parseCsPkgData,
|
|
94
95
|
parseCsProjData,
|
|
96
|
+
parsePaketLockData,
|
|
95
97
|
DEBUG_MODE,
|
|
96
98
|
parsePyProjectToml,
|
|
97
99
|
addEvidenceForImports,
|
|
@@ -2308,24 +2310,36 @@ export const createPythonBom = async (path, options) => {
|
|
|
2308
2310
|
for (const f of poetryFiles) {
|
|
2309
2311
|
const basePath = dirname(f);
|
|
2310
2312
|
const lockData = readFileSync(f, { encoding: "utf-8" });
|
|
2311
|
-
|
|
2312
|
-
if (
|
|
2313
|
-
pkgList = pkgList.concat(
|
|
2314
|
-
|
|
2315
|
-
const pkgMap = getPipFrozenTree(basePath, f, tempDir);
|
|
2316
|
-
if (pkgMap.pkgList && pkgMap.pkgList.length) {
|
|
2317
|
-
pkgList = pkgList.concat(pkgMap.pkgList);
|
|
2313
|
+
let retMap = await parsePoetrylockData(lockData, f);
|
|
2314
|
+
if (retMap.pkgList && retMap.pkgList.length) {
|
|
2315
|
+
pkgList = pkgList.concat(retMap.pkgList);
|
|
2316
|
+
pkgList = trimComponents(pkgList, "json");
|
|
2318
2317
|
}
|
|
2319
|
-
if (
|
|
2318
|
+
if (retMap.dependenciesList && retMap.dependenciesList.length) {
|
|
2320
2319
|
dependencies = mergeDependencies(
|
|
2321
2320
|
dependencies,
|
|
2322
|
-
|
|
2321
|
+
retMap.dependenciesList,
|
|
2323
2322
|
parentComponent
|
|
2324
2323
|
);
|
|
2325
2324
|
}
|
|
2325
|
+
// Retrieve the tree using virtualenv in deep mode and as a fallback
|
|
2326
|
+
// This is a slow operation
|
|
2327
|
+
if (options.deep || !dependencies.length) {
|
|
2328
|
+
retMap = getPipFrozenTree(basePath, f, tempDir);
|
|
2329
|
+
if (retMap.pkgList && retMap.pkgList.length) {
|
|
2330
|
+
pkgList = pkgList.concat(retMap.pkgList);
|
|
2331
|
+
}
|
|
2332
|
+
if (retMap.dependenciesList) {
|
|
2333
|
+
dependencies = mergeDependencies(
|
|
2334
|
+
dependencies,
|
|
2335
|
+
retMap.dependenciesList,
|
|
2336
|
+
parentComponent
|
|
2337
|
+
);
|
|
2338
|
+
}
|
|
2339
|
+
}
|
|
2326
2340
|
const parentDependsOn = [];
|
|
2327
2341
|
// Complete the dependency tree by making parent component depend on the first level
|
|
2328
|
-
for (const p of
|
|
2342
|
+
for (const p of retMap.rootList) {
|
|
2329
2343
|
parentDependsOn.push(`pkg:pypi/${p.name}@${p.version}`);
|
|
2330
2344
|
}
|
|
2331
2345
|
const pdependencies = {
|
|
@@ -2396,6 +2410,8 @@ export const createPythonBom = async (path, options) => {
|
|
|
2396
2410
|
let frozen = false;
|
|
2397
2411
|
// Attempt to pip freeze in a virtualenv to improve precision
|
|
2398
2412
|
if (options.installDeps) {
|
|
2413
|
+
// If there are multiple requirements files then the tree is getting constructed for each one
|
|
2414
|
+
// adding to the delay.
|
|
2399
2415
|
const pkgMap = getPipFrozenTree(basePath, f, tempDir);
|
|
2400
2416
|
if (pkgMap.pkgList && pkgMap.pkgList.length) {
|
|
2401
2417
|
pkgList = pkgList.concat(pkgMap.pkgList);
|
|
@@ -2453,7 +2469,7 @@ export const createPythonBom = async (path, options) => {
|
|
|
2453
2469
|
}
|
|
2454
2470
|
// Get the imported modules and a dedupe list of packages
|
|
2455
2471
|
const parentDependsOn = new Set();
|
|
2456
|
-
const retMap = await getPyModules(path, pkgList);
|
|
2472
|
+
const retMap = await getPyModules(path, pkgList, options);
|
|
2457
2473
|
if (retMap.pkgList && retMap.pkgList.length) {
|
|
2458
2474
|
pkgList = pkgList.concat(retMap.pkgList);
|
|
2459
2475
|
for (const p of retMap.pkgList) {
|
|
@@ -2547,6 +2563,9 @@ export const createPythonBom = async (path, options) => {
|
|
|
2547
2563
|
*/
|
|
2548
2564
|
export const createGoBom = async (path, options) => {
|
|
2549
2565
|
let pkgList = [];
|
|
2566
|
+
let dependencies = [];
|
|
2567
|
+
const allImports = {};
|
|
2568
|
+
let parentComponent = createDefaultParentComponent(path, "golang", options);
|
|
2550
2569
|
// Is this a binary file
|
|
2551
2570
|
let maybeBinary = false;
|
|
2552
2571
|
try {
|
|
@@ -2568,6 +2587,8 @@ export const createGoBom = async (path, options) => {
|
|
|
2568
2587
|
}
|
|
2569
2588
|
return buildBomNSData(options, pkgList, "golang", {
|
|
2570
2589
|
allImports,
|
|
2590
|
+
dependencies,
|
|
2591
|
+
parentComponent,
|
|
2571
2592
|
src: path,
|
|
2572
2593
|
filename: path
|
|
2573
2594
|
});
|
|
@@ -2597,8 +2618,70 @@ export const createGoBom = async (path, options) => {
|
|
|
2597
2618
|
pkgList = pkgList.concat(dlist);
|
|
2598
2619
|
}
|
|
2599
2620
|
}
|
|
2621
|
+
const doneList = {};
|
|
2622
|
+
let circuitBreak = false;
|
|
2623
|
+
if (DEBUG_MODE) {
|
|
2624
|
+
console.log(
|
|
2625
|
+
`Attempting to detect required packages using "go mod why" command for ${pkgList.length} packages`
|
|
2626
|
+
);
|
|
2627
|
+
}
|
|
2628
|
+
// Using go mod why detect required packages
|
|
2629
|
+
for (const apkg of pkgList) {
|
|
2630
|
+
if (circuitBreak) {
|
|
2631
|
+
break;
|
|
2632
|
+
}
|
|
2633
|
+
const pkgFullName = `${apkg.name}`;
|
|
2634
|
+
if (apkg.scope === "required") {
|
|
2635
|
+
allImports[pkgFullName] = true;
|
|
2636
|
+
continue;
|
|
2637
|
+
}
|
|
2638
|
+
if (
|
|
2639
|
+
apkg.scope === "optional" ||
|
|
2640
|
+
allImports[pkgFullName] ||
|
|
2641
|
+
doneList[pkgFullName]
|
|
2642
|
+
) {
|
|
2643
|
+
continue;
|
|
2644
|
+
}
|
|
2645
|
+
if (DEBUG_MODE) {
|
|
2646
|
+
console.log(`go mod why -m -vendor ${pkgFullName}`);
|
|
2647
|
+
}
|
|
2648
|
+
const mresult = spawnSync(
|
|
2649
|
+
"go",
|
|
2650
|
+
["mod", "why", "-m", "-vendor", pkgFullName],
|
|
2651
|
+
{ cwd: path, encoding: "utf-8", timeout: TIMEOUT_MS }
|
|
2652
|
+
);
|
|
2653
|
+
if (mresult.status !== 0 || mresult.error) {
|
|
2654
|
+
if (DEBUG_MODE) {
|
|
2655
|
+
if (mresult.stdout) {
|
|
2656
|
+
console.log(mresult.stdout);
|
|
2657
|
+
}
|
|
2658
|
+
if (mresult.stderr) {
|
|
2659
|
+
console.log(mresult.stderr);
|
|
2660
|
+
}
|
|
2661
|
+
}
|
|
2662
|
+
circuitBreak = true;
|
|
2663
|
+
} else {
|
|
2664
|
+
const mstdout = mresult.stdout;
|
|
2665
|
+
if (mstdout) {
|
|
2666
|
+
const cmdOutput = Buffer.from(mstdout).toString();
|
|
2667
|
+
const whyPkg = parseGoModWhy(cmdOutput);
|
|
2668
|
+
// whyPkg would include this package string
|
|
2669
|
+
// github.com/golang/protobuf/proto github.com/golang/protobuf
|
|
2670
|
+
// golang.org/x/tools/cmd/goimports golang.org/x/tools
|
|
2671
|
+
if (whyPkg && whyPkg.includes(pkgFullName)) {
|
|
2672
|
+
allImports[pkgFullName] = true;
|
|
2673
|
+
}
|
|
2674
|
+
doneList[pkgFullName] = true;
|
|
2675
|
+
}
|
|
2676
|
+
}
|
|
2677
|
+
}
|
|
2678
|
+
if (DEBUG_MODE) {
|
|
2679
|
+
console.log(`Required packages: ${Object.keys(allImports).length}`);
|
|
2680
|
+
}
|
|
2600
2681
|
return buildBomNSData(options, pkgList, "golang", {
|
|
2601
2682
|
src: path,
|
|
2683
|
+
dependencies,
|
|
2684
|
+
parentComponent,
|
|
2602
2685
|
filename: gosumFiles.join(", ")
|
|
2603
2686
|
});
|
|
2604
2687
|
}
|
|
@@ -2614,7 +2697,7 @@ export const createGoBom = async (path, options) => {
|
|
|
2614
2697
|
const dlist = await parseGosumData(gosumData);
|
|
2615
2698
|
if (dlist && dlist.length) {
|
|
2616
2699
|
dlist.forEach((pkg) => {
|
|
2617
|
-
gosumMap[`${pkg.group}/${pkg.name}
|
|
2700
|
+
gosumMap[`${pkg.group}/${pkg.name}@${pkg.version}`] = pkg._integrity;
|
|
2618
2701
|
});
|
|
2619
2702
|
}
|
|
2620
2703
|
}
|
|
@@ -2633,7 +2716,7 @@ export const createGoBom = async (path, options) => {
|
|
|
2633
2716
|
);
|
|
2634
2717
|
if (gomodFiles.length) {
|
|
2635
2718
|
let shouldManuallyParse = false;
|
|
2636
|
-
// Use the go list -deps and go mod why commands to generate a good quality
|
|
2719
|
+
// Use the go list -deps and go mod why commands to generate a good quality BOM for non-docker invocations
|
|
2637
2720
|
if (!["docker", "oci", "os"].includes(options.projectType)) {
|
|
2638
2721
|
for (const f of gomodFiles) {
|
|
2639
2722
|
const basePath = dirname(f);
|
|
@@ -2641,36 +2724,85 @@ export const createGoBom = async (path, options) => {
|
|
|
2641
2724
|
if (basePath.includes("/vendor/") || basePath.includes("/build/")) {
|
|
2642
2725
|
continue;
|
|
2643
2726
|
}
|
|
2727
|
+
// First we execute the go list -deps command which gives the correct list of dependencies
|
|
2644
2728
|
if (DEBUG_MODE) {
|
|
2645
2729
|
console.log("Executing go list -deps in", basePath);
|
|
2646
2730
|
}
|
|
2647
|
-
|
|
2731
|
+
let result = spawnSync(
|
|
2648
2732
|
"go",
|
|
2649
2733
|
[
|
|
2650
2734
|
"list",
|
|
2651
2735
|
"-deps",
|
|
2652
2736
|
"-f",
|
|
2653
|
-
"'{{with .Module}}{{.Path}} {{.Version}} {{.Indirect}} {{.GoMod}} {{.GoVersion}}{{end}}'",
|
|
2737
|
+
"'{{with .Module}}{{.Path}} {{.Version}} {{.Indirect}} {{.GoMod}} {{.GoVersion}} {{.Main}}{{end}}'",
|
|
2654
2738
|
"./..."
|
|
2655
2739
|
],
|
|
2656
2740
|
{ cwd: basePath, encoding: "utf-8", timeout: TIMEOUT_MS }
|
|
2657
2741
|
);
|
|
2742
|
+
if (DEBUG_MODE) {
|
|
2743
|
+
console.log("Executing go mod graph in", basePath);
|
|
2744
|
+
}
|
|
2658
2745
|
if (result.status !== 0 || result.error) {
|
|
2659
2746
|
shouldManuallyParse = true;
|
|
2660
|
-
if (result.stdout) {
|
|
2747
|
+
if (DEBUG_MODE && result.stdout) {
|
|
2661
2748
|
console.log(result.stdout);
|
|
2662
2749
|
}
|
|
2663
|
-
if (result.stderr) {
|
|
2750
|
+
if (DEBUG_MODE && result.stderr) {
|
|
2664
2751
|
console.log(result.stderr);
|
|
2665
2752
|
}
|
|
2666
2753
|
options.failOnError && process.exit(1);
|
|
2667
2754
|
}
|
|
2668
2755
|
const stdout = result.stdout;
|
|
2669
2756
|
if (stdout) {
|
|
2670
|
-
|
|
2671
|
-
const
|
|
2672
|
-
if (
|
|
2673
|
-
pkgList = pkgList.concat(
|
|
2757
|
+
let cmdOutput = Buffer.from(stdout).toString();
|
|
2758
|
+
const retMap = await parseGoListDep(cmdOutput, gosumMap);
|
|
2759
|
+
if (retMap.pkgList && retMap.pkgList.length) {
|
|
2760
|
+
pkgList = pkgList.concat(retMap.pkgList);
|
|
2761
|
+
}
|
|
2762
|
+
// We treat the main module as our parent
|
|
2763
|
+
if (
|
|
2764
|
+
retMap.parentComponent &&
|
|
2765
|
+
Object.keys(retMap.parentComponent).length
|
|
2766
|
+
) {
|
|
2767
|
+
parentComponent = retMap.parentComponent;
|
|
2768
|
+
parentComponent.type = "application";
|
|
2769
|
+
}
|
|
2770
|
+
// Next we use the go mod graph command to construct the dependency tree
|
|
2771
|
+
result = spawnSync("go", ["mod", "graph"], {
|
|
2772
|
+
cwd: basePath,
|
|
2773
|
+
encoding: "utf-8",
|
|
2774
|
+
timeout: TIMEOUT_MS
|
|
2775
|
+
});
|
|
2776
|
+
// Check if got a mod graph successfully
|
|
2777
|
+
if (result.status !== 0 || result.error) {
|
|
2778
|
+
if (DEBUG_MODE && result.stdout) {
|
|
2779
|
+
console.log(result.stdout);
|
|
2780
|
+
}
|
|
2781
|
+
if (DEBUG_MODE && result.stderr) {
|
|
2782
|
+
console.log(result.stderr);
|
|
2783
|
+
}
|
|
2784
|
+
options.failOnError && process.exit(1);
|
|
2785
|
+
}
|
|
2786
|
+
if (result.stdout) {
|
|
2787
|
+
cmdOutput = Buffer.from(result.stdout).toString();
|
|
2788
|
+
const retMap = await parseGoModGraph(
|
|
2789
|
+
cmdOutput,
|
|
2790
|
+
f,
|
|
2791
|
+
gosumMap,
|
|
2792
|
+
pkgList,
|
|
2793
|
+
parentComponent
|
|
2794
|
+
);
|
|
2795
|
+
if (retMap.pkgList && retMap.pkgList.length) {
|
|
2796
|
+
pkgList = pkgList.concat(retMap.pkgList);
|
|
2797
|
+
pkgList = trimComponents(pkgList, "json");
|
|
2798
|
+
}
|
|
2799
|
+
if (retMap.dependenciesList && retMap.dependenciesList.length) {
|
|
2800
|
+
dependencies = mergeDependencies(
|
|
2801
|
+
dependencies,
|
|
2802
|
+
retMap.dependenciesList,
|
|
2803
|
+
parentComponent
|
|
2804
|
+
);
|
|
2805
|
+
}
|
|
2674
2806
|
}
|
|
2675
2807
|
} else {
|
|
2676
2808
|
shouldManuallyParse = true;
|
|
@@ -2680,67 +2812,20 @@ export const createGoBom = async (path, options) => {
|
|
|
2680
2812
|
options.failOnError && process.exit(1);
|
|
2681
2813
|
}
|
|
2682
2814
|
}
|
|
2683
|
-
const allImports = {};
|
|
2684
|
-
let circuitBreak = false;
|
|
2685
|
-
if (DEBUG_MODE) {
|
|
2686
|
-
console.log(
|
|
2687
|
-
`Attempting to detect required packages using "go mod why" command for ${pkgList.length} packages`
|
|
2688
|
-
);
|
|
2689
|
-
}
|
|
2690
|
-
// Using go mod why detect required packages
|
|
2691
|
-
for (const apkg of pkgList) {
|
|
2692
|
-
if (circuitBreak) {
|
|
2693
|
-
break;
|
|
2694
|
-
}
|
|
2695
|
-
const pkgFullName = `${apkg.name}`;
|
|
2696
|
-
if (apkg.scope === "required") {
|
|
2697
|
-
allImports[pkgFullName] = true;
|
|
2698
|
-
continue;
|
|
2699
|
-
}
|
|
2700
|
-
if (DEBUG_MODE) {
|
|
2701
|
-
console.log(`go mod why -m -vendor ${pkgFullName}`);
|
|
2702
|
-
}
|
|
2703
|
-
const mresult = spawnSync(
|
|
2704
|
-
"go",
|
|
2705
|
-
["mod", "why", "-m", "-vendor", pkgFullName],
|
|
2706
|
-
{ cwd: path, encoding: "utf-8", timeout: TIMEOUT_MS }
|
|
2707
|
-
);
|
|
2708
|
-
if (mresult.status !== 0 || mresult.error) {
|
|
2709
|
-
if (DEBUG_MODE) {
|
|
2710
|
-
if (mresult.stdout) {
|
|
2711
|
-
console.log(mresult.stdout);
|
|
2712
|
-
}
|
|
2713
|
-
if (mresult.stderr) {
|
|
2714
|
-
console.log(mresult.stderr);
|
|
2715
|
-
}
|
|
2716
|
-
}
|
|
2717
|
-
circuitBreak = true;
|
|
2718
|
-
} else {
|
|
2719
|
-
const mstdout = mresult.stdout;
|
|
2720
|
-
if (mstdout) {
|
|
2721
|
-
const cmdOutput = Buffer.from(mstdout).toString();
|
|
2722
|
-
const whyPkg = parseGoModWhy(cmdOutput);
|
|
2723
|
-
if (whyPkg == pkgFullName) {
|
|
2724
|
-
allImports[pkgFullName] = true;
|
|
2725
|
-
}
|
|
2726
|
-
}
|
|
2727
|
-
}
|
|
2728
|
-
}
|
|
2729
|
-
if (DEBUG_MODE) {
|
|
2730
|
-
console.log(`Required packages: ${Object.keys(allImports).length}`);
|
|
2731
|
-
}
|
|
2732
2815
|
if (pkgList.length && !shouldManuallyParse) {
|
|
2733
2816
|
return buildBomNSData(options, pkgList, "golang", {
|
|
2734
2817
|
allImports,
|
|
2818
|
+
dependencies,
|
|
2819
|
+
parentComponent,
|
|
2735
2820
|
src: path,
|
|
2736
2821
|
filename: gomodFiles.join(", ")
|
|
2737
2822
|
});
|
|
2738
2823
|
}
|
|
2739
2824
|
}
|
|
2740
|
-
// Parse the gomod files manually. The resultant
|
|
2825
|
+
// Parse the gomod files manually. The resultant BOM would be incomplete
|
|
2741
2826
|
if (!["docker", "oci", "os"].includes(options.projectType)) {
|
|
2742
2827
|
console.log(
|
|
2743
|
-
"Manually parsing go.mod files. The resultant
|
|
2828
|
+
"Manually parsing go.mod files. The resultant BOM would be incomplete."
|
|
2744
2829
|
);
|
|
2745
2830
|
}
|
|
2746
2831
|
for (const f of gomodFiles) {
|
|
@@ -2755,6 +2840,8 @@ export const createGoBom = async (path, options) => {
|
|
|
2755
2840
|
}
|
|
2756
2841
|
return buildBomNSData(options, pkgList, "golang", {
|
|
2757
2842
|
src: path,
|
|
2843
|
+
dependencies,
|
|
2844
|
+
parentComponent,
|
|
2758
2845
|
filename: gomodFiles.join(", ")
|
|
2759
2846
|
});
|
|
2760
2847
|
} else if (gopkgLockFiles.length) {
|
|
@@ -2772,6 +2859,8 @@ export const createGoBom = async (path, options) => {
|
|
|
2772
2859
|
}
|
|
2773
2860
|
return buildBomNSData(options, pkgList, "golang", {
|
|
2774
2861
|
src: path,
|
|
2862
|
+
dependencies,
|
|
2863
|
+
parentComponent,
|
|
2775
2864
|
filename: gopkgLockFiles.join(", ")
|
|
2776
2865
|
});
|
|
2777
2866
|
}
|
|
@@ -3284,7 +3373,7 @@ export const createCloudBuildBom = (path, options) => {
|
|
|
3284
3373
|
*/
|
|
3285
3374
|
export const createOSBom = (path, options) => {
|
|
3286
3375
|
console.warn(
|
|
3287
|
-
"About to generate
|
|
3376
|
+
"About to generate OBOM for the current OS installation. This will take several minutes ..."
|
|
3288
3377
|
);
|
|
3289
3378
|
let pkgList = [];
|
|
3290
3379
|
let bomData = {};
|
|
@@ -3963,6 +4052,10 @@ export const createCsharpBom = async (
|
|
|
3963
4052
|
path,
|
|
3964
4053
|
(options.multiProject ? "**/" : "") + "packages.lock.json"
|
|
3965
4054
|
);
|
|
4055
|
+
const paketLockFiles = getAllFiles(
|
|
4056
|
+
path,
|
|
4057
|
+
(options.multiProject ? "**/" : "") + "paket.lock"
|
|
4058
|
+
);
|
|
3966
4059
|
const nupkgFiles = getAllFiles(
|
|
3967
4060
|
path,
|
|
3968
4061
|
(options.multiProject ? "**/" : "") + "*.nupkg"
|
|
@@ -4046,6 +4139,20 @@ export const createCsharpBom = async (
|
|
|
4046
4139
|
}
|
|
4047
4140
|
}
|
|
4048
4141
|
}
|
|
4142
|
+
if (paketLockFiles.length) {
|
|
4143
|
+
manifestFiles = manifestFiles.concat(paketLockFiles);
|
|
4144
|
+
// paket.lock parsing
|
|
4145
|
+
for (const f of paketLockFiles) {
|
|
4146
|
+
if (DEBUG_MODE) {
|
|
4147
|
+
console.log(`Parsing ${f}`);
|
|
4148
|
+
}
|
|
4149
|
+
pkgData = readFileSync(f, { encoding: "utf-8" });
|
|
4150
|
+
const dlist = await parsePaketLockData(pkgData);
|
|
4151
|
+
if (dlist && dlist.length) {
|
|
4152
|
+
pkgList = pkgList.concat(dlist);
|
|
4153
|
+
}
|
|
4154
|
+
}
|
|
4155
|
+
}
|
|
4049
4156
|
if (!parentComponent) {
|
|
4050
4157
|
parentComponent = createDefaultParentComponent(path, options.type, options);
|
|
4051
4158
|
}
|
|
@@ -4110,13 +4217,16 @@ export const trimComponents = (components, format) => {
|
|
|
4110
4217
|
const filteredComponents = [];
|
|
4111
4218
|
for (const comp of components) {
|
|
4112
4219
|
if (format === "xml" && comp.component) {
|
|
4113
|
-
const key =
|
|
4220
|
+
const key =
|
|
4221
|
+
comp.component.purl ||
|
|
4222
|
+
comp.component["bom-ref"] ||
|
|
4223
|
+
comp.name + comp.version;
|
|
4114
4224
|
if (!keyCache[key]) {
|
|
4115
4225
|
keyCache[key] = true;
|
|
4116
4226
|
filteredComponents.push(comp);
|
|
4117
4227
|
}
|
|
4118
4228
|
} else {
|
|
4119
|
-
const key = comp.purl || comp["bom-ref"];
|
|
4229
|
+
const key = comp.purl || comp["bom-ref"] || comp.name + comp.version;
|
|
4120
4230
|
if (!keyCache[key]) {
|
|
4121
4231
|
keyCache[key] = true;
|
|
4122
4232
|
filteredComponents.push(comp);
|
|
@@ -4143,7 +4253,7 @@ export const dedupeBom = (
|
|
|
4143
4253
|
componentsXmls = trimComponents(componentsXmls, "xml");
|
|
4144
4254
|
if (DEBUG_MODE) {
|
|
4145
4255
|
console.log(
|
|
4146
|
-
`
|
|
4256
|
+
`BOM includes ${components.length} components and ${dependencies.length} dependencies after dedupe`
|
|
4147
4257
|
);
|
|
4148
4258
|
}
|
|
4149
4259
|
const serialNum = "urn:uuid:" + uuidv4();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cyclonedx/cdxgen",
|
|
3
|
-
"version": "9.8.
|
|
3
|
+
"version": "9.8.8",
|
|
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>",
|
|
@@ -31,11 +31,11 @@
|
|
|
31
31
|
"type": "module",
|
|
32
32
|
"exports": "./index.js",
|
|
33
33
|
"bin": {
|
|
34
|
-
"cdxgen": "
|
|
35
|
-
"obom": "
|
|
36
|
-
"cdxi": "
|
|
37
|
-
"evinse": "
|
|
38
|
-
"cdx-verify": "
|
|
34
|
+
"cdxgen": "bin/cdxgen.js",
|
|
35
|
+
"obom": "bin/cdxgen.js",
|
|
36
|
+
"cdxi": "bin/repl.js",
|
|
37
|
+
"evinse": "bin/evinse.js",
|
|
38
|
+
"cdx-verify": "bin/verify.js"
|
|
39
39
|
},
|
|
40
40
|
"scripts": {
|
|
41
41
|
"docs": "docsify serve docs",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
},
|
|
50
50
|
"repository": {
|
|
51
51
|
"type": "git",
|
|
52
|
-
"url": "git+https://github.com/CycloneDX/cdxgen"
|
|
52
|
+
"url": "git+https://github.com/CycloneDX/cdxgen.git"
|
|
53
53
|
},
|
|
54
54
|
"bugs": {
|
|
55
55
|
"url": "https://github.com/cyclonedx/cdxgen/issues"
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
"yargs": "^17.7.2"
|
|
83
83
|
},
|
|
84
84
|
"optionalDependencies": {
|
|
85
|
-
"@appthreat/atom": "
|
|
85
|
+
"@appthreat/atom": "1.2.5",
|
|
86
86
|
"@cyclonedx/cdxgen-plugins-bin": "^1.4.0",
|
|
87
87
|
"@cyclonedx/cdxgen-plugins-bin-arm64": "^1.4.0",
|
|
88
88
|
"@cyclonedx/cdxgen-plugins-bin-ppc64": "^1.4.0",
|
|
@@ -107,4 +107,4 @@
|
|
|
107
107
|
"jest": "^29.7.0",
|
|
108
108
|
"prettier": "3.0.3"
|
|
109
109
|
}
|
|
110
|
-
}
|
|
110
|
+
}
|
package/server.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import connect from "connect";
|
|
2
2
|
import http from "node:http";
|
|
3
3
|
import bodyParser from "body-parser";
|
|
4
|
-
import url from "node:url";
|
|
4
|
+
import url, { URL } from "node:url";
|
|
5
5
|
import { spawnSync } from "node:child_process";
|
|
6
6
|
import os from "node:os";
|
|
7
7
|
import fs from "node:fs";
|
|
@@ -24,10 +24,14 @@ app.use(
|
|
|
24
24
|
app.use(compression());
|
|
25
25
|
|
|
26
26
|
const gitClone = (repoUrl) => {
|
|
27
|
+
const parsedUrl = new URL(repoUrl);
|
|
28
|
+
|
|
29
|
+
const sanitizedRepoUrl = `${parsedUrl.protocol}//${parsedUrl.host}${parsedUrl.pathname}`;
|
|
30
|
+
|
|
27
31
|
const tempDir = fs.mkdtempSync(
|
|
28
|
-
path.join(os.tmpdir(), path.basename(
|
|
32
|
+
path.join(os.tmpdir(), path.basename(parsedUrl.pathname))
|
|
29
33
|
);
|
|
30
|
-
console.log("Cloning",
|
|
34
|
+
console.log("Cloning", sanitizedRepoUrl, "to", tempDir);
|
|
31
35
|
const result = spawnSync("git", ["clone", repoUrl, "--depth", "1", tempDir], {
|
|
32
36
|
encoding: "utf-8",
|
|
33
37
|
shell: false
|