@cyclonedx/cdxgen 12.3.3 → 12.4.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.
Files changed (175) hide show
  1. package/README.md +69 -25
  2. package/bin/audit.js +21 -7
  3. package/bin/cdxgen.js +270 -127
  4. package/bin/convert.js +34 -15
  5. package/bin/hbom.js +495 -0
  6. package/bin/repl.js +592 -37
  7. package/bin/validate.js +31 -4
  8. package/bin/verify.js +18 -5
  9. package/data/README.md +298 -25
  10. package/data/component-tags.json +6 -0
  11. package/data/crypto-oid.json +16 -0
  12. package/data/cyclonedx-2.0-bundled.schema.json +7182 -0
  13. package/data/predictive-audit-allowlist.json +11 -0
  14. package/data/queries-darwin.json +12 -1
  15. package/data/queries-win.json +7 -1
  16. package/data/queries.json +39 -2
  17. package/data/rules/ai-agent-governance.yaml +16 -0
  18. package/data/rules/asar-archives.yaml +150 -0
  19. package/data/rules/chrome-extensions.yaml +8 -0
  20. package/data/rules/ci-permissions.yaml +42 -18
  21. package/data/rules/container-risk.yaml +14 -7
  22. package/data/rules/dependency-sources.yaml +11 -0
  23. package/data/rules/hbom-compliance.yaml +325 -0
  24. package/data/rules/hbom-performance.yaml +307 -0
  25. package/data/rules/hbom-security.yaml +248 -0
  26. package/data/rules/host-topology.yaml +165 -0
  27. package/data/rules/mcp-servers.yaml +18 -3
  28. package/data/rules/obom-runtime.yaml +907 -22
  29. package/data/rules/package-integrity.yaml +14 -0
  30. package/data/rules/rootfs-hardening.yaml +179 -0
  31. package/data/rules/vscode-extensions.yaml +9 -0
  32. package/lib/audit/index.js +210 -8
  33. package/lib/audit/index.poku.js +332 -0
  34. package/lib/audit/reporters.js +222 -0
  35. package/lib/audit/targets.js +146 -1
  36. package/lib/audit/targets.poku.js +186 -0
  37. package/lib/cli/asar.poku.js +328 -0
  38. package/lib/cli/index.js +527 -99
  39. package/lib/cli/index.poku.js +1469 -212
  40. package/lib/evinser/evinser.js +14 -9
  41. package/lib/helpers/analyzer.js +1406 -29
  42. package/lib/helpers/analyzer.poku.js +342 -0
  43. package/lib/helpers/analyzerScope.js +712 -0
  44. package/lib/helpers/asarutils.js +1556 -0
  45. package/lib/helpers/asarutils.poku.js +443 -0
  46. package/lib/helpers/auditCategories.js +12 -0
  47. package/lib/helpers/auditCategories.poku.js +32 -0
  48. package/lib/helpers/bomUtils.js +155 -1
  49. package/lib/helpers/bomUtils.poku.js +79 -1
  50. package/lib/helpers/cbomutils.js +271 -1
  51. package/lib/helpers/cbomutils.poku.js +248 -5
  52. package/lib/helpers/display.js +291 -1
  53. package/lib/helpers/display.poku.js +149 -0
  54. package/lib/helpers/evidenceUtils.js +58 -0
  55. package/lib/helpers/evidenceUtils.poku.js +54 -0
  56. package/lib/helpers/exportUtils.js +9 -0
  57. package/lib/helpers/gtfobins.js +142 -8
  58. package/lib/helpers/gtfobins.poku.js +24 -1
  59. package/lib/helpers/hbom.js +710 -0
  60. package/lib/helpers/hbom.poku.js +496 -0
  61. package/lib/helpers/hbomAnalysis.js +268 -0
  62. package/lib/helpers/hbomAnalysis.poku.js +249 -0
  63. package/lib/helpers/hbomLoader.js +35 -0
  64. package/lib/helpers/hostTopology.js +803 -0
  65. package/lib/helpers/hostTopology.poku.js +363 -0
  66. package/lib/helpers/inventoryStats.js +69 -0
  67. package/lib/helpers/inventoryStats.poku.js +86 -0
  68. package/lib/helpers/lolbas.js +19 -1
  69. package/lib/helpers/lolbas.poku.js +23 -0
  70. package/lib/helpers/osqueryTransform.js +47 -0
  71. package/lib/helpers/osqueryTransform.poku.js +47 -0
  72. package/lib/helpers/plugins.js +350 -0
  73. package/lib/helpers/plugins.poku.js +57 -0
  74. package/lib/helpers/protobom.js +209 -45
  75. package/lib/helpers/protobom.poku.js +183 -5
  76. package/lib/helpers/protobomLoader.js +43 -0
  77. package/lib/helpers/protobomLoader.poku.js +31 -0
  78. package/lib/helpers/remote/dependency-track.js +36 -3
  79. package/lib/helpers/remote/dependency-track.poku.js +44 -0
  80. package/lib/helpers/source.js +24 -0
  81. package/lib/helpers/source.poku.js +32 -0
  82. package/lib/helpers/utils.js +1438 -93
  83. package/lib/helpers/utils.poku.js +846 -4
  84. package/lib/managers/binary.e2e.poku.js +367 -0
  85. package/lib/managers/binary.js +2293 -353
  86. package/lib/managers/binary.poku.js +1699 -1
  87. package/lib/managers/docker.js +201 -79
  88. package/lib/managers/docker.poku.js +337 -12
  89. package/lib/server/server.js +4 -28
  90. package/lib/stages/postgen/annotator.js +38 -0
  91. package/lib/stages/postgen/annotator.poku.js +107 -1
  92. package/lib/stages/postgen/auditBom.js +121 -18
  93. package/lib/stages/postgen/auditBom.poku.js +1366 -31
  94. package/lib/stages/postgen/hostTopologyAudit.poku.js +186 -0
  95. package/lib/stages/postgen/postgen.js +406 -8
  96. package/lib/stages/postgen/postgen.poku.js +484 -0
  97. package/lib/stages/postgen/ruleEngine.js +116 -0
  98. package/lib/stages/pregen/envAudit.js +14 -3
  99. package/lib/validator/bomValidator.js +90 -38
  100. package/lib/validator/bomValidator.poku.js +90 -0
  101. package/lib/validator/complianceRules.js +4 -2
  102. package/lib/validator/index.poku.js +14 -0
  103. package/package.json +23 -21
  104. package/types/bin/hbom.d.ts +3 -0
  105. package/types/bin/hbom.d.ts.map +1 -0
  106. package/types/bin/repl.d.ts +1 -1
  107. package/types/bin/repl.d.ts.map +1 -1
  108. package/types/lib/audit/index.d.ts +44 -0
  109. package/types/lib/audit/index.d.ts.map +1 -1
  110. package/types/lib/audit/reporters.d.ts +16 -0
  111. package/types/lib/audit/reporters.d.ts.map +1 -1
  112. package/types/lib/audit/targets.d.ts.map +1 -1
  113. package/types/lib/cli/index.d.ts +16 -0
  114. package/types/lib/cli/index.d.ts.map +1 -1
  115. package/types/lib/evinser/evinser.d.ts +4 -0
  116. package/types/lib/evinser/evinser.d.ts.map +1 -1
  117. package/types/lib/helpers/analyzer.d.ts +33 -0
  118. package/types/lib/helpers/analyzer.d.ts.map +1 -1
  119. package/types/lib/helpers/analyzerScope.d.ts +11 -0
  120. package/types/lib/helpers/analyzerScope.d.ts.map +1 -0
  121. package/types/lib/helpers/asarutils.d.ts +34 -0
  122. package/types/lib/helpers/asarutils.d.ts.map +1 -0
  123. package/types/lib/helpers/auditCategories.d.ts +5 -0
  124. package/types/lib/helpers/auditCategories.d.ts.map +1 -1
  125. package/types/lib/helpers/bomUtils.d.ts +10 -0
  126. package/types/lib/helpers/bomUtils.d.ts.map +1 -1
  127. package/types/lib/helpers/cbomutils.d.ts +3 -2
  128. package/types/lib/helpers/cbomutils.d.ts.map +1 -1
  129. package/types/lib/helpers/display.d.ts.map +1 -1
  130. package/types/lib/helpers/evidenceUtils.d.ts +8 -0
  131. package/types/lib/helpers/evidenceUtils.d.ts.map +1 -0
  132. package/types/lib/helpers/exportUtils.d.ts.map +1 -1
  133. package/types/lib/helpers/gtfobins.d.ts +8 -0
  134. package/types/lib/helpers/gtfobins.d.ts.map +1 -1
  135. package/types/lib/helpers/hbom.d.ts +49 -0
  136. package/types/lib/helpers/hbom.d.ts.map +1 -0
  137. package/types/lib/helpers/hbomAnalysis.d.ts +76 -0
  138. package/types/lib/helpers/hbomAnalysis.d.ts.map +1 -0
  139. package/types/lib/helpers/hbomLoader.d.ts +7 -0
  140. package/types/lib/helpers/hbomLoader.d.ts.map +1 -0
  141. package/types/lib/helpers/hostTopology.d.ts +12 -0
  142. package/types/lib/helpers/hostTopology.d.ts.map +1 -0
  143. package/types/lib/helpers/inventoryStats.d.ts +11 -0
  144. package/types/lib/helpers/inventoryStats.d.ts.map +1 -0
  145. package/types/lib/helpers/lolbas.d.ts.map +1 -1
  146. package/types/lib/helpers/osqueryTransform.d.ts +3 -0
  147. package/types/lib/helpers/osqueryTransform.d.ts.map +1 -1
  148. package/types/lib/helpers/plugins.d.ts +58 -0
  149. package/types/lib/helpers/plugins.d.ts.map +1 -0
  150. package/types/lib/helpers/protobom.d.ts +5 -4
  151. package/types/lib/helpers/protobom.d.ts.map +1 -1
  152. package/types/lib/helpers/protobomLoader.d.ts +17 -0
  153. package/types/lib/helpers/protobomLoader.d.ts.map +1 -0
  154. package/types/lib/helpers/remote/dependency-track.d.ts +10 -3
  155. package/types/lib/helpers/remote/dependency-track.d.ts.map +1 -1
  156. package/types/lib/helpers/source.d.ts.map +1 -1
  157. package/types/lib/helpers/utils.d.ts +45 -8
  158. package/types/lib/helpers/utils.d.ts.map +1 -1
  159. package/types/lib/managers/binary.d.ts +5 -0
  160. package/types/lib/managers/binary.d.ts.map +1 -1
  161. package/types/lib/managers/docker.d.ts.map +1 -1
  162. package/types/lib/server/server.d.ts +2 -1
  163. package/types/lib/server/server.d.ts.map +1 -1
  164. package/types/lib/stages/postgen/annotator.d.ts.map +1 -1
  165. package/types/lib/stages/postgen/auditBom.d.ts +26 -1
  166. package/types/lib/stages/postgen/auditBom.d.ts.map +1 -1
  167. package/types/lib/stages/postgen/postgen.d.ts +2 -1
  168. package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
  169. package/types/lib/stages/postgen/ruleEngine.d.ts.map +1 -1
  170. package/types/lib/stages/pregen/envAudit.d.ts.map +1 -1
  171. package/types/lib/third-party/arborist/lib/node.d.ts +23 -0
  172. package/types/lib/third-party/arborist/lib/node.d.ts.map +1 -1
  173. package/types/lib/validator/bomValidator.d.ts.map +1 -1
  174. package/types/lib/validator/complianceRules.d.ts.map +1 -1
  175. package/data/spdx-model-v3.0.1.jsonld +0 -15999
@@ -20,8 +20,12 @@ import {
20
20
  getAllFiles,
21
21
  getTmpDir,
22
22
  isDryRun,
23
+ readEnvironmentVariable,
23
24
  recordActivity,
25
+ recordDecisionActivity,
26
+ recordSensitiveFileRead,
24
27
  safeExistsSync,
28
+ safeExtractArchive,
25
29
  safeMkdirSync,
26
30
  safeMkdtempSync,
27
31
  safeRmSync,
@@ -404,8 +408,34 @@ const REQUEST_TIMEOUT_SECS = 60000;
404
408
  */
405
409
  const getDefaultOptions = (forRegistry, requestedRegistryRef = forRegistry) => {
406
410
  let authTokenSet = false;
411
+ const credentialSourceEvaluations = [];
412
+ let selectedCredentialSource;
413
+ const noteCredentialSource = (source, outcome, detail = undefined) => {
414
+ credentialSourceEvaluations.push({
415
+ detail,
416
+ outcome,
417
+ source,
418
+ });
419
+ if (outcome === "selected") {
420
+ selectedCredentialSource = source;
421
+ }
422
+ };
423
+ const dockerServerAddress = readEnvironmentVariable("DOCKER_SERVER_ADDRESS");
424
+ const dockerConfig = readEnvironmentVariable("DOCKER_CONFIG");
425
+ const dockerAuthConfig = readEnvironmentVariable("DOCKER_AUTH_CONFIG", {
426
+ sensitive: true,
427
+ });
428
+ const dockerUser = readEnvironmentVariable("DOCKER_USER", {
429
+ sensitive: true,
430
+ });
431
+ const dockerPassword = readEnvironmentVariable("DOCKER_PASSWORD", {
432
+ sensitive: true,
433
+ });
434
+ const dockerEmail = readEnvironmentVariable("DOCKER_EMAIL", {
435
+ sensitive: true,
436
+ });
407
437
  if (!forRegistry) {
408
- forRegistry = process.env.DOCKER_SERVER_ADDRESS ?? DOCKER_HUB_REGISTRY;
438
+ forRegistry = dockerServerAddress ?? DOCKER_HUB_REGISTRY;
409
439
  }
410
440
  requestedRegistryRef = resolveRequestedRegistryRef(
411
441
  forRegistry,
@@ -413,6 +443,11 @@ const getDefaultOptions = (forRegistry, requestedRegistryRef = forRegistry) => {
413
443
  );
414
444
  const normalizedForRegistry =
415
445
  parseRegistryReference(forRegistry)?.authority ?? forRegistry;
446
+ const authDecisionTarget =
447
+ requestedRegistryRef ||
448
+ normalizedForRegistry ||
449
+ forRegistry ||
450
+ DOCKER_HUB_REGISTRY;
416
451
  const opts = {
417
452
  enableUnixSockets: true,
418
453
  throwHttpErrors: true,
@@ -429,41 +464,57 @@ const getDefaultOptions = (forRegistry, requestedRegistryRef = forRegistry) => {
429
464
  hooks: { beforeError: [] },
430
465
  mutableDefaults: true,
431
466
  };
432
- const DOCKER_CONFIG = process.env.DOCKER_CONFIG || join(homedir(), ".docker");
467
+ const DOCKER_CONFIG = dockerConfig || join(homedir(), ".docker");
468
+ const dockerConfigFile = join(DOCKER_CONFIG, "config.json");
433
469
  // Support for private registry
434
- if (process.env.DOCKER_AUTH_CONFIG) {
470
+ if (dockerAuthConfig) {
435
471
  opts.headers = {
436
- "X-Registry-Auth": process.env.DOCKER_AUTH_CONFIG,
472
+ "X-Registry-Auth": dockerAuthConfig,
437
473
  };
438
474
  authTokenSet = true;
475
+ noteCredentialSource("DOCKER_AUTH_CONFIG", "selected");
476
+ } else {
477
+ noteCredentialSource("DOCKER_AUTH_CONFIG", "skipped", "not set");
439
478
  }
440
479
  if (
441
480
  !authTokenSet &&
442
- process.env.DOCKER_USER &&
443
- process.env.DOCKER_PASSWORD &&
444
- process.env.DOCKER_EMAIL &&
481
+ dockerUser &&
482
+ dockerPassword &&
483
+ dockerEmail &&
445
484
  normalizedForRegistry
446
485
  ) {
447
486
  const authPayload = {
448
- username: process.env.DOCKER_USER,
449
- email: process.env.DOCKER_EMAIL,
487
+ username: dockerUser,
488
+ email: dockerEmail,
450
489
  serveraddress: normalizedForRegistry,
451
490
  };
452
- if (process.env.DOCKER_USER === "<token>") {
453
- authPayload.IdentityToken = process.env.DOCKER_PASSWORD;
491
+ if (dockerUser === "<token>") {
492
+ authPayload.IdentityToken = dockerPassword;
454
493
  } else {
455
- authPayload.password = process.env.DOCKER_PASSWORD;
494
+ authPayload.password = dockerPassword;
456
495
  }
457
496
  opts.headers = {
458
497
  "X-Registry-Auth": toBase64Url(JSON.stringify(authPayload)),
459
498
  };
460
499
  authTokenSet = true;
461
- }
462
- if (!authTokenSet && safeExistsSync(join(DOCKER_CONFIG, "config.json"))) {
463
- const configData = readFileSync(
464
- join(DOCKER_CONFIG, "config.json"),
465
- "utf-8",
500
+ noteCredentialSource(
501
+ "DOCKER_USER/DOCKER_PASSWORD/DOCKER_EMAIL",
502
+ "selected",
466
503
  );
504
+ } else if (!authTokenSet) {
505
+ noteCredentialSource(
506
+ "DOCKER_USER/DOCKER_PASSWORD/DOCKER_EMAIL",
507
+ "skipped",
508
+ dockerUser || dockerPassword || dockerEmail
509
+ ? "incomplete environment credentials"
510
+ : "not set",
511
+ );
512
+ }
513
+ if (!authTokenSet && safeExistsSync(dockerConfigFile)) {
514
+ const configData = readFileSync(dockerConfigFile, "utf-8");
515
+ recordSensitiveFileRead(dockerConfigFile, {
516
+ label: "Docker credential file",
517
+ });
467
518
  if (configData) {
468
519
  try {
469
520
  const configJson = JSON.parse(configData);
@@ -490,6 +541,11 @@ const getDefaultOptions = (forRegistry, requestedRegistryRef = forRegistry) => {
490
541
  "X-Registry-Auth": toBase64Url(JSON.stringify(authPayload)),
491
542
  };
492
543
  authTokenSet = true;
544
+ noteCredentialSource(
545
+ "docker-config-auth",
546
+ "selected",
547
+ serverAddress,
548
+ );
493
549
  break;
494
550
  }
495
551
  if (configJson.credsStore) {
@@ -502,6 +558,11 @@ const getDefaultOptions = (forRegistry, requestedRegistryRef = forRegistry) => {
502
558
  "X-Registry-Auth": helperAuthToken,
503
559
  };
504
560
  authTokenSet = true;
561
+ noteCredentialSource(
562
+ `docker-credential-helper:${configJson.credsStore}`,
563
+ "selected",
564
+ serverAddress,
565
+ );
505
566
  break;
506
567
  }
507
568
  }
@@ -522,22 +583,40 @@ const getDefaultOptions = (forRegistry, requestedRegistryRef = forRegistry) => {
522
583
  "X-Registry-Auth": helperAuthToken,
523
584
  };
524
585
  authTokenSet = true;
586
+ noteCredentialSource(
587
+ `docker-credential-helper:${configJson.credHelpers[serverAddress]}`,
588
+ "selected",
589
+ serverAddress,
590
+ );
525
591
  break;
526
592
  }
527
593
  }
528
594
  }
529
595
  }
596
+ if (!authTokenSet) {
597
+ noteCredentialSource(
598
+ "docker-config",
599
+ "skipped",
600
+ "no matching config.json auth entry",
601
+ );
602
+ }
530
603
  } catch (_err) {
531
604
  // pass
605
+ noteCredentialSource("docker-config", "skipped", "config parse failed");
532
606
  }
533
607
  }
608
+ } else if (!authTokenSet) {
609
+ noteCredentialSource("docker-config", "skipped", "config.json not found");
534
610
  }
535
611
  const userInfo = _userInfo();
536
612
  opts.podmanPrefixUrl = isWin ? "" : "http://unix:/run/podman/podman.sock:";
537
613
  opts.podmanRootlessPrefixUrl = isWin
538
614
  ? ""
539
615
  : `http://unix:/run/user/${userInfo.uid}/podman/podman.sock:`;
540
- if (!process.env.DOCKER_HOST) {
616
+ const dockerHost = readEnvironmentVariable("DOCKER_HOST");
617
+ const dockerCertPath = readEnvironmentVariable("DOCKER_CERT_PATH");
618
+ const dockerTlsVerify = readEnvironmentVariable("DOCKER_TLS_VERIFY");
619
+ if (!dockerHost) {
541
620
  if (isPodman) {
542
621
  opts.prefixUrl = isPodmanRootless
543
622
  ? opts.podmanRootlessPrefixUrl
@@ -561,7 +640,7 @@ const getDefaultOptions = (forRegistry, requestedRegistryRef = forRegistry) => {
561
640
  }
562
641
  }
563
642
  } else {
564
- let hostStr = process.env.DOCKER_HOST;
643
+ let hostStr = dockerHost;
565
644
  if (hostStr.startsWith("unix:///")) {
566
645
  hostStr = hostStr.replace("unix:///", "http://unix:/");
567
646
  if (hostStr.includes("docker.sock")) {
@@ -570,29 +649,54 @@ const getDefaultOptions = (forRegistry, requestedRegistryRef = forRegistry) => {
570
649
  }
571
650
  }
572
651
  opts.prefixUrl = hostStr;
573
- if (process.env.DOCKER_CERT_PATH) {
652
+ if (dockerCertPath) {
653
+ const dockerCertFile = join(dockerCertPath, "cert.pem");
654
+ const dockerKeyFile = join(dockerCertPath, "key.pem");
655
+ const dockerCertificate = readFileSync(dockerCertFile, "utf8");
656
+ recordSensitiveFileRead(dockerCertFile, {
657
+ label: "Docker client certificate",
658
+ });
659
+ const dockerKey = readFileSync(dockerKeyFile, "utf8");
660
+ recordSensitiveFileRead(dockerKeyFile, {
661
+ label: "Docker client private key",
662
+ });
574
663
  opts.https = {
575
- certificate: readFileSync(
576
- join(process.env.DOCKER_CERT_PATH, "cert.pem"),
577
- "utf8",
578
- ),
579
- key: readFileSync(
580
- join(process.env.DOCKER_CERT_PATH, "key.pem"),
581
- "utf8",
582
- ),
664
+ certificate: dockerCertificate,
665
+ key: dockerKey,
583
666
  };
584
667
  // Disable tls on empty values
585
668
  // From the docker docs: Setting the DOCKER_TLS_VERIFY environment variable to any value other than the empty string is equivalent to setting the --tlsverify flag
586
- if (
587
- process.env.DOCKER_TLS_VERIFY &&
588
- process.env.DOCKER_TLS_VERIFY === ""
589
- ) {
669
+ if (dockerTlsVerify === "") {
590
670
  opts.https.rejectUnauthorized = false;
591
671
  console.log("TLS Verification disabled for", hostStr);
592
672
  }
593
673
  }
594
674
  }
595
675
 
676
+ if (!selectedCredentialSource) {
677
+ noteCredentialSource(
678
+ "anonymous",
679
+ "selected",
680
+ "no credential source resolved",
681
+ );
682
+ }
683
+ const skippedSources = credentialSourceEvaluations
684
+ .filter((entry) => entry.outcome !== "selected")
685
+ .map((entry) =>
686
+ entry.detail ? `${entry.source} (${entry.detail})` : entry.source,
687
+ );
688
+ recordDecisionActivity(`docker-auth:${authDecisionTarget}`, {
689
+ metadata: {
690
+ decisionType: "credential-source-selection",
691
+ evaluatedSources: credentialSourceEvaluations.map(
692
+ ({ detail, outcome, source }) =>
693
+ detail ? `${source}:${outcome}:${detail}` : `${source}:${outcome}`,
694
+ ),
695
+ selectedSource: selectedCredentialSource,
696
+ },
697
+ reason: `Selected Docker auth source '${selectedCredentialSource}' for ${authDecisionTarget}. Skipped: ${skippedSources.length ? skippedSources.join(", ") : "none"}.`,
698
+ });
699
+
596
700
  return opts;
597
701
  };
598
702
 
@@ -611,7 +715,20 @@ const getDefaultOptions = (forRegistry, requestedRegistryRef = forRegistry) => {
611
715
  * daemon base URL, or `undefined`
612
716
  */
613
717
  export const getConnection = async (options, forRegistry) => {
718
+ if (isContainerd || isNerdctl) {
719
+ return undefined;
720
+ }
614
721
  if (isDryRun) {
722
+ try {
723
+ getDefaultOptions(forRegistry);
724
+ } catch (error) {
725
+ recordActivity({
726
+ kind: "read",
727
+ reason: `Dry run mode failed while tracing Docker credential inputs: ${error.message}`,
728
+ status: "failed",
729
+ target: error?.path || forRegistry || "container-daemon",
730
+ });
731
+ }
615
732
  recordActivity({
616
733
  kind: "network",
617
734
  reason:
@@ -621,9 +738,6 @@ export const getConnection = async (options, forRegistry) => {
621
738
  });
622
739
  return undefined;
623
740
  }
624
- if (isContainerd || isNerdctl) {
625
- return undefined;
626
- }
627
741
  if (!dockerConn) {
628
742
  const defaultOptions = getDefaultOptions(forRegistry);
629
743
  const podmanRootlessUrl = defaultOptions.podmanRootlessPrefixUrl;
@@ -1204,34 +1318,36 @@ const EXTRACT_EXCLUDE_TYPES = new Set([
1204
1318
  * empty or a non-fatal error was encountered
1205
1319
  */
1206
1320
  export const extractTar = async (fullImageName, dir, options) => {
1207
- if (isDryRun) {
1208
- recordActivity({
1209
- kind: "untar",
1210
- reason:
1211
- "Dry run mode blocks untar and layer extraction operations because they create files on disk.",
1212
- status: "blocked",
1213
- target: `${fullImageName} -> ${dir}`,
1214
- });
1215
- return false;
1216
- }
1217
1321
  try {
1218
- await stream.pipeline(
1219
- createReadStream(fullImageName),
1220
- x({
1221
- sync: false,
1222
- preserveOwner: false,
1223
- noMtime: true,
1224
- noChmod: true,
1225
- strict: !NON_STRICT_TAR_EXTRACT,
1226
- C: dir,
1227
- portable: true,
1228
- unlink: true,
1229
- onwarn: handleTarWarning,
1230
- onReadEntry: handleAbsolutePath,
1231
- filter: tarFilter,
1232
- }),
1322
+ return await safeExtractArchive(
1323
+ fullImageName,
1324
+ dir,
1325
+ async () =>
1326
+ await stream.pipeline(
1327
+ createReadStream(fullImageName),
1328
+ x({
1329
+ sync: false,
1330
+ preserveOwner: false,
1331
+ noMtime: true,
1332
+ noChmod: true,
1333
+ strict: !NON_STRICT_TAR_EXTRACT,
1334
+ C: dir,
1335
+ portable: true,
1336
+ unlink: true,
1337
+ onwarn: handleTarWarning,
1338
+ onReadEntry: handleAbsolutePath,
1339
+ filter: tarFilter,
1340
+ }),
1341
+ ),
1342
+ "untar",
1343
+ {
1344
+ blockedReason:
1345
+ "Dry run mode blocks untar and layer extraction operations because they create files on disk.",
1346
+ metadata: {
1347
+ archiveFormat: "tar",
1348
+ },
1349
+ },
1233
1350
  );
1234
- return true;
1235
1351
  } catch (err) {
1236
1352
  if (err.code === "EPERM" && err.syscall === "symlink") {
1237
1353
  console.log(
@@ -1605,7 +1721,22 @@ export const extractFromManifest = async (
1605
1721
  * Returns the location of the layers with additional packages related metadata
1606
1722
  */
1607
1723
  export const exportImage = async (fullImageName, options) => {
1724
+ // Safely ignore local directories
1725
+ if (
1726
+ !fullImageName ||
1727
+ fullImageName === "." ||
1728
+ safeExistsSync(resolve(fullImageName))
1729
+ ) {
1730
+ return undefined;
1731
+ }
1608
1732
  if (isDryRun) {
1733
+ const imageDetails = parseImageName(fullImageName);
1734
+ const requestedRegistryRef = imageDetails.registry
1735
+ ? imageDetails.repo
1736
+ ? `${imageDetails.registry}/${imageDetails.repo}`
1737
+ : imageDetails.registry
1738
+ : DOCKER_HUB_REGISTRY;
1739
+ await getConnection({}, requestedRegistryRef);
1609
1740
  recordActivity({
1610
1741
  kind: "container",
1611
1742
  reason:
@@ -1615,14 +1746,6 @@ export const exportImage = async (fullImageName, options) => {
1615
1746
  });
1616
1747
  return undefined;
1617
1748
  }
1618
- // Safely ignore local directories
1619
- if (
1620
- !fullImageName ||
1621
- fullImageName === "." ||
1622
- safeExistsSync(resolve(fullImageName))
1623
- ) {
1624
- return undefined;
1625
- }
1626
1749
  // Try to get the data locally first
1627
1750
  const localData = await getImage(fullImageName);
1628
1751
  if (!localData) {
@@ -1935,18 +2058,17 @@ export const getCredsFromHelper = (exeSuffix, serverAddress) => {
1935
2058
  } else if (result.stdout) {
1936
2059
  const cmdOutput = Buffer.from(result.stdout).toString();
1937
2060
  try {
2061
+ const dockerUser = readEnvironmentVariable("DOCKER_USER", {
2062
+ sensitive: true,
2063
+ });
2064
+ const dockerPassword = readEnvironmentVariable("DOCKER_PASSWORD", {
2065
+ sensitive: true,
2066
+ });
1938
2067
  const authPayload = JSON.parse(cmdOutput);
1939
2068
  const fixedAuthPayload = {
1940
- username:
1941
- authPayload.username ||
1942
- authPayload.Username ||
1943
- process.env.DOCKER_USER,
1944
- password:
1945
- authPayload.password ||
1946
- authPayload.Secret ||
1947
- process.env.DOCKER_PASSWORD,
1948
- email:
1949
- authPayload.email || authPayload.username || process.env.DOCKER_USER,
2069
+ username: authPayload.username || authPayload.Username || dockerUser,
2070
+ password: authPayload.password || authPayload.Secret || dockerPassword,
2071
+ email: authPayload.email || authPayload.username || dockerUser,
1950
2072
  serveraddress: serverAddress,
1951
2073
  };
1952
2074
  const authKey = toBase64Url(JSON.stringify(fixedAuthPayload));