@cyclonedx/cdxgen 12.1.2 → 12.1.4
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 +11 -9
- package/bin/cdxgen.js +1 -1
- package/lib/cli/index.js +9 -5
- package/lib/evinser/evinser.js +2 -8
- package/lib/helpers/display.js +1 -1
- package/lib/helpers/envcontext.js +10 -2
- package/lib/helpers/utils.js +462 -86
- package/lib/helpers/utils.poku.js +179 -2
- package/lib/helpers/validator.js +8 -5
- package/lib/managers/docker.getConnection.poku.js +61 -0
- package/lib/managers/docker.js +36 -23
- package/lib/parsers/iri.js +1 -2
- package/lib/server/server.js +164 -34
- package/lib/server/server.poku.js +232 -10
- package/lib/stages/postgen/annotator.js +281 -3
- package/lib/stages/postgen/postgen.js +4 -7
- package/lib/third-party/arborist/lib/diff.js +1 -1
- package/lib/third-party/arborist/lib/node.js +1 -1
- package/lib/third-party/arborist/lib/yarn-lock.js +1 -1
- package/package.json +22 -328
- package/types/bin/dependencies.d.ts.map +1 -1
- package/types/lib/cli/index.d.ts +39 -39
- package/types/lib/cli/index.d.ts.map +1 -1
- package/types/lib/evinser/evinser.d.ts +19 -19
- package/types/lib/evinser/evinser.d.ts.map +1 -1
- package/types/lib/evinser/swiftsem.d.ts +14 -14
- package/types/lib/evinser/swiftsem.d.ts.map +1 -1
- package/types/lib/helpers/cbomutils.d.ts +1 -1
- package/types/lib/helpers/cbomutils.d.ts.map +1 -1
- package/types/lib/helpers/db.d.ts +2 -2
- package/types/lib/helpers/db.d.ts.map +1 -1
- package/types/lib/helpers/display.d.ts +2 -2
- package/types/lib/helpers/display.d.ts.map +1 -1
- package/types/lib/helpers/envcontext.d.ts +14 -14
- package/types/lib/helpers/envcontext.d.ts.map +1 -1
- package/types/lib/helpers/logger.d.ts +1 -1
- package/types/lib/helpers/logger.d.ts.map +1 -1
- package/types/lib/helpers/protobom.d.ts +4 -2
- package/types/lib/helpers/protobom.d.ts.map +1 -1
- package/types/lib/helpers/utils.d.ts +103 -88
- package/types/lib/helpers/utils.d.ts.map +1 -1
- package/types/lib/helpers/validator.d.ts.map +1 -1
- package/types/lib/managers/binary.d.ts +2 -2
- package/types/lib/managers/binary.d.ts.map +1 -1
- package/types/lib/managers/docker.d.ts +2 -2
- package/types/lib/managers/docker.d.ts.map +1 -1
- package/types/lib/managers/oci.d.ts +1 -1
- package/types/lib/managers/oci.d.ts.map +1 -1
- package/types/lib/managers/piptree.d.ts +1 -1
- package/types/lib/managers/piptree.d.ts.map +1 -1
- package/types/lib/parsers/iri.d.ts +6 -6
- package/types/lib/parsers/iri.d.ts.map +1 -1
- package/types/lib/server/server.d.ts +14 -0
- package/types/lib/server/server.d.ts.map +1 -1
- package/types/lib/stages/postgen/annotator.d.ts +3 -3
- package/types/lib/stages/postgen/annotator.d.ts.map +1 -1
- package/types/lib/stages/postgen/postgen.d.ts +5 -5
- package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
- package/types/lib/stages/pregen/pregen.d.ts +6 -6
- package/types/lib/stages/pregen/pregen.d.ts.map +1 -1
- package/types/lib/third-party/arborist/lib/arborist/index.d.ts +4 -3
- package/types/lib/third-party/arborist/lib/arborist/index.d.ts.map +1 -1
- package/types/lib/third-party/arborist/lib/can-place-dep.d.ts +5 -5
- package/types/lib/third-party/arborist/lib/can-place-dep.d.ts.map +1 -1
- package/types/lib/third-party/arborist/lib/case-insensitive-map.d.ts +4 -4
- package/types/lib/third-party/arborist/lib/case-insensitive-map.d.ts.map +1 -1
- package/types/lib/third-party/arborist/lib/diff.d.ts +3 -3
- package/types/lib/third-party/arborist/lib/diff.d.ts.map +1 -1
- package/types/lib/third-party/arborist/lib/edge.d.ts +2 -2
- package/types/lib/third-party/arborist/lib/edge.d.ts.map +1 -1
- package/types/lib/third-party/arborist/lib/gather-dep-set.d.ts +1 -1
- package/types/lib/third-party/arborist/lib/gather-dep-set.d.ts.map +1 -1
- package/types/lib/third-party/arborist/lib/inventory.d.ts +3 -2
- package/types/lib/third-party/arborist/lib/inventory.d.ts.map +1 -1
- package/types/lib/third-party/arborist/lib/link.d.ts +10 -7
- package/types/lib/third-party/arborist/lib/link.d.ts.map +1 -1
- package/types/lib/third-party/arborist/lib/node.d.ts +8 -8
- package/types/lib/third-party/arborist/lib/node.d.ts.map +1 -1
- package/types/lib/third-party/arborist/lib/optional-set.d.ts +1 -1
- package/types/lib/third-party/arborist/lib/optional-set.d.ts.map +1 -1
- package/types/lib/third-party/arborist/lib/override-set.d.ts +3 -3
- package/types/lib/third-party/arborist/lib/override-set.d.ts.map +1 -1
- package/types/lib/third-party/arborist/lib/peer-entry-sets.d.ts +1 -1
- package/types/lib/third-party/arborist/lib/peer-entry-sets.d.ts.map +1 -1
- package/types/lib/third-party/arborist/lib/place-dep.d.ts +3 -3
- package/types/lib/third-party/arborist/lib/place-dep.d.ts.map +1 -1
- package/types/lib/third-party/arborist/lib/shrinkwrap.d.ts +7 -7
- package/types/lib/third-party/arborist/lib/shrinkwrap.d.ts.map +1 -1
- package/types/lib/third-party/arborist/lib/version-from-tgz.d.ts +1 -1
- package/types/lib/third-party/arborist/lib/version-from-tgz.d.ts.map +1 -1
- package/types/lib/third-party/arborist/lib/yarn-lock.d.ts +4 -3
- package/types/lib/third-party/arborist/lib/yarn-lock.d.ts.map +1 -1
- package/bin/dependencies.js +0 -131
- package/bin/licenses.js +0 -78
- package/lib/helpers/dependencies.poku.js +0 -11
- package/lib/helpers/licenses.poku.js +0 -11
- package/types/lib/third-party/arborist/lib/arborist/load-actual.d.ts +0 -34
- package/types/lib/third-party/arborist/lib/arborist/load-actual.d.ts.map +0 -1
- package/types/lib/third-party/arborist/lib/arborist/load-virtual.d.ts +0 -24
- package/types/lib/third-party/arborist/lib/arborist/load-virtual.d.ts.map +0 -1
- package/types/lib/third-party/arborist/lib/tracker.d.ts +0 -13
- package/types/lib/third-party/arborist/lib/tracker.d.ts.map +0 -1
|
@@ -2592,10 +2592,11 @@ it("parse mix lock data", () => {
|
|
|
2592
2592
|
});
|
|
2593
2593
|
});
|
|
2594
2594
|
|
|
2595
|
+
// biome-ignore-start lint/suspicious/noTemplateCurlyInString: fp
|
|
2595
2596
|
it("parse github actions workflow data", () => {
|
|
2596
2597
|
assert.deepStrictEqual(parseGitHubWorkflowData(null), []);
|
|
2597
2598
|
let dep_list = parseGitHubWorkflowData("./.github/workflows/nodejs.yml");
|
|
2598
|
-
assert.deepStrictEqual(dep_list.length,
|
|
2599
|
+
assert.deepStrictEqual(dep_list.length, 8);
|
|
2599
2600
|
assert.deepStrictEqual(dep_list[0], {
|
|
2600
2601
|
group: "actions",
|
|
2601
2602
|
name: "checkout",
|
|
@@ -2606,10 +2607,43 @@ it("parse github actions workflow data", () => {
|
|
|
2606
2607
|
name: "SrcFile",
|
|
2607
2608
|
value: "./.github/workflows/nodejs.yml",
|
|
2608
2609
|
},
|
|
2610
|
+
{
|
|
2611
|
+
name: "cdx:github:workflow:name",
|
|
2612
|
+
value: "Node CI",
|
|
2613
|
+
},
|
|
2614
|
+
{
|
|
2615
|
+
name: "cdx:github:job:name",
|
|
2616
|
+
value: "read-node-versions",
|
|
2617
|
+
},
|
|
2618
|
+
{
|
|
2619
|
+
name: "cdx:github:job:runner",
|
|
2620
|
+
value: "ubuntu-latest",
|
|
2621
|
+
},
|
|
2622
|
+
{
|
|
2623
|
+
name: "cdx:github:action:uses",
|
|
2624
|
+
value: "actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd",
|
|
2625
|
+
},
|
|
2626
|
+
{
|
|
2627
|
+
name: "cdx:github:action:versionPinningType",
|
|
2628
|
+
value: "sha",
|
|
2629
|
+
},
|
|
2630
|
+
{
|
|
2631
|
+
name: "cdx:github:action:isShaPinned",
|
|
2632
|
+
value: "true",
|
|
2633
|
+
},
|
|
2634
|
+
{
|
|
2635
|
+
name: "cdx:github:workflow:concurrencyGroup",
|
|
2636
|
+
value:
|
|
2637
|
+
"${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}",
|
|
2638
|
+
},
|
|
2609
2639
|
{
|
|
2610
2640
|
name: "cdx:actions:isOfficial",
|
|
2611
2641
|
value: "true",
|
|
2612
2642
|
},
|
|
2643
|
+
{
|
|
2644
|
+
name: "cdx:github:workflow:triggers",
|
|
2645
|
+
value: "pull_request,push,workflow_dispatch",
|
|
2646
|
+
},
|
|
2613
2647
|
],
|
|
2614
2648
|
evidence: {
|
|
2615
2649
|
identity: {
|
|
@@ -2638,6 +2672,38 @@ it("parse github actions workflow data", () => {
|
|
|
2638
2672
|
name: "SrcFile",
|
|
2639
2673
|
value: "./test/data/github-actions-tj.yaml",
|
|
2640
2674
|
},
|
|
2675
|
+
{
|
|
2676
|
+
name: "cdx:github:workflow:name",
|
|
2677
|
+
value: "Testing",
|
|
2678
|
+
},
|
|
2679
|
+
{
|
|
2680
|
+
name: "cdx:github:job:name",
|
|
2681
|
+
value: "vulnerable-actions",
|
|
2682
|
+
},
|
|
2683
|
+
{
|
|
2684
|
+
name: "cdx:github:job:runner",
|
|
2685
|
+
value: "ubuntu-latest",
|
|
2686
|
+
},
|
|
2687
|
+
{
|
|
2688
|
+
name: "cdx:github:action:uses",
|
|
2689
|
+
value: "pixel/steamcmd@foo",
|
|
2690
|
+
},
|
|
2691
|
+
{
|
|
2692
|
+
name: "cdx:github:action:versionPinningType",
|
|
2693
|
+
value: "tag",
|
|
2694
|
+
},
|
|
2695
|
+
{
|
|
2696
|
+
name: "cdx:github:action:isShaPinned",
|
|
2697
|
+
value: "false",
|
|
2698
|
+
},
|
|
2699
|
+
{
|
|
2700
|
+
name: "cdx:github:step:name",
|
|
2701
|
+
value: "Test action 1",
|
|
2702
|
+
},
|
|
2703
|
+
{
|
|
2704
|
+
name: "cdx:github:workflow:triggers",
|
|
2705
|
+
value: "push,pull_request_target",
|
|
2706
|
+
},
|
|
2641
2707
|
],
|
|
2642
2708
|
evidence: {
|
|
2643
2709
|
identity: {
|
|
@@ -2663,6 +2729,38 @@ it("parse github actions workflow data", () => {
|
|
|
2663
2729
|
name: "SrcFile",
|
|
2664
2730
|
value: "./test/data/github-actions-tj.yaml",
|
|
2665
2731
|
},
|
|
2732
|
+
{
|
|
2733
|
+
name: "cdx:github:workflow:name",
|
|
2734
|
+
value: "Testing",
|
|
2735
|
+
},
|
|
2736
|
+
{
|
|
2737
|
+
name: "cdx:github:job:name",
|
|
2738
|
+
value: "vulnerable-actions",
|
|
2739
|
+
},
|
|
2740
|
+
{
|
|
2741
|
+
name: "cdx:github:job:runner",
|
|
2742
|
+
value: "ubuntu-latest",
|
|
2743
|
+
},
|
|
2744
|
+
{
|
|
2745
|
+
name: "cdx:github:action:uses",
|
|
2746
|
+
value: "tj/branch@47dd",
|
|
2747
|
+
},
|
|
2748
|
+
{
|
|
2749
|
+
name: "cdx:github:action:versionPinningType",
|
|
2750
|
+
value: "tag",
|
|
2751
|
+
},
|
|
2752
|
+
{
|
|
2753
|
+
name: "cdx:github:action:isShaPinned",
|
|
2754
|
+
value: "false",
|
|
2755
|
+
},
|
|
2756
|
+
{
|
|
2757
|
+
name: "cdx:github:step:name",
|
|
2758
|
+
value: "Test action 2",
|
|
2759
|
+
},
|
|
2760
|
+
{
|
|
2761
|
+
name: "cdx:github:workflow:triggers",
|
|
2762
|
+
value: "push,pull_request_target",
|
|
2763
|
+
},
|
|
2666
2764
|
],
|
|
2667
2765
|
evidence: {
|
|
2668
2766
|
identity: {
|
|
@@ -2688,6 +2786,38 @@ it("parse github actions workflow data", () => {
|
|
|
2688
2786
|
name: "SrcFile",
|
|
2689
2787
|
value: "./test/data/github-actions-tj.yaml",
|
|
2690
2788
|
},
|
|
2789
|
+
{
|
|
2790
|
+
name: "cdx:github:workflow:name",
|
|
2791
|
+
value: "Testing",
|
|
2792
|
+
},
|
|
2793
|
+
{
|
|
2794
|
+
name: "cdx:github:job:name",
|
|
2795
|
+
value: "vulnerable-actions",
|
|
2796
|
+
},
|
|
2797
|
+
{
|
|
2798
|
+
name: "cdx:github:job:runner",
|
|
2799
|
+
value: "ubuntu-latest",
|
|
2800
|
+
},
|
|
2801
|
+
{
|
|
2802
|
+
name: "cdx:github:action:uses",
|
|
2803
|
+
value: "tj/branch2@v0.0.18",
|
|
2804
|
+
},
|
|
2805
|
+
{
|
|
2806
|
+
name: "cdx:github:action:versionPinningType",
|
|
2807
|
+
value: "tag",
|
|
2808
|
+
},
|
|
2809
|
+
{
|
|
2810
|
+
name: "cdx:github:action:isShaPinned",
|
|
2811
|
+
value: "false",
|
|
2812
|
+
},
|
|
2813
|
+
{
|
|
2814
|
+
name: "cdx:github:step:name",
|
|
2815
|
+
value: "Test action 3",
|
|
2816
|
+
},
|
|
2817
|
+
{
|
|
2818
|
+
name: "cdx:github:workflow:triggers",
|
|
2819
|
+
value: "push,pull_request_target",
|
|
2820
|
+
},
|
|
2691
2821
|
],
|
|
2692
2822
|
evidence: {
|
|
2693
2823
|
identity: {
|
|
@@ -2713,10 +2843,47 @@ it("parse github actions workflow data", () => {
|
|
|
2713
2843
|
name: "SrcFile",
|
|
2714
2844
|
value: "./test/data/github-actions-tj.yaml",
|
|
2715
2845
|
},
|
|
2846
|
+
{
|
|
2847
|
+
name: "cdx:github:workflow:name",
|
|
2848
|
+
value: "Testing",
|
|
2849
|
+
},
|
|
2850
|
+
{
|
|
2851
|
+
name: "cdx:github:job:name",
|
|
2852
|
+
value: "vulnerable-actions",
|
|
2853
|
+
},
|
|
2854
|
+
{
|
|
2855
|
+
name: "cdx:github:job:runner",
|
|
2856
|
+
value: "ubuntu-latest",
|
|
2857
|
+
},
|
|
2858
|
+
{
|
|
2859
|
+
name: "cdx:github:action:uses",
|
|
2860
|
+
value:
|
|
2861
|
+
"github/codeql-action/upload-sarif@192325c86100d080feab897ff886c34abd4c83a3",
|
|
2862
|
+
},
|
|
2863
|
+
{
|
|
2864
|
+
name: "cdx:github:action:versionPinningType",
|
|
2865
|
+
value: "sha",
|
|
2866
|
+
},
|
|
2867
|
+
{
|
|
2868
|
+
name: "cdx:github:action:isShaPinned",
|
|
2869
|
+
value: "true",
|
|
2870
|
+
},
|
|
2871
|
+
{
|
|
2872
|
+
name: "cdx:github:step:name",
|
|
2873
|
+
value: "Upload to code-scanning",
|
|
2874
|
+
},
|
|
2716
2875
|
{
|
|
2717
2876
|
name: "cdx:actions:isOfficial",
|
|
2718
2877
|
value: "true",
|
|
2719
2878
|
},
|
|
2879
|
+
{
|
|
2880
|
+
name: "cdx:actions:isVerified",
|
|
2881
|
+
value: "true",
|
|
2882
|
+
},
|
|
2883
|
+
{
|
|
2884
|
+
name: "cdx:github:workflow:triggers",
|
|
2885
|
+
value: "push,pull_request_target",
|
|
2886
|
+
},
|
|
2720
2887
|
],
|
|
2721
2888
|
evidence: {
|
|
2722
2889
|
identity: {
|
|
@@ -2734,8 +2901,9 @@ it("parse github actions workflow data", () => {
|
|
|
2734
2901
|
},
|
|
2735
2902
|
]);
|
|
2736
2903
|
dep_list = parseGitHubWorkflowData("./.github/workflows/repotests.yml");
|
|
2737
|
-
assert.deepStrictEqual(dep_list.length,
|
|
2904
|
+
assert.deepStrictEqual(dep_list.length, 17);
|
|
2738
2905
|
});
|
|
2906
|
+
// biome-ignore-end lint/suspicious/noTemplateCurlyInString: fp
|
|
2739
2907
|
|
|
2740
2908
|
it("parse cs pkg data", () => {
|
|
2741
2909
|
assert.deepStrictEqual(parseCsPkgData(null), []);
|
|
@@ -6275,6 +6443,15 @@ it("parse requirements.txt", async () => {
|
|
|
6275
6443
|
assert.ok(!d.version.includes(";"));
|
|
6276
6444
|
}
|
|
6277
6445
|
}
|
|
6446
|
+
deps = await parseReqFile(
|
|
6447
|
+
"./test/data/req_files/requirements-with-license.txt",
|
|
6448
|
+
false,
|
|
6449
|
+
);
|
|
6450
|
+
assert.deepStrictEqual(deps.length, 19);
|
|
6451
|
+
for (const d of deps) {
|
|
6452
|
+
assert.ok(d.licenses);
|
|
6453
|
+
assert.ok(d.licenses.length);
|
|
6454
|
+
}
|
|
6278
6455
|
});
|
|
6279
6456
|
|
|
6280
6457
|
it("parse pyproject.toml", () => {
|
package/lib/helpers/validator.js
CHANGED
|
@@ -9,6 +9,7 @@ import { thoughtLog } from "./logger.js";
|
|
|
9
9
|
import { DEBUG_MODE, dirNameStr, isPartialTree } from "./utils.js";
|
|
10
10
|
|
|
11
11
|
const dirName = dirNameStr;
|
|
12
|
+
const PLACEHOLDER_COMPONENT_NAMES = new Set(["app", "application", "project"]);
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Validate the generated bom using jsonschema
|
|
@@ -61,9 +62,13 @@ export const validateBom = (bomJson) => {
|
|
|
61
62
|
);
|
|
62
63
|
const isValid = validate(bomJson);
|
|
63
64
|
if (!isValid) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
if (bomJson.metadata?.component?.name) {
|
|
66
|
+
console.log(
|
|
67
|
+
`Schema validation failed for ${bomJson.metadata.component.name}`,
|
|
68
|
+
);
|
|
69
|
+
} else {
|
|
70
|
+
console.log("Schema validation failed");
|
|
71
|
+
}
|
|
67
72
|
console.log(validate.errors);
|
|
68
73
|
return false;
|
|
69
74
|
}
|
|
@@ -81,8 +86,6 @@ export const validateBom = (bomJson) => {
|
|
|
81
86
|
*
|
|
82
87
|
* @param {object} bomJson Bom json object
|
|
83
88
|
*/
|
|
84
|
-
const PLACEHOLDER_COMPONENT_NAMES = new Set(["app", "application", "project"]);
|
|
85
|
-
|
|
86
89
|
export const validateMetadata = (bomJson) => {
|
|
87
90
|
const errorList = [];
|
|
88
91
|
const warningsList = [];
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { userInfo as _userInfo } from "node:os";
|
|
3
|
+
import process from "node:process";
|
|
4
|
+
|
|
5
|
+
import { assert, it, skip } from "poku";
|
|
6
|
+
|
|
7
|
+
import { getConnection, isWin } from "./docker.js";
|
|
8
|
+
|
|
9
|
+
if (process.env.CI === "true" && (isWin || process.platform === "darwin")) {
|
|
10
|
+
skip("Skipping podman detection tests on Windows and Mac");
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const uid = _userInfo().uid;
|
|
14
|
+
const podmanSock = `/run/user/${uid}/podman/podman.sock`;
|
|
15
|
+
const hasPodmanSocket = !isWin && existsSync(podmanSock);
|
|
16
|
+
|
|
17
|
+
if (!hasPodmanSocket) {
|
|
18
|
+
skip("Skipping: podman rootless socket not available");
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Remove DOCKER_HOST to force auto-detection through the fallback chain.
|
|
22
|
+
// Without the fix, getDefaultOptions sets podmanPrefixUrl and
|
|
23
|
+
// podmanRootlessPrefixUrl on its return object, but getConnection's
|
|
24
|
+
// Object.assign only copies standard got properties into opts. The fallback
|
|
25
|
+
// code then reads opts.podmanRootlessPrefixUrl which is undefined, causing
|
|
26
|
+
// got to receive an invalid URL and the detection to silently fail.
|
|
27
|
+
const origDockerHost = process.env.DOCKER_HOST;
|
|
28
|
+
delete process.env.DOCKER_HOST;
|
|
29
|
+
|
|
30
|
+
await it("should detect podman rootless via auto-detection", async () => {
|
|
31
|
+
const conn = await getConnection({}, false);
|
|
32
|
+
assert.ok(
|
|
33
|
+
conn,
|
|
34
|
+
"getConnection must return a connection when podman rootless socket exists, got undefined",
|
|
35
|
+
);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
await it("should return a functional connection that can ping", async () => {
|
|
39
|
+
const conn = await getConnection({}, false);
|
|
40
|
+
assert.ok(conn, "getConnection must return a connection");
|
|
41
|
+
// podman responds to both compat and native ping endpoints
|
|
42
|
+
let pingOk = false;
|
|
43
|
+
try {
|
|
44
|
+
const response = await conn.get("_ping");
|
|
45
|
+
pingOk = response.body === "OK";
|
|
46
|
+
} catch (_err) {
|
|
47
|
+
// fall through to libpod endpoint
|
|
48
|
+
}
|
|
49
|
+
if (!pingOk) {
|
|
50
|
+
const response = await conn.get("libpod/_ping");
|
|
51
|
+
pingOk = response.body === "OK";
|
|
52
|
+
}
|
|
53
|
+
assert.ok(pingOk, "connection must be able to ping the container runtime");
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// Restore DOCKER_HOST
|
|
57
|
+
if (origDockerHost !== undefined) {
|
|
58
|
+
process.env.DOCKER_HOST = origDockerHost;
|
|
59
|
+
} else {
|
|
60
|
+
delete process.env.DOCKER_HOST;
|
|
61
|
+
}
|
package/lib/managers/docker.js
CHANGED
|
@@ -30,6 +30,15 @@ import { getDirs, getOnlyDirs } from "./containerutils.js";
|
|
|
30
30
|
export const isWin = _platform() === "win32";
|
|
31
31
|
export const DOCKER_HUB_REGISTRY = "docker.io";
|
|
32
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Encode a value as base64url (RFC 4648 §5) with padding.
|
|
35
|
+
* Docker Engine decodes X-Registry-Auth with Go's base64.URLEncoding,
|
|
36
|
+
* which uses the URL-safe alphabet (-_ instead of +/) and expects = padding.
|
|
37
|
+
* Node's "base64url" omits padding, so we convert from standard base64.
|
|
38
|
+
*/
|
|
39
|
+
const toBase64Url = (value) =>
|
|
40
|
+
Buffer.from(value).toString("base64").replace(/\+/g, "-").replace(/\//g, "_");
|
|
41
|
+
|
|
33
42
|
// Should we extract the tar image in non-strict mode
|
|
34
43
|
const NON_STRICT_TAR_EXTRACT = ["true", "1"].includes(
|
|
35
44
|
process?.env?.NON_STRICT_TAR_EXTRACT,
|
|
@@ -209,9 +218,7 @@ const getDefaultOptions = (forRegistry) => {
|
|
|
209
218
|
authPayload.password = process.env.DOCKER_PASSWORD;
|
|
210
219
|
}
|
|
211
220
|
opts.headers = {
|
|
212
|
-
"X-Registry-Auth":
|
|
213
|
-
"base64",
|
|
214
|
-
),
|
|
221
|
+
"X-Registry-Auth": toBase64Url(JSON.stringify(authPayload)),
|
|
215
222
|
};
|
|
216
223
|
}
|
|
217
224
|
if (!authTokenSet && safeExistsSync(join(DOCKER_CONFIG, "config.json"))) {
|
|
@@ -229,8 +236,20 @@ const getDefaultOptions = (forRegistry) => {
|
|
|
229
236
|
continue;
|
|
230
237
|
}
|
|
231
238
|
if (configJson.auths[serverAddress].auth) {
|
|
239
|
+
// The Docker config stores auth as base64("user:pass").
|
|
240
|
+
// The X-Registry-Auth header expects base64-encoded JSON.
|
|
241
|
+
const decoded = Buffer.from(
|
|
242
|
+
configJson.auths[serverAddress].auth,
|
|
243
|
+
"base64",
|
|
244
|
+
).toString();
|
|
245
|
+
const sepIdx = decoded.indexOf(":");
|
|
246
|
+
const authPayload = {
|
|
247
|
+
username: decoded.substring(0, sepIdx),
|
|
248
|
+
password: decoded.substring(sepIdx + 1),
|
|
249
|
+
serveraddress: serverAddress,
|
|
250
|
+
};
|
|
232
251
|
opts.headers = {
|
|
233
|
-
"X-Registry-Auth":
|
|
252
|
+
"X-Registry-Auth": toBase64Url(JSON.stringify(authPayload)),
|
|
234
253
|
};
|
|
235
254
|
authTokenSet = true;
|
|
236
255
|
break;
|
|
@@ -345,6 +364,8 @@ export const getConnection = async (options, forRegistry) => {
|
|
|
345
364
|
}
|
|
346
365
|
if (!dockerConn) {
|
|
347
366
|
const defaultOptions = getDefaultOptions(forRegistry);
|
|
367
|
+
const podmanRootlessUrl = defaultOptions.podmanRootlessPrefixUrl;
|
|
368
|
+
const podmanRootUrl = defaultOptions.podmanPrefixUrl;
|
|
348
369
|
const opts = Object.assign(
|
|
349
370
|
{},
|
|
350
371
|
{
|
|
@@ -352,7 +373,6 @@ export const getConnection = async (options, forRegistry) => {
|
|
|
352
373
|
throwHttpErrors: defaultOptions.throwHttpErrors,
|
|
353
374
|
method: defaultOptions.method,
|
|
354
375
|
prefixUrl: defaultOptions.prefixUrl,
|
|
355
|
-
headers: defaultOptions.headers,
|
|
356
376
|
},
|
|
357
377
|
options,
|
|
358
378
|
);
|
|
@@ -391,7 +411,7 @@ export const getConnection = async (options, forRegistry) => {
|
|
|
391
411
|
console.log("Docker desktop on Windows detected.");
|
|
392
412
|
}
|
|
393
413
|
} else {
|
|
394
|
-
opts.prefixUrl =
|
|
414
|
+
opts.prefixUrl = podmanRootlessUrl;
|
|
395
415
|
await got.get("libpod/_ping", opts);
|
|
396
416
|
isPodman = true;
|
|
397
417
|
isPodmanRootless = true;
|
|
@@ -404,7 +424,7 @@ export const getConnection = async (options, forRegistry) => {
|
|
|
404
424
|
}
|
|
405
425
|
} catch (_err) {
|
|
406
426
|
try {
|
|
407
|
-
opts.prefixUrl =
|
|
427
|
+
opts.prefixUrl = podmanRootUrl;
|
|
408
428
|
await got.get("libpod/_ping", opts);
|
|
409
429
|
isPodman = true;
|
|
410
430
|
isPodmanRootless = false;
|
|
@@ -446,24 +466,19 @@ export const makeRequest = async (path, method, forRegistry) => {
|
|
|
446
466
|
if (!client) {
|
|
447
467
|
return undefined;
|
|
448
468
|
}
|
|
449
|
-
|
|
469
|
+
// Use the client's prefixUrl (set correctly by getConnection for
|
|
470
|
+
// docker/podman). Only pass per-request auth headers and method options.
|
|
471
|
+
const defaultOptions = getDefaultOptions(forRegistry);
|
|
472
|
+
const opts = {
|
|
450
473
|
responseType: method === "GET" ? "json" : "buffer",
|
|
451
474
|
resolveBodyOnly: true,
|
|
452
475
|
enableUnixSockets: true,
|
|
476
|
+
throwHttpErrors: true,
|
|
453
477
|
method,
|
|
454
478
|
};
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
{
|
|
459
|
-
enableUnixSockets: defaultOptions.enableUnixSockets,
|
|
460
|
-
throwHttpErrors: defaultOptions.throwHttpErrors,
|
|
461
|
-
method: defaultOptions.method,
|
|
462
|
-
prefixUrl: defaultOptions.prefixUrl,
|
|
463
|
-
headers: defaultOptions.headers,
|
|
464
|
-
},
|
|
465
|
-
extraOptions,
|
|
466
|
-
);
|
|
479
|
+
if (defaultOptions.headers) {
|
|
480
|
+
opts.headers = defaultOptions.headers;
|
|
481
|
+
}
|
|
467
482
|
return await client(path, opts);
|
|
468
483
|
};
|
|
469
484
|
|
|
@@ -1435,9 +1450,7 @@ export const getCredsFromHelper = (exeSuffix, serverAddress) => {
|
|
|
1435
1450
|
authPayload.email || authPayload.username || process.env.DOCKER_USER,
|
|
1436
1451
|
serveraddress: serverAddress,
|
|
1437
1452
|
};
|
|
1438
|
-
const authKey =
|
|
1439
|
-
"base64",
|
|
1440
|
-
);
|
|
1453
|
+
const authKey = toBase64Url(JSON.stringify(fixedAuthPayload));
|
|
1441
1454
|
registry_auth_keys[serverAddress] = authKey;
|
|
1442
1455
|
return authKey;
|
|
1443
1456
|
} catch (_err) {
|
package/lib/parsers/iri.js
CHANGED
|
@@ -436,8 +436,7 @@ function validateParsedComponents(components) {
|
|
|
436
436
|
// Special handling for IPv6 literals
|
|
437
437
|
if (
|
|
438
438
|
components.scheme &&
|
|
439
|
-
components.host &&
|
|
440
|
-
components.host.startsWith("[") &&
|
|
439
|
+
components.host?.startsWith("[") &&
|
|
441
440
|
components.host.endsWith("]")
|
|
442
441
|
) {
|
|
443
442
|
return components;
|