@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.
- package/README.md +69 -25
- package/bin/audit.js +21 -7
- package/bin/cdxgen.js +270 -127
- package/bin/convert.js +34 -15
- package/bin/hbom.js +495 -0
- package/bin/repl.js +592 -37
- package/bin/validate.js +31 -4
- package/bin/verify.js +18 -5
- package/data/README.md +298 -25
- package/data/component-tags.json +6 -0
- package/data/crypto-oid.json +16 -0
- package/data/cyclonedx-2.0-bundled.schema.json +7182 -0
- package/data/predictive-audit-allowlist.json +11 -0
- package/data/queries-darwin.json +12 -1
- package/data/queries-win.json +7 -1
- package/data/queries.json +39 -2
- package/data/rules/ai-agent-governance.yaml +16 -0
- package/data/rules/asar-archives.yaml +150 -0
- package/data/rules/chrome-extensions.yaml +8 -0
- package/data/rules/ci-permissions.yaml +42 -18
- package/data/rules/container-risk.yaml +14 -7
- package/data/rules/dependency-sources.yaml +11 -0
- package/data/rules/hbom-compliance.yaml +325 -0
- package/data/rules/hbom-performance.yaml +307 -0
- package/data/rules/hbom-security.yaml +248 -0
- package/data/rules/host-topology.yaml +165 -0
- package/data/rules/mcp-servers.yaml +18 -3
- package/data/rules/obom-runtime.yaml +907 -22
- package/data/rules/package-integrity.yaml +14 -0
- package/data/rules/rootfs-hardening.yaml +179 -0
- package/data/rules/vscode-extensions.yaml +9 -0
- package/lib/audit/index.js +210 -8
- package/lib/audit/index.poku.js +332 -0
- package/lib/audit/reporters.js +222 -0
- package/lib/audit/targets.js +146 -1
- package/lib/audit/targets.poku.js +186 -0
- package/lib/cli/asar.poku.js +328 -0
- package/lib/cli/index.js +527 -99
- package/lib/cli/index.poku.js +1469 -212
- package/lib/evinser/evinser.js +14 -9
- package/lib/helpers/analyzer.js +1406 -29
- package/lib/helpers/analyzer.poku.js +342 -0
- package/lib/helpers/analyzerScope.js +712 -0
- package/lib/helpers/asarutils.js +1556 -0
- package/lib/helpers/asarutils.poku.js +443 -0
- package/lib/helpers/auditCategories.js +12 -0
- package/lib/helpers/auditCategories.poku.js +32 -0
- package/lib/helpers/bomUtils.js +155 -1
- package/lib/helpers/bomUtils.poku.js +79 -1
- package/lib/helpers/cbomutils.js +271 -1
- package/lib/helpers/cbomutils.poku.js +248 -5
- package/lib/helpers/display.js +291 -1
- package/lib/helpers/display.poku.js +149 -0
- package/lib/helpers/evidenceUtils.js +58 -0
- package/lib/helpers/evidenceUtils.poku.js +54 -0
- package/lib/helpers/exportUtils.js +9 -0
- package/lib/helpers/gtfobins.js +142 -8
- package/lib/helpers/gtfobins.poku.js +24 -1
- package/lib/helpers/hbom.js +710 -0
- package/lib/helpers/hbom.poku.js +496 -0
- package/lib/helpers/hbomAnalysis.js +268 -0
- package/lib/helpers/hbomAnalysis.poku.js +249 -0
- package/lib/helpers/hbomLoader.js +35 -0
- package/lib/helpers/hostTopology.js +803 -0
- package/lib/helpers/hostTopology.poku.js +363 -0
- package/lib/helpers/inventoryStats.js +69 -0
- package/lib/helpers/inventoryStats.poku.js +86 -0
- package/lib/helpers/lolbas.js +19 -1
- package/lib/helpers/lolbas.poku.js +23 -0
- package/lib/helpers/osqueryTransform.js +47 -0
- package/lib/helpers/osqueryTransform.poku.js +47 -0
- package/lib/helpers/plugins.js +350 -0
- package/lib/helpers/plugins.poku.js +57 -0
- package/lib/helpers/protobom.js +209 -45
- package/lib/helpers/protobom.poku.js +183 -5
- package/lib/helpers/protobomLoader.js +43 -0
- package/lib/helpers/protobomLoader.poku.js +31 -0
- package/lib/helpers/remote/dependency-track.js +36 -3
- package/lib/helpers/remote/dependency-track.poku.js +44 -0
- package/lib/helpers/source.js +24 -0
- package/lib/helpers/source.poku.js +32 -0
- package/lib/helpers/utils.js +1438 -93
- package/lib/helpers/utils.poku.js +846 -4
- package/lib/managers/binary.e2e.poku.js +367 -0
- package/lib/managers/binary.js +2293 -353
- package/lib/managers/binary.poku.js +1699 -1
- package/lib/managers/docker.js +201 -79
- package/lib/managers/docker.poku.js +337 -12
- package/lib/server/server.js +4 -28
- package/lib/stages/postgen/annotator.js +38 -0
- package/lib/stages/postgen/annotator.poku.js +107 -1
- package/lib/stages/postgen/auditBom.js +121 -18
- package/lib/stages/postgen/auditBom.poku.js +1366 -31
- package/lib/stages/postgen/hostTopologyAudit.poku.js +186 -0
- package/lib/stages/postgen/postgen.js +406 -8
- package/lib/stages/postgen/postgen.poku.js +484 -0
- package/lib/stages/postgen/ruleEngine.js +116 -0
- package/lib/stages/pregen/envAudit.js +14 -3
- package/lib/validator/bomValidator.js +90 -38
- package/lib/validator/bomValidator.poku.js +90 -0
- package/lib/validator/complianceRules.js +4 -2
- package/lib/validator/index.poku.js +14 -0
- package/package.json +23 -21
- package/types/bin/hbom.d.ts +3 -0
- package/types/bin/hbom.d.ts.map +1 -0
- package/types/bin/repl.d.ts +1 -1
- package/types/bin/repl.d.ts.map +1 -1
- package/types/lib/audit/index.d.ts +44 -0
- package/types/lib/audit/index.d.ts.map +1 -1
- package/types/lib/audit/reporters.d.ts +16 -0
- package/types/lib/audit/reporters.d.ts.map +1 -1
- package/types/lib/audit/targets.d.ts.map +1 -1
- package/types/lib/cli/index.d.ts +16 -0
- package/types/lib/cli/index.d.ts.map +1 -1
- package/types/lib/evinser/evinser.d.ts +4 -0
- package/types/lib/evinser/evinser.d.ts.map +1 -1
- package/types/lib/helpers/analyzer.d.ts +33 -0
- package/types/lib/helpers/analyzer.d.ts.map +1 -1
- package/types/lib/helpers/analyzerScope.d.ts +11 -0
- package/types/lib/helpers/analyzerScope.d.ts.map +1 -0
- package/types/lib/helpers/asarutils.d.ts +34 -0
- package/types/lib/helpers/asarutils.d.ts.map +1 -0
- package/types/lib/helpers/auditCategories.d.ts +5 -0
- package/types/lib/helpers/auditCategories.d.ts.map +1 -1
- package/types/lib/helpers/bomUtils.d.ts +10 -0
- package/types/lib/helpers/bomUtils.d.ts.map +1 -1
- package/types/lib/helpers/cbomutils.d.ts +3 -2
- package/types/lib/helpers/cbomutils.d.ts.map +1 -1
- package/types/lib/helpers/display.d.ts.map +1 -1
- package/types/lib/helpers/evidenceUtils.d.ts +8 -0
- package/types/lib/helpers/evidenceUtils.d.ts.map +1 -0
- package/types/lib/helpers/exportUtils.d.ts.map +1 -1
- package/types/lib/helpers/gtfobins.d.ts +8 -0
- package/types/lib/helpers/gtfobins.d.ts.map +1 -1
- package/types/lib/helpers/hbom.d.ts +49 -0
- package/types/lib/helpers/hbom.d.ts.map +1 -0
- package/types/lib/helpers/hbomAnalysis.d.ts +76 -0
- package/types/lib/helpers/hbomAnalysis.d.ts.map +1 -0
- package/types/lib/helpers/hbomLoader.d.ts +7 -0
- package/types/lib/helpers/hbomLoader.d.ts.map +1 -0
- package/types/lib/helpers/hostTopology.d.ts +12 -0
- package/types/lib/helpers/hostTopology.d.ts.map +1 -0
- package/types/lib/helpers/inventoryStats.d.ts +11 -0
- package/types/lib/helpers/inventoryStats.d.ts.map +1 -0
- package/types/lib/helpers/lolbas.d.ts.map +1 -1
- package/types/lib/helpers/osqueryTransform.d.ts +3 -0
- package/types/lib/helpers/osqueryTransform.d.ts.map +1 -1
- package/types/lib/helpers/plugins.d.ts +58 -0
- package/types/lib/helpers/plugins.d.ts.map +1 -0
- package/types/lib/helpers/protobom.d.ts +5 -4
- package/types/lib/helpers/protobom.d.ts.map +1 -1
- package/types/lib/helpers/protobomLoader.d.ts +17 -0
- package/types/lib/helpers/protobomLoader.d.ts.map +1 -0
- package/types/lib/helpers/remote/dependency-track.d.ts +10 -3
- package/types/lib/helpers/remote/dependency-track.d.ts.map +1 -1
- package/types/lib/helpers/source.d.ts.map +1 -1
- package/types/lib/helpers/utils.d.ts +45 -8
- package/types/lib/helpers/utils.d.ts.map +1 -1
- package/types/lib/managers/binary.d.ts +5 -0
- package/types/lib/managers/binary.d.ts.map +1 -1
- package/types/lib/managers/docker.d.ts.map +1 -1
- package/types/lib/server/server.d.ts +2 -1
- package/types/lib/server/server.d.ts.map +1 -1
- package/types/lib/stages/postgen/annotator.d.ts.map +1 -1
- package/types/lib/stages/postgen/auditBom.d.ts +26 -1
- package/types/lib/stages/postgen/auditBom.d.ts.map +1 -1
- package/types/lib/stages/postgen/postgen.d.ts +2 -1
- package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
- package/types/lib/stages/postgen/ruleEngine.d.ts.map +1 -1
- package/types/lib/stages/pregen/envAudit.d.ts.map +1 -1
- package/types/lib/third-party/arborist/lib/node.d.ts +23 -0
- package/types/lib/third-party/arborist/lib/node.d.ts.map +1 -1
- package/types/lib/validator/bomValidator.d.ts.map +1 -1
- package/types/lib/validator/complianceRules.d.ts.map +1 -1
- package/data/spdx-model-v3.0.1.jsonld +0 -15999
package/lib/managers/docker.js
CHANGED
|
@@ -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 =
|
|
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 =
|
|
467
|
+
const DOCKER_CONFIG = dockerConfig || join(homedir(), ".docker");
|
|
468
|
+
const dockerConfigFile = join(DOCKER_CONFIG, "config.json");
|
|
433
469
|
// Support for private registry
|
|
434
|
-
if (
|
|
470
|
+
if (dockerAuthConfig) {
|
|
435
471
|
opts.headers = {
|
|
436
|
-
"X-Registry-Auth":
|
|
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
|
-
|
|
443
|
-
|
|
444
|
-
|
|
481
|
+
dockerUser &&
|
|
482
|
+
dockerPassword &&
|
|
483
|
+
dockerEmail &&
|
|
445
484
|
normalizedForRegistry
|
|
446
485
|
) {
|
|
447
486
|
const authPayload = {
|
|
448
|
-
username:
|
|
449
|
-
email:
|
|
487
|
+
username: dockerUser,
|
|
488
|
+
email: dockerEmail,
|
|
450
489
|
serveraddress: normalizedForRegistry,
|
|
451
490
|
};
|
|
452
|
-
if (
|
|
453
|
-
authPayload.IdentityToken =
|
|
491
|
+
if (dockerUser === "<token>") {
|
|
492
|
+
authPayload.IdentityToken = dockerPassword;
|
|
454
493
|
} else {
|
|
455
|
-
authPayload.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
|
-
|
|
463
|
-
|
|
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
|
-
|
|
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 =
|
|
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 (
|
|
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:
|
|
576
|
-
|
|
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
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
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
|
-
|
|
1942
|
-
|
|
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));
|