@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.
Files changed (102) hide show
  1. package/README.md +11 -9
  2. package/bin/cdxgen.js +1 -1
  3. package/lib/cli/index.js +9 -5
  4. package/lib/evinser/evinser.js +2 -8
  5. package/lib/helpers/display.js +1 -1
  6. package/lib/helpers/envcontext.js +10 -2
  7. package/lib/helpers/utils.js +462 -86
  8. package/lib/helpers/utils.poku.js +179 -2
  9. package/lib/helpers/validator.js +8 -5
  10. package/lib/managers/docker.getConnection.poku.js +61 -0
  11. package/lib/managers/docker.js +36 -23
  12. package/lib/parsers/iri.js +1 -2
  13. package/lib/server/server.js +164 -34
  14. package/lib/server/server.poku.js +232 -10
  15. package/lib/stages/postgen/annotator.js +281 -3
  16. package/lib/stages/postgen/postgen.js +4 -7
  17. package/lib/third-party/arborist/lib/diff.js +1 -1
  18. package/lib/third-party/arborist/lib/node.js +1 -1
  19. package/lib/third-party/arborist/lib/yarn-lock.js +1 -1
  20. package/package.json +22 -328
  21. package/types/bin/dependencies.d.ts.map +1 -1
  22. package/types/lib/cli/index.d.ts +39 -39
  23. package/types/lib/cli/index.d.ts.map +1 -1
  24. package/types/lib/evinser/evinser.d.ts +19 -19
  25. package/types/lib/evinser/evinser.d.ts.map +1 -1
  26. package/types/lib/evinser/swiftsem.d.ts +14 -14
  27. package/types/lib/evinser/swiftsem.d.ts.map +1 -1
  28. package/types/lib/helpers/cbomutils.d.ts +1 -1
  29. package/types/lib/helpers/cbomutils.d.ts.map +1 -1
  30. package/types/lib/helpers/db.d.ts +2 -2
  31. package/types/lib/helpers/db.d.ts.map +1 -1
  32. package/types/lib/helpers/display.d.ts +2 -2
  33. package/types/lib/helpers/display.d.ts.map +1 -1
  34. package/types/lib/helpers/envcontext.d.ts +14 -14
  35. package/types/lib/helpers/envcontext.d.ts.map +1 -1
  36. package/types/lib/helpers/logger.d.ts +1 -1
  37. package/types/lib/helpers/logger.d.ts.map +1 -1
  38. package/types/lib/helpers/protobom.d.ts +4 -2
  39. package/types/lib/helpers/protobom.d.ts.map +1 -1
  40. package/types/lib/helpers/utils.d.ts +103 -88
  41. package/types/lib/helpers/utils.d.ts.map +1 -1
  42. package/types/lib/helpers/validator.d.ts.map +1 -1
  43. package/types/lib/managers/binary.d.ts +2 -2
  44. package/types/lib/managers/binary.d.ts.map +1 -1
  45. package/types/lib/managers/docker.d.ts +2 -2
  46. package/types/lib/managers/docker.d.ts.map +1 -1
  47. package/types/lib/managers/oci.d.ts +1 -1
  48. package/types/lib/managers/oci.d.ts.map +1 -1
  49. package/types/lib/managers/piptree.d.ts +1 -1
  50. package/types/lib/managers/piptree.d.ts.map +1 -1
  51. package/types/lib/parsers/iri.d.ts +6 -6
  52. package/types/lib/parsers/iri.d.ts.map +1 -1
  53. package/types/lib/server/server.d.ts +14 -0
  54. package/types/lib/server/server.d.ts.map +1 -1
  55. package/types/lib/stages/postgen/annotator.d.ts +3 -3
  56. package/types/lib/stages/postgen/annotator.d.ts.map +1 -1
  57. package/types/lib/stages/postgen/postgen.d.ts +5 -5
  58. package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
  59. package/types/lib/stages/pregen/pregen.d.ts +6 -6
  60. package/types/lib/stages/pregen/pregen.d.ts.map +1 -1
  61. package/types/lib/third-party/arborist/lib/arborist/index.d.ts +4 -3
  62. package/types/lib/third-party/arborist/lib/arborist/index.d.ts.map +1 -1
  63. package/types/lib/third-party/arborist/lib/can-place-dep.d.ts +5 -5
  64. package/types/lib/third-party/arborist/lib/can-place-dep.d.ts.map +1 -1
  65. package/types/lib/third-party/arborist/lib/case-insensitive-map.d.ts +4 -4
  66. package/types/lib/third-party/arborist/lib/case-insensitive-map.d.ts.map +1 -1
  67. package/types/lib/third-party/arborist/lib/diff.d.ts +3 -3
  68. package/types/lib/third-party/arborist/lib/diff.d.ts.map +1 -1
  69. package/types/lib/third-party/arborist/lib/edge.d.ts +2 -2
  70. package/types/lib/third-party/arborist/lib/edge.d.ts.map +1 -1
  71. package/types/lib/third-party/arborist/lib/gather-dep-set.d.ts +1 -1
  72. package/types/lib/third-party/arborist/lib/gather-dep-set.d.ts.map +1 -1
  73. package/types/lib/third-party/arborist/lib/inventory.d.ts +3 -2
  74. package/types/lib/third-party/arborist/lib/inventory.d.ts.map +1 -1
  75. package/types/lib/third-party/arborist/lib/link.d.ts +10 -7
  76. package/types/lib/third-party/arborist/lib/link.d.ts.map +1 -1
  77. package/types/lib/third-party/arborist/lib/node.d.ts +8 -8
  78. package/types/lib/third-party/arborist/lib/node.d.ts.map +1 -1
  79. package/types/lib/third-party/arborist/lib/optional-set.d.ts +1 -1
  80. package/types/lib/third-party/arborist/lib/optional-set.d.ts.map +1 -1
  81. package/types/lib/third-party/arborist/lib/override-set.d.ts +3 -3
  82. package/types/lib/third-party/arborist/lib/override-set.d.ts.map +1 -1
  83. package/types/lib/third-party/arborist/lib/peer-entry-sets.d.ts +1 -1
  84. package/types/lib/third-party/arborist/lib/peer-entry-sets.d.ts.map +1 -1
  85. package/types/lib/third-party/arborist/lib/place-dep.d.ts +3 -3
  86. package/types/lib/third-party/arborist/lib/place-dep.d.ts.map +1 -1
  87. package/types/lib/third-party/arborist/lib/shrinkwrap.d.ts +7 -7
  88. package/types/lib/third-party/arborist/lib/shrinkwrap.d.ts.map +1 -1
  89. package/types/lib/third-party/arborist/lib/version-from-tgz.d.ts +1 -1
  90. package/types/lib/third-party/arborist/lib/version-from-tgz.d.ts.map +1 -1
  91. package/types/lib/third-party/arborist/lib/yarn-lock.d.ts +4 -3
  92. package/types/lib/third-party/arborist/lib/yarn-lock.d.ts.map +1 -1
  93. package/bin/dependencies.js +0 -131
  94. package/bin/licenses.js +0 -78
  95. package/lib/helpers/dependencies.poku.js +0 -11
  96. package/lib/helpers/licenses.poku.js +0 -11
  97. package/types/lib/third-party/arborist/lib/arborist/load-actual.d.ts +0 -34
  98. package/types/lib/third-party/arborist/lib/arborist/load-actual.d.ts.map +0 -1
  99. package/types/lib/third-party/arborist/lib/arborist/load-virtual.d.ts +0 -24
  100. package/types/lib/third-party/arborist/lib/arborist/load-virtual.d.ts.map +0 -1
  101. package/types/lib/third-party/arborist/lib/tracker.d.ts +0 -13
  102. 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, 7);
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, 14);
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", () => {
@@ -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
- console.log(
65
- `Schema validation failed for ${bomJson.metadata.component.name}`,
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
+ }
@@ -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": Buffer.from(JSON.stringify(authPayload)).toString(
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": configJson.auths[serverAddress].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 = opts.podmanRootlessPrefixUrl;
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 = opts.podmanPrefixUrl;
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
- const extraOptions = {
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
- const defaultOptions = getDefaultOptions(forRegistry);
456
- const opts = Object.assign(
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 = Buffer.from(JSON.stringify(fixedAuthPayload)).toString(
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) {
@@ -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;