@cdxgen/cdxgen 0.0.1 → 13.0.0
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 +921 -87
- package/bin/audit.js +239 -0
- package/bin/cdxgen.js +2324 -0
- package/bin/convert.js +213 -0
- package/bin/evinse.js +353 -0
- package/bin/hbom.js +495 -0
- package/bin/repl.js +2224 -0
- package/bin/sign.js +195 -0
- package/bin/tracebom.js +295 -0
- package/bin/validate.js +268 -0
- package/bin/verify.js +189 -0
- package/data/README.md +307 -0
- package/data/bom-1.4.schema.json +1605 -0
- package/data/bom-1.5.schema.json +3660 -0
- package/data/bom-1.6.schema.json +5511 -0
- package/data/bom-1.7.schema.json +6700 -0
- package/data/cbomosdb-queries.json +68 -0
- package/data/component-tags.json +339 -0
- package/data/container-knowledge-index.json +125 -0
- package/data/cosdb-queries.json +17 -0
- package/data/crypto-oid.json +1998 -0
- package/data/cryptography-defs.json +3793 -0
- package/data/cryptography-defs.schema.json +576 -0
- package/data/cyclonedx-2.0-bundled.schema.json +7182 -0
- package/data/frameworks-list.json +219 -0
- package/data/glibc-stdlib.json +117 -0
- package/data/gtfobins-index.json +6296 -0
- package/data/helpers/init.gradle +71 -0
- package/data/jsf-0.82.schema.json +211 -0
- package/data/known-licenses.json +82 -0
- package/data/lic-mapping.json +338 -0
- package/data/license-aliases.json +6624 -0
- package/data/license-db.json +39059 -0
- package/data/license-deprecations.json +302 -0
- package/data/lolbas-index.json +150 -0
- package/data/predictive-audit-allowlist.json +11 -0
- package/data/pypi-pkg-aliases.json +1199 -0
- package/data/python-stdlib.json +308 -0
- package/data/queries-darwin.json +193 -0
- package/data/queries-win.json +257 -0
- package/data/queries.json +268 -0
- package/data/ruby-known-modules.json +281 -0
- package/data/rules/ai-agent-governance.yaml +323 -0
- package/data/rules/ai-bom.yaml +268 -0
- package/data/rules/ai-oversight.yaml +186 -0
- package/data/rules/ai-provenance.yaml +92 -0
- package/data/rules/asar-archives.yaml +150 -0
- package/data/rules/cbom-security.yaml +165 -0
- package/data/rules/chrome-extensions.yaml +248 -0
- package/data/rules/ci-permissions.yaml +802 -0
- package/data/rules/container-risk.yaml +353 -0
- package/data/rules/dependency-sources.yaml +236 -0
- package/data/rules/golem-go.yaml +229 -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 +388 -0
- package/data/rules/obom-runtime.yaml +1776 -0
- package/data/rules/package-integrity.yaml +364 -0
- package/data/rules/rootfs-hardening.yaml +179 -0
- package/data/rules/vscode-extensions.yaml +237 -0
- package/data/spdx-export.schema.json +6794 -0
- package/data/spdx-license-list.json +7449 -0
- package/data/spdx-licenses.json +759 -0
- package/data/spdx.schema.json +819 -0
- package/data/templates/README.md +3 -0
- package/data/templates/asvs-4.0.3.cdx.json +2943 -0
- package/data/templates/asvs-5.0.cdx.json +3046 -0
- package/data/templates/bsimm-v13.cdx.json +1008 -0
- package/data/templates/masvs-2.0.0.cdx.json +225 -0
- package/data/templates/nist-ssdf-1.1.cdx.json +828 -0
- package/data/templates/pcissc-secure-slc-1.1.cdx.json +1027 -0
- package/data/templates/scvs-1.0.0.cdx.json +813 -0
- package/data/templates/ssaf-DRAFT-2023-11.cdx.json +127 -0
- package/data/vendor-alias.json +41967 -0
- package/data/wrapdb-releases.json +4227 -0
- package/index.cjs +15 -0
- package/lib/audit/index.js +2800 -0
- package/lib/audit/progress.js +114 -0
- package/lib/audit/reporters.js +937 -0
- package/lib/audit/scoring.js +560 -0
- package/lib/audit/targets.js +798 -0
- package/lib/cli/bomAssembly.js +1833 -0
- package/lib/cli/cliOptions.js +513 -0
- package/lib/cli/index.js +2759 -0
- package/lib/cli/jsBom.js +2087 -0
- package/lib/cli/jvmBom.js +1858 -0
- package/lib/cli/managedBom.js +2083 -0
- package/lib/cli/nativeBom.js +2125 -0
- package/lib/core/activity.js +1087 -0
- package/lib/core/env.js +719 -0
- package/lib/core/fs.js +1058 -0
- package/lib/core/httpClient.js +730 -0
- package/lib/core/logger.js +142 -0
- package/lib/core/parallel.js +323 -0
- package/lib/core/paths.js +70 -0
- package/lib/core/projectConfig.js +122 -0
- package/lib/core/propertySanitizer.js +174 -0
- package/lib/core/spdx.js +5 -0
- package/lib/core/state.js +59 -0
- package/lib/core/text.js +207 -0
- package/lib/core/ui.js +876 -0
- package/lib/core/urls.js +84 -0
- package/lib/ecosystems/asarutils.js +1636 -0
- package/lib/ecosystems/bunutils.js +402 -0
- package/lib/ecosystems/caxa.js +77 -0
- package/lib/ecosystems/chromextutils.js +1174 -0
- package/lib/ecosystems/cmakeResolver.js +587 -0
- package/lib/ecosystems/cppEvidence.js +305 -0
- package/lib/ecosystems/denoutils.js +1094 -0
- package/lib/ecosystems/dotnetutils.js +132 -0
- package/lib/ecosystems/ecosystems.js +2772 -0
- package/lib/ecosystems/golem.js +1807 -0
- package/lib/ecosystems/gradleutils.js +1048 -0
- package/lib/ecosystems/jsEvidence.js +317 -0
- package/lib/ecosystems/npmutils.js +586 -0
- package/lib/ecosystems/parsers-bazel.js +875 -0
- package/lib/ecosystems/parsers-dotnet.js +1430 -0
- package/lib/ecosystems/parsers-gleam.js +302 -0
- package/lib/ecosystems/parsers-go.js +818 -0
- package/lib/ecosystems/parsers-js.js +4222 -0
- package/lib/ecosystems/parsers-jvm.js +948 -0
- package/lib/ecosystems/parsers-misc.js +3191 -0
- package/lib/ecosystems/parsers-python.js +2070 -0
- package/lib/ecosystems/parsers-rust.js +1294 -0
- package/lib/ecosystems/parsers-zig.js +861 -0
- package/lib/ecosystems/pep770.js +341 -0
- package/lib/ecosystems/pylockutils.js +427 -0
- package/lib/ecosystems/pythonutils.js +1281 -0
- package/lib/ecosystems/registryProvenance.js +1003 -0
- package/lib/ecosystems/remote/huggingface.js +1343 -0
- package/lib/ecosystems/rubyutils.js +1629 -0
- package/lib/ecosystems/rusi.js +820 -0
- package/lib/ecosystems/sbtutils.js +972 -0
- package/lib/ecosystems/tea.js +607 -0
- package/lib/ecosystems/utils.js +575 -0
- package/lib/ecosystems/zigResolver.js +410 -0
- package/lib/evinser/db.js +145 -0
- package/lib/evinser/evinser.js +2362 -0
- package/lib/evinser/scalasem.js +65 -0
- package/lib/evinser/swiftsem.js +767 -0
- package/lib/helpers/annotationFormatter.js +84 -0
- package/lib/helpers/bomSigner.js +312 -0
- package/lib/helpers/exportUtils.js +160 -0
- package/lib/helpers/remote/dependency-track.js +117 -0
- package/lib/helpers/versutils.js +202 -0
- package/lib/helpers/vsixutils.js +1069 -0
- package/lib/inventory/agentFormulationParser.js +322 -0
- package/lib/inventory/aiCollector.js +2140 -0
- package/lib/inventory/aiInventory.js +414 -0
- package/lib/inventory/aiModelVariants.js +121 -0
- package/lib/inventory/aiOversightCollector.js +661 -0
- package/lib/inventory/aiProvenanceCollector.js +822 -0
- package/lib/inventory/analyzer.js +6089 -0
- package/lib/inventory/analyzerScope.js +807 -0
- package/lib/inventory/astWorker.js +20 -0
- package/lib/inventory/atomUtils.js +1092 -0
- package/lib/inventory/auditCategories.js +192 -0
- package/lib/inventory/bomUtils.js +369 -0
- package/lib/inventory/cacheCommands.js +182 -0
- package/lib/inventory/cacheDir.js +104 -0
- package/lib/inventory/cbomutils.js +590 -0
- package/lib/inventory/cdxrs.js +434 -0
- package/lib/inventory/ciParsers/azurePipelines.js +295 -0
- package/lib/inventory/ciParsers/circleCi.js +286 -0
- package/lib/inventory/ciParsers/common.js +24 -0
- package/lib/inventory/ciParsers/githubActions.js +2434 -0
- package/lib/inventory/ciParsers/gitlabCi.js +213 -0
- package/lib/inventory/ciParsers/jenkins.js +180 -0
- package/lib/inventory/citations.js +234 -0
- package/lib/inventory/communityAiConfigParser.js +756 -0
- package/lib/inventory/containerRisk.js +204 -0
- package/lib/inventory/cryptoAlgorithmFamily.js +258 -0
- package/lib/inventory/deps.js +807 -0
- package/lib/inventory/depsUtils.js +588 -0
- package/lib/inventory/display.js +2128 -0
- package/lib/inventory/dosai.js +601 -0
- package/lib/inventory/dosaiParsers.js +154 -0
- package/lib/inventory/dynamic.js +145 -0
- package/lib/inventory/envcontext.js +1789 -0
- package/lib/inventory/evidenceUtils.js +774 -0
- package/lib/inventory/fetchBatch.js +779 -0
- package/lib/inventory/fetchRate.js +255 -0
- package/lib/inventory/forgeEnricher.js +300 -0
- package/lib/inventory/formulationParsers.js +422 -0
- package/lib/inventory/gtfobins.js +339 -0
- package/lib/inventory/hbom.js +719 -0
- package/lib/inventory/hbomAnalysis.js +310 -0
- package/lib/inventory/hbomLoader.js +35 -0
- package/lib/inventory/hostTopology.js +835 -0
- package/lib/inventory/inventoryStats.js +100 -0
- package/lib/inventory/jsonLike.js +121 -0
- package/lib/inventory/licenseEnhancer.js +918 -0
- package/lib/inventory/lolbas.js +285 -0
- package/lib/inventory/mcp.js +253 -0
- package/lib/inventory/mcpConfigParser.js +683 -0
- package/lib/inventory/mcpDiscovery.js +112 -0
- package/lib/inventory/mcpPinning.js +209 -0
- package/lib/inventory/osPackageResolver.js +493 -0
- package/lib/inventory/osinfo.js +277 -0
- package/lib/inventory/osqueryTransform.js +274 -0
- package/lib/inventory/plugins.js +466 -0
- package/lib/inventory/protobom.js +231 -0
- package/lib/inventory/protobomLoader.js +43 -0
- package/lib/inventory/provenanceUtils.js +224 -0
- package/lib/inventory/purl.js +749 -0
- package/lib/inventory/rustFormulationParser.js +339 -0
- package/lib/inventory/sbomDocument.js +340 -0
- package/lib/inventory/source.js +1488 -0
- package/lib/inventory/spdx.js +361 -0
- package/lib/inventory/spdxExpression.js +512 -0
- package/lib/inventory/spdxUtils.js +107 -0
- package/lib/inventory/table.js +263 -0
- package/lib/inventory/traceRunner.js +439 -0
- package/lib/inventory/unicodeScan.js +147 -0
- package/lib/managers/binary.js +3307 -0
- package/lib/managers/containerutils.js +125 -0
- package/lib/managers/docker.js +2145 -0
- package/lib/managers/dockerConnection.js +162 -0
- package/lib/managers/oci.js +704 -0
- package/lib/managers/piptree.js +267 -0
- package/lib/parsers/cmakeCache.js +199 -0
- package/lib/parsers/gguf.js +492 -0
- package/lib/parsers/gitAiNotes.js +233 -0
- package/lib/parsers/gitmodules.js +239 -0
- package/lib/parsers/htmlExtract.js +610 -0
- package/lib/parsers/huggingfaceManifest.js +551 -0
- package/lib/parsers/huggingfaceUtils.js +506 -0
- package/lib/parsers/iri.js +618 -0
- package/lib/parsers/npmrc.js +99 -0
- package/lib/parsers/ollama.js +101 -0
- package/lib/parsers/xml.js +841 -0
- package/lib/server/openapi.yaml +433 -0
- package/lib/server/server.js +616 -0
- package/lib/stages/postgen/annotator.js +977 -0
- package/lib/stages/postgen/auditBom.js +468 -0
- package/lib/stages/postgen/postgen.js +1239 -0
- package/lib/stages/postgen/ruleEngine.js +731 -0
- package/lib/stages/postgen/sortBom.js +195 -0
- package/lib/stages/postgen/spdxConverter.js +796 -0
- package/lib/stages/postgen/specVersionCompat.js +703 -0
- package/lib/stages/pregen/envAudit.js +388 -0
- package/lib/stages/pregen/pregen.js +637 -0
- package/lib/third-party/README.md +9 -0
- package/lib/third-party/arborist/CHANGELOG.md +1109 -0
- package/lib/third-party/arborist/LICENSE.md +20 -0
- package/lib/third-party/arborist/README.md +315 -0
- package/lib/third-party/arborist/lib/arborist/index.js +258 -0
- package/lib/third-party/arborist/lib/arborist/load-actual.js +605 -0
- package/lib/third-party/arborist/lib/arborist/load-virtual.js +300 -0
- package/lib/third-party/arborist/lib/bin-links.js +120 -0
- package/lib/third-party/arborist/lib/calc-dep-flags.js +130 -0
- package/lib/third-party/arborist/lib/case-insensitive-map.js +51 -0
- package/lib/third-party/arborist/lib/consistent-resolve.js +42 -0
- package/lib/third-party/arborist/lib/debug.js +50 -0
- package/lib/third-party/arborist/lib/dep-valid.js +190 -0
- package/lib/third-party/arborist/lib/edge.js +417 -0
- package/lib/third-party/arborist/lib/from-path.js +36 -0
- package/lib/third-party/arborist/lib/gather-dep-set.js +43 -0
- package/lib/third-party/arborist/lib/index.js +22 -0
- package/lib/third-party/arborist/lib/inventory.js +138 -0
- package/lib/third-party/arborist/lib/link.js +169 -0
- package/lib/third-party/arborist/lib/node.js +1673 -0
- package/lib/third-party/arborist/lib/npm-extension.js +45 -0
- package/lib/third-party/arborist/lib/override-resolves.js +11 -0
- package/lib/third-party/arborist/lib/override-set.js +319 -0
- package/lib/third-party/arborist/lib/package-extensions.js +289 -0
- package/lib/third-party/arborist/lib/printable.js +210 -0
- package/lib/third-party/arborist/lib/proc-log.js +30 -0
- package/lib/third-party/arborist/lib/realpath.js +100 -0
- package/lib/third-party/arborist/lib/relpath.js +4 -0
- package/lib/third-party/arborist/lib/shrinkwrap.js +1291 -0
- package/lib/third-party/arborist/lib/spec-from-lock.js +34 -0
- package/lib/third-party/arborist/lib/tree-check.js +165 -0
- package/lib/third-party/arborist/lib/validate-npm-package-name.js +107 -0
- package/lib/third-party/arborist/lib/version-from-tgz.js +51 -0
- package/lib/third-party/arborist/lib/yarn-lock.js +397 -0
- package/lib/validator/bomValidator.js +985 -0
- package/lib/validator/complianceEngine.js +241 -0
- package/lib/validator/complianceRules.js +1680 -0
- package/lib/validator/generated/runtime.mjs +17 -0
- package/lib/validator/generated/validate-1.6.mjs +21258 -0
- package/lib/validator/generated/validate-1.7.mjs +24803 -0
- package/lib/validator/generated/validate-2.0.mjs +22931 -0
- package/lib/validator/index.js +246 -0
- package/lib/validator/reporters/annotations.js +142 -0
- package/lib/validator/reporters/console.js +160 -0
- package/lib/validator/reporters/index.js +41 -0
- package/lib/validator/reporters/json.js +37 -0
- package/lib/validator/reporters/sarif.js +184 -0
- package/package.json +209 -26
- package/types/bin/audit.d.ts +3 -0
- package/types/bin/audit.d.ts.map +1 -0
- package/types/bin/cdxgen.d.ts +3 -0
- package/types/bin/cdxgen.d.ts.map +1 -0
- package/types/bin/convert.d.ts +3 -0
- package/types/bin/convert.d.ts.map +1 -0
- package/types/bin/evinse.d.ts +3 -0
- package/types/bin/evinse.d.ts.map +1 -0
- package/types/bin/hbom.d.ts +3 -0
- package/types/bin/hbom.d.ts.map +1 -0
- package/types/bin/repl.d.ts +3 -0
- package/types/bin/repl.d.ts.map +1 -0
- package/types/bin/sign.d.ts +3 -0
- package/types/bin/sign.d.ts.map +1 -0
- package/types/bin/tracebom.d.ts +3 -0
- package/types/bin/tracebom.d.ts.map +1 -0
- package/types/bin/validate.d.ts +14 -0
- package/types/bin/validate.d.ts.map +1 -0
- package/types/bin/verify.d.ts +3 -0
- package/types/bin/verify.d.ts.map +1 -0
- package/types/lib/audit/index.d.ts +153 -0
- package/types/lib/audit/index.d.ts.map +1 -0
- package/types/lib/audit/progress.d.ts +31 -0
- package/types/lib/audit/progress.d.ts.map +1 -0
- package/types/lib/audit/reporters.d.ts +62 -0
- package/types/lib/audit/reporters.d.ts.map +1 -0
- package/types/lib/audit/scoring.d.ts +36 -0
- package/types/lib/audit/scoring.d.ts.map +1 -0
- package/types/lib/audit/targets.d.ts +77 -0
- package/types/lib/audit/targets.d.ts.map +1 -0
- package/types/lib/cli/bomAssembly.d.ts +315 -0
- package/types/lib/cli/bomAssembly.d.ts.map +1 -0
- package/types/lib/cli/cliOptions.d.ts +156 -0
- package/types/lib/cli/cliOptions.d.ts.map +1 -0
- package/types/lib/cli/index.d.ts +107 -0
- package/types/lib/cli/index.d.ts.map +1 -0
- package/types/lib/cli/jsBom.d.ts +94 -0
- package/types/lib/cli/jsBom.d.ts.map +1 -0
- package/types/lib/cli/jvmBom.d.ts +54 -0
- package/types/lib/cli/jvmBom.d.ts.map +1 -0
- package/types/lib/cli/managedBom.d.ts +105 -0
- package/types/lib/cli/managedBom.d.ts.map +1 -0
- package/types/lib/cli/nativeBom.d.ts +143 -0
- package/types/lib/cli/nativeBom.d.ts.map +1 -0
- package/types/lib/core/activity.d.ts +178 -0
- package/types/lib/core/activity.d.ts.map +1 -0
- package/types/lib/core/env.d.ts +192 -0
- package/types/lib/core/env.d.ts.map +1 -0
- package/types/lib/core/fs.d.ts +158 -0
- package/types/lib/core/fs.d.ts.map +1 -0
- package/types/lib/core/httpClient.d.ts +149 -0
- package/types/lib/core/httpClient.d.ts.map +1 -0
- package/types/lib/core/logger.d.ts +28 -0
- package/types/lib/core/logger.d.ts.map +1 -0
- package/types/lib/core/parallel.d.ts +95 -0
- package/types/lib/core/parallel.d.ts.map +1 -0
- package/types/lib/core/paths.d.ts +36 -0
- package/types/lib/core/paths.d.ts.map +1 -0
- package/types/lib/core/projectConfig.d.ts +23 -0
- package/types/lib/core/projectConfig.d.ts.map +1 -0
- package/types/lib/core/propertySanitizer.d.ts +23 -0
- package/types/lib/core/propertySanitizer.d.ts.map +1 -0
- package/types/lib/core/spdx.d.ts +5 -0
- package/types/lib/core/spdx.d.ts.map +1 -0
- package/types/lib/core/state.d.ts +20 -0
- package/types/lib/core/state.d.ts.map +1 -0
- package/types/lib/core/text.d.ts +78 -0
- package/types/lib/core/text.d.ts.map +1 -0
- package/types/lib/core/ui.d.ts +87 -0
- package/types/lib/core/ui.d.ts.map +1 -0
- package/types/lib/core/urls.d.ts +43 -0
- package/types/lib/core/urls.d.ts.map +1 -0
- package/types/lib/ecosystems/asarutils.d.ts +71 -0
- package/types/lib/ecosystems/asarutils.d.ts.map +1 -0
- package/types/lib/ecosystems/bunutils.d.ts +38 -0
- package/types/lib/ecosystems/bunutils.d.ts.map +1 -0
- package/types/lib/ecosystems/caxa.d.ts +8 -0
- package/types/lib/ecosystems/caxa.d.ts.map +1 -0
- package/types/lib/ecosystems/chromextutils.d.ts +97 -0
- package/types/lib/ecosystems/chromextutils.d.ts.map +1 -0
- package/types/lib/ecosystems/cmakeResolver.d.ts +176 -0
- package/types/lib/ecosystems/cmakeResolver.d.ts.map +1 -0
- package/types/lib/ecosystems/cppEvidence.d.ts +35 -0
- package/types/lib/ecosystems/cppEvidence.d.ts.map +1 -0
- package/types/lib/ecosystems/denoutils.d.ts +76 -0
- package/types/lib/ecosystems/denoutils.d.ts.map +1 -0
- package/types/lib/ecosystems/dotnetutils.d.ts +45 -0
- package/types/lib/ecosystems/dotnetutils.d.ts.map +1 -0
- package/types/lib/ecosystems/ecosystems.d.ts +279 -0
- package/types/lib/ecosystems/ecosystems.d.ts.map +1 -0
- package/types/lib/ecosystems/golem.d.ts +60 -0
- package/types/lib/ecosystems/golem.d.ts.map +1 -0
- package/types/lib/ecosystems/gradleutils.d.ts +139 -0
- package/types/lib/ecosystems/gradleutils.d.ts.map +1 -0
- package/types/lib/ecosystems/jsEvidence.d.ts +17 -0
- package/types/lib/ecosystems/jsEvidence.d.ts.map +1 -0
- package/types/lib/ecosystems/npmutils.d.ts +183 -0
- package/types/lib/ecosystems/npmutils.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-bazel.d.ts +36 -0
- package/types/lib/ecosystems/parsers-bazel.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-dotnet.d.ts +116 -0
- package/types/lib/ecosystems/parsers-dotnet.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-gleam.d.ts +33 -0
- package/types/lib/ecosystems/parsers-gleam.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-go.d.ts +92 -0
- package/types/lib/ecosystems/parsers-go.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-js.d.ts +242 -0
- package/types/lib/ecosystems/parsers-js.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-jvm.d.ts +100 -0
- package/types/lib/ecosystems/parsers-jvm.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-misc.d.ts +450 -0
- package/types/lib/ecosystems/parsers-misc.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-python.d.ts +145 -0
- package/types/lib/ecosystems/parsers-python.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-rust.d.ts +56 -0
- package/types/lib/ecosystems/parsers-rust.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-zig.d.ts +83 -0
- package/types/lib/ecosystems/parsers-zig.d.ts.map +1 -0
- package/types/lib/ecosystems/pep770.d.ts +38 -0
- package/types/lib/ecosystems/pep770.d.ts.map +1 -0
- package/types/lib/ecosystems/pylockutils.d.ts +68 -0
- package/types/lib/ecosystems/pylockutils.d.ts.map +1 -0
- package/types/lib/ecosystems/pythonutils.d.ts +70 -0
- package/types/lib/ecosystems/pythonutils.d.ts.map +1 -0
- package/types/lib/ecosystems/registryProvenance.d.ts +26 -0
- package/types/lib/ecosystems/registryProvenance.d.ts.map +1 -0
- package/types/lib/ecosystems/remote/huggingface.d.ts +31 -0
- package/types/lib/ecosystems/remote/huggingface.d.ts.map +1 -0
- package/types/lib/ecosystems/rubyutils.d.ts +182 -0
- package/types/lib/ecosystems/rubyutils.d.ts.map +1 -0
- package/types/lib/ecosystems/rusi.d.ts +40 -0
- package/types/lib/ecosystems/rusi.d.ts.map +1 -0
- package/types/lib/ecosystems/sbtutils.d.ts +179 -0
- package/types/lib/ecosystems/sbtutils.d.ts.map +1 -0
- package/types/lib/ecosystems/tea.d.ts +180 -0
- package/types/lib/ecosystems/tea.d.ts.map +1 -0
- package/types/lib/ecosystems/utils.d.ts +41 -0
- package/types/lib/ecosystems/utils.d.ts.map +1 -0
- package/types/lib/ecosystems/zigResolver.d.ts +70 -0
- package/types/lib/ecosystems/zigResolver.d.ts.map +1 -0
- package/types/lib/evinser/db.d.ts +17 -0
- package/types/lib/evinser/db.d.ts.map +1 -0
- package/types/lib/evinser/evinser.d.ts +354 -0
- package/types/lib/evinser/evinser.d.ts.map +1 -0
- package/types/lib/evinser/scalasem.d.ts +15 -0
- package/types/lib/evinser/scalasem.d.ts.map +1 -0
- package/types/lib/evinser/swiftsem.d.ts +103 -0
- package/types/lib/evinser/swiftsem.d.ts.map +1 -0
- package/types/lib/helpers/annotationFormatter.d.ts +23 -0
- package/types/lib/helpers/annotationFormatter.d.ts.map +1 -0
- package/types/lib/helpers/bomSigner.d.ts +28 -0
- package/types/lib/helpers/bomSigner.d.ts.map +1 -0
- package/types/lib/helpers/exportUtils.d.ts +52 -0
- package/types/lib/helpers/exportUtils.d.ts.map +1 -0
- package/types/lib/helpers/remote/dependency-track.d.ts +23 -0
- package/types/lib/helpers/remote/dependency-track.d.ts.map +1 -0
- package/types/lib/helpers/versutils.d.ts +8 -0
- package/types/lib/helpers/versutils.d.ts.map +1 -0
- package/types/lib/helpers/vsixutils.d.ts +130 -0
- package/types/lib/helpers/vsixutils.d.ts.map +1 -0
- package/types/lib/inventory/agentFormulationParser.d.ts +21 -0
- package/types/lib/inventory/agentFormulationParser.d.ts.map +1 -0
- package/types/lib/inventory/aiCollector.d.ts +61 -0
- package/types/lib/inventory/aiCollector.d.ts.map +1 -0
- package/types/lib/inventory/aiInventory.d.ts +103 -0
- package/types/lib/inventory/aiInventory.d.ts.map +1 -0
- package/types/lib/inventory/aiModelVariants.d.ts +31 -0
- package/types/lib/inventory/aiModelVariants.d.ts.map +1 -0
- package/types/lib/inventory/aiOversightCollector.d.ts +28 -0
- package/types/lib/inventory/aiOversightCollector.d.ts.map +1 -0
- package/types/lib/inventory/aiProvenanceCollector.d.ts +13 -0
- package/types/lib/inventory/aiProvenanceCollector.d.ts.map +1 -0
- package/types/lib/inventory/analyzer.d.ts +157 -0
- package/types/lib/inventory/analyzer.d.ts.map +1 -0
- package/types/lib/inventory/analyzerScope.d.ts +106 -0
- package/types/lib/inventory/analyzerScope.d.ts.map +1 -0
- package/types/lib/inventory/astWorker.d.ts +9 -0
- package/types/lib/inventory/astWorker.d.ts.map +1 -0
- package/types/lib/inventory/atomUtils.d.ts +159 -0
- package/types/lib/inventory/atomUtils.d.ts.map +1 -0
- package/types/lib/inventory/auditCategories.d.ts +80 -0
- package/types/lib/inventory/auditCategories.d.ts.map +1 -0
- package/types/lib/inventory/bomUtils.d.ts +145 -0
- package/types/lib/inventory/bomUtils.d.ts.map +1 -0
- package/types/lib/inventory/cacheCommands.d.ts +28 -0
- package/types/lib/inventory/cacheCommands.d.ts.map +1 -0
- package/types/lib/inventory/cacheDir.d.ts +55 -0
- package/types/lib/inventory/cacheDir.d.ts.map +1 -0
- package/types/lib/inventory/cbomutils.d.ts +37 -0
- package/types/lib/inventory/cbomutils.d.ts.map +1 -0
- package/types/lib/inventory/cdxrs.d.ts +90 -0
- package/types/lib/inventory/cdxrs.d.ts.map +1 -0
- package/types/lib/inventory/ciParsers/azurePipelines.d.ts +27 -0
- package/types/lib/inventory/ciParsers/azurePipelines.d.ts.map +1 -0
- package/types/lib/inventory/ciParsers/circleCi.d.ts +27 -0
- package/types/lib/inventory/ciParsers/circleCi.d.ts.map +1 -0
- package/types/lib/inventory/ciParsers/common.d.ts +11 -0
- package/types/lib/inventory/ciParsers/common.d.ts.map +1 -0
- package/types/lib/inventory/ciParsers/githubActions.d.ts +38 -0
- package/types/lib/inventory/ciParsers/githubActions.d.ts.map +1 -0
- package/types/lib/inventory/ciParsers/gitlabCi.d.ts +26 -0
- package/types/lib/inventory/ciParsers/gitlabCi.d.ts.map +1 -0
- package/types/lib/inventory/ciParsers/jenkins.d.ts +26 -0
- package/types/lib/inventory/ciParsers/jenkins.d.ts.map +1 -0
- package/types/lib/inventory/citations.d.ts +90 -0
- package/types/lib/inventory/citations.d.ts.map +1 -0
- package/types/lib/inventory/communityAiConfigParser.d.ts +14 -0
- package/types/lib/inventory/communityAiConfigParser.d.ts.map +1 -0
- package/types/lib/inventory/containerRisk.d.ts +20 -0
- package/types/lib/inventory/containerRisk.d.ts.map +1 -0
- package/types/lib/inventory/cryptoAlgorithmFamily.d.ts +37 -0
- package/types/lib/inventory/cryptoAlgorithmFamily.d.ts.map +1 -0
- package/types/lib/inventory/deps.d.ts +140 -0
- package/types/lib/inventory/deps.d.ts.map +1 -0
- package/types/lib/inventory/depsUtils.d.ts +74 -0
- package/types/lib/inventory/depsUtils.d.ts.map +1 -0
- package/types/lib/inventory/display.d.ts +227 -0
- package/types/lib/inventory/display.d.ts.map +1 -0
- package/types/lib/inventory/dosai.d.ts +130 -0
- package/types/lib/inventory/dosai.d.ts.map +1 -0
- package/types/lib/inventory/dosaiParsers.d.ts +59 -0
- package/types/lib/inventory/dosaiParsers.d.ts.map +1 -0
- package/types/lib/inventory/dynamic.d.ts +25 -0
- package/types/lib/inventory/dynamic.d.ts.map +1 -0
- package/types/lib/inventory/envcontext.d.ts +377 -0
- package/types/lib/inventory/envcontext.d.ts.map +1 -0
- package/types/lib/inventory/evidenceUtils.d.ts +74 -0
- package/types/lib/inventory/evidenceUtils.d.ts.map +1 -0
- package/types/lib/inventory/fetchBatch.d.ts +127 -0
- package/types/lib/inventory/fetchBatch.d.ts.map +1 -0
- package/types/lib/inventory/fetchRate.d.ts +118 -0
- package/types/lib/inventory/fetchRate.d.ts.map +1 -0
- package/types/lib/inventory/forgeEnricher.d.ts +31 -0
- package/types/lib/inventory/forgeEnricher.d.ts.map +1 -0
- package/types/lib/inventory/formulationParsers.d.ts +50 -0
- package/types/lib/inventory/formulationParsers.d.ts.map +1 -0
- package/types/lib/inventory/gtfobins.d.ts +27 -0
- package/types/lib/inventory/gtfobins.d.ts.map +1 -0
- package/types/lib/inventory/hbom.d.ts +58 -0
- package/types/lib/inventory/hbom.d.ts.map +1 -0
- package/types/lib/inventory/hbomAnalysis.d.ts +56 -0
- package/types/lib/inventory/hbomAnalysis.d.ts.map +1 -0
- package/types/lib/inventory/hbomLoader.d.ts +7 -0
- package/types/lib/inventory/hbomLoader.d.ts.map +1 -0
- package/types/lib/inventory/hostTopology.d.ts +47 -0
- package/types/lib/inventory/hostTopology.d.ts.map +1 -0
- package/types/lib/inventory/inventoryStats.d.ts +42 -0
- package/types/lib/inventory/inventoryStats.d.ts.map +1 -0
- package/types/lib/inventory/jsonLike.d.ts +23 -0
- package/types/lib/inventory/jsonLike.d.ts.map +1 -0
- package/types/lib/inventory/licenseEnhancer.d.ts +70 -0
- package/types/lib/inventory/licenseEnhancer.d.ts.map +1 -0
- package/types/lib/inventory/lolbas.d.ts +16 -0
- package/types/lib/inventory/lolbas.d.ts.map +1 -0
- package/types/lib/inventory/mcp.d.ts +29 -0
- package/types/lib/inventory/mcp.d.ts.map +1 -0
- package/types/lib/inventory/mcpConfigParser.d.ts +20 -0
- package/types/lib/inventory/mcpConfigParser.d.ts.map +1 -0
- package/types/lib/inventory/mcpDiscovery.d.ts +33 -0
- package/types/lib/inventory/mcpDiscovery.d.ts.map +1 -0
- package/types/lib/inventory/mcpPinning.d.ts +11 -0
- package/types/lib/inventory/mcpPinning.d.ts.map +1 -0
- package/types/lib/inventory/osPackageResolver.d.ts +49 -0
- package/types/lib/inventory/osPackageResolver.d.ts.map +1 -0
- package/types/lib/inventory/osinfo.d.ts +120 -0
- package/types/lib/inventory/osinfo.d.ts.map +1 -0
- package/types/lib/inventory/osqueryTransform.d.ts +84 -0
- package/types/lib/inventory/osqueryTransform.d.ts.map +1 -0
- package/types/lib/inventory/plugins.d.ts +58 -0
- package/types/lib/inventory/plugins.d.ts.map +1 -0
- package/types/lib/inventory/protobom.d.ts +71 -0
- package/types/lib/inventory/protobom.d.ts.map +1 -0
- package/types/lib/inventory/protobomLoader.d.ts +17 -0
- package/types/lib/inventory/protobomLoader.d.ts.map +1 -0
- package/types/lib/inventory/provenanceUtils.d.ts +98 -0
- package/types/lib/inventory/provenanceUtils.d.ts.map +1 -0
- package/types/lib/inventory/purl.d.ts +313 -0
- package/types/lib/inventory/purl.d.ts.map +1 -0
- package/types/lib/inventory/rustFormulationParser.d.ts +17 -0
- package/types/lib/inventory/rustFormulationParser.d.ts.map +1 -0
- package/types/lib/inventory/sbomDocument.d.ts +59 -0
- package/types/lib/inventory/sbomDocument.d.ts.map +1 -0
- package/types/lib/inventory/source.d.ts +163 -0
- package/types/lib/inventory/source.d.ts.map +1 -0
- package/types/lib/inventory/spdx.d.ts +66 -0
- package/types/lib/inventory/spdx.d.ts.map +1 -0
- package/types/lib/inventory/spdxExpression.d.ts +58 -0
- package/types/lib/inventory/spdxExpression.d.ts.map +1 -0
- package/types/lib/inventory/spdxUtils.d.ts +12 -0
- package/types/lib/inventory/spdxUtils.d.ts.map +1 -0
- package/types/lib/inventory/table.d.ts +19 -0
- package/types/lib/inventory/table.d.ts.map +1 -0
- package/types/lib/inventory/traceRunner.d.ts +80 -0
- package/types/lib/inventory/traceRunner.d.ts.map +1 -0
- package/types/lib/inventory/unicodeScan.d.ts +46 -0
- package/types/lib/inventory/unicodeScan.d.ts.map +1 -0
- package/types/lib/managers/binary.d.ts +76 -0
- package/types/lib/managers/binary.d.ts.map +1 -0
- package/types/lib/managers/containerutils.d.ts +30 -0
- package/types/lib/managers/containerutils.d.ts.map +1 -0
- package/types/lib/managers/docker.d.ts +157 -0
- package/types/lib/managers/docker.d.ts.map +1 -0
- package/types/lib/managers/dockerConnection.d.ts +42 -0
- package/types/lib/managers/dockerConnection.d.ts.map +1 -0
- package/types/lib/managers/oci.d.ts +21 -0
- package/types/lib/managers/oci.d.ts.map +1 -0
- package/types/lib/managers/piptree.d.ts +13 -0
- package/types/lib/managers/piptree.d.ts.map +1 -0
- package/types/lib/parsers/cmakeCache.d.ts +70 -0
- package/types/lib/parsers/cmakeCache.d.ts.map +1 -0
- package/types/lib/parsers/gguf.d.ts +39 -0
- package/types/lib/parsers/gguf.d.ts.map +1 -0
- package/types/lib/parsers/gitAiNotes.d.ts +15 -0
- package/types/lib/parsers/gitAiNotes.d.ts.map +1 -0
- package/types/lib/parsers/gitmodules.d.ts +88 -0
- package/types/lib/parsers/gitmodules.d.ts.map +1 -0
- package/types/lib/parsers/htmlExtract.d.ts +34 -0
- package/types/lib/parsers/htmlExtract.d.ts.map +1 -0
- package/types/lib/parsers/huggingfaceManifest.d.ts +153 -0
- package/types/lib/parsers/huggingfaceManifest.d.ts.map +1 -0
- package/types/lib/parsers/huggingfaceUtils.d.ts +155 -0
- package/types/lib/parsers/huggingfaceUtils.d.ts.map +1 -0
- package/types/lib/parsers/iri.d.ts +68 -0
- package/types/lib/parsers/iri.d.ts.map +1 -0
- package/types/lib/parsers/npmrc.d.ts +33 -0
- package/types/lib/parsers/npmrc.d.ts.map +1 -0
- package/types/lib/parsers/ollama.d.ts +22 -0
- package/types/lib/parsers/ollama.d.ts.map +1 -0
- package/types/lib/parsers/xml.d.ts +47 -0
- package/types/lib/parsers/xml.d.ts.map +1 -0
- package/types/lib/server/server.d.ts +51 -0
- package/types/lib/server/server.d.ts.map +1 -0
- package/types/lib/stages/postgen/annotator.d.ts +36 -0
- package/types/lib/stages/postgen/annotator.d.ts.map +1 -0
- package/types/lib/stages/postgen/auditBom.d.ts +92 -0
- package/types/lib/stages/postgen/auditBom.d.ts.map +1 -0
- package/types/lib/stages/postgen/postgen.d.ts +59 -0
- package/types/lib/stages/postgen/postgen.d.ts.map +1 -0
- package/types/lib/stages/postgen/ruleEngine.d.ts +18 -0
- package/types/lib/stages/postgen/ruleEngine.d.ts.map +1 -0
- package/types/lib/stages/postgen/sortBom.d.ts +34 -0
- package/types/lib/stages/postgen/sortBom.d.ts.map +1 -0
- package/types/lib/stages/postgen/spdxConverter.d.ts +11 -0
- package/types/lib/stages/postgen/spdxConverter.d.ts.map +1 -0
- package/types/lib/stages/postgen/specVersionCompat.d.ts +71 -0
- package/types/lib/stages/postgen/specVersionCompat.d.ts.map +1 -0
- package/types/lib/stages/pregen/envAudit.d.ts +14 -0
- package/types/lib/stages/pregen/envAudit.d.ts.map +1 -0
- package/types/lib/stages/pregen/pregen.d.ts +59 -0
- package/types/lib/stages/pregen/pregen.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/arborist/index.d.ts +47 -0
- package/types/lib/third-party/arborist/lib/arborist/index.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/arborist/load-actual.d.ts +4 -0
- package/types/lib/third-party/arborist/lib/arborist/load-actual.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/arborist/load-virtual.d.ts +4 -0
- package/types/lib/third-party/arborist/lib/arborist/load-virtual.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/bin-links.d.ts +18 -0
- package/types/lib/third-party/arborist/lib/bin-links.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/calc-dep-flags.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/calc-dep-flags.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/case-insensitive-map.d.ts +9 -0
- package/types/lib/third-party/arborist/lib/case-insensitive-map.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/consistent-resolve.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/consistent-resolve.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/debug.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/debug.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/dep-valid.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/dep-valid.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/edge.d.ts +46 -0
- package/types/lib/third-party/arborist/lib/edge.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/from-path.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/from-path.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/gather-dep-set.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/gather-dep-set.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/index.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/index.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/inventory.d.ts +14 -0
- package/types/lib/third-party/arborist/lib/inventory.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/link.d.ts +18 -0
- package/types/lib/third-party/arborist/lib/link.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/node.d.ts +112 -0
- package/types/lib/third-party/arborist/lib/node.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/npm-extension.d.ts +18 -0
- package/types/lib/third-party/arborist/lib/npm-extension.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/override-resolves.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/override-resolves.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/override-set.d.ts +27 -0
- package/types/lib/third-party/arborist/lib/override-set.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/package-extensions.d.ts +36 -0
- package/types/lib/third-party/arborist/lib/package-extensions.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/printable.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/printable.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/proc-log.d.ts +20 -0
- package/types/lib/third-party/arborist/lib/proc-log.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/realpath.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/realpath.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/relpath.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/relpath.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/shrinkwrap.d.ts +54 -0
- package/types/lib/third-party/arborist/lib/shrinkwrap.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/spec-from-lock.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/spec-from-lock.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/tree-check.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/tree-check.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/validate-npm-package-name.d.ts +13 -0
- package/types/lib/third-party/arborist/lib/validate-npm-package-name.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/version-from-tgz.d.ts +6 -0
- package/types/lib/third-party/arborist/lib/version-from-tgz.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/yarn-lock.d.ts +35 -0
- package/types/lib/third-party/arborist/lib/yarn-lock.d.ts.map +1 -0
- package/types/lib/validator/bomValidator.d.ts +40 -0
- package/types/lib/validator/bomValidator.d.ts.map +1 -0
- package/types/lib/validator/complianceEngine.d.ts +72 -0
- package/types/lib/validator/complianceEngine.d.ts.map +1 -0
- package/types/lib/validator/complianceRules.d.ts +61 -0
- package/types/lib/validator/complianceRules.d.ts.map +1 -0
- package/types/lib/validator/index.d.ts +101 -0
- package/types/lib/validator/index.d.ts.map +1 -0
- package/types/lib/validator/reporters/annotations.d.ts +37 -0
- package/types/lib/validator/reporters/annotations.d.ts.map +1 -0
- package/types/lib/validator/reporters/console.d.ts +34 -0
- package/types/lib/validator/reporters/console.d.ts.map +1 -0
- package/types/lib/validator/reporters/index.d.ts +30 -0
- package/types/lib/validator/reporters/index.d.ts.map +1 -0
- package/types/lib/validator/reporters/json.d.ts +11 -0
- package/types/lib/validator/reporters/json.d.ts.map +1 -0
- package/types/lib/validator/reporters/sarif.d.ts +22 -0
- package/types/lib/validator/reporters/sarif.d.ts.map +1 -0
- package/mod.d.ts +0 -7
- package/mod.js +0 -22
|
@@ -0,0 +1,704 @@
|
|
|
1
|
+
import { Buffer } from "node:buffer";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
|
|
7
|
+
import { cdxgenAgent, readEnvironmentVariable } from "../core/activity.js";
|
|
8
|
+
import { getAllFiles, safeExistsSync } from "../core/fs.js";
|
|
9
|
+
import { isCycloneDxBom } from "../inventory/bomUtils.js";
|
|
10
|
+
|
|
11
|
+
const ORAS_CREATED_ANNOTATION = "org.opencontainers.image.created";
|
|
12
|
+
|
|
13
|
+
// artifactType values used for CycloneDX SBOM referrers. Registries such as
|
|
14
|
+
// ghcr.io ignore the `?artifactType=` referrers query filter and return *every*
|
|
15
|
+
// referrer (build-provenance attestations, cosign signatures, other SBOM
|
|
16
|
+
// formats, ...) alongside the CycloneDX SBOM. Tags that accumulate many
|
|
17
|
+
// referrers over time (e.g. the rolling `nightly`/`master` tags) therefore
|
|
18
|
+
// require us to filter client-side, otherwise the newest referrer selected may
|
|
19
|
+
// not be a CycloneDX SBOM at all and its layer will fail to parse as JSON.
|
|
20
|
+
const CYCLONEDX_ARTIFACT_TYPES = new Set([
|
|
21
|
+
"application/vnd.cyclonedx+json",
|
|
22
|
+
"sbom/cyclonedx",
|
|
23
|
+
]);
|
|
24
|
+
|
|
25
|
+
function isCycloneDxArtifactType(artifactType) {
|
|
26
|
+
return !!artifactType && CYCLONEDX_ARTIFACT_TYPES.has(artifactType);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// mediaType values a referrer manifest layer may use to carry a CycloneDX BOM.
|
|
30
|
+
// `attachBomNative` writes `application/vnd.cyclonedx+json`; BuildKit native
|
|
31
|
+
// attestations wrap the BOM in an in-toto statement layer. We use the layer
|
|
32
|
+
// descriptor's mediaType (the authoritative signal — blob responses are served
|
|
33
|
+
// as octet-stream) to pick the correct layer instead of assuming layers[0].
|
|
34
|
+
const CYCLONEDX_LAYER_MEDIA_TYPES = new Set([
|
|
35
|
+
"application/vnd.cyclonedx+json",
|
|
36
|
+
"application/vnd.in-toto+json",
|
|
37
|
+
]);
|
|
38
|
+
|
|
39
|
+
function selectBomLayer(layers) {
|
|
40
|
+
if (!Array.isArray(layers) || !layers.length) {
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
return (
|
|
44
|
+
layers.find((layer) => CYCLONEDX_LAYER_MEDIA_TYPES.has(layer?.mediaType)) ||
|
|
45
|
+
// Fall back to the first layer for older attachments / registries that omit
|
|
46
|
+
// the layer mediaType.
|
|
47
|
+
layers[0]
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// OCI registry probes (manifest/token/referrers/blob lookups) run on the audit
|
|
52
|
+
// hot path — including from inside JSONata rules (`$hasSbom`/`$hasSignedSbom`),
|
|
53
|
+
// whose evaluation is time-bounded. Use a smaller per-request timeout than the
|
|
54
|
+
// global cdxgenAgent default so an unreachable/slow registry fails fast instead
|
|
55
|
+
// of tying up the scan. Overridable via CDXGEN_OCI_TIMEOUT_MS.
|
|
56
|
+
const DEFAULT_OCI_TIMEOUT_MS = 8000;
|
|
57
|
+
const MAX_OCI_TIMEOUT_MS = 300000;
|
|
58
|
+
|
|
59
|
+
function getOciTimeoutMs() {
|
|
60
|
+
const raw = readEnvironmentVariable("CDXGEN_OCI_TIMEOUT_MS");
|
|
61
|
+
if (raw === undefined || raw === "") {
|
|
62
|
+
return DEFAULT_OCI_TIMEOUT_MS;
|
|
63
|
+
}
|
|
64
|
+
const parsed = Number.parseInt(raw, 10);
|
|
65
|
+
if (!Number.isInteger(parsed) || parsed <= 0) {
|
|
66
|
+
return DEFAULT_OCI_TIMEOUT_MS;
|
|
67
|
+
}
|
|
68
|
+
return Math.min(parsed, MAX_OCI_TIMEOUT_MS);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function getManifestDescriptors(manifestObj) {
|
|
72
|
+
if (Array.isArray(manifestObj?.manifests)) {
|
|
73
|
+
return manifestObj.manifests;
|
|
74
|
+
}
|
|
75
|
+
if (Array.isArray(manifestObj?.referrers)) {
|
|
76
|
+
return manifestObj.referrers;
|
|
77
|
+
}
|
|
78
|
+
return [];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function getRepositoryRef(image) {
|
|
82
|
+
let repositoryRef = image;
|
|
83
|
+
const digestIndex = repositoryRef.indexOf("@");
|
|
84
|
+
if (digestIndex !== -1) {
|
|
85
|
+
repositoryRef = repositoryRef.slice(0, digestIndex);
|
|
86
|
+
}
|
|
87
|
+
const lastSlashIndex = repositoryRef.lastIndexOf("/");
|
|
88
|
+
const tagIndex = repositoryRef.lastIndexOf(":");
|
|
89
|
+
if (tagIndex > lastSlashIndex) {
|
|
90
|
+
repositoryRef = repositoryRef.slice(0, tagIndex);
|
|
91
|
+
}
|
|
92
|
+
return repositoryRef;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function getManifestImageRef(image, manifest) {
|
|
96
|
+
if (manifest?.reference) {
|
|
97
|
+
return manifest.reference;
|
|
98
|
+
}
|
|
99
|
+
if (manifest?.digest) {
|
|
100
|
+
return `${getRepositoryRef(image)}@${manifest.digest}`;
|
|
101
|
+
}
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function getManifestCreatedAt(manifest) {
|
|
106
|
+
const createdAt = manifest?.annotations?.[ORAS_CREATED_ANNOTATION];
|
|
107
|
+
if (!createdAt) {
|
|
108
|
+
return undefined;
|
|
109
|
+
}
|
|
110
|
+
const createdAtTimestamp = Date.parse(createdAt);
|
|
111
|
+
if (Number.isNaN(createdAtTimestamp)) {
|
|
112
|
+
return undefined;
|
|
113
|
+
}
|
|
114
|
+
return createdAtTimestamp;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Return the candidate SBOM referrer image references, newest first.
|
|
119
|
+
*
|
|
120
|
+
* Descriptors whose `artifactType` identifies them as a CycloneDX SBOM are
|
|
121
|
+
* preferred. Only when no descriptor advertises a CycloneDX artifactType (e.g.
|
|
122
|
+
* a registry that strips the field, or an older attachment) do we fall back to
|
|
123
|
+
* considering every descriptor, preserving the previous best-effort behaviour.
|
|
124
|
+
*
|
|
125
|
+
* @param {string} image OCI image reference used to build digest references.
|
|
126
|
+
* @param {Object} manifestObj Referrers response / image index object.
|
|
127
|
+
* @returns {string[]} Ordered list of candidate image references (newest first).
|
|
128
|
+
*/
|
|
129
|
+
function selectManifestImageRefs(image, manifestObj) {
|
|
130
|
+
const manifestDescriptors = getManifestDescriptors(manifestObj);
|
|
131
|
+
const allCandidates = manifestDescriptors
|
|
132
|
+
.map((manifest, index) => {
|
|
133
|
+
const imageRef = getManifestImageRef(image, manifest);
|
|
134
|
+
if (!imageRef) {
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
artifactType: manifest?.artifactType,
|
|
139
|
+
createdAt: getManifestCreatedAt(manifest),
|
|
140
|
+
imageRef,
|
|
141
|
+
index,
|
|
142
|
+
};
|
|
143
|
+
})
|
|
144
|
+
.filter(Boolean);
|
|
145
|
+
const cdxCandidates = allCandidates.filter((c) =>
|
|
146
|
+
isCycloneDxArtifactType(c.artifactType),
|
|
147
|
+
);
|
|
148
|
+
const candidates = cdxCandidates.length ? cdxCandidates : allCandidates;
|
|
149
|
+
candidates.sort((a, b) => {
|
|
150
|
+
if (a.createdAt !== undefined || b.createdAt !== undefined) {
|
|
151
|
+
if (a.createdAt === undefined) {
|
|
152
|
+
return 1;
|
|
153
|
+
}
|
|
154
|
+
if (b.createdAt === undefined) {
|
|
155
|
+
return -1;
|
|
156
|
+
}
|
|
157
|
+
if (b.createdAt !== a.createdAt) {
|
|
158
|
+
return b.createdAt - a.createdAt;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return b.index - a.index;
|
|
162
|
+
});
|
|
163
|
+
return candidates.map((c) => c.imageRef);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function _getBomFiles(tmpDir) {
|
|
167
|
+
let bomFiles = getAllFiles(tmpDir, "**/*.{bom,cdx}.json");
|
|
168
|
+
if (!bomFiles.length) {
|
|
169
|
+
bomFiles = getAllFiles(tmpDir, "**/bom.json");
|
|
170
|
+
}
|
|
171
|
+
if (!bomFiles.length) {
|
|
172
|
+
bomFiles = getAllFiles(tmpDir, "**/*.json");
|
|
173
|
+
}
|
|
174
|
+
return bomFiles;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function parseImageRef(image) {
|
|
178
|
+
let registry = "docker.io";
|
|
179
|
+
let repoAndTag = image;
|
|
180
|
+
const firstSlash = image.indexOf("/");
|
|
181
|
+
if (firstSlash !== -1) {
|
|
182
|
+
const hostCandidate = image.slice(0, firstSlash);
|
|
183
|
+
if (
|
|
184
|
+
hostCandidate.includes(".") ||
|
|
185
|
+
hostCandidate.includes(":") ||
|
|
186
|
+
hostCandidate === "localhost"
|
|
187
|
+
) {
|
|
188
|
+
registry = hostCandidate;
|
|
189
|
+
repoAndTag = image.slice(firstSlash + 1);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
let repository = repoAndTag;
|
|
193
|
+
let reference = "latest";
|
|
194
|
+
const atIndex = repoAndTag.indexOf("@");
|
|
195
|
+
if (atIndex !== -1) {
|
|
196
|
+
repository = repoAndTag.slice(0, atIndex);
|
|
197
|
+
reference = repoAndTag.slice(atIndex + 1);
|
|
198
|
+
} else {
|
|
199
|
+
const colonIndex = repoAndTag.lastIndexOf(":");
|
|
200
|
+
if (colonIndex !== -1) {
|
|
201
|
+
repository = repoAndTag.slice(0, colonIndex);
|
|
202
|
+
reference = repoAndTag.slice(colonIndex + 1);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
if (registry === "docker.io" && !repository.includes("/")) {
|
|
206
|
+
repository = `library/${repository}`;
|
|
207
|
+
}
|
|
208
|
+
return { registry, repository, reference };
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function getDockerCreds(registry) {
|
|
212
|
+
try {
|
|
213
|
+
const configPath = join(homedir(), ".docker", "config.json");
|
|
214
|
+
if (safeExistsSync(configPath)) {
|
|
215
|
+
const config = JSON.parse(fs.readFileSync(configPath, "utf8"));
|
|
216
|
+
if (config.auths) {
|
|
217
|
+
const auth =
|
|
218
|
+
config.auths[registry] ||
|
|
219
|
+
config.auths[`https://${registry}`] ||
|
|
220
|
+
config.auths[`https://${registry}/v1/`];
|
|
221
|
+
if (auth?.auth) {
|
|
222
|
+
return auth.auth;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
} catch (_e) {
|
|
227
|
+
/* ignore */
|
|
228
|
+
}
|
|
229
|
+
return readEnvironmentVariable("DOCKER_AUTH");
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
async function getOciToken(registry, repository, scope) {
|
|
233
|
+
const creds = getDockerCreds(registry);
|
|
234
|
+
const scheme = registry.startsWith("localhost") ? "http" : "https";
|
|
235
|
+
const authUrl = `${scheme}://${registry}/v2/`;
|
|
236
|
+
try {
|
|
237
|
+
const res = await cdxgenAgent.get(authUrl, {
|
|
238
|
+
throwHttpErrors: false,
|
|
239
|
+
timeout: getOciTimeoutMs(),
|
|
240
|
+
});
|
|
241
|
+
if (res.statusCode === 401) {
|
|
242
|
+
const wwwAuth = res.headers["www-authenticate"];
|
|
243
|
+
if (wwwAuth?.toLowerCase().startsWith("bearer ")) {
|
|
244
|
+
const params = {};
|
|
245
|
+
wwwAuth
|
|
246
|
+
.substring(7)
|
|
247
|
+
.split(",")
|
|
248
|
+
.forEach((part) => {
|
|
249
|
+
const [k, v] = part.split("=");
|
|
250
|
+
if (v) params[k.trim()] = v.trim().replace(/"/g, "");
|
|
251
|
+
});
|
|
252
|
+
if (params.realm) {
|
|
253
|
+
const reqUrl = new URL(params.realm);
|
|
254
|
+
if (params.service)
|
|
255
|
+
reqUrl.searchParams.set("service", params.service);
|
|
256
|
+
reqUrl.searchParams.set("scope", `repository:${repository}:${scope}`);
|
|
257
|
+
const options = {
|
|
258
|
+
responseType: "json",
|
|
259
|
+
timeout: getOciTimeoutMs(),
|
|
260
|
+
};
|
|
261
|
+
if (creds) {
|
|
262
|
+
options.headers = { Authorization: `Basic ${creds}` };
|
|
263
|
+
}
|
|
264
|
+
const tokenRes = await cdxgenAgent.get(reqUrl.toString(), options);
|
|
265
|
+
if (
|
|
266
|
+
tokenRes.body &&
|
|
267
|
+
(tokenRes.body.token || tokenRes.body.access_token)
|
|
268
|
+
) {
|
|
269
|
+
return tokenRes.body.token || tokenRes.body.access_token;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
} catch (_e) {
|
|
275
|
+
/* ignore */
|
|
276
|
+
}
|
|
277
|
+
if (creds) return `Basic ${creds}`;
|
|
278
|
+
return null;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Fetch a URL and parse the response body as JSON without throwing on a
|
|
283
|
+
* non-JSON payload. Registries that do not implement an endpoint (notably
|
|
284
|
+
* ghcr.io for the OCI referrers API) answer with a 404 *HTML* error page; the
|
|
285
|
+
* shared httpClient parses `responseType: "json"` eagerly and would throw on
|
|
286
|
+
* that HTML before the caller can inspect the status code. Reading as text and
|
|
287
|
+
* parsing defensively lets callers route on `statusCode` and fall back cleanly.
|
|
288
|
+
*
|
|
289
|
+
* @returns {Promise<{statusCode: number, headers: Object, body: Object|undefined}>}
|
|
290
|
+
*/
|
|
291
|
+
async function fetchJson(url, headers) {
|
|
292
|
+
const res = await cdxgenAgent.get(url, {
|
|
293
|
+
headers,
|
|
294
|
+
responseType: "text",
|
|
295
|
+
throwHttpErrors: false,
|
|
296
|
+
timeout: getOciTimeoutMs(),
|
|
297
|
+
});
|
|
298
|
+
let body;
|
|
299
|
+
if (typeof res.body === "string" && res.body.length) {
|
|
300
|
+
try {
|
|
301
|
+
body = JSON.parse(res.body);
|
|
302
|
+
} catch {
|
|
303
|
+
body = undefined;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
return { statusCode: res.statusCode, headers: res.headers, body };
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
async function fetchManifest(registry, repository, reference, token) {
|
|
310
|
+
const scheme = registry.startsWith("localhost") ? "http" : "https";
|
|
311
|
+
const url = `${scheme}://${registry}/v2/${repository}/manifests/${reference}`;
|
|
312
|
+
const headers = {
|
|
313
|
+
Accept:
|
|
314
|
+
"application/vnd.oci.image.manifest.v1+json, application/vnd.docker.distribution.manifest.v2+json, application/vnd.oci.image.index.v1+json",
|
|
315
|
+
};
|
|
316
|
+
if (token) {
|
|
317
|
+
headers.Authorization = token.startsWith("Basic")
|
|
318
|
+
? token
|
|
319
|
+
: `Bearer ${token}`;
|
|
320
|
+
}
|
|
321
|
+
const res = await fetchJson(url, headers);
|
|
322
|
+
if (res.statusCode === 200) {
|
|
323
|
+
return {
|
|
324
|
+
manifest: res.body,
|
|
325
|
+
digest: res.headers["docker-content-digest"],
|
|
326
|
+
mediaType: res.headers["content-type"],
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
return null;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
async function discoverReferrers(registry, repository, digest, token) {
|
|
333
|
+
const scheme = registry.startsWith("localhost") ? "http" : "https";
|
|
334
|
+
const url = `${scheme}://${registry}/v2/${repository}/referrers/${digest}?artifactType=application/vnd.cyclonedx+json`;
|
|
335
|
+
const headers = {};
|
|
336
|
+
if (token) {
|
|
337
|
+
headers.Authorization = token.startsWith("Basic")
|
|
338
|
+
? token
|
|
339
|
+
: `Bearer ${token}`;
|
|
340
|
+
}
|
|
341
|
+
try {
|
|
342
|
+
const res = await fetchJson(url, headers);
|
|
343
|
+
if (res.statusCode === 200) {
|
|
344
|
+
return res.body;
|
|
345
|
+
}
|
|
346
|
+
} catch (_e) {
|
|
347
|
+
/* ignore */
|
|
348
|
+
}
|
|
349
|
+
return undefined;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
async function pullBlob(registry, repository, digest, token) {
|
|
353
|
+
const scheme = registry.startsWith("localhost") ? "http" : "https";
|
|
354
|
+
const url = `${scheme}://${registry}/v2/${repository}/blobs/${digest}`;
|
|
355
|
+
const headers = {};
|
|
356
|
+
if (token) {
|
|
357
|
+
headers.Authorization = token.startsWith("Basic")
|
|
358
|
+
? token
|
|
359
|
+
: `Bearer ${token}`;
|
|
360
|
+
}
|
|
361
|
+
const res = await cdxgenAgent.get(url, {
|
|
362
|
+
headers,
|
|
363
|
+
responseType: "buffer",
|
|
364
|
+
timeout: getOciTimeoutMs(),
|
|
365
|
+
});
|
|
366
|
+
return res.body;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Retrieves a CycloneDX BOM attached to an OCI image purely in JavaScript
|
|
371
|
+
* without relying on the `oras` CLI tool.
|
|
372
|
+
*
|
|
373
|
+
* @param {string} image OCI image reference (e.g. `"registry.example.com/org/app:tag"`)
|
|
374
|
+
* @param {string} [platform] OCI platform string (e.g. `"linux/amd64"`); no-op for JS implementation
|
|
375
|
+
* @returns {Promise<Object|undefined>} Parsed CycloneDX BOM JSON object, or `undefined` if not found
|
|
376
|
+
*/
|
|
377
|
+
export async function getBomWithOras(image, _platform = undefined) {
|
|
378
|
+
const { registry, repository, reference } = parseImageRef(image);
|
|
379
|
+
const token = await getOciToken(registry, repository, "pull");
|
|
380
|
+
|
|
381
|
+
try {
|
|
382
|
+
const targetManifest = await fetchManifest(
|
|
383
|
+
registry,
|
|
384
|
+
repository,
|
|
385
|
+
reference,
|
|
386
|
+
token,
|
|
387
|
+
);
|
|
388
|
+
if (!targetManifest?.digest) {
|
|
389
|
+
return undefined;
|
|
390
|
+
}
|
|
391
|
+
const digest = targetManifest.digest;
|
|
392
|
+
|
|
393
|
+
let referrersObj = await discoverReferrers(
|
|
394
|
+
registry,
|
|
395
|
+
repository,
|
|
396
|
+
digest,
|
|
397
|
+
token,
|
|
398
|
+
);
|
|
399
|
+
|
|
400
|
+
// If not found with artifactType filter, try fetching all referrers
|
|
401
|
+
if (!referrersObj?.manifests || referrersObj.manifests.length === 0) {
|
|
402
|
+
const scheme = registry.startsWith("localhost") ? "http" : "https";
|
|
403
|
+
let url = `${scheme}://${registry}/v2/${repository}/referrers/${digest}`;
|
|
404
|
+
const headers = token
|
|
405
|
+
? {
|
|
406
|
+
Authorization: token.startsWith("Basic")
|
|
407
|
+
? token
|
|
408
|
+
: `Bearer ${token}`,
|
|
409
|
+
}
|
|
410
|
+
: {};
|
|
411
|
+
let res = await fetchJson(url, headers);
|
|
412
|
+
if (res.statusCode === 200 && res.body?.manifests) {
|
|
413
|
+
referrersObj = res.body;
|
|
414
|
+
} else {
|
|
415
|
+
// Registries such as ghcr.io do not implement the referrers API and
|
|
416
|
+
// answer with a 404 HTML page. Fall back to the OCI referrers tag
|
|
417
|
+
// schema, where the SBOM index is stored under a `sha256-<digest>` tag.
|
|
418
|
+
const fallbackTag = digest.replace(":", "-");
|
|
419
|
+
url = `${scheme}://${registry}/v2/${repository}/manifests/${fallbackTag}`;
|
|
420
|
+
headers.Accept = "application/vnd.oci.image.index.v1+json";
|
|
421
|
+
res = await fetchJson(url, headers);
|
|
422
|
+
if (res.statusCode === 200) {
|
|
423
|
+
referrersObj = res.body;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// Prefer CycloneDX-typed referrers, newest first. Registries that ignore
|
|
429
|
+
// the artifactType query filter return every referrer, so we may still see
|
|
430
|
+
// non-SBOM referrers here (e.g. on the rolling nightly tag). Try each
|
|
431
|
+
// candidate until one yields a valid CycloneDX BOM instead of failing on
|
|
432
|
+
// the first non-JSON layer.
|
|
433
|
+
const imageRefs = selectManifestImageRefs(image, referrersObj);
|
|
434
|
+
|
|
435
|
+
for (const imageRef of imageRefs) {
|
|
436
|
+
const refParsed = parseImageRef(imageRef);
|
|
437
|
+
const manifestNode = await fetchManifest(
|
|
438
|
+
refParsed.registry,
|
|
439
|
+
refParsed.repository,
|
|
440
|
+
refParsed.reference,
|
|
441
|
+
token,
|
|
442
|
+
);
|
|
443
|
+
const bomLayer = selectBomLayer(manifestNode?.manifest?.layers);
|
|
444
|
+
if (!bomLayer?.digest) {
|
|
445
|
+
continue;
|
|
446
|
+
}
|
|
447
|
+
const blob = await pullBlob(
|
|
448
|
+
registry,
|
|
449
|
+
refParsed.repository,
|
|
450
|
+
bomLayer.digest,
|
|
451
|
+
token,
|
|
452
|
+
);
|
|
453
|
+
let bomJson;
|
|
454
|
+
try {
|
|
455
|
+
bomJson = JSON.parse(blob.toString("utf8"));
|
|
456
|
+
} catch {
|
|
457
|
+
// Defensive: the mediaType claimed JSON but the layer did not parse
|
|
458
|
+
// (truncated/corrupt blob). Skip it and try the next candidate.
|
|
459
|
+
continue;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
// Extract from in-toto envelope (BuildKit native attestations)
|
|
463
|
+
if (
|
|
464
|
+
bomJson &&
|
|
465
|
+
(bomJson._type === "https://in-toto.io/Statement/v0.1" ||
|
|
466
|
+
bomJson._type === "https://in-toto.io/Statement/v1") &&
|
|
467
|
+
bomJson.predicateType === "https://cyclonedx.org/bom" &&
|
|
468
|
+
bomJson.predicate
|
|
469
|
+
) {
|
|
470
|
+
bomJson = bomJson.predicate;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
if (isCycloneDxBom(bomJson)) {
|
|
474
|
+
return bomJson;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
} catch (e) {
|
|
478
|
+
console.log(
|
|
479
|
+
`Unable to pull the SBOM attachment for ${image} natively! ${e.message}`,
|
|
480
|
+
);
|
|
481
|
+
}
|
|
482
|
+
return undefined;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
function getDigest(buffer) {
|
|
486
|
+
return `sha256:${createHash("sha256").update(buffer).digest("hex")}`;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
async function pushBlob(registry, repository, buffer, token) {
|
|
490
|
+
const scheme = registry.startsWith("localhost") ? "http" : "https";
|
|
491
|
+
const digest = getDigest(buffer);
|
|
492
|
+
const headers = {};
|
|
493
|
+
if (token) {
|
|
494
|
+
headers.Authorization = token.startsWith("Basic")
|
|
495
|
+
? token
|
|
496
|
+
: `Bearer ${token}`;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
// 1. Initiate upload
|
|
500
|
+
const initUrl = `${scheme}://${registry}/v2/${repository}/blobs/uploads/`;
|
|
501
|
+
const initRes = await cdxgenAgent.post(initUrl, {
|
|
502
|
+
headers,
|
|
503
|
+
throwHttpErrors: false,
|
|
504
|
+
});
|
|
505
|
+
if (initRes.statusCode === 201 || initRes.statusCode === 202) {
|
|
506
|
+
let location = initRes.headers.location;
|
|
507
|
+
if (!location.startsWith("http")) {
|
|
508
|
+
location = `${scheme}://${registry}${location.startsWith("/") ? "" : "/"}${location}`;
|
|
509
|
+
}
|
|
510
|
+
const uploadUrl = new URL(location);
|
|
511
|
+
uploadUrl.searchParams.set("digest", digest);
|
|
512
|
+
|
|
513
|
+
// 2. Upload blob
|
|
514
|
+
const putHeaders = {
|
|
515
|
+
...headers,
|
|
516
|
+
"Content-Length": buffer.length.toString(),
|
|
517
|
+
"Content-Type": "application/octet-stream",
|
|
518
|
+
};
|
|
519
|
+
const putRes = await cdxgenAgent.put(uploadUrl.toString(), {
|
|
520
|
+
headers: putHeaders,
|
|
521
|
+
body: buffer,
|
|
522
|
+
throwHttpErrors: false,
|
|
523
|
+
});
|
|
524
|
+
if (putRes.statusCode === 201 || putRes.statusCode === 202) {
|
|
525
|
+
return { digest, size: buffer.length };
|
|
526
|
+
}
|
|
527
|
+
throw new Error(
|
|
528
|
+
`Failed to upload blob: ${putRes.statusCode} ${putRes.body}`,
|
|
529
|
+
);
|
|
530
|
+
}
|
|
531
|
+
if (initRes.statusCode === 401) {
|
|
532
|
+
throw new Error(
|
|
533
|
+
`Unauthorized to initiate blob upload: ${initRes.statusCode}`,
|
|
534
|
+
);
|
|
535
|
+
}
|
|
536
|
+
throw new Error(
|
|
537
|
+
`Failed to initiate blob upload: ${initRes.statusCode} ${initRes.body}`,
|
|
538
|
+
);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
async function pushManifest(registry, repository, manifestObj, token) {
|
|
542
|
+
const scheme = registry.startsWith("localhost") ? "http" : "https";
|
|
543
|
+
const buffer = Buffer.from(JSON.stringify(manifestObj));
|
|
544
|
+
const digest = getDigest(buffer);
|
|
545
|
+
const url = `${scheme}://${registry}/v2/${repository}/manifests/${digest}`;
|
|
546
|
+
const headers = {
|
|
547
|
+
"Content-Type":
|
|
548
|
+
manifestObj.mediaType || "application/vnd.oci.image.manifest.v1+json",
|
|
549
|
+
};
|
|
550
|
+
if (token) {
|
|
551
|
+
headers.Authorization = token.startsWith("Basic")
|
|
552
|
+
? token
|
|
553
|
+
: `Bearer ${token}`;
|
|
554
|
+
}
|
|
555
|
+
const res = await cdxgenAgent.put(url, {
|
|
556
|
+
headers,
|
|
557
|
+
body: buffer,
|
|
558
|
+
throwHttpErrors: false,
|
|
559
|
+
});
|
|
560
|
+
if (res.statusCode === 201 || res.statusCode === 202) {
|
|
561
|
+
return digest;
|
|
562
|
+
}
|
|
563
|
+
throw new Error(`Failed to push manifest: ${res.statusCode} ${res.body}`);
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
/**
|
|
567
|
+
* Attach a CycloneDX BOM to an OCI image using the OCI 1.1 artifact manifest
|
|
568
|
+
* API, pushing the BOM as a blob and linking it via the referrers API (with a
|
|
569
|
+
* fallback tag when the registry does not support referrers).
|
|
570
|
+
*
|
|
571
|
+
* @param {string} image The target OCI image reference to attach the BOM to.
|
|
572
|
+
* @param {Object} bomJson The CycloneDX BOM document to attach.
|
|
573
|
+
* @returns {Promise<string|undefined>} The digest of the pushed manifest, or
|
|
574
|
+
* undefined when the manifest could not be pushed.
|
|
575
|
+
*/
|
|
576
|
+
export async function attachBomNative(image, bomJson) {
|
|
577
|
+
const { registry, repository, reference } = parseImageRef(image);
|
|
578
|
+
const token = await getOciToken(registry, repository, "pull,push");
|
|
579
|
+
|
|
580
|
+
// 1. Fetch target manifest
|
|
581
|
+
const targetManifest = await fetchManifest(
|
|
582
|
+
registry,
|
|
583
|
+
repository,
|
|
584
|
+
reference,
|
|
585
|
+
token,
|
|
586
|
+
);
|
|
587
|
+
if (!targetManifest?.digest) {
|
|
588
|
+
throw new Error(`Target image ${image} not found or no access.`);
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
// 2. Push SBOM blob
|
|
592
|
+
const bomBuffer = Buffer.from(JSON.stringify(bomJson));
|
|
593
|
+
const blobInfo = await pushBlob(registry, repository, bomBuffer, token);
|
|
594
|
+
|
|
595
|
+
// Push the empty config blob ({}) required by the OCI 1.1 artifact manifest
|
|
596
|
+
const emptyConfigBuffer = Buffer.from("{}");
|
|
597
|
+
await pushBlob(registry, repository, emptyConfigBuffer, token);
|
|
598
|
+
|
|
599
|
+
// 3. Push OCI 1.1 Manifest
|
|
600
|
+
const manifestObj = {
|
|
601
|
+
schemaVersion: 2,
|
|
602
|
+
mediaType: "application/vnd.oci.image.manifest.v1+json",
|
|
603
|
+
artifactType: "application/vnd.cyclonedx+json",
|
|
604
|
+
config: {
|
|
605
|
+
mediaType: "application/vnd.oci.empty.v1+json",
|
|
606
|
+
digest:
|
|
607
|
+
"sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a",
|
|
608
|
+
size: 2,
|
|
609
|
+
},
|
|
610
|
+
layers: [
|
|
611
|
+
{
|
|
612
|
+
mediaType: "application/vnd.cyclonedx+json",
|
|
613
|
+
digest: blobInfo.digest,
|
|
614
|
+
size: blobInfo.size,
|
|
615
|
+
},
|
|
616
|
+
],
|
|
617
|
+
subject: {
|
|
618
|
+
mediaType:
|
|
619
|
+
targetManifest.mediaType ||
|
|
620
|
+
"application/vnd.oci.image.manifest.v1+json",
|
|
621
|
+
digest: targetManifest.digest,
|
|
622
|
+
size: targetManifest.manifest
|
|
623
|
+
? Buffer.from(JSON.stringify(targetManifest.manifest)).length
|
|
624
|
+
: 0,
|
|
625
|
+
},
|
|
626
|
+
annotations: {
|
|
627
|
+
"org.opencontainers.image.created": new Date().toISOString(),
|
|
628
|
+
},
|
|
629
|
+
};
|
|
630
|
+
|
|
631
|
+
let manifestDigest = await pushManifest(
|
|
632
|
+
registry,
|
|
633
|
+
repository,
|
|
634
|
+
manifestObj,
|
|
635
|
+
token,
|
|
636
|
+
);
|
|
637
|
+
|
|
638
|
+
// Probe if referrers API is supported by the registry
|
|
639
|
+
const probeUrl = `${registry.startsWith("localhost") ? "http" : "https"}://${registry}/v2/${repository}/referrers/${targetManifest.digest}`;
|
|
640
|
+
const probeHeaders = token
|
|
641
|
+
? { Authorization: token.startsWith("Basic") ? token : `Bearer ${token}` }
|
|
642
|
+
: {};
|
|
643
|
+
const probeRes = await cdxgenAgent.get(probeUrl, {
|
|
644
|
+
headers: probeHeaders,
|
|
645
|
+
throwHttpErrors: false,
|
|
646
|
+
timeout: getOciTimeoutMs(),
|
|
647
|
+
});
|
|
648
|
+
|
|
649
|
+
if (probeRes.statusCode === 404 || probeRes.statusCode === 400) {
|
|
650
|
+
// Registry does not support referrers API natively. Create the fallback tag.
|
|
651
|
+
const fallbackTag = targetManifest.digest.replace(":", "-");
|
|
652
|
+
|
|
653
|
+
// Check if the fallback tag already exists (an Image Index)
|
|
654
|
+
const fallbackUrl = `${registry.startsWith("localhost") ? "http" : "https"}://${registry}/v2/${repository}/manifests/${fallbackTag}`;
|
|
655
|
+
const getRes = await cdxgenAgent.get(fallbackUrl, {
|
|
656
|
+
headers: {
|
|
657
|
+
...probeHeaders,
|
|
658
|
+
Accept: "application/vnd.oci.image.index.v1+json",
|
|
659
|
+
},
|
|
660
|
+
responseType: "json",
|
|
661
|
+
throwHttpErrors: false,
|
|
662
|
+
timeout: getOciTimeoutMs(),
|
|
663
|
+
});
|
|
664
|
+
|
|
665
|
+
let indexObj;
|
|
666
|
+
if (getRes.statusCode === 200 && getRes.body && getRes.body.manifests) {
|
|
667
|
+
indexObj = getRes.body;
|
|
668
|
+
indexObj.manifests.push({
|
|
669
|
+
mediaType: "application/vnd.oci.image.manifest.v1+json",
|
|
670
|
+
digest: manifestDigest,
|
|
671
|
+
size: Buffer.from(JSON.stringify(manifestObj)).length,
|
|
672
|
+
artifactType: "application/vnd.cyclonedx+json",
|
|
673
|
+
});
|
|
674
|
+
} else {
|
|
675
|
+
indexObj = {
|
|
676
|
+
schemaVersion: 2,
|
|
677
|
+
mediaType: "application/vnd.oci.image.index.v1+json",
|
|
678
|
+
manifests: [
|
|
679
|
+
{
|
|
680
|
+
mediaType: "application/vnd.oci.image.manifest.v1+json",
|
|
681
|
+
digest: manifestDigest,
|
|
682
|
+
size: Buffer.from(JSON.stringify(manifestObj)).length,
|
|
683
|
+
artifactType: "application/vnd.cyclonedx+json",
|
|
684
|
+
},
|
|
685
|
+
],
|
|
686
|
+
};
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
const indexBuffer = Buffer.from(JSON.stringify(indexObj));
|
|
690
|
+
const putHeaders = {
|
|
691
|
+
...probeHeaders,
|
|
692
|
+
"Content-Type": "application/vnd.oci.image.index.v1+json",
|
|
693
|
+
};
|
|
694
|
+
await cdxgenAgent.put(fallbackUrl, {
|
|
695
|
+
headers: putHeaders,
|
|
696
|
+
body: indexBuffer,
|
|
697
|
+
throwHttpErrors: false,
|
|
698
|
+
});
|
|
699
|
+
manifestDigest = getDigest(indexBuffer);
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
console.log(`Attached SBOM natively to ${image} via ${manifestDigest}`);
|
|
703
|
+
return manifestDigest;
|
|
704
|
+
}
|