@cdxgen/cdxgen 13.5.0 → 13.7.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 +17 -10
- package/bin/audit.js +7 -4
- package/bin/cdxgen.js +260 -37
- package/bin/convert.js +146 -22
- package/bin/evinse.js +28 -3
- package/bin/repl.js +47 -3
- package/bin/sign.js +211 -34
- package/bin/tracebom.js +18 -6
- package/bin/validate.js +24 -3
- package/bin/verify.js +113 -5
- package/data/behavior-taxonomy.schema.json +1491 -0
- package/data/cyclonedx-2.0-bundled.schema.json +18606 -5528
- package/data/cyclonedx-2.0-cryptography-defs.schema.json +857 -0
- package/data/license-aliases.json +24 -2
- package/data/pqc-migration.json +239 -0
- package/data/remediations.json +176 -0
- package/data/rules/ai-bom.yaml +1 -1
- package/data/rules/brotli-decoder.yaml +107 -0
- package/data/rules/cbom-security.yaml +4 -3
- package/data/rules/package-integrity.yaml +28 -0
- package/data/rules/vscode-extensions.yaml +75 -0
- package/data/spdx-license-list.json +121 -7
- package/data/spdx-licenses.json +69 -0
- package/data/spdx.schema.json +845 -2
- package/lib/audit/index.js +25 -3
- package/lib/cli/bomAssembly.js +172 -4
- package/lib/cli/cliOptions.js +121 -17
- package/lib/cli/index.js +720 -902
- package/lib/cli/jsBom.js +156 -64
- package/lib/cli/jvmBom.js +602 -86
- package/lib/cli/managedBom.js +161 -19
- package/lib/cli/nativeBom.js +52 -5
- package/lib/core/boundedFile.js +344 -0
- package/lib/core/brotliProbe.js +182 -0
- package/lib/core/env.js +34 -0
- package/lib/core/fs.js +138 -3
- package/lib/core/globPatterns.js +218 -0
- package/lib/core/httpClient.js +98 -1
- package/lib/core/lockPaths.js +38 -0
- package/lib/core/paths.js +24 -1
- package/lib/core/processTree.js +100 -8
- package/lib/core/projectConfig.js +332 -25
- package/lib/core/toolRegistry.js +184 -0
- package/lib/ecosystems/cppEvidence.js +263 -106
- package/lib/ecosystems/cppIncludeResolver.js +16 -5
- package/lib/ecosystems/denoutils.js +2 -2
- package/lib/ecosystems/ecosystems.js +25 -10
- package/lib/ecosystems/gemHostProbe.js +301 -0
- package/lib/ecosystems/golem.js +3 -8
- package/lib/ecosystems/gradleutils.js +1909 -229
- package/lib/ecosystems/jsEvidence.js +90 -38
- package/lib/ecosystems/kosi.js +3 -5
- package/lib/ecosystems/npmVersionResolution.js +376 -0
- package/lib/ecosystems/parsers-bazel.js +107 -6
- package/lib/ecosystems/parsers-js.js +505 -22
- package/lib/ecosystems/parsers-misc.js +209 -20
- package/lib/ecosystems/parsers-python.js +178 -30
- package/lib/ecosystems/parsers-rust.js +117 -15
- package/lib/ecosystems/pythonutils.js +128 -2
- package/lib/ecosystems/remote/huggingface.js +22 -0
- package/lib/ecosystems/rubyutils.js +538 -31
- package/lib/ecosystems/rusi.js +2 -4
- package/lib/ecosystems/scalacliutils.js +2 -0
- package/lib/ecosystems/scalasem.js +798 -152
- package/lib/ecosystems/vendoredCode.js +237 -3
- package/lib/ecosystems/venvProbe.js +360 -0
- package/lib/evinser/evinser.js +536 -71
- package/lib/evinser/scalasem.js +5 -1
- package/lib/helpers/agenticToolutils.js +525 -94
- package/lib/helpers/bomSigner.js +43 -9
- package/lib/helpers/jssSigner.js +1276 -0
- package/lib/helpers/vsixutils.js +1574 -315
- package/lib/inventory/agentBlueprint.js +193 -0
- package/lib/inventory/agentToolNames.js +145 -0
- package/lib/inventory/aiCollector.js +153 -7
- package/lib/inventory/aiInventory.js +44 -8
- package/lib/inventory/aiProviders.js +324 -0
- package/lib/inventory/atomUtils.js +77 -0
- package/lib/inventory/bomUtils.js +8 -1
- package/lib/inventory/brotliDecoder.js +142 -0
- package/lib/inventory/buildToolRateLimit.js +1 -1
- package/lib/inventory/cbomutils.js +56 -7
- package/lib/inventory/ciParsers/githubActionsLock.js +821 -0
- package/lib/inventory/citations.js +31 -2
- package/lib/inventory/communityAiConfigParser.js +978 -80
- package/lib/inventory/cyclonedx20.js +152 -0
- package/lib/inventory/cyclonedx20Common.js +286 -0
- package/lib/inventory/cyclonedx20Derived.js +159 -0
- package/lib/inventory/cyclonedx20Parties.js +552 -0
- package/lib/inventory/cyclonedx20Read.js +768 -0
- package/lib/inventory/cyclonedx20ReadCommon.js +374 -0
- package/lib/inventory/cyclonedx20ReadComponents.js +692 -0
- package/lib/inventory/cyclonedx20ReadContext.js +380 -0
- package/lib/inventory/cyclonedx20ReadEvidence.js +466 -0
- package/lib/inventory/cyclonedx20ReadSections.js +599 -0
- package/lib/inventory/cyclonedx20Render.js +766 -0
- package/lib/inventory/cyclonedx20RenderComponents.js +716 -0
- package/lib/inventory/cyclonedx20RenderDefinitions.js +405 -0
- package/lib/inventory/cyclonedx20RenderEvidence.js +726 -0
- package/lib/inventory/cyclonedx20RenderHardware.js +203 -0
- package/lib/inventory/cyclonedx20RenderPatents.js +174 -0
- package/lib/inventory/cyclonedx20RenderRefIds.js +314 -0
- package/lib/inventory/cyclonedx20RenderSections.js +499 -0
- package/lib/inventory/cyclonedx20Tables.js +594 -0
- package/lib/inventory/deps.js +141 -13
- package/lib/inventory/dosai.js +375 -6
- package/lib/inventory/dosaiParsers.js +3 -6
- package/lib/inventory/dotnetRuntime.js +367 -0
- package/lib/inventory/ecosystemFormulationParsers.js +979 -0
- package/lib/inventory/envcontext.js +436 -48
- package/lib/inventory/evidenceUtils.js +13 -1
- package/lib/inventory/fetchBatch.js +1 -1
- package/lib/inventory/formulationParsers.js +124 -14
- package/lib/inventory/gtfobins.js +13 -0
- package/lib/inventory/hbom.js +45 -6
- package/lib/inventory/hbomLoader.js +166 -0
- package/lib/inventory/hostRuntimeProbe.js +686 -0
- package/lib/inventory/jvmLocalRepos.js +9 -2
- package/lib/inventory/jvmToolEnv.js +29 -0
- package/lib/inventory/licenseEnhancer.js +12 -0
- package/lib/inventory/mavenCentralMirror.js +534 -0
- package/lib/inventory/mcpConfigParser.js +5 -0
- package/lib/inventory/nodeBuildInfo.js +218 -0
- package/lib/inventory/nodeHostProbe.js +202 -0
- package/lib/inventory/occurrenceKey.js +90 -0
- package/lib/inventory/osPackageResolver.js +182 -0
- package/lib/inventory/phpBuildInfo.js +10 -59
- package/lib/inventory/phpHostProbe.js +32 -488
- package/lib/inventory/pqcMigration.js +426 -0
- package/lib/inventory/rubyBuildInfo.js +972 -0
- package/lib/inventory/rubyHostProbe.js +218 -0
- package/lib/inventory/rustFormulationParser.js +21 -10
- package/lib/inventory/scalaCoords.js +4 -3
- package/lib/inventory/scalaDedupe.js +440 -0
- package/lib/inventory/source.js +114 -8
- package/lib/managers/binary.js +337 -3
- package/lib/managers/docker.js +79 -0
- package/lib/parsers/huggingfaceManifest.js +9 -1
- package/lib/parsers/huggingfaceUtils.js +18 -0
- package/lib/parsers/kiroPermissions.js +166 -0
- package/lib/parsers/largeJson.js +28 -11
- package/lib/parsers/vscodeExtensionId.js +183 -0
- package/lib/server/server.js +48 -35
- package/lib/stages/postgen/postgen.js +41 -1
- package/lib/stages/postgen/ruleEngine.js +13 -5
- package/lib/stages/postgen/specVersionCompat.js +76 -0
- package/lib/stages/pregen/envAudit.js +1 -0
- package/lib/stages/pregen/pregen.js +114 -57
- package/lib/validator/bomValidator.js +14 -2
- package/lib/validator/complianceEngine.js +30 -3
- package/lib/validator/complianceRules.js +1416 -4
- package/lib/validator/generated/validate-1.6.mjs +1 -1
- package/lib/validator/generated/validate-1.7.mjs +1 -1
- package/lib/validator/generated/validate-2.0.mjs +57554 -13851
- package/lib/validator/index.js +49 -8
- package/lib/validator/reporters/json.js +6 -0
- package/package.json +11 -10
- package/types/bin/repl.d.ts.map +1 -1
- package/types/lib/audit/index.d.ts +6 -2
- package/types/lib/audit/index.d.ts.map +1 -1
- package/types/lib/cli/bomAssembly.d.ts +29 -1
- package/types/lib/cli/bomAssembly.d.ts.map +1 -1
- package/types/lib/cli/cliOptions.d.ts +6 -0
- package/types/lib/cli/cliOptions.d.ts.map +1 -1
- package/types/lib/cli/index.d.ts.map +1 -1
- package/types/lib/cli/jsBom.d.ts +3 -18
- package/types/lib/cli/jsBom.d.ts.map +1 -1
- package/types/lib/cli/jvmBom.d.ts +15 -0
- package/types/lib/cli/jvmBom.d.ts.map +1 -1
- package/types/lib/cli/managedBom.d.ts.map +1 -1
- package/types/lib/cli/nativeBom.d.ts.map +1 -1
- package/types/lib/core/boundedFile.d.ts +100 -0
- package/types/lib/core/boundedFile.d.ts.map +1 -0
- package/types/lib/core/brotliProbe.d.ts +37 -0
- package/types/lib/core/brotliProbe.d.ts.map +1 -0
- package/types/lib/core/env.d.ts +14 -0
- package/types/lib/core/env.d.ts.map +1 -1
- package/types/lib/core/fs.d.ts +4 -0
- package/types/lib/core/fs.d.ts.map +1 -1
- package/types/lib/core/globPatterns.d.ts +70 -0
- package/types/lib/core/globPatterns.d.ts.map +1 -0
- package/types/lib/core/httpClient.d.ts +24 -0
- package/types/lib/core/httpClient.d.ts.map +1 -1
- package/types/lib/core/lockPaths.d.ts +19 -0
- package/types/lib/core/lockPaths.d.ts.map +1 -0
- package/types/lib/core/paths.d.ts +9 -0
- package/types/lib/core/paths.d.ts.map +1 -1
- package/types/lib/core/processTree.d.ts +17 -4
- package/types/lib/core/processTree.d.ts.map +1 -1
- package/types/lib/core/projectConfig.d.ts +47 -8
- package/types/lib/core/projectConfig.d.ts.map +1 -1
- package/types/lib/core/toolRegistry.d.ts +36 -0
- package/types/lib/core/toolRegistry.d.ts.map +1 -0
- package/types/lib/ecosystems/cppEvidence.d.ts +40 -13
- package/types/lib/ecosystems/cppEvidence.d.ts.map +1 -1
- package/types/lib/ecosystems/cppIncludeResolver.d.ts +2 -1
- package/types/lib/ecosystems/cppIncludeResolver.d.ts.map +1 -1
- package/types/lib/ecosystems/ecosystems.d.ts.map +1 -1
- package/types/lib/ecosystems/gemHostProbe.d.ts +28 -0
- package/types/lib/ecosystems/gemHostProbe.d.ts.map +1 -0
- package/types/lib/ecosystems/golem.d.ts.map +1 -1
- package/types/lib/ecosystems/gradleutils.d.ts +294 -20
- package/types/lib/ecosystems/gradleutils.d.ts.map +1 -1
- package/types/lib/ecosystems/jsEvidence.d.ts +14 -1
- package/types/lib/ecosystems/jsEvidence.d.ts.map +1 -1
- package/types/lib/ecosystems/kosi.d.ts.map +1 -1
- package/types/lib/ecosystems/npmVersionResolution.d.ts +119 -0
- package/types/lib/ecosystems/npmVersionResolution.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-bazel.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-js.d.ts +17 -20
- package/types/lib/ecosystems/parsers-js.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-misc.d.ts +19 -0
- package/types/lib/ecosystems/parsers-misc.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-python.d.ts +10 -0
- package/types/lib/ecosystems/parsers-python.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-rust.d.ts.map +1 -1
- package/types/lib/ecosystems/pythonutils.d.ts +19 -1
- package/types/lib/ecosystems/pythonutils.d.ts.map +1 -1
- package/types/lib/ecosystems/remote/huggingface.d.ts.map +1 -1
- package/types/lib/ecosystems/rubyutils.d.ts +144 -12
- package/types/lib/ecosystems/rubyutils.d.ts.map +1 -1
- package/types/lib/ecosystems/rusi.d.ts.map +1 -1
- package/types/lib/ecosystems/scalacliutils.d.ts.map +1 -1
- package/types/lib/ecosystems/scalasem.d.ts +58 -16
- package/types/lib/ecosystems/scalasem.d.ts.map +1 -1
- package/types/lib/ecosystems/vendoredCode.d.ts +26 -0
- package/types/lib/ecosystems/vendoredCode.d.ts.map +1 -1
- package/types/lib/ecosystems/venvProbe.d.ts +40 -0
- package/types/lib/ecosystems/venvProbe.d.ts.map +1 -0
- package/types/lib/evinser/evinser.d.ts +120 -13
- package/types/lib/evinser/evinser.d.ts.map +1 -1
- package/types/lib/evinser/scalasem.d.ts.map +1 -1
- package/types/lib/helpers/agenticToolutils.d.ts +53 -19
- package/types/lib/helpers/agenticToolutils.d.ts.map +1 -1
- package/types/lib/helpers/bomSigner.d.ts +20 -3
- package/types/lib/helpers/bomSigner.d.ts.map +1 -1
- package/types/lib/helpers/jssSigner.d.ts +288 -0
- package/types/lib/helpers/jssSigner.d.ts.map +1 -0
- package/types/lib/helpers/vsixutils.d.ts +303 -19
- package/types/lib/helpers/vsixutils.d.ts.map +1 -1
- package/types/lib/inventory/agentBlueprint.d.ts +70 -0
- package/types/lib/inventory/agentBlueprint.d.ts.map +1 -0
- package/types/lib/inventory/agentToolNames.d.ts +51 -0
- package/types/lib/inventory/agentToolNames.d.ts.map +1 -0
- package/types/lib/inventory/aiCollector.d.ts.map +1 -1
- package/types/lib/inventory/aiInventory.d.ts.map +1 -1
- package/types/lib/inventory/aiProviders.d.ts +85 -0
- package/types/lib/inventory/aiProviders.d.ts.map +1 -0
- package/types/lib/inventory/atomUtils.d.ts +19 -0
- package/types/lib/inventory/atomUtils.d.ts.map +1 -1
- package/types/lib/inventory/bomUtils.d.ts.map +1 -1
- package/types/lib/inventory/brotliDecoder.d.ts +58 -0
- package/types/lib/inventory/brotliDecoder.d.ts.map +1 -0
- package/types/lib/inventory/cbomutils.d.ts +17 -0
- package/types/lib/inventory/cbomutils.d.ts.map +1 -1
- package/types/lib/inventory/ciParsers/githubActionsLock.d.ts +101 -0
- package/types/lib/inventory/ciParsers/githubActionsLock.d.ts.map +1 -0
- package/types/lib/inventory/citations.d.ts +5 -0
- package/types/lib/inventory/citations.d.ts.map +1 -1
- package/types/lib/inventory/communityAiConfigParser.d.ts.map +1 -1
- package/types/lib/inventory/cyclonedx20.d.ts +99 -0
- package/types/lib/inventory/cyclonedx20.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Common.d.ts +102 -0
- package/types/lib/inventory/cyclonedx20Common.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Derived.d.ts +74 -0
- package/types/lib/inventory/cyclonedx20Derived.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Parties.d.ts +91 -0
- package/types/lib/inventory/cyclonedx20Parties.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Read.d.ts +51 -0
- package/types/lib/inventory/cyclonedx20Read.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20ReadCommon.d.ts +69 -0
- package/types/lib/inventory/cyclonedx20ReadCommon.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20ReadComponents.d.ts +77 -0
- package/types/lib/inventory/cyclonedx20ReadComponents.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20ReadContext.d.ts +118 -0
- package/types/lib/inventory/cyclonedx20ReadContext.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20ReadEvidence.d.ts +40 -0
- package/types/lib/inventory/cyclonedx20ReadEvidence.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20ReadSections.d.ts +45 -0
- package/types/lib/inventory/cyclonedx20ReadSections.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Render.d.ts +53 -0
- package/types/lib/inventory/cyclonedx20Render.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderComponents.d.ts +73 -0
- package/types/lib/inventory/cyclonedx20RenderComponents.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderDefinitions.d.ts +29 -0
- package/types/lib/inventory/cyclonedx20RenderDefinitions.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderEvidence.d.ts +110 -0
- package/types/lib/inventory/cyclonedx20RenderEvidence.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderHardware.d.ts +42 -0
- package/types/lib/inventory/cyclonedx20RenderHardware.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderPatents.d.ts +26 -0
- package/types/lib/inventory/cyclonedx20RenderPatents.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderRefIds.d.ts +55 -0
- package/types/lib/inventory/cyclonedx20RenderRefIds.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderSections.d.ts +45 -0
- package/types/lib/inventory/cyclonedx20RenderSections.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Tables.d.ts +134 -0
- package/types/lib/inventory/cyclonedx20Tables.d.ts.map +1 -0
- package/types/lib/inventory/deps.d.ts +35 -2
- package/types/lib/inventory/deps.d.ts.map +1 -1
- package/types/lib/inventory/dosai.d.ts +36 -1
- package/types/lib/inventory/dosai.d.ts.map +1 -1
- package/types/lib/inventory/dosaiParsers.d.ts.map +1 -1
- package/types/lib/inventory/dotnetRuntime.d.ts +91 -0
- package/types/lib/inventory/dotnetRuntime.d.ts.map +1 -0
- package/types/lib/inventory/ecosystemFormulationParsers.d.ts +73 -0
- package/types/lib/inventory/ecosystemFormulationParsers.d.ts.map +1 -0
- package/types/lib/inventory/envcontext.d.ts +74 -12
- package/types/lib/inventory/envcontext.d.ts.map +1 -1
- package/types/lib/inventory/evidenceUtils.d.ts.map +1 -1
- package/types/lib/inventory/formulationParsers.d.ts.map +1 -1
- package/types/lib/inventory/gtfobins.d.ts.map +1 -1
- package/types/lib/inventory/hbom.d.ts +11 -0
- package/types/lib/inventory/hbom.d.ts.map +1 -1
- package/types/lib/inventory/hbomLoader.d.ts +54 -0
- package/types/lib/inventory/hbomLoader.d.ts.map +1 -1
- package/types/lib/inventory/hostRuntimeProbe.d.ts +44 -0
- package/types/lib/inventory/hostRuntimeProbe.d.ts.map +1 -0
- package/types/lib/inventory/jvmLocalRepos.d.ts +5 -1
- package/types/lib/inventory/jvmLocalRepos.d.ts.map +1 -1
- package/types/lib/inventory/jvmToolEnv.d.ts +12 -0
- package/types/lib/inventory/jvmToolEnv.d.ts.map +1 -1
- package/types/lib/inventory/licenseEnhancer.d.ts.map +1 -1
- package/types/lib/inventory/mavenCentralMirror.d.ts +170 -0
- package/types/lib/inventory/mavenCentralMirror.d.ts.map +1 -0
- package/types/lib/inventory/mcpConfigParser.d.ts.map +1 -1
- package/types/lib/inventory/nodeBuildInfo.d.ts +95 -0
- package/types/lib/inventory/nodeBuildInfo.d.ts.map +1 -0
- package/types/lib/inventory/nodeHostProbe.d.ts +15 -0
- package/types/lib/inventory/nodeHostProbe.d.ts.map +1 -0
- package/types/lib/inventory/occurrenceKey.d.ts +52 -0
- package/types/lib/inventory/occurrenceKey.d.ts.map +1 -0
- package/types/lib/inventory/osPackageResolver.d.ts +38 -0
- package/types/lib/inventory/osPackageResolver.d.ts.map +1 -1
- package/types/lib/inventory/phpBuildInfo.d.ts.map +1 -1
- package/types/lib/inventory/phpHostProbe.d.ts.map +1 -1
- package/types/lib/inventory/pqcMigration.d.ts +84 -0
- package/types/lib/inventory/pqcMigration.d.ts.map +1 -0
- package/types/lib/inventory/rubyBuildInfo.d.ts +271 -0
- package/types/lib/inventory/rubyBuildInfo.d.ts.map +1 -0
- package/types/lib/inventory/rubyHostProbe.d.ts +47 -0
- package/types/lib/inventory/rubyHostProbe.d.ts.map +1 -0
- package/types/lib/inventory/rustFormulationParser.d.ts +7 -2
- package/types/lib/inventory/rustFormulationParser.d.ts.map +1 -1
- package/types/lib/inventory/scalaCoords.d.ts.map +1 -1
- package/types/lib/inventory/scalaDedupe.d.ts +43 -0
- package/types/lib/inventory/scalaDedupe.d.ts.map +1 -0
- package/types/lib/inventory/source.d.ts +25 -0
- package/types/lib/inventory/source.d.ts.map +1 -1
- package/types/lib/managers/binary.d.ts.map +1 -1
- package/types/lib/managers/docker.d.ts +12 -0
- package/types/lib/managers/docker.d.ts.map +1 -1
- package/types/lib/parsers/huggingfaceManifest.d.ts +10 -1
- package/types/lib/parsers/huggingfaceManifest.d.ts.map +1 -1
- package/types/lib/parsers/huggingfaceUtils.d.ts +12 -0
- package/types/lib/parsers/huggingfaceUtils.d.ts.map +1 -1
- package/types/lib/parsers/kiroPermissions.d.ts +62 -0
- package/types/lib/parsers/kiroPermissions.d.ts.map +1 -0
- package/types/lib/parsers/largeJson.d.ts +4 -3
- package/types/lib/parsers/largeJson.d.ts.map +1 -1
- package/types/lib/parsers/vscodeExtensionId.d.ts +48 -0
- package/types/lib/parsers/vscodeExtensionId.d.ts.map +1 -0
- package/types/lib/server/server.d.ts.map +1 -1
- package/types/lib/stages/postgen/postgen.d.ts +7 -0
- 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/postgen/specVersionCompat.d.ts +25 -0
- package/types/lib/stages/postgen/specVersionCompat.d.ts.map +1 -1
- package/types/lib/stages/pregen/envAudit.d.ts.map +1 -1
- package/types/lib/stages/pregen/pregen.d.ts +12 -8
- package/types/lib/stages/pregen/pregen.d.ts.map +1 -1
- package/types/lib/validator/bomValidator.d.ts +5 -1
- package/types/lib/validator/bomValidator.d.ts.map +1 -1
- package/types/lib/validator/complianceEngine.d.ts +4 -4
- package/types/lib/validator/complianceEngine.d.ts.map +1 -1
- package/types/lib/validator/complianceRules.d.ts +14 -2
- package/types/lib/validator/complianceRules.d.ts.map +1 -1
- package/types/lib/validator/index.d.ts +10 -0
- package/types/lib/validator/index.d.ts.map +1 -1
- package/types/lib/validator/reporters/json.d.ts.map +1 -1
|
@@ -0,0 +1,716 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Render-side conversion of 1.x components, services and tools to CycloneDX
|
|
3
|
+
* 2.0 components (#/$defs/cyclonedx-component-2.0/$defs/component).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
clone,
|
|
8
|
+
copyDefined,
|
|
9
|
+
countDrop,
|
|
10
|
+
countUnmapped,
|
|
11
|
+
identifierValues,
|
|
12
|
+
isNonEmptyString,
|
|
13
|
+
isObjectRecord,
|
|
14
|
+
takeShadow,
|
|
15
|
+
uniqueByValue,
|
|
16
|
+
} from "./cyclonedx20Common.js";
|
|
17
|
+
import {
|
|
18
|
+
collectParties,
|
|
19
|
+
contactToParty,
|
|
20
|
+
entityToParties,
|
|
21
|
+
} from "./cyclonedx20Parties.js";
|
|
22
|
+
import {
|
|
23
|
+
convertComponentEvidence,
|
|
24
|
+
convertCryptoProperties,
|
|
25
|
+
identifierPartyRefId,
|
|
26
|
+
} from "./cyclonedx20RenderEvidence.js";
|
|
27
|
+
import { applyHardwareMapping } from "./cyclonedx20RenderHardware.js";
|
|
28
|
+
import { convertPatentAssertions } from "./cyclonedx20RenderPatents.js";
|
|
29
|
+
import {
|
|
30
|
+
CARRIED_SERVICE_PROPERTIES,
|
|
31
|
+
COMPONENT_COPY_FIELDS,
|
|
32
|
+
COMPONENT_DATA_FIELDS,
|
|
33
|
+
COMPONENT_DATA_TYPE_ENUM,
|
|
34
|
+
COMPONENT_ENTRY_ARRAY_KEYS,
|
|
35
|
+
COMPONENT_HANDLED_FIELDS,
|
|
36
|
+
DATA_CLASSIFICATION_ENUM,
|
|
37
|
+
SERVICE_COPY_FIELDS,
|
|
38
|
+
SERVICE_HANDLED_FIELDS,
|
|
39
|
+
} from "./cyclonedx20Tables.js";
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Convert identifier fields of a 1.x component into the identities array of
|
|
43
|
+
* one `identifier` group
|
|
44
|
+
* (#/$defs/cyclonedx-component-2.0/$defs/identifiers → identifier → identity,
|
|
45
|
+
* required `[party, identities]` / `[scheme, value]`). The group's required
|
|
46
|
+
* asserting party is identifierPartyRefId: the cdxgen party when cdxgen is
|
|
47
|
+
* the listed tool, the party of the first other listed tool when cdxgen is
|
|
48
|
+
* not listed, and, when the BOM lists no tool at all, cdxgen again: as the
|
|
49
|
+
* converting tool it then asserts the identifiers it wrote.
|
|
50
|
+
*/
|
|
51
|
+
function collectIdentities(component) {
|
|
52
|
+
const identities = [];
|
|
53
|
+
const push = (scheme, value) => {
|
|
54
|
+
if (isNonEmptyString(value)) {
|
|
55
|
+
identities.push({ scheme, value });
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
push("purl", component.purl);
|
|
59
|
+
push("cpe", component.cpe);
|
|
60
|
+
const swid = component.swid;
|
|
61
|
+
if (isObjectRecord(swid) && typeof swid.tagId === "string") {
|
|
62
|
+
// The swid identity value is the tagId (ISO/IEC 19770-2 tag identifier).
|
|
63
|
+
push("swid", swid.tagId);
|
|
64
|
+
} else if (typeof swid === "string") {
|
|
65
|
+
push("swid", swid);
|
|
66
|
+
}
|
|
67
|
+
for (const oid of identifierValues(component.omniborId)) {
|
|
68
|
+
push("omniborid", oid);
|
|
69
|
+
}
|
|
70
|
+
for (const swhidValue of identifierValues(component.swhid)) {
|
|
71
|
+
push("swhid", swhidValue);
|
|
72
|
+
}
|
|
73
|
+
return uniqueByValue(identities);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Convert license choices: 1.x license objects and expressions may carry
|
|
78
|
+
* `bom-ref`, which the 2.0 licenseDeclaration renames to `refId`
|
|
79
|
+
* (#/$defs/cyclonedx-license-2.0/$defs/licenseDeclaration), and a license
|
|
80
|
+
* `text` is an attachment.
|
|
81
|
+
*
|
|
82
|
+
* @param {object[]} licenses 1.x license choices
|
|
83
|
+
* @param {object} stats Render counters
|
|
84
|
+
* @returns {object[]|undefined} 2.0 license choices
|
|
85
|
+
*/
|
|
86
|
+
export function convertLicenses(licenses, stats) {
|
|
87
|
+
if (!Array.isArray(licenses)) {
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
const renameRef = (entry) => {
|
|
91
|
+
if (isObjectRecord(entry) && entry["bom-ref"] !== undefined) {
|
|
92
|
+
entry.refId = entry["bom-ref"];
|
|
93
|
+
delete entry["bom-ref"];
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
return licenses.map((choice) => {
|
|
97
|
+
const converted = clone(choice);
|
|
98
|
+
if (isObjectRecord(converted?.license)) {
|
|
99
|
+
renameRef(converted.license);
|
|
100
|
+
if (converted.license.text !== undefined) {
|
|
101
|
+
const text = convertAttachment(
|
|
102
|
+
converted.license.text,
|
|
103
|
+
stats,
|
|
104
|
+
"license.text",
|
|
105
|
+
);
|
|
106
|
+
if (text) {
|
|
107
|
+
converted.license.text = text;
|
|
108
|
+
} else {
|
|
109
|
+
delete converted.license.text;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
} else {
|
|
113
|
+
renameRef(converted);
|
|
114
|
+
}
|
|
115
|
+
return converted;
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// #/$defs/cyclonedx-common-2.0/$defs/mediaType
|
|
120
|
+
const MEDIA_TYPE_PATTERN =
|
|
121
|
+
/^[-+a-z0-9.]+\/[-+a-z0-9.]+(\s*;\s*[a-zA-Z0-9!#$&^_.+-]+=("[^"]*"|[^\s;"]+))*$/;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Convert a 1.x attachment ({contentType, encoding, content}) to the 2.0
|
|
125
|
+
* attachment (#/$defs/cyclonedx-common-2.0/$defs/attachment, `mediaType`
|
|
126
|
+
* instead of `contentType`, `content` required). A content type that is not
|
|
127
|
+
* a media type the 2.0 pattern accepts is counted and left out.
|
|
128
|
+
*
|
|
129
|
+
* @param {object} attachment 1.x attachment
|
|
130
|
+
* @param {object} stats Render counters
|
|
131
|
+
* @param {string} label Counter label of the attachment's position
|
|
132
|
+
* @returns {object|undefined} 2.0 attachment, or undefined without content
|
|
133
|
+
*/
|
|
134
|
+
export function convertAttachment(attachment, stats, label) {
|
|
135
|
+
if (!isObjectRecord(attachment) || typeof attachment.content !== "string") {
|
|
136
|
+
countDrop(stats, `${label} (no content)`);
|
|
137
|
+
return undefined;
|
|
138
|
+
}
|
|
139
|
+
const converted = {};
|
|
140
|
+
if (attachment.contentType !== undefined) {
|
|
141
|
+
const mediaType =
|
|
142
|
+
typeof attachment.contentType === "string"
|
|
143
|
+
? attachment.contentType.trim()
|
|
144
|
+
: "";
|
|
145
|
+
// Type and subtype are case-insensitive (RFC 6838 section 4.2); the 2.0
|
|
146
|
+
// pattern accepts only the lowercase form.
|
|
147
|
+
const slash = mediaType.indexOf("/");
|
|
148
|
+
const semicolon = mediaType.indexOf(";");
|
|
149
|
+
const essenceEnd = semicolon === -1 ? mediaType.length : semicolon;
|
|
150
|
+
const normalized =
|
|
151
|
+
mediaType.slice(0, essenceEnd).toLowerCase() +
|
|
152
|
+
mediaType.slice(essenceEnd);
|
|
153
|
+
if (slash > 0 && MEDIA_TYPE_PATTERN.test(normalized)) {
|
|
154
|
+
converted.mediaType = normalized;
|
|
155
|
+
} else {
|
|
156
|
+
countDrop(stats, `${label}.contentType (not a media type)`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (attachment.encoding === "base64") {
|
|
160
|
+
converted.encoding = "base64";
|
|
161
|
+
} else if (attachment.encoding !== undefined) {
|
|
162
|
+
countDrop(stats, `${label}.encoding`);
|
|
163
|
+
}
|
|
164
|
+
converted.content = attachment.content;
|
|
165
|
+
return converted;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Convert release notes
|
|
170
|
+
* (#/$defs/cyclonedx-release-notes-2.0/$defs/releaseNotes): the members are
|
|
171
|
+
* the same, but each note's `text` is an attachment and a note requires it.
|
|
172
|
+
*
|
|
173
|
+
* @param {object} releaseNotes 1.x release notes
|
|
174
|
+
* @param {object} stats Render counters
|
|
175
|
+
* @returns {object|undefined} 2.0 release notes
|
|
176
|
+
*/
|
|
177
|
+
export function convertReleaseNotes(releaseNotes, stats) {
|
|
178
|
+
if (!isObjectRecord(releaseNotes)) {
|
|
179
|
+
return clone(releaseNotes);
|
|
180
|
+
}
|
|
181
|
+
const converted = clone(releaseNotes);
|
|
182
|
+
if (Array.isArray(converted.notes)) {
|
|
183
|
+
const notes = [];
|
|
184
|
+
for (const note of converted.notes) {
|
|
185
|
+
const text = convertAttachment(
|
|
186
|
+
note?.text,
|
|
187
|
+
stats,
|
|
188
|
+
"releaseNotes.notes.text",
|
|
189
|
+
);
|
|
190
|
+
if (text) {
|
|
191
|
+
notes.push({ ...note, text });
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
if (notes.length) {
|
|
195
|
+
converted.notes = notes;
|
|
196
|
+
} else {
|
|
197
|
+
delete converted.notes;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return converted;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/** Map a 1.x free-text data classification onto the 2.0 enum or `{name}`. */
|
|
204
|
+
export function toDataClassification(classification) {
|
|
205
|
+
if (isNonEmptyString(classification)) {
|
|
206
|
+
return DATA_CLASSIFICATION_ENUM.has(classification)
|
|
207
|
+
? classification
|
|
208
|
+
: { name: classification };
|
|
209
|
+
}
|
|
210
|
+
if (isNonEmptyString(classification?.name)) {
|
|
211
|
+
return { name: classification.name };
|
|
212
|
+
}
|
|
213
|
+
return undefined;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Convert 1.x dataGovernance ({custodians, stewards, owners} of
|
|
218
|
+
* organization-or-contact entries) into the 2.0 array of parties
|
|
219
|
+
* (#/$defs/cyclonedx-data-2.0/$defs/dataGovernance) with the matching roles.
|
|
220
|
+
*/
|
|
221
|
+
export function convertGovernance(governance, stats) {
|
|
222
|
+
if (!isObjectRecord(governance)) {
|
|
223
|
+
return undefined;
|
|
224
|
+
}
|
|
225
|
+
const parties = [];
|
|
226
|
+
for (const [field, role] of [
|
|
227
|
+
["custodians", "custodian"],
|
|
228
|
+
["stewards", "steward"],
|
|
229
|
+
["owners", "owner"],
|
|
230
|
+
]) {
|
|
231
|
+
for (const entry of Array.isArray(governance[field])
|
|
232
|
+
? governance[field]
|
|
233
|
+
: []) {
|
|
234
|
+
if (isObjectRecord(entry?.organization)) {
|
|
235
|
+
parties.push(...entityToParties(entry.organization, role, stats));
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
const party = contactToParty(entry?.contact, role, stats);
|
|
239
|
+
if (party) {
|
|
240
|
+
parties.push(party);
|
|
241
|
+
} else {
|
|
242
|
+
countDrop(stats, "data.governance (empty)");
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
const unique = uniqueByValue(parties);
|
|
247
|
+
return unique.length ? unique : undefined;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/** Convert 1.x data contents ({attachment, url, properties}). */
|
|
251
|
+
export function convertDataContents(contents, stats) {
|
|
252
|
+
if (!isObjectRecord(contents)) {
|
|
253
|
+
return undefined;
|
|
254
|
+
}
|
|
255
|
+
const converted = {};
|
|
256
|
+
if (contents.attachment !== undefined) {
|
|
257
|
+
const attachment = convertAttachment(
|
|
258
|
+
contents.attachment,
|
|
259
|
+
stats,
|
|
260
|
+
"data.contents.attachment",
|
|
261
|
+
);
|
|
262
|
+
if (attachment) {
|
|
263
|
+
converted.attachment = attachment;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
copyDefined(converted, contents, ["url", "properties"]);
|
|
267
|
+
countUnmapped(
|
|
268
|
+
stats,
|
|
269
|
+
"data.contents",
|
|
270
|
+
contents,
|
|
271
|
+
new Set(["attachment", "url", "properties"]),
|
|
272
|
+
);
|
|
273
|
+
return Object.keys(converted).length ? converted : undefined;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/** Convert a 1.x graphics collection; each 2.0 graphic requires `image`. */
|
|
277
|
+
function convertGraphics(graphics, stats) {
|
|
278
|
+
if (!isObjectRecord(graphics) || !Array.isArray(graphics.collection)) {
|
|
279
|
+
return undefined;
|
|
280
|
+
}
|
|
281
|
+
const collection = [];
|
|
282
|
+
for (const graphic of graphics.collection) {
|
|
283
|
+
const image = convertAttachment(graphic?.image, stats, "data.graphics");
|
|
284
|
+
if (!image) {
|
|
285
|
+
continue;
|
|
286
|
+
}
|
|
287
|
+
collection.push(
|
|
288
|
+
typeof graphic.name === "string"
|
|
289
|
+
? { name: graphic.name, image }
|
|
290
|
+
: { image },
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
return collection.length ? { collection } : undefined;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Convert 1.x component data to componentData
|
|
298
|
+
* (#/$defs/cyclonedx-component-2.0/$defs/componentData, required `[type]`).
|
|
299
|
+
* 2.0 has no `description` here.
|
|
300
|
+
*/
|
|
301
|
+
function convertComponentData(data, stats) {
|
|
302
|
+
if (!Array.isArray(data)) {
|
|
303
|
+
return undefined;
|
|
304
|
+
}
|
|
305
|
+
const converted = [];
|
|
306
|
+
for (const entry of data) {
|
|
307
|
+
if (!isObjectRecord(entry) || !COMPONENT_DATA_TYPE_ENUM.has(entry.type)) {
|
|
308
|
+
countDrop(stats, "component.data (type outside the 2.0 enum)");
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
311
|
+
const item = {};
|
|
312
|
+
if (isNonEmptyString(entry["bom-ref"])) {
|
|
313
|
+
item.refId = entry["bom-ref"];
|
|
314
|
+
}
|
|
315
|
+
item.type = entry.type;
|
|
316
|
+
if (typeof entry.name === "string") {
|
|
317
|
+
item.name = entry.name;
|
|
318
|
+
}
|
|
319
|
+
const contents = convertDataContents(entry.contents, stats);
|
|
320
|
+
if (contents) {
|
|
321
|
+
item.contents = contents;
|
|
322
|
+
}
|
|
323
|
+
const classification = toDataClassification(entry.classification);
|
|
324
|
+
if (classification !== undefined) {
|
|
325
|
+
item.classification = classification;
|
|
326
|
+
}
|
|
327
|
+
copyDefined(item, entry, ["sensitiveData"]);
|
|
328
|
+
const graphics = convertGraphics(entry.graphics, stats);
|
|
329
|
+
if (graphics) {
|
|
330
|
+
item.graphics = graphics;
|
|
331
|
+
}
|
|
332
|
+
const governance = convertGovernance(entry.governance, stats);
|
|
333
|
+
if (governance) {
|
|
334
|
+
item.governance = governance;
|
|
335
|
+
}
|
|
336
|
+
countUnmapped(stats, "component.data", entry, COMPONENT_DATA_FIELDS);
|
|
337
|
+
converted.push(item);
|
|
338
|
+
}
|
|
339
|
+
return converted.length ? converted : undefined;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Convert pedigree (#/$defs/cyclonedx-component-2.0/$defs/pedigree): the
|
|
344
|
+
* ancestor, descendant and variant entries are components or references.
|
|
345
|
+
*/
|
|
346
|
+
function convertPedigree(pedigree, stats) {
|
|
347
|
+
if (!isObjectRecord(pedigree)) {
|
|
348
|
+
return clone(pedigree);
|
|
349
|
+
}
|
|
350
|
+
const converted = {};
|
|
351
|
+
for (const [key, value] of Object.entries(pedigree)) {
|
|
352
|
+
if (COMPONENT_ENTRY_ARRAY_KEYS.has(key) && Array.isArray(value)) {
|
|
353
|
+
converted[key] = value.map((entry) =>
|
|
354
|
+
convertComponentEntry(entry, stats),
|
|
355
|
+
);
|
|
356
|
+
} else if (key === "patches" && Array.isArray(value)) {
|
|
357
|
+
converted.patches = value.map((patch) => convertPatch(patch, stats));
|
|
358
|
+
} else if (key === "commits") {
|
|
359
|
+
converted[key] = clone(value);
|
|
360
|
+
} else if (value !== undefined) {
|
|
361
|
+
countDrop(stats, `component.pedigree.${key}`);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
return converted;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Convert a pedigree patch (#/$defs/cyclonedx-common-2.0/$defs/patch): the
|
|
369
|
+
* diff `text` is an attachment.
|
|
370
|
+
*/
|
|
371
|
+
function convertPatch(patch, stats) {
|
|
372
|
+
const converted = clone(patch);
|
|
373
|
+
if (isObjectRecord(converted?.diff) && converted.diff.text !== undefined) {
|
|
374
|
+
const text = convertAttachment(
|
|
375
|
+
converted.diff.text,
|
|
376
|
+
stats,
|
|
377
|
+
"pedigree.patches.diff.text",
|
|
378
|
+
);
|
|
379
|
+
if (text) {
|
|
380
|
+
converted.diff.text = text;
|
|
381
|
+
} else {
|
|
382
|
+
delete converted.diff.text;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
return converted;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Convert a nested entry: componentReference ({ref}) and component-choice
|
|
390
|
+
* wrappers (#/$defs/cyclonedx-component-2.0/$defs/componentEntry oneOf) pass
|
|
391
|
+
* through, everything else is a component.
|
|
392
|
+
*/
|
|
393
|
+
function convertComponentEntry(entry, stats) {
|
|
394
|
+
if (
|
|
395
|
+
isObjectRecord(entry) &&
|
|
396
|
+
(entry.type === "component-choice" ||
|
|
397
|
+
(typeof entry.ref === "string" && !entry.name))
|
|
398
|
+
) {
|
|
399
|
+
return clone(entry);
|
|
400
|
+
}
|
|
401
|
+
return convertComponent(entry, stats);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
const SWID_FIELDS = new Set(["tagId"]);
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Convert the release notes and patent assertions copied by name, which
|
|
408
|
+
* components and services share.
|
|
409
|
+
*/
|
|
410
|
+
function convertSharedMembers(source, converted, stats) {
|
|
411
|
+
if (source.releaseNotes !== undefined) {
|
|
412
|
+
converted.releaseNotes = convertReleaseNotes(source.releaseNotes, stats);
|
|
413
|
+
}
|
|
414
|
+
if (source.patentAssertions !== undefined) {
|
|
415
|
+
const assertions = convertPatentAssertions(source.patentAssertions, stats);
|
|
416
|
+
if (assertions === undefined) {
|
|
417
|
+
delete converted.patentAssertions;
|
|
418
|
+
} else {
|
|
419
|
+
converted.patentAssertions = assertions;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/** Copy the media type and the model card under their 2.0 names. */
|
|
425
|
+
function convertComponentRenames(component, converted, stats) {
|
|
426
|
+
if (component.mimeType !== undefined) {
|
|
427
|
+
converted.mediaType = clone(component.mimeType);
|
|
428
|
+
} else if (component["mime-type"] !== undefined) {
|
|
429
|
+
converted.mediaType = clone(component["mime-type"]);
|
|
430
|
+
}
|
|
431
|
+
const modelCard = component.modelCard ?? component.modelProperties;
|
|
432
|
+
if (modelCard !== undefined) {
|
|
433
|
+
const modelProperties = convertModelCard(modelCard, stats);
|
|
434
|
+
if (modelProperties) {
|
|
435
|
+
converted.modelProperties = modelProperties;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* Convert a 1.x modelCard to 2.0 modelProperties
|
|
442
|
+
* (#/$defs/cyclonedx-ai-ml-2.0/$defs/modelProperties). The two share only
|
|
443
|
+
* `properties`; modelParameters, quantitativeAnalysis and considerations
|
|
444
|
+
* have a different 2.0 structure and are counted.
|
|
445
|
+
*/
|
|
446
|
+
function convertModelCard(modelCard, stats) {
|
|
447
|
+
if (!isObjectRecord(modelCard)) {
|
|
448
|
+
countDrop(stats, "component.modelCard (not an object)");
|
|
449
|
+
return undefined;
|
|
450
|
+
}
|
|
451
|
+
const converted = {};
|
|
452
|
+
copyDefined(converted, modelCard, ["properties"]);
|
|
453
|
+
countUnmapped(stats, "component.modelCard", modelCard, MODEL_CARD_FIELDS);
|
|
454
|
+
return Object.keys(converted).length ? converted : undefined;
|
|
455
|
+
}
|
|
456
|
+
const MODEL_CARD_FIELDS = new Set(["properties"]);
|
|
457
|
+
|
|
458
|
+
/** Convert evidence, cryptoProperties and data of a component. */
|
|
459
|
+
function convertComponentDetails(component, converted, stats) {
|
|
460
|
+
const evidence = convertComponentEvidence(component.evidence, stats);
|
|
461
|
+
if (evidence) {
|
|
462
|
+
converted.evidence = evidence;
|
|
463
|
+
}
|
|
464
|
+
const cryptoProperties = convertCryptoProperties(
|
|
465
|
+
component.cryptoProperties,
|
|
466
|
+
stats,
|
|
467
|
+
);
|
|
468
|
+
if (cryptoProperties) {
|
|
469
|
+
converted.cryptoProperties = cryptoProperties;
|
|
470
|
+
}
|
|
471
|
+
const data = convertComponentData(component.data, stats);
|
|
472
|
+
if (data) {
|
|
473
|
+
converted.data = data;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/** Nested components and services both become 2.0 `components`. */
|
|
478
|
+
function convertNestedEntries(component, converted, stats) {
|
|
479
|
+
if (Array.isArray(component.components)) {
|
|
480
|
+
converted.components = component.components.map((child) =>
|
|
481
|
+
convertComponentEntry(child, stats),
|
|
482
|
+
);
|
|
483
|
+
}
|
|
484
|
+
if (Array.isArray(component.services)) {
|
|
485
|
+
const nestedServices = component.services.map((service) =>
|
|
486
|
+
convertService(service, stats),
|
|
487
|
+
);
|
|
488
|
+
converted.components = [...(converted.components || []), ...nestedServices];
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* Convert one 1.x component to the 2.0 component shape
|
|
494
|
+
* (#/$defs/cyclonedx-component-2.0/$defs/component). Fields with no 2.0
|
|
495
|
+
* home (`signature`, the deprecated `modified`, …) are counted.
|
|
496
|
+
*/
|
|
497
|
+
export function convertComponent(component, stats) {
|
|
498
|
+
if (!isObjectRecord(component)) {
|
|
499
|
+
return clone(component);
|
|
500
|
+
}
|
|
501
|
+
// A component read from 2.0 is restored while unchanged.
|
|
502
|
+
const shadow = takeShadow(stats, "component", component);
|
|
503
|
+
if (shadow) {
|
|
504
|
+
return shadow;
|
|
505
|
+
}
|
|
506
|
+
const converted = {};
|
|
507
|
+
if (isNonEmptyString(component["bom-ref"])) {
|
|
508
|
+
converted.refId = component["bom-ref"];
|
|
509
|
+
}
|
|
510
|
+
copyDefined(converted, component, COMPONENT_COPY_FIELDS);
|
|
511
|
+
if (component.pedigree !== undefined) {
|
|
512
|
+
converted.pedigree = convertPedigree(component.pedigree, stats);
|
|
513
|
+
}
|
|
514
|
+
const identities = collectIdentities(component);
|
|
515
|
+
if (identities.length) {
|
|
516
|
+
converted.identifiers = [
|
|
517
|
+
{ party: identifierPartyRefId(stats.claims), identities },
|
|
518
|
+
];
|
|
519
|
+
}
|
|
520
|
+
const parties = collectParties(component, stats);
|
|
521
|
+
if (parties.length) {
|
|
522
|
+
converted.parties = parties;
|
|
523
|
+
}
|
|
524
|
+
const licenses = convertLicenses(component.licenses, stats);
|
|
525
|
+
if (licenses) {
|
|
526
|
+
converted.licenses = licenses;
|
|
527
|
+
}
|
|
528
|
+
convertSharedMembers(component, converted, stats);
|
|
529
|
+
if (isObjectRecord(component.swid)) {
|
|
530
|
+
// 2.0 identifies a SWID tag by its tagId alone.
|
|
531
|
+
countUnmapped(stats, "component.swid", component.swid, SWID_FIELDS);
|
|
532
|
+
}
|
|
533
|
+
convertComponentRenames(component, converted, stats);
|
|
534
|
+
convertComponentDetails(component, converted, stats);
|
|
535
|
+
convertNestedEntries(component, converted, stats);
|
|
536
|
+
countUnmapped(stats, "component", component, COMPONENT_HANDLED_FIELDS);
|
|
537
|
+
return applyHardwareMapping(component, converted, stats);
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* Convert 1.x service data to componentData entries of type `other`. 2.0 has
|
|
542
|
+
* no data flow, source or destination on componentData, so those are
|
|
543
|
+
* counted.
|
|
544
|
+
*/
|
|
545
|
+
function convertServiceData(data, stats) {
|
|
546
|
+
if (!Array.isArray(data)) {
|
|
547
|
+
return undefined;
|
|
548
|
+
}
|
|
549
|
+
const converted = [];
|
|
550
|
+
for (const entry of data) {
|
|
551
|
+
if (!isObjectRecord(entry)) {
|
|
552
|
+
countDrop(stats, "service.data (not an object)");
|
|
553
|
+
continue;
|
|
554
|
+
}
|
|
555
|
+
const item = { type: "other" };
|
|
556
|
+
if (typeof entry.name === "string") {
|
|
557
|
+
item.name = entry.name;
|
|
558
|
+
}
|
|
559
|
+
const classification = toDataClassification(entry.classification);
|
|
560
|
+
if (classification !== undefined) {
|
|
561
|
+
item.classification = classification;
|
|
562
|
+
}
|
|
563
|
+
copyDefined(item, entry, ["sensitiveData", "description"]);
|
|
564
|
+
const governance = convertGovernance(entry.governance, stats);
|
|
565
|
+
if (governance) {
|
|
566
|
+
item.governance = governance;
|
|
567
|
+
}
|
|
568
|
+
countUnmapped(
|
|
569
|
+
stats,
|
|
570
|
+
"service.data",
|
|
571
|
+
entry,
|
|
572
|
+
new Set([
|
|
573
|
+
"name",
|
|
574
|
+
"classification",
|
|
575
|
+
"sensitiveData",
|
|
576
|
+
"description",
|
|
577
|
+
"governance",
|
|
578
|
+
]),
|
|
579
|
+
);
|
|
580
|
+
converted.push(item);
|
|
581
|
+
}
|
|
582
|
+
return converted.length ? converted : undefined;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
/**
|
|
586
|
+
* The cdx:service:* properties that carry a 1.x service's `authenticated`,
|
|
587
|
+
* `x-trust-boundary` and `trustZone` at 2.0, in CARRIED_SERVICE_PROPERTIES
|
|
588
|
+
* order.
|
|
589
|
+
*/
|
|
590
|
+
function carriedServiceProperties(service) {
|
|
591
|
+
const carried = [];
|
|
592
|
+
for (const [field, name] of CARRIED_SERVICE_PROPERTIES) {
|
|
593
|
+
if (service[field] !== undefined && service[field] !== null) {
|
|
594
|
+
carried.push({ name, value: `${service[field]}` });
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
return carried;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
/**
|
|
601
|
+
* Convert one 1.x service into a 2.0 component of type `service`
|
|
602
|
+
* (#/$defs/cyclonedx-component-2.0/$defs/component/properties/type). The
|
|
603
|
+
* provider becomes a party with the `provider` role. `authenticated`,
|
|
604
|
+
* `x-trust-boundary` and `trustZone` have no 2.0 field; they ride as the
|
|
605
|
+
* cdx:service:* properties of CARRIED_SERVICE_PROPERTIES, after the service's
|
|
606
|
+
* own properties, and the reader turns them back into the 1.x fields.
|
|
607
|
+
*/
|
|
608
|
+
export function convertService(service, stats) {
|
|
609
|
+
if (!isObjectRecord(service)) {
|
|
610
|
+
return clone(service);
|
|
611
|
+
}
|
|
612
|
+
const shadow = takeShadow(stats, "component", service);
|
|
613
|
+
if (shadow) {
|
|
614
|
+
return shadow;
|
|
615
|
+
}
|
|
616
|
+
const converted = { type: "service" };
|
|
617
|
+
if (isNonEmptyString(service["bom-ref"])) {
|
|
618
|
+
converted.refId = service["bom-ref"];
|
|
619
|
+
}
|
|
620
|
+
copyDefined(converted, service, SERVICE_COPY_FIELDS);
|
|
621
|
+
const carried = carriedServiceProperties(service);
|
|
622
|
+
if (carried.length) {
|
|
623
|
+
converted.properties = [
|
|
624
|
+
...(Array.isArray(converted.properties) ? converted.properties : []),
|
|
625
|
+
...carried,
|
|
626
|
+
];
|
|
627
|
+
}
|
|
628
|
+
if (service.licenses !== undefined) {
|
|
629
|
+
converted.licenses =
|
|
630
|
+
convertLicenses(service.licenses, stats) ?? converted.licenses;
|
|
631
|
+
}
|
|
632
|
+
convertSharedMembers(service, converted, stats);
|
|
633
|
+
const providers = entityToParties(service.provider, "provider", stats);
|
|
634
|
+
if (providers.length) {
|
|
635
|
+
converted.parties = providers;
|
|
636
|
+
}
|
|
637
|
+
const data = convertServiceData(service.data, stats);
|
|
638
|
+
if (data) {
|
|
639
|
+
converted.data = data;
|
|
640
|
+
}
|
|
641
|
+
const evidence = convertComponentEvidence(service.evidence, stats);
|
|
642
|
+
if (evidence) {
|
|
643
|
+
converted.evidence = evidence;
|
|
644
|
+
}
|
|
645
|
+
if (Array.isArray(service.services)) {
|
|
646
|
+
converted.components = service.services.map((nested) =>
|
|
647
|
+
convertService(nested, stats),
|
|
648
|
+
);
|
|
649
|
+
}
|
|
650
|
+
countUnmapped(stats, "service", service, SERVICE_HANDLED_FIELDS);
|
|
651
|
+
return converted;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
/**
|
|
655
|
+
* Convert a legacy 1.5 `metadata.tools` array of {vendor, name, version,
|
|
656
|
+
* hashes, externalReferences} into components of type `application`, the way
|
|
657
|
+
* specVersionCompat maps `vendor` to `publisher`.
|
|
658
|
+
*/
|
|
659
|
+
function convertLegacyTools(tools, stats) {
|
|
660
|
+
const components = [];
|
|
661
|
+
for (const tool of tools) {
|
|
662
|
+
if (!isObjectRecord(tool) || !isNonEmptyString(tool.name)) {
|
|
663
|
+
countDrop(stats, "metadata.tools (legacy entry without a name)");
|
|
664
|
+
continue;
|
|
665
|
+
}
|
|
666
|
+
const asComponent = { type: "application", name: tool.name };
|
|
667
|
+
if (isNonEmptyString(tool["bom-ref"])) {
|
|
668
|
+
asComponent["bom-ref"] = tool["bom-ref"];
|
|
669
|
+
}
|
|
670
|
+
copyDefined(asComponent, tool, ["version", "hashes", "externalReferences"]);
|
|
671
|
+
if (isNonEmptyString(tool.vendor)) {
|
|
672
|
+
asComponent.publisher = tool.vendor;
|
|
673
|
+
}
|
|
674
|
+
countUnmapped(
|
|
675
|
+
stats,
|
|
676
|
+
"metadata.tools",
|
|
677
|
+
tool,
|
|
678
|
+
new Set([
|
|
679
|
+
"bom-ref",
|
|
680
|
+
"vendor",
|
|
681
|
+
"name",
|
|
682
|
+
"version",
|
|
683
|
+
"hashes",
|
|
684
|
+
"externalReferences",
|
|
685
|
+
]),
|
|
686
|
+
);
|
|
687
|
+
components.push(convertComponent(asComponent, stats));
|
|
688
|
+
}
|
|
689
|
+
return components.length ? { components } : undefined;
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
/**
|
|
693
|
+
* Convert metadata.tools: the 1.x {components, services} object, or the
|
|
694
|
+
* legacy 1.5 array. 2.0 tools hold only `components`
|
|
695
|
+
* (#/$defs/cyclonedx-metadata-2.0/$defs/metadata/properties/tools).
|
|
696
|
+
*/
|
|
697
|
+
export function convertTools(tools, stats) {
|
|
698
|
+
if (Array.isArray(tools)) {
|
|
699
|
+
return convertLegacyTools(tools, stats);
|
|
700
|
+
}
|
|
701
|
+
if (!isObjectRecord(tools)) {
|
|
702
|
+
if (tools !== undefined) {
|
|
703
|
+
countDrop(stats, "metadata.tools");
|
|
704
|
+
}
|
|
705
|
+
return undefined;
|
|
706
|
+
}
|
|
707
|
+
const components = [];
|
|
708
|
+
if (Array.isArray(tools.components)) {
|
|
709
|
+
components.push(...tools.components.map((c) => convertComponent(c, stats)));
|
|
710
|
+
}
|
|
711
|
+
if (Array.isArray(tools.services)) {
|
|
712
|
+
components.push(...tools.services.map((s) => convertService(s, stats)));
|
|
713
|
+
}
|
|
714
|
+
countUnmapped(stats, "tools", tools, new Set(["components", "services"]));
|
|
715
|
+
return components.length ? { components } : undefined;
|
|
716
|
+
}
|