@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,726 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Render-side conversion of 1.x component evidence and cryptoProperties to
|
|
3
|
+
* the CycloneDX 2.0 shapes (#/$defs/cyclonedx-component-2.0/$defs/componentEvidence,
|
|
4
|
+
* #/$defs/cyclonedx-cryptography-2.0/$defs/cryptoProperties).
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { thoughtLog } from "../core/logger.js";
|
|
8
|
+
import { collectToolBomRefs } from "./citations.js";
|
|
9
|
+
import {
|
|
10
|
+
clone,
|
|
11
|
+
copyDefined,
|
|
12
|
+
countDrop,
|
|
13
|
+
countRewrite,
|
|
14
|
+
countUnmapped,
|
|
15
|
+
isNonEmptyString,
|
|
16
|
+
isObjectRecord,
|
|
17
|
+
peekShadow,
|
|
18
|
+
} from "./cyclonedx20Common.js";
|
|
19
|
+
import {
|
|
20
|
+
ALGORITHM_FAMILY_ENUM,
|
|
21
|
+
ANALYSIS_TECHNIQUE_ENUM,
|
|
22
|
+
CDXGEN_PARTY_REF_ID,
|
|
23
|
+
FORBIDDEN_IDENTITY_TECHNIQUES,
|
|
24
|
+
IDENTITY_SCHEME_ENUM,
|
|
25
|
+
LICENSE_EVIDENCE_DETAIL_FIELDS,
|
|
26
|
+
PROTOCOL_FAMILY_ENUM,
|
|
27
|
+
} from "./cyclonedx20Tables.js";
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Convert 1.x `evidence.identity[].field` into the 2.0 `scheme`
|
|
31
|
+
* (#/$defs/cyclonedx-component-2.0/$defs/identityScheme). Predefined schemes
|
|
32
|
+
* pass through; anything else uses the custom `{name}` branch when it
|
|
33
|
+
* validates, and is counted for the report either way.
|
|
34
|
+
*/
|
|
35
|
+
function toIdentityScheme(field, stats) {
|
|
36
|
+
if (typeof field !== "string" || field.length === 0) {
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
if (IDENTITY_SCHEME_ENUM.has(field)) {
|
|
40
|
+
return field;
|
|
41
|
+
}
|
|
42
|
+
stats.customSchemes.add(field);
|
|
43
|
+
// identityScheme oneOf: predefined enum or a custom object with a name.
|
|
44
|
+
return { name: field };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Convert one identity-evidence method to the 2.0 identificationMethod shape.
|
|
49
|
+
* analysisMethod requires `[technique, confidence]`; a method without its own
|
|
50
|
+
* confidence inherits the identity entry's, and one with neither is dropped
|
|
51
|
+
* (never given an invented number).
|
|
52
|
+
*/
|
|
53
|
+
function convertIdentityMethod(method, identityConfidence, attributed, stats) {
|
|
54
|
+
if (!isObjectRecord(method)) {
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
let technique = method.technique;
|
|
58
|
+
if (technique === "other") {
|
|
59
|
+
technique = "unknown";
|
|
60
|
+
}
|
|
61
|
+
let reason;
|
|
62
|
+
if (!ANALYSIS_TECHNIQUE_ENUM.has(technique)) {
|
|
63
|
+
reason = "technique not in the 2.0 analysisTechnique enum";
|
|
64
|
+
} else if (FORBIDDEN_IDENTITY_TECHNIQUES.has(technique)) {
|
|
65
|
+
reason = "technique forbidden for identificationMethod";
|
|
66
|
+
}
|
|
67
|
+
const confidence =
|
|
68
|
+
typeof method.confidence === "number"
|
|
69
|
+
? method.confidence
|
|
70
|
+
: typeof identityConfidence === "number"
|
|
71
|
+
? identityConfidence
|
|
72
|
+
: undefined;
|
|
73
|
+
if (!reason && confidence === undefined) {
|
|
74
|
+
reason = "method has no confidence and the identity entry has none";
|
|
75
|
+
}
|
|
76
|
+
if (reason) {
|
|
77
|
+
stats.droppedMethods.push({ reason, technique: method.technique });
|
|
78
|
+
countDrop(stats, "evidence.identity.methods");
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
const converted = { technique, confidence };
|
|
82
|
+
if (typeof method.value === "string") {
|
|
83
|
+
converted.value = method.value;
|
|
84
|
+
if (attributed) {
|
|
85
|
+
// A method of cdxgen's own analysis that names its matched value found
|
|
86
|
+
// the subject (#/$defs/cyclonedx-evidence-2.0/$defs/analysisResult:
|
|
87
|
+
// "detected"). For another tool's entry the result is not cdxgen's to
|
|
88
|
+
// claim.
|
|
89
|
+
converted.result = "detected";
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (typeof method.description === "string") {
|
|
93
|
+
converted.description = method.description;
|
|
94
|
+
}
|
|
95
|
+
return converted;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* The refId prefix of the party derived for a tool other than cdxgen. Any
|
|
100
|
+
* refId that starts with it is a valid refIdType
|
|
101
|
+
* (#/$defs/cyclonedx-common-2.0/$defs/refIdType: non-empty and not starting
|
|
102
|
+
* with the BOM-Link intro `urn:cdx:`), whatever the tool's own refId is, so
|
|
103
|
+
* the tool refId is appended unchanged and the party refId stays readable and
|
|
104
|
+
* deterministic.
|
|
105
|
+
*/
|
|
106
|
+
export const TOOL_PARTY_REF_ID_PREFIX = "party-tool-";
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* What the claims cdxgen writes at 2.0 are attributed with (#4591). cdxgen
|
|
110
|
+
* claims only analysis it did:
|
|
111
|
+
*
|
|
112
|
+
* - `toolRefId` is the refId of the cdxgen tool component, present only when
|
|
113
|
+
* the BOM's `metadata.tools` lists cdxgen with a `bom-ref` (the tool named
|
|
114
|
+
* "cdxgen", the same match findCdxgenToolBomRef in
|
|
115
|
+
* lib/inventory/citations.js makes). Identity evidence carries cdxgen's
|
|
116
|
+
* assertion, its tool and method results only when this is set.
|
|
117
|
+
* - `assertingTool` is set only without `toolRefId`: the first other tool
|
|
118
|
+
* component with a `bom-ref` (`{refId, toolRefId, label?}`), whose party
|
|
119
|
+
* asserts the component identifiers (`identifiers[].party` is required).
|
|
120
|
+
* With neither, cdxgen, as the converting tool, asserts the identifiers it
|
|
121
|
+
* wrote.
|
|
122
|
+
* - `timestamp` is the BOM timestamp when it has one.
|
|
123
|
+
*
|
|
124
|
+
* Nothing is invented: absent members stay absent.
|
|
125
|
+
*
|
|
126
|
+
* @param {object} bom BOM in the 1.x shape (only `metadata` is read)
|
|
127
|
+
* @returns {{toolRefId?: string, assertingTool?: {refId: string, toolRefId: string, label?: string}, timestamp?: string}} Claim context
|
|
128
|
+
*/
|
|
129
|
+
export function identityClaimContext(bom) {
|
|
130
|
+
const toolRefs = new Set(collectToolBomRefs(bom));
|
|
131
|
+
const tools = bom?.metadata?.tools;
|
|
132
|
+
const candidates = Array.isArray(tools) ? tools : tools?.components || [];
|
|
133
|
+
const declaredTools = candidates.filter(
|
|
134
|
+
(tool) =>
|
|
135
|
+
isObjectRecord(tool) &&
|
|
136
|
+
isNonEmptyString(tool["bom-ref"]) &&
|
|
137
|
+
toolRefs.has(tool["bom-ref"]),
|
|
138
|
+
);
|
|
139
|
+
const cdxgenTool = declaredTools.find((tool) => tool.name === "cdxgen");
|
|
140
|
+
const claims = {};
|
|
141
|
+
if (cdxgenTool) {
|
|
142
|
+
claims.toolRefId = cdxgenTool["bom-ref"];
|
|
143
|
+
} else {
|
|
144
|
+
const otherTool = declaredTools.find((tool) => tool.name !== "cdxgen");
|
|
145
|
+
if (otherTool) {
|
|
146
|
+
claims.assertingTool = {
|
|
147
|
+
refId: `${TOOL_PARTY_REF_ID_PREFIX}${otherTool["bom-ref"]}`,
|
|
148
|
+
toolRefId: otherTool["bom-ref"],
|
|
149
|
+
};
|
|
150
|
+
if (isNonEmptyString(otherTool.name)) {
|
|
151
|
+
claims.assertingTool.label = otherTool.name;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (isNonEmptyString(bom?.metadata?.timestamp)) {
|
|
156
|
+
claims.timestamp = bom.metadata.timestamp;
|
|
157
|
+
}
|
|
158
|
+
return claims;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* The refId of the party asserting the component identifiers: the cdxgen
|
|
163
|
+
* party when cdxgen is the listed tool or no tool is listed, else the party
|
|
164
|
+
* of the first other listed tool (see identityClaimContext).
|
|
165
|
+
*
|
|
166
|
+
* @param {object} claims Claim context from identityClaimContext
|
|
167
|
+
* @returns {string} Party refId
|
|
168
|
+
*/
|
|
169
|
+
export function identifierPartyRefId(claims) {
|
|
170
|
+
return claims?.assertingTool?.refId || CDXGEN_PARTY_REF_ID;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* The parties the renderer derives from the claim context, in the order it
|
|
175
|
+
* appends them: the cdxgen party, then the asserting tool's party when there
|
|
176
|
+
* is one. Each is a party (#/$defs/cyclonedx-party-2.0/$defs/party) with the
|
|
177
|
+
* `asserter` role and a system identity
|
|
178
|
+
* (#/$defs/cyclonedx-party-2.0/$defs/system, kind `automation`) whose `ref`
|
|
179
|
+
* names the tool component only when that refId is declared. The renderer
|
|
180
|
+
* declares one only when the document references it; the reader drops one
|
|
181
|
+
* that matches exactly, since the render derives it again.
|
|
182
|
+
*
|
|
183
|
+
* @param {object} claims Claim context from identityClaimContext
|
|
184
|
+
* @param {Set<string>} declared refIds declared in the document
|
|
185
|
+
* @returns {object[]} Party declarations
|
|
186
|
+
*/
|
|
187
|
+
export function derivedPartyDeclarations(claims, declared) {
|
|
188
|
+
const cdxgenSystem = { kind: "automation", label: "cdxgen" };
|
|
189
|
+
if (claims?.toolRefId && declared.has(claims.toolRefId)) {
|
|
190
|
+
cdxgenSystem.ref = claims.toolRefId;
|
|
191
|
+
}
|
|
192
|
+
const parties = [
|
|
193
|
+
{
|
|
194
|
+
refId: CDXGEN_PARTY_REF_ID,
|
|
195
|
+
roles: [{ role: "asserter" }],
|
|
196
|
+
system: cdxgenSystem,
|
|
197
|
+
},
|
|
198
|
+
];
|
|
199
|
+
const tool = claims?.assertingTool;
|
|
200
|
+
if (tool) {
|
|
201
|
+
const system = { kind: "automation" };
|
|
202
|
+
if (tool.label) {
|
|
203
|
+
system.label = tool.label;
|
|
204
|
+
}
|
|
205
|
+
if (declared.has(tool.toolRefId)) {
|
|
206
|
+
system.ref = tool.toolRefId;
|
|
207
|
+
}
|
|
208
|
+
parties.push({ refId: tool.refId, roles: [{ role: "asserter" }], system });
|
|
209
|
+
}
|
|
210
|
+
return parties;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Convert one 1.x identity entry to componentIdentityEvidence
|
|
215
|
+
* (#/$defs/cyclonedx-component-2.0/$defs/componentIdentityEvidence). When
|
|
216
|
+
* cdxgen is the listed tool (#4591), the entry is cdxgen's attributed claim:
|
|
217
|
+
* `tools` names the helper recorded on the entry or, failing that, the cdxgen
|
|
218
|
+
* tool; `assertion` credits the cdxgen party as asserter
|
|
219
|
+
* (#/$defs/cyclonedx-evidence-2.0/$defs/assertion); and a method with a
|
|
220
|
+
* matched value has the result `detected`. For another tool's BOM cdxgen did
|
|
221
|
+
* not do that analysis, so none of these is added; the entry's own `tools`
|
|
222
|
+
* are kept. `timestamp` is the BOM's own when it has one.
|
|
223
|
+
*
|
|
224
|
+
* @param {object} entry 1.x identity evidence entry
|
|
225
|
+
* @param {object} stats Render counters from createRenderStats
|
|
226
|
+
* @returns {object|undefined} The 2.0 entry, or undefined without a field
|
|
227
|
+
*/
|
|
228
|
+
export function convertIdentityEntry(entry, stats) {
|
|
229
|
+
if (!isObjectRecord(entry)) {
|
|
230
|
+
return undefined;
|
|
231
|
+
}
|
|
232
|
+
const scheme = toIdentityScheme(entry.field, stats);
|
|
233
|
+
if (scheme === undefined) {
|
|
234
|
+
countDrop(stats, "evidence.identity (no field)");
|
|
235
|
+
return undefined;
|
|
236
|
+
}
|
|
237
|
+
const attributed = isNonEmptyString(stats.claims.toolRefId);
|
|
238
|
+
const converted = { scheme };
|
|
239
|
+
if (typeof entry.concludedValue === "string") {
|
|
240
|
+
converted.concludedValue = entry.concludedValue;
|
|
241
|
+
}
|
|
242
|
+
if (typeof entry.confidence === "number") {
|
|
243
|
+
converted.confidence = entry.confidence;
|
|
244
|
+
}
|
|
245
|
+
if (Array.isArray(entry.methods)) {
|
|
246
|
+
const methods = entry.methods
|
|
247
|
+
.map((method) =>
|
|
248
|
+
convertIdentityMethod(method, entry.confidence, attributed, stats),
|
|
249
|
+
)
|
|
250
|
+
.filter(Boolean);
|
|
251
|
+
if (methods.length) {
|
|
252
|
+
converted.methods = methods;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
if (Array.isArray(entry.tools) && entry.tools.length) {
|
|
256
|
+
converted.tools = clone(entry.tools);
|
|
257
|
+
} else if (attributed) {
|
|
258
|
+
converted.tools = [stats.claims.toolRefId];
|
|
259
|
+
}
|
|
260
|
+
if (attributed) {
|
|
261
|
+
converted.assertion = {
|
|
262
|
+
parties: [
|
|
263
|
+
{ party: { ref: CDXGEN_PARTY_REF_ID }, role: { role: "asserter" } },
|
|
264
|
+
],
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
if (isNonEmptyString(stats.claims.timestamp)) {
|
|
268
|
+
converted.timestamp = stats.claims.timestamp;
|
|
269
|
+
}
|
|
270
|
+
return converted;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Convert 1.x `evidence.identity` (an array or a single 1.5 object). An
|
|
275
|
+
* entry read from 2.0 whose 1.x projection is unchanged gets its 2.0
|
|
276
|
+
* original back (a foreign assertion stays the foreign party's); an edited
|
|
277
|
+
* one renders from the 1.x model.
|
|
278
|
+
*/
|
|
279
|
+
function convertIdentityEvidence(identity, stats) {
|
|
280
|
+
const identities = [];
|
|
281
|
+
for (const entry of Array.isArray(identity) ? identity : [identity]) {
|
|
282
|
+
const converted =
|
|
283
|
+
peekShadow(stats, "identity", entry) ??
|
|
284
|
+
convertIdentityEntry(entry, stats);
|
|
285
|
+
if (converted) {
|
|
286
|
+
identities.push(converted);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
return identities;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Convert occurrences
|
|
294
|
+
* (#/$defs/cyclonedx-evidence-2.0/$defs/occurrence, required `[location]`):
|
|
295
|
+
* the 1.x `bom-ref` becomes `refId`, every other 1.x field keeps its name.
|
|
296
|
+
*/
|
|
297
|
+
function convertOccurrences(occurrences, stats) {
|
|
298
|
+
const converted = [];
|
|
299
|
+
for (const occurrence of occurrences) {
|
|
300
|
+
if (!isObjectRecord(occurrence) || !isNonEmptyString(occurrence.location)) {
|
|
301
|
+
countDrop(stats, "evidence.occurrences (no location)");
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
const entry = clone(occurrence);
|
|
305
|
+
if (entry["bom-ref"] !== undefined) {
|
|
306
|
+
if (isNonEmptyString(entry["bom-ref"])) {
|
|
307
|
+
entry.refId = entry["bom-ref"];
|
|
308
|
+
}
|
|
309
|
+
delete entry["bom-ref"];
|
|
310
|
+
}
|
|
311
|
+
converted.push(entry);
|
|
312
|
+
}
|
|
313
|
+
return converted;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Convert 1.x call stacks: the `callstack` object (or an array of them)
|
|
318
|
+
* becomes the `callStacks` array, and frames need `module`
|
|
319
|
+
* (#/$defs/cyclonedx-evidence-2.0/$defs/frame, required `[module]`).
|
|
320
|
+
*/
|
|
321
|
+
function convertCallStacks(callstack, stats) {
|
|
322
|
+
const callStacks = [];
|
|
323
|
+
for (const entry of Array.isArray(callstack) ? callstack : [callstack]) {
|
|
324
|
+
if (!isObjectRecord(entry)) {
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
327
|
+
const frames = [];
|
|
328
|
+
for (const frame of entry.frames || []) {
|
|
329
|
+
if (isObjectRecord(frame) && typeof frame.module === "string") {
|
|
330
|
+
frames.push(clone(frame));
|
|
331
|
+
} else {
|
|
332
|
+
countDrop(stats, "evidence.callstack.frames (no module)");
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
if (frames.length) {
|
|
336
|
+
callStacks.push({ frames });
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
return callStacks;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/** Carry the licenseEvidence details; a 1.x `bom-ref` becomes `refId`. */
|
|
343
|
+
function withLicenseEvidenceDetails(entry, choice, stats) {
|
|
344
|
+
const converted = { ...entry };
|
|
345
|
+
if (isNonEmptyString(choice["bom-ref"]) && choice.refId === undefined) {
|
|
346
|
+
converted.refId = choice["bom-ref"];
|
|
347
|
+
}
|
|
348
|
+
copyDefined(converted, choice, LICENSE_EVIDENCE_DETAIL_FIELDS);
|
|
349
|
+
countUnmapped(
|
|
350
|
+
stats,
|
|
351
|
+
"evidence.licenses",
|
|
352
|
+
choice,
|
|
353
|
+
new Set([
|
|
354
|
+
"license",
|
|
355
|
+
"expression",
|
|
356
|
+
"bom-ref",
|
|
357
|
+
...LICENSE_EVIDENCE_DETAIL_FIELDS,
|
|
358
|
+
]),
|
|
359
|
+
);
|
|
360
|
+
return converted;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Convert evidence licenses to licenseEvidence
|
|
365
|
+
* (#/$defs/cyclonedx-component-2.0/$defs/licenseEvidence): a license may
|
|
366
|
+
* carry only `id` or `name`, or the entry is an `expression`.
|
|
367
|
+
*/
|
|
368
|
+
function convertEvidenceLicenses(licenses, stats) {
|
|
369
|
+
const converted = [];
|
|
370
|
+
for (const choice of licenses) {
|
|
371
|
+
if (isObjectRecord(choice?.license)) {
|
|
372
|
+
const { id, name } = choice.license;
|
|
373
|
+
const license = isNonEmptyString(id)
|
|
374
|
+
? { id }
|
|
375
|
+
: isNonEmptyString(name)
|
|
376
|
+
? { name }
|
|
377
|
+
: undefined;
|
|
378
|
+
if (!license) {
|
|
379
|
+
countDrop(stats, "evidence.licenses (no id or name)");
|
|
380
|
+
continue;
|
|
381
|
+
}
|
|
382
|
+
for (const key of Object.keys(choice.license)) {
|
|
383
|
+
if (!Object.hasOwn(license, key)) {
|
|
384
|
+
countDrop(stats, `evidence.licenses.license.${key}`);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
converted.push(withLicenseEvidenceDetails({ license }, choice, stats));
|
|
388
|
+
} else if (isNonEmptyString(choice?.expression)) {
|
|
389
|
+
converted.push(
|
|
390
|
+
withLicenseEvidenceDetails(
|
|
391
|
+
{ expression: choice.expression },
|
|
392
|
+
choice,
|
|
393
|
+
stats,
|
|
394
|
+
),
|
|
395
|
+
);
|
|
396
|
+
} else {
|
|
397
|
+
countDrop(stats, "evidence.licenses (not a license or expression)");
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
return converted;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Convert component evidence
|
|
405
|
+
* (#/$defs/cyclonedx-component-2.0/$defs/componentEvidence). The 1.x
|
|
406
|
+
* `callstack` object becomes the `callStacks` array; identity `field` becomes
|
|
407
|
+
* `scheme`. Every nested object is cloned, so nothing is shared with the
|
|
408
|
+
* input.
|
|
409
|
+
*/
|
|
410
|
+
export function convertComponentEvidence(evidence, stats) {
|
|
411
|
+
if (!isObjectRecord(evidence)) {
|
|
412
|
+
return undefined;
|
|
413
|
+
}
|
|
414
|
+
const converted = {};
|
|
415
|
+
if (evidence.identity !== undefined) {
|
|
416
|
+
const identities = convertIdentityEvidence(evidence.identity, stats);
|
|
417
|
+
if (identities.length) {
|
|
418
|
+
converted.identity = identities;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
if (Array.isArray(evidence.occurrences)) {
|
|
422
|
+
const occurrences = convertOccurrences(evidence.occurrences, stats);
|
|
423
|
+
if (occurrences.length) {
|
|
424
|
+
converted.occurrences = occurrences;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
if (evidence.callstack !== undefined) {
|
|
428
|
+
const callStacks = convertCallStacks(evidence.callstack, stats);
|
|
429
|
+
if (callStacks.length) {
|
|
430
|
+
converted.callStacks = callStacks;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
if (Array.isArray(evidence.licenses) && evidence.licenses.length) {
|
|
434
|
+
const licenses = convertEvidenceLicenses(evidence.licenses, stats);
|
|
435
|
+
if (licenses.length) {
|
|
436
|
+
converted.licenses = licenses;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
if (Array.isArray(evidence.copyright) && evidence.copyright.length) {
|
|
440
|
+
// copyrightEvidence requires `text`; drop entries without it.
|
|
441
|
+
const copyright = [];
|
|
442
|
+
for (const entry of evidence.copyright) {
|
|
443
|
+
if (isObjectRecord(entry) && typeof entry.text === "string") {
|
|
444
|
+
copyright.push(clone(entry));
|
|
445
|
+
} else {
|
|
446
|
+
countDrop(stats, "evidence.copyright (no text)");
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
if (copyright.length) {
|
|
450
|
+
converted.copyright = copyright;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
countUnmapped(
|
|
454
|
+
stats,
|
|
455
|
+
"evidence",
|
|
456
|
+
evidence,
|
|
457
|
+
new Set(["identity", "occurrences", "callstack", "licenses", "copyright"]),
|
|
458
|
+
);
|
|
459
|
+
return Object.keys(converted).length ? converted : undefined;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
// Members of each 2.0 cryptoProperties object
|
|
463
|
+
// (#/$defs/cyclonedx-cryptography-2.0/$defs/cryptoProperties); a 1.x member
|
|
464
|
+
// outside these that no conversion below maps is counted.
|
|
465
|
+
const CRYPTO_MEMBERS_20 = Object.freeze({
|
|
466
|
+
cryptoProperties: new Set([
|
|
467
|
+
"assetType",
|
|
468
|
+
"algorithmProperties",
|
|
469
|
+
"certificateProperties",
|
|
470
|
+
"relatedCryptoMaterialProperties",
|
|
471
|
+
"protocolProperties",
|
|
472
|
+
"oid",
|
|
473
|
+
]),
|
|
474
|
+
algorithmProperties: new Set([
|
|
475
|
+
"primitive",
|
|
476
|
+
"algorithmFamily",
|
|
477
|
+
"parameterSetIdentifier",
|
|
478
|
+
"ellipticCurve",
|
|
479
|
+
"executionEnvironment",
|
|
480
|
+
"implementationPlatform",
|
|
481
|
+
"mode",
|
|
482
|
+
"padding",
|
|
483
|
+
"cryptoFunctions",
|
|
484
|
+
"classicalSecurityLevel",
|
|
485
|
+
"nistQuantumSecurityLevel",
|
|
486
|
+
"secProperties",
|
|
487
|
+
]),
|
|
488
|
+
certificateProperties: new Set([
|
|
489
|
+
"serialNumber",
|
|
490
|
+
"subjectName",
|
|
491
|
+
"issuerName",
|
|
492
|
+
"notValidBefore",
|
|
493
|
+
"notValidAfter",
|
|
494
|
+
"certificateFormat",
|
|
495
|
+
"certificateFileExtension",
|
|
496
|
+
"fingerprint",
|
|
497
|
+
"certificateState",
|
|
498
|
+
"creationDate",
|
|
499
|
+
"activationDate",
|
|
500
|
+
"deactivationDate",
|
|
501
|
+
"revocationDate",
|
|
502
|
+
"destructionDate",
|
|
503
|
+
"renewal",
|
|
504
|
+
"certificateExtensions",
|
|
505
|
+
"relatedCryptographicAssets",
|
|
506
|
+
]),
|
|
507
|
+
relatedCryptoMaterialProperties: new Set([
|
|
508
|
+
"type",
|
|
509
|
+
"id",
|
|
510
|
+
"state",
|
|
511
|
+
"rotation",
|
|
512
|
+
"creationDate",
|
|
513
|
+
"activationDate",
|
|
514
|
+
"updateDate",
|
|
515
|
+
"expirationDate",
|
|
516
|
+
"value",
|
|
517
|
+
"size",
|
|
518
|
+
"format",
|
|
519
|
+
"securedBy",
|
|
520
|
+
"fingerprint",
|
|
521
|
+
"relatedCryptographicAssets",
|
|
522
|
+
"keyUsage",
|
|
523
|
+
]),
|
|
524
|
+
protocolProperties: new Set([
|
|
525
|
+
"type",
|
|
526
|
+
"version",
|
|
527
|
+
"cipherSuites",
|
|
528
|
+
"ikev2TransformTypes",
|
|
529
|
+
"relatedCryptographicAssets",
|
|
530
|
+
]),
|
|
531
|
+
});
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
* Move deprecated 1.x reference members into `relatedCryptographicAssets`
|
|
535
|
+
* (#/$defs/cyclonedx-cryptography-2.0/$defs/relatedCryptographicAsset), the
|
|
536
|
+
* list 1.7 names as their replacement. Each entry is [1.x member, asset
|
|
537
|
+
* type]; a member may hold one refType or a list of them. A reference the
|
|
538
|
+
* list already has is not repeated.
|
|
539
|
+
*/
|
|
540
|
+
function moveToRelatedAssets(properties, members, label, stats) {
|
|
541
|
+
for (const [member, type] of members) {
|
|
542
|
+
if (properties[member] === undefined) {
|
|
543
|
+
continue;
|
|
544
|
+
}
|
|
545
|
+
const refs = [].concat(properties[member]);
|
|
546
|
+
delete properties[member];
|
|
547
|
+
const related = Array.isArray(properties.relatedCryptographicAssets)
|
|
548
|
+
? properties.relatedCryptographicAssets
|
|
549
|
+
: [];
|
|
550
|
+
for (const ref of refs) {
|
|
551
|
+
if (!isNonEmptyString(ref)) {
|
|
552
|
+
countDrop(stats, `${label}.${member} (not a reference)`);
|
|
553
|
+
continue;
|
|
554
|
+
}
|
|
555
|
+
if (!related.some((asset) => asset?.ref === ref)) {
|
|
556
|
+
related.push({ type, ref });
|
|
557
|
+
}
|
|
558
|
+
countRewrite(
|
|
559
|
+
stats,
|
|
560
|
+
`${label}.${member} (moved to relatedCryptographicAssets)`,
|
|
561
|
+
);
|
|
562
|
+
}
|
|
563
|
+
if (related.length) {
|
|
564
|
+
properties.relatedCryptographicAssets = related;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
/** Remove and count the members of `properties` 2.0 has no field for. */
|
|
570
|
+
function dropUnmapped(properties, kind, label, stats) {
|
|
571
|
+
for (const key of Object.keys(properties)) {
|
|
572
|
+
if (!CRYPTO_MEMBERS_20[kind].has(key)) {
|
|
573
|
+
if (properties[key] !== undefined) {
|
|
574
|
+
countDrop(stats, `${label}.${key}`);
|
|
575
|
+
}
|
|
576
|
+
delete properties[key];
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
/** algorithmProperties: enum and list-shape differences. */
|
|
582
|
+
function convertAlgorithmProperties(algorithmProperties, stats) {
|
|
583
|
+
if (algorithmProperties.curve !== undefined) {
|
|
584
|
+
countDrop(stats, "cryptoProperties.algorithmProperties.curve");
|
|
585
|
+
delete algorithmProperties.curve;
|
|
586
|
+
}
|
|
587
|
+
if (
|
|
588
|
+
algorithmProperties.algorithmFamily !== undefined &&
|
|
589
|
+
!ALGORITHM_FAMILY_ENUM.has(algorithmProperties.algorithmFamily)
|
|
590
|
+
) {
|
|
591
|
+
countDrop(stats, "cryptoProperties.algorithmProperties.algorithmFamily");
|
|
592
|
+
thoughtLog(
|
|
593
|
+
`CycloneDX 2.0 render dropped the algorithm family '${algorithmProperties.algorithmFamily}', which the pinned 2.0 cryptography defs do not list.`,
|
|
594
|
+
);
|
|
595
|
+
delete algorithmProperties.algorithmFamily;
|
|
596
|
+
}
|
|
597
|
+
// algorithmProperties.implementationPlatform and cryptoFunctions are
|
|
598
|
+
// arrays at 2.0; tolerate a 1.x emitter that wrote a plain string.
|
|
599
|
+
for (const listField of ["implementationPlatform", "cryptoFunctions"]) {
|
|
600
|
+
if (typeof algorithmProperties[listField] === "string") {
|
|
601
|
+
algorithmProperties[listField] = [algorithmProperties[listField]];
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
dropUnmapped(
|
|
605
|
+
algorithmProperties,
|
|
606
|
+
"algorithmProperties",
|
|
607
|
+
"cryptoProperties.algorithmProperties",
|
|
608
|
+
stats,
|
|
609
|
+
);
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
/**
|
|
613
|
+
* certificateProperties: the deprecated signature algorithm and subject
|
|
614
|
+
* public key references become related assets, and the deprecated
|
|
615
|
+
* `certificateExtension` (the file extension) becomes
|
|
616
|
+
* `certificateFileExtension` unless that is set already.
|
|
617
|
+
*/
|
|
618
|
+
function convertCertificateProperties(certificateProperties, stats) {
|
|
619
|
+
const label = "cryptoProperties.certificateProperties";
|
|
620
|
+
moveToRelatedAssets(
|
|
621
|
+
certificateProperties,
|
|
622
|
+
[
|
|
623
|
+
["signatureAlgorithmRef", "algorithm"],
|
|
624
|
+
["subjectPublicKeyRef", "publicKey"],
|
|
625
|
+
],
|
|
626
|
+
label,
|
|
627
|
+
stats,
|
|
628
|
+
);
|
|
629
|
+
const extension = certificateProperties.certificateExtension;
|
|
630
|
+
if (extension !== undefined) {
|
|
631
|
+
delete certificateProperties.certificateExtension;
|
|
632
|
+
if (certificateProperties.certificateFileExtension === undefined) {
|
|
633
|
+
certificateProperties.certificateFileExtension = extension;
|
|
634
|
+
countRewrite(
|
|
635
|
+
stats,
|
|
636
|
+
`${label}.certificateExtension (renamed certificateFileExtension)`,
|
|
637
|
+
);
|
|
638
|
+
} else if (certificateProperties.certificateFileExtension !== extension) {
|
|
639
|
+
countDrop(stats, `${label}.certificateExtension`);
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
dropUnmapped(certificateProperties, "certificateProperties", label, stats);
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
/**
|
|
646
|
+
* relatedCryptoMaterialProperties: the 1.7 securedBy.algorithmRef is one
|
|
647
|
+
* refType and a 2.0 list; the deprecated `algorithmRef` (the algorithm that
|
|
648
|
+
* generated the material) becomes a related asset, as 1.7 directs.
|
|
649
|
+
*/
|
|
650
|
+
function convertRelatedMaterialProperties(related, stats) {
|
|
651
|
+
const label = "cryptoProperties.relatedCryptoMaterialProperties";
|
|
652
|
+
if (
|
|
653
|
+
isObjectRecord(related.securedBy) &&
|
|
654
|
+
typeof related.securedBy.algorithmRef === "string"
|
|
655
|
+
) {
|
|
656
|
+
related.securedBy.algorithmRef = [related.securedBy.algorithmRef];
|
|
657
|
+
}
|
|
658
|
+
moveToRelatedAssets(related, [["algorithmRef", "algorithm"]], label, stats);
|
|
659
|
+
dropUnmapped(related, "relatedCryptoMaterialProperties", label, stats);
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
/**
|
|
663
|
+
* protocolProperties: protocol types outside the pinned 2.0 enum are
|
|
664
|
+
* dropped, and the deprecated `cryptoRefArray` becomes related assets.
|
|
665
|
+
*/
|
|
666
|
+
function convertProtocolProperties(protocolProperties, stats) {
|
|
667
|
+
const label = "cryptoProperties.protocolProperties";
|
|
668
|
+
if (
|
|
669
|
+
protocolProperties.type !== undefined &&
|
|
670
|
+
!PROTOCOL_FAMILY_ENUM.has(protocolProperties.type)
|
|
671
|
+
) {
|
|
672
|
+
delete protocolProperties.type;
|
|
673
|
+
countDrop(stats, `${label}.type`);
|
|
674
|
+
}
|
|
675
|
+
moveToRelatedAssets(
|
|
676
|
+
protocolProperties,
|
|
677
|
+
[["cryptoRefArray", "algorithm"]],
|
|
678
|
+
label,
|
|
679
|
+
stats,
|
|
680
|
+
);
|
|
681
|
+
// 1.7 still accepts the deprecated reference arrays as IKEv2 transform
|
|
682
|
+
// lists; a 2.0 transform holds the reference as its `algorithm`.
|
|
683
|
+
const transforms = protocolProperties.ikev2TransformTypes;
|
|
684
|
+
for (const transform of ["encr", "prf", "integ", "ke", "auth"]) {
|
|
685
|
+
if (Array.isArray(transforms?.[transform])) {
|
|
686
|
+
transforms[transform] = transforms[transform].map((entry) => {
|
|
687
|
+
if (typeof entry !== "string") {
|
|
688
|
+
return entry;
|
|
689
|
+
}
|
|
690
|
+
countRewrite(
|
|
691
|
+
stats,
|
|
692
|
+
`${label}.ikev2TransformTypes (reference → algorithm)`,
|
|
693
|
+
);
|
|
694
|
+
return { algorithm: entry };
|
|
695
|
+
});
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
dropUnmapped(protocolProperties, "protocolProperties", label, stats);
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
/**
|
|
702
|
+
* Convert cryptoProperties
|
|
703
|
+
* (#/$defs/cyclonedx-cryptography-2.0/$defs/cryptoProperties, required
|
|
704
|
+
* `[assetType]`): drop the deprecated free-text `curve` (2.0 keeps only
|
|
705
|
+
* `ellipticCurve`) and the algorithm families and protocol types the pinned
|
|
706
|
+
* 2.0 enums do not list, move the deprecated 1.x reference members into
|
|
707
|
+
* `relatedCryptographicAssets`, and count every member 2.0 has no field for.
|
|
708
|
+
*/
|
|
709
|
+
export function convertCryptoProperties(cryptoProperties, stats) {
|
|
710
|
+
if (!isObjectRecord(cryptoProperties)) {
|
|
711
|
+
return undefined;
|
|
712
|
+
}
|
|
713
|
+
const converted = clone(cryptoProperties);
|
|
714
|
+
for (const [kind, convert] of [
|
|
715
|
+
["algorithmProperties", convertAlgorithmProperties],
|
|
716
|
+
["certificateProperties", convertCertificateProperties],
|
|
717
|
+
["relatedCryptoMaterialProperties", convertRelatedMaterialProperties],
|
|
718
|
+
["protocolProperties", convertProtocolProperties],
|
|
719
|
+
]) {
|
|
720
|
+
if (isObjectRecord(converted[kind])) {
|
|
721
|
+
convert(converted[kind], stats);
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
dropUnmapped(converted, "cryptoProperties", "cryptoProperties", stats);
|
|
725
|
+
return converted;
|
|
726
|
+
}
|