@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,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Summarize Kiro CLI V3 permission documents into policy-safe posture facts.
|
|
3
|
+
*
|
|
4
|
+
* Kiro V3 describes what an agent may do with `capability`/`effect` rules that
|
|
5
|
+
* live in an agent definition's `permissions` object, in the user-scope
|
|
6
|
+
* `~/.kiro/settings/permissions.yaml`, and in the per-workspace
|
|
7
|
+
* `~/.kiro/workspace-roots/<hash>/permissions.yaml`. The rules carry `match`
|
|
8
|
+
* pattern lists, free-text reasons, and paths, none of which belong in a BOM.
|
|
9
|
+
* This module reduces a document to counts, allowlisted effect counts,
|
|
10
|
+
* validated capability names, and booleans, and never returns the patterns or
|
|
11
|
+
* any other free text.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
// Effects documented at kiro.dev/docs/permissions. An unknown effect is
|
|
15
|
+
// counted by `ruleCount` alone and by no per-effect counter.
|
|
16
|
+
const KIRO_EFFECTS = new Set(["allow", "deny", "ask", "evaluate"]);
|
|
17
|
+
|
|
18
|
+
// Policy presets that may be listed under the top-level `policies` key.
|
|
19
|
+
// kiro.dev documents `approve-for-me`; other preset names are dropped rather
|
|
20
|
+
// than copied, because the full set is not documented.
|
|
21
|
+
const KIRO_POLICY_PRESET_ALLOWLIST = new Set(["approve-for-me"]);
|
|
22
|
+
|
|
23
|
+
// A capability is a short lowercase token such as `fs_read`, `shell`, or the
|
|
24
|
+
// meta-capability `all`. Anything outside this shape is dropped instead of
|
|
25
|
+
// being copied into the BOM.
|
|
26
|
+
const KIRO_CAPABILITY_PATTERN = /^[a-z][a-z0-9_-]{0,63}$/u;
|
|
27
|
+
|
|
28
|
+
const isPlainEntry = (value) =>
|
|
29
|
+
value !== null && typeof value === "object" && !Array.isArray(value);
|
|
30
|
+
|
|
31
|
+
const sortedUnique = (values) => [...new Set(values)].sort();
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Decide whether a rule's `match` list holds at least one non-empty pattern.
|
|
35
|
+
*
|
|
36
|
+
* @param {unknown} match The rule's match value
|
|
37
|
+
* @returns {boolean} True when a non-empty string pattern is present
|
|
38
|
+
*/
|
|
39
|
+
const hasNonEmptyMatch = (match) =>
|
|
40
|
+
Array.isArray(match) &&
|
|
41
|
+
match.some((entry) => typeof entry === "string" && entry.trim() !== "");
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Summarize a Kiro V3 permission document.
|
|
45
|
+
*
|
|
46
|
+
* Accepts the parsed `permissions` object of an agent definition or a parsed
|
|
47
|
+
* `permissions.yaml` document. A bare rules array is accepted as well. The
|
|
48
|
+
* result carries only counts, booleans, and validated token lists; `match`
|
|
49
|
+
* patterns, `exclude` lists, reasons, and paths are never returned.
|
|
50
|
+
*
|
|
51
|
+
* @param {Object|Array|undefined} rulesOrDoc Parsed permissions object, YAML
|
|
52
|
+
* document, or rules array
|
|
53
|
+
* @returns {{
|
|
54
|
+
* ruleCount: number,
|
|
55
|
+
* allowRuleCount: number,
|
|
56
|
+
* denyRuleCount: number,
|
|
57
|
+
* askRuleCount: number,
|
|
58
|
+
* evaluateRuleCount: number,
|
|
59
|
+
* capabilities: string[],
|
|
60
|
+
* allowsAllCapabilities: boolean,
|
|
61
|
+
* unrestrictedAllowCapabilities: string[],
|
|
62
|
+
* workspaceTrusted: boolean|undefined,
|
|
63
|
+
* policyPresets: string[],
|
|
64
|
+
* unknownPolicyPresetCount: number,
|
|
65
|
+
* }} Permission posture summary
|
|
66
|
+
*/
|
|
67
|
+
export function summarizeKiroPermissions(rulesOrDoc) {
|
|
68
|
+
const doc = Array.isArray(rulesOrDoc) ? { rules: rulesOrDoc } : rulesOrDoc;
|
|
69
|
+
const rules = Array.isArray(doc?.rules) ? doc.rules : [];
|
|
70
|
+
let ruleCount = 0;
|
|
71
|
+
const effectCounts = { allow: 0, deny: 0, ask: 0, evaluate: 0 };
|
|
72
|
+
const capabilities = [];
|
|
73
|
+
const unrestrictedAllowCapabilities = [];
|
|
74
|
+
let allowsAllCapabilities = false;
|
|
75
|
+
for (const rule of rules) {
|
|
76
|
+
if (!isPlainEntry(rule)) {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
ruleCount += 1;
|
|
80
|
+
if (typeof rule.effect === "string" && KIRO_EFFECTS.has(rule.effect)) {
|
|
81
|
+
effectCounts[rule.effect] += 1;
|
|
82
|
+
}
|
|
83
|
+
if (typeof rule.capability === "string") {
|
|
84
|
+
const capability = rule.capability;
|
|
85
|
+
if (KIRO_CAPABILITY_PATTERN.test(capability)) {
|
|
86
|
+
capabilities.push(capability);
|
|
87
|
+
if (rule.effect === "allow" && !hasNonEmptyMatch(rule.match)) {
|
|
88
|
+
unrestrictedAllowCapabilities.push(capability);
|
|
89
|
+
if (capability === "all") {
|
|
90
|
+
allowsAllCapabilities = true;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
const listedPresets = Array.isArray(doc?.policies)
|
|
97
|
+
? doc.policies.filter((entry) => typeof entry === "string")
|
|
98
|
+
: [];
|
|
99
|
+
// Preset names outside the allowlist are counted, never copied, so a
|
|
100
|
+
// reviewer still learns that an unrecognised preset is active.
|
|
101
|
+
const policyPresets = listedPresets.filter((entry) =>
|
|
102
|
+
KIRO_POLICY_PRESET_ALLOWLIST.has(entry),
|
|
103
|
+
);
|
|
104
|
+
const unknownPolicyPresetCount = new Set(
|
|
105
|
+
listedPresets.filter((entry) => !KIRO_POLICY_PRESET_ALLOWLIST.has(entry)),
|
|
106
|
+
).size;
|
|
107
|
+
return {
|
|
108
|
+
allowRuleCount: effectCounts.allow,
|
|
109
|
+
allowsAllCapabilities,
|
|
110
|
+
askRuleCount: effectCounts.ask,
|
|
111
|
+
capabilities: sortedUnique(capabilities),
|
|
112
|
+
denyRuleCount: effectCounts.deny,
|
|
113
|
+
evaluateRuleCount: effectCounts.evaluate,
|
|
114
|
+
policyPresets: sortedUnique(policyPresets),
|
|
115
|
+
ruleCount,
|
|
116
|
+
unknownPolicyPresetCount,
|
|
117
|
+
unrestrictedAllowCapabilities: sortedUnique(unrestrictedAllowCapabilities),
|
|
118
|
+
...(typeof doc?.workspaceTrusted === "boolean"
|
|
119
|
+
? { workspaceTrusted: doc.workspaceTrusted }
|
|
120
|
+
: {}),
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Flatten a permission summary into property suffix/value pairs.
|
|
126
|
+
*
|
|
127
|
+
* Both scans that consume Kiro permission documents emit the same suffixes;
|
|
128
|
+
* the host scan prefixes them with `cdx:agentic:` and the project scan with
|
|
129
|
+
* `cdx:agent:`. Values are numbers, booleans, or comma-separated validated
|
|
130
|
+
* tokens, so no free text reaches a BOM through this mapping.
|
|
131
|
+
*
|
|
132
|
+
* @param {ReturnType<summarizeKiroPermissions>} summary Permission posture summary
|
|
133
|
+
* @returns {Record<string, number|boolean|string>} Property suffix mapped to its value
|
|
134
|
+
*/
|
|
135
|
+
export function kiroPermissionSummaryEntries(summary) {
|
|
136
|
+
const entries = {
|
|
137
|
+
permissionAllowRuleCount: summary.allowRuleCount,
|
|
138
|
+
permissionAllowsAll: Boolean(summary.allowsAllCapabilities),
|
|
139
|
+
permissionAskRuleCount: summary.askRuleCount,
|
|
140
|
+
permissionDenyRuleCount: summary.denyRuleCount,
|
|
141
|
+
permissionEvaluateRuleCount: summary.evaluateRuleCount,
|
|
142
|
+
permissionRuleCount: summary.ruleCount,
|
|
143
|
+
};
|
|
144
|
+
// An empty list carries no information, so the property is omitted instead
|
|
145
|
+
// of being emitted with an empty value.
|
|
146
|
+
for (const [suffix, list] of [
|
|
147
|
+
["permissionCapabilities", summary.capabilities],
|
|
148
|
+
[
|
|
149
|
+
"permissionUnrestrictedAllowCapabilities",
|
|
150
|
+
summary.unrestrictedAllowCapabilities,
|
|
151
|
+
],
|
|
152
|
+
["permissionPolicyPresets", summary.policyPresets],
|
|
153
|
+
]) {
|
|
154
|
+
if (list?.length) {
|
|
155
|
+
entries[suffix] = list.join(",");
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
if (summary.unknownPolicyPresetCount) {
|
|
159
|
+
entries.permissionUnknownPolicyPresetCount =
|
|
160
|
+
summary.unknownPolicyPresetCount;
|
|
161
|
+
}
|
|
162
|
+
if (typeof summary.workspaceTrusted === "boolean") {
|
|
163
|
+
entries.permissionWorkspaceTrusted = summary.workspaceTrusted;
|
|
164
|
+
}
|
|
165
|
+
return entries;
|
|
166
|
+
}
|
package/lib/parsers/largeJson.js
CHANGED
|
@@ -54,9 +54,20 @@ function applySpec(value, spec) {
|
|
|
54
54
|
return value;
|
|
55
55
|
}
|
|
56
56
|
if (Array.isArray(value)) {
|
|
57
|
+
let elements = value;
|
|
58
|
+
if (spec.map) {
|
|
59
|
+
const mapped = [];
|
|
60
|
+
for (const element of elements) {
|
|
61
|
+
const transformed = spec.map(element);
|
|
62
|
+
if (transformed !== undefined) {
|
|
63
|
+
mapped.push(transformed);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
elements = mapped;
|
|
67
|
+
}
|
|
57
68
|
return spec.filter
|
|
58
|
-
?
|
|
59
|
-
:
|
|
69
|
+
? elements.filter((element) => spec.filter(element))
|
|
70
|
+
: elements;
|
|
60
71
|
}
|
|
61
72
|
if (!spec.members) {
|
|
62
73
|
return value;
|
|
@@ -294,9 +305,10 @@ function scanObjectMembers(cursor, stopAt = undefined) {
|
|
|
294
305
|
}
|
|
295
306
|
}
|
|
296
307
|
|
|
297
|
-
// Decode the array at the cursor in runs of whole elements,
|
|
298
|
-
// `
|
|
299
|
-
|
|
308
|
+
// Decode the array at the cursor in runs of whole elements, mapping each one
|
|
309
|
+
// through `spec.map` (an undefined result drops it) and keeping those that
|
|
310
|
+
// `spec.filter` accepts.
|
|
311
|
+
function readArrayElements(cursor, spec, batchBytes) {
|
|
300
312
|
if (cursor.nextToken() !== OPEN_BRACKET) {
|
|
301
313
|
cursor.fail("Expected an array");
|
|
302
314
|
}
|
|
@@ -310,8 +322,12 @@ function readArrayElements(cursor, filter, batchBytes) {
|
|
|
310
322
|
for (const element of JSON.parse(
|
|
311
323
|
`[${cursor.endCapture(cursor.pos - 1)}]`,
|
|
312
324
|
)) {
|
|
313
|
-
|
|
314
|
-
|
|
325
|
+
const mapped = spec?.map ? spec.map(element) : element;
|
|
326
|
+
if (mapped === undefined) {
|
|
327
|
+
continue;
|
|
328
|
+
}
|
|
329
|
+
if (!spec?.filter || spec.filter(mapped)) {
|
|
330
|
+
elements.push(mapped);
|
|
315
331
|
}
|
|
316
332
|
}
|
|
317
333
|
};
|
|
@@ -367,7 +383,7 @@ function decodeRange(fd, start, end, spec, options) {
|
|
|
367
383
|
);
|
|
368
384
|
}
|
|
369
385
|
} else if (first === OPEN_BRACKET) {
|
|
370
|
-
value = readArrayElements(cursor, spec
|
|
386
|
+
value = readArrayElements(cursor, spec, options.batchBytes);
|
|
371
387
|
} else {
|
|
372
388
|
// A string or number this large has no smaller parts; JSON.parse reports
|
|
373
389
|
// it the way it would for the whole file.
|
|
@@ -449,9 +465,10 @@ export function readJsonMember(filePath, name, options = {}) {
|
|
|
449
465
|
* more than a bounded run of it in one string.
|
|
450
466
|
*
|
|
451
467
|
* `spec` narrows what is kept. `{ members: { name: spec } }` keeps only the
|
|
452
|
-
* named members of an object, each narrowed by its own spec. `{
|
|
453
|
-
*
|
|
454
|
-
* keeps the
|
|
468
|
+
* named members of an object, each narrowed by its own spec. `{ map }`
|
|
469
|
+
* transforms each element of an array, an undefined result dropping it, and
|
|
470
|
+
* `{ filter }` keeps the mapped elements that `filter(element)` accepts.
|
|
471
|
+
* Anything else keeps the whole value.
|
|
455
472
|
*
|
|
456
473
|
* @param {string} filePath JSON file
|
|
457
474
|
* @param {{start: number, end: number}} range Byte range of the value, such as one returned by indexJsonObject
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
// The one place that reads the identity of an installed VS Code-family
|
|
2
|
+
// extension from the name of its folder.
|
|
3
|
+
//
|
|
4
|
+
// An editor installs an extension into `<publisher>.<name>-<version>`, and a
|
|
5
|
+
// platform-specific build into `<publisher>.<name>-<version>-<platform>`, for
|
|
6
|
+
// example `anthropic.claude-code-2.1.313-darwin-arm64`. The extension scan and
|
|
7
|
+
// the osquery `vscode_extensions` rows both name the extension from this, so an
|
|
8
|
+
// extension found by `cdxgen -t vscode-extension` and by `obom` is the same
|
|
9
|
+
// component with the same purl.
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Target platforms a VS Code-family marketplace publishes an extension for.
|
|
13
|
+
* `universal` and `web` builds are the same artefact on every platform and are
|
|
14
|
+
* not part of the extension's identity.
|
|
15
|
+
*/
|
|
16
|
+
export const VSCODE_TARGET_PLATFORMS = new Set([
|
|
17
|
+
"win32-x64",
|
|
18
|
+
"win32-arm64",
|
|
19
|
+
"win32-ia32",
|
|
20
|
+
"linux-x64",
|
|
21
|
+
"linux-arm64",
|
|
22
|
+
"linux-armhf",
|
|
23
|
+
"alpine-x64",
|
|
24
|
+
"alpine-arm64",
|
|
25
|
+
"darwin-x64",
|
|
26
|
+
"darwin-arm64",
|
|
27
|
+
]);
|
|
28
|
+
|
|
29
|
+
// Folder suffixes for builds that run on every platform.
|
|
30
|
+
const NEUTRAL_PLATFORMS = ["universal", "web"];
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Normalize a target platform value from a manifest, an `extensions.json`
|
|
34
|
+
* record, or a folder name. Values that do not name a specific platform, such
|
|
35
|
+
* as `universal`, `web`, `undefined`, or an empty string, return an empty
|
|
36
|
+
* string.
|
|
37
|
+
*
|
|
38
|
+
* @param {string} value Raw target platform
|
|
39
|
+
* @returns {string} A value from VSCODE_TARGET_PLATFORMS, or an empty string
|
|
40
|
+
*/
|
|
41
|
+
export function normalizeVscodeTargetPlatform(value) {
|
|
42
|
+
const platform = `${value || ""}`.trim().toLowerCase();
|
|
43
|
+
return VSCODE_TARGET_PLATFORMS.has(platform) ? platform : "";
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Split an installed extension folder name into its publisher, name, version
|
|
48
|
+
* and target platform.
|
|
49
|
+
*
|
|
50
|
+
* @param {string} dirName Folder name, such as `ms-python.python-2025.4.0` or
|
|
51
|
+
* `anthropic.claude-code-2.1.313-darwin-arm64`
|
|
52
|
+
* @returns {{publisher: string, name: string, version: string, platform: string}|undefined}
|
|
53
|
+
* The parts, or undefined when the name does not follow the pattern
|
|
54
|
+
*/
|
|
55
|
+
export function parseVscodeExtensionDirName(dirName) {
|
|
56
|
+
let value = `${dirName || ""}`.trim();
|
|
57
|
+
while (value.endsWith("/") || value.endsWith("\\")) {
|
|
58
|
+
value = value.slice(0, -1);
|
|
59
|
+
}
|
|
60
|
+
const dotIdx = value.indexOf(".");
|
|
61
|
+
if (dotIdx < 1) {
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
const publisher = value.substring(0, dotIdx);
|
|
65
|
+
let rest = value.substring(dotIdx + 1);
|
|
66
|
+
let platform = "";
|
|
67
|
+
for (const candidate of [...VSCODE_TARGET_PLATFORMS, ...NEUTRAL_PLATFORMS]) {
|
|
68
|
+
if (rest.toLowerCase().endsWith(`-${candidate}`)) {
|
|
69
|
+
platform = normalizeVscodeTargetPlatform(candidate);
|
|
70
|
+
rest = rest.substring(0, rest.length - candidate.length - 1);
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// Marketplaces require semver versions, so the version starts at the first
|
|
75
|
+
// hyphen whose remainder is a whole semver: `python-3.11-tools-1.0.0` is the
|
|
76
|
+
// name `python-3.11-tools` at 1.0.0, and `1.0.0-beta-2` stays one version.
|
|
77
|
+
// A folder whose version is not semver falls back to the first hyphen
|
|
78
|
+
// followed by digits and a dot.
|
|
79
|
+
let versionStart = -1;
|
|
80
|
+
let fallbackStart = -1;
|
|
81
|
+
for (let i = 1; i < rest.length - 2; i++) {
|
|
82
|
+
if (rest[i] !== "-" || !isDigit(rest[i + 1])) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
if (isSemver(rest.substring(i + 1))) {
|
|
86
|
+
versionStart = i;
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
let j = i + 1;
|
|
90
|
+
while (j < rest.length && isDigit(rest[j])) {
|
|
91
|
+
j++;
|
|
92
|
+
}
|
|
93
|
+
if (fallbackStart < 0 && rest[j] === ".") {
|
|
94
|
+
fallbackStart = i;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (versionStart < 0) {
|
|
98
|
+
versionStart = fallbackStart;
|
|
99
|
+
}
|
|
100
|
+
if (versionStart < 1) {
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
103
|
+
const name = rest.substring(0, versionStart);
|
|
104
|
+
const version = rest.substring(versionStart + 1);
|
|
105
|
+
if (!name || !version) {
|
|
106
|
+
return undefined;
|
|
107
|
+
}
|
|
108
|
+
return { publisher, name, version, platform };
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function isDigit(character) {
|
|
112
|
+
return character >= "0" && character <= "9";
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function isIdentifierList(text, numericNoLeadingZero) {
|
|
116
|
+
if (!text) {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
return text.split(".").every((part) => {
|
|
120
|
+
if (!part.length) {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
for (const character of part) {
|
|
124
|
+
const ok =
|
|
125
|
+
isDigit(character) ||
|
|
126
|
+
character === "-" ||
|
|
127
|
+
(character >= "a" && character <= "z") ||
|
|
128
|
+
(character >= "A" && character <= "Z");
|
|
129
|
+
if (!ok) {
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (numericNoLeadingZero && [...part].every(isDigit)) {
|
|
134
|
+
return part === "0" || part[0] !== "0";
|
|
135
|
+
}
|
|
136
|
+
return true;
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Check a string is a semantic version: three numeric parts, then an optional
|
|
142
|
+
* `-prerelease` and `+build`.
|
|
143
|
+
*
|
|
144
|
+
* @param {string} text Candidate version
|
|
145
|
+
* @returns {boolean} true for a semver
|
|
146
|
+
*/
|
|
147
|
+
export function isSemver(text) {
|
|
148
|
+
const plus = text.indexOf("+");
|
|
149
|
+
const core = plus >= 0 ? text.substring(0, plus) : text;
|
|
150
|
+
if (plus >= 0 && !isIdentifierList(text.substring(plus + 1), false)) {
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
const dash = core.indexOf("-");
|
|
154
|
+
const numbers = dash >= 0 ? core.substring(0, dash) : core;
|
|
155
|
+
if (dash >= 0 && !isIdentifierList(core.substring(dash + 1), true)) {
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
const parts = numbers.split(".");
|
|
159
|
+
return (
|
|
160
|
+
parts.length === 3 &&
|
|
161
|
+
parts.every(
|
|
162
|
+
(part) =>
|
|
163
|
+
part.length > 0 &&
|
|
164
|
+
[...part].every(isDigit) &&
|
|
165
|
+
(part === "0" || part[0] !== "0"),
|
|
166
|
+
)
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Read the target platform from the path of an installed extension folder.
|
|
172
|
+
*
|
|
173
|
+
* @param {string} extensionPath Path to the extension folder, with either
|
|
174
|
+
* separator
|
|
175
|
+
* @returns {string} The target platform, or an empty string
|
|
176
|
+
*/
|
|
177
|
+
export function vscodeExtensionPlatformFromPath(extensionPath) {
|
|
178
|
+
const segments = `${extensionPath || ""}`
|
|
179
|
+
.split(/[/\\]/u)
|
|
180
|
+
.filter((segment) => segment.length);
|
|
181
|
+
const dirName = segments[segments.length - 1];
|
|
182
|
+
return parseVscodeExtensionDirName(dirName)?.platform || "";
|
|
183
|
+
}
|
package/lib/server/server.js
CHANGED
|
@@ -14,7 +14,12 @@ import {
|
|
|
14
14
|
isSecureMode,
|
|
15
15
|
readEnvironmentVariable,
|
|
16
16
|
} from "../core/activity.js";
|
|
17
|
-
import {
|
|
17
|
+
import { HOST_SCOPE_PROJECT_TYPES } from "../core/env.js";
|
|
18
|
+
import {
|
|
19
|
+
boundUntrustedGlobPatterns,
|
|
20
|
+
UNTRUSTED_GLOB_EXPANSION_BUDGET,
|
|
21
|
+
UNTRUSTED_GLOB_PATTERN_MAX_LENGTH,
|
|
22
|
+
} from "../core/globPatterns.js";
|
|
18
23
|
import { isWin } from "../core/paths.js";
|
|
19
24
|
import { isSecureModeActive } from "../core/projectTooling.js";
|
|
20
25
|
import { resetRunState } from "../core/runState.js";
|
|
@@ -22,7 +27,11 @@ import { CDXGEN_VERSION } from "../core/state.js";
|
|
|
22
27
|
import { installConsoleShim, ui } from "../core/ui.js";
|
|
23
28
|
import { fetchPomXmlAsJson } from "../ecosystems/ecosystems.js";
|
|
24
29
|
import { normalizeOutputFormats } from "../helpers/exportUtils.js";
|
|
25
|
-
import {
|
|
30
|
+
import {
|
|
31
|
+
isCycloneDx20SpecVersion,
|
|
32
|
+
isCycloneDxBom,
|
|
33
|
+
} from "../inventory/bomUtils.js";
|
|
34
|
+
import { DEPENDENCY_TRACK_CDX20_ERROR } from "../inventory/cyclonedx20.js";
|
|
26
35
|
import {
|
|
27
36
|
cleanupSourceDir,
|
|
28
37
|
findGitRefForPurlVersion,
|
|
@@ -227,27 +236,6 @@ function restrictRequestOptions(options, operatorOptions) {
|
|
|
227
236
|
}
|
|
228
237
|
}
|
|
229
238
|
|
|
230
|
-
// Project types that inventory the host the server runs on, such as installed
|
|
231
|
-
// packages, users, shell history, IDE and browser extensions, or the Maven,
|
|
232
|
-
// Gradle, sbt, Cargo and Helm caches in the server user's home directory.
|
|
233
|
-
// They ignore the scan path, so the path allowlist does not limit them.
|
|
234
|
-
const HOST_SCOPE_PROJECT_TYPES = new Set(
|
|
235
|
-
[
|
|
236
|
-
"os",
|
|
237
|
-
"hbom",
|
|
238
|
-
"cargo-cache",
|
|
239
|
-
"helm-index",
|
|
240
|
-
"gradle-index",
|
|
241
|
-
"sbt-index",
|
|
242
|
-
"maven-index",
|
|
243
|
-
"vscode-extension",
|
|
244
|
-
"chrome-extension",
|
|
245
|
-
"agentic",
|
|
246
|
-
]
|
|
247
|
-
.flatMap((key) => PROJECT_TYPE_ALIASES[key] || [key])
|
|
248
|
-
.concat(["maven-repo"]),
|
|
249
|
-
);
|
|
250
|
-
|
|
251
239
|
/**
|
|
252
240
|
* Check request options that the server must refuse outright.
|
|
253
241
|
*
|
|
@@ -270,22 +258,18 @@ export function validateRequestOptions(reqOptions, operatorOptions = {}) {
|
|
|
270
258
|
details: `The '${hostScopeType}' project type scans the server host. Start the server with this type to allow it.`,
|
|
271
259
|
};
|
|
272
260
|
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
// Brace patterns expand before matching, so one short pattern such as
|
|
277
|
-
// {1..100000} can keep the server busy for minutes.
|
|
261
|
+
// Every exclude pattern is matched against every file the scan walks, and
|
|
262
|
+
// brace patterns expand before matching, so one short pattern such as
|
|
263
|
+
// {1..100000}, or a long enough list, can keep the server busy for minutes.
|
|
278
264
|
if (
|
|
279
265
|
reqOptions.exclude !== operatorOptions.exclude &&
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
)
|
|
266
|
+
boundUntrustedGlobPatterns(reqOptions.exclude, { allowBraces: false })
|
|
267
|
+
.refused.length
|
|
283
268
|
) {
|
|
284
269
|
return {
|
|
285
270
|
status: 400,
|
|
286
271
|
error: "Invalid Exclude Pattern",
|
|
287
|
-
details:
|
|
288
|
-
"Exclude patterns sent to the server cannot use braces or exceed 512 characters.",
|
|
272
|
+
details: `Exclude patterns sent to the server cannot use braces, exceed ${UNTRUSTED_GLOB_PATTERN_MAX_LENGTH} characters, or number more than ${UNTRUSTED_GLOB_EXPANSION_BUDGET}.`,
|
|
289
273
|
};
|
|
290
274
|
}
|
|
291
275
|
if (
|
|
@@ -333,6 +317,19 @@ export function validateRequestOptions(reqOptions, operatorOptions = {}) {
|
|
|
333
317
|
"Formulation data may contain secrets and is not submitted to Dependency-Track in secure mode.",
|
|
334
318
|
};
|
|
335
319
|
}
|
|
320
|
+
// Dependency-Track ingests CycloneDX 1.x only, so a request that would
|
|
321
|
+
// upload (server URL plus API key) cannot ask for the 2.0 draft.
|
|
322
|
+
if (
|
|
323
|
+
reqOptions.serverUrl &&
|
|
324
|
+
reqOptions.apiKey &&
|
|
325
|
+
isCycloneDx20SpecVersion(reqOptions.specVersion)
|
|
326
|
+
) {
|
|
327
|
+
return {
|
|
328
|
+
status: 400,
|
|
329
|
+
error: "Unsupported Spec Version For Dependency-Track",
|
|
330
|
+
details: DEPENDENCY_TRACK_CDX20_ERROR,
|
|
331
|
+
};
|
|
332
|
+
}
|
|
336
333
|
return null;
|
|
337
334
|
}
|
|
338
335
|
|
|
@@ -659,7 +656,18 @@ const start = (options) => {
|
|
|
659
656
|
);
|
|
660
657
|
}
|
|
661
658
|
}
|
|
662
|
-
|
|
659
|
+
try {
|
|
660
|
+
cloneDir = gitClone(sourcePath, gitRef);
|
|
661
|
+
} catch (_err) {
|
|
662
|
+
console.log("Unable to clone repository. See the server log.");
|
|
663
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
664
|
+
return res.end(
|
|
665
|
+
JSON.stringify({
|
|
666
|
+
error: "Unable to clone repository",
|
|
667
|
+
details: "Cloning the repository failed. See the server log.",
|
|
668
|
+
}),
|
|
669
|
+
);
|
|
670
|
+
}
|
|
663
671
|
srcDir = cloneDir;
|
|
664
672
|
if (purlResolution?.type === "npm") {
|
|
665
673
|
const cloneRootDir = cloneDir;
|
|
@@ -738,7 +746,12 @@ const start = (options) => {
|
|
|
738
746
|
requestedFormats.includes("spdx") &&
|
|
739
747
|
isCycloneDxBom(bomNSData?.bomJson)
|
|
740
748
|
) {
|
|
741
|
-
|
|
749
|
+
// The SPDX converter reads the 1.x shape; at 2.0 that is the
|
|
750
|
+
// internal model rather than the rendered document.
|
|
751
|
+
responseBomJson = convertCycloneDxToSpdx(
|
|
752
|
+
bomNSData.internalBomJson ?? bomNSData.bomJson,
|
|
753
|
+
reqOptions,
|
|
754
|
+
);
|
|
742
755
|
}
|
|
743
756
|
if (reqOptions.serverUrl && reqOptions.apiKey) {
|
|
744
757
|
let serverHostname;
|
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
} from "../../inventory/aiInventory.js";
|
|
32
32
|
import {
|
|
33
33
|
DEFAULT_CDX_SPEC_VERSION,
|
|
34
|
+
isCycloneDx20SpecVersion,
|
|
34
35
|
normalizeCycloneDxComponentTypeFilter,
|
|
35
36
|
normalizeCycloneDxSpecVersion,
|
|
36
37
|
} from "../../inventory/bomUtils.js";
|
|
@@ -40,8 +41,13 @@ import {
|
|
|
40
41
|
createCitation,
|
|
41
42
|
findCdxgenToolBomRef,
|
|
42
43
|
} from "../../inventory/citations.js";
|
|
44
|
+
import {
|
|
45
|
+
CDX20_INTERNAL_SECTIONS_KEY,
|
|
46
|
+
renderCycloneDx20,
|
|
47
|
+
} from "../../inventory/cyclonedx20.js";
|
|
43
48
|
import { mergeDependencies, mergeServices } from "../../inventory/depsUtils.js";
|
|
44
49
|
import { addFormulationSection } from "../../inventory/formulationParsers.js";
|
|
50
|
+
import { hardwareRenderContext } from "../../inventory/hbomLoader.js";
|
|
45
51
|
import { getContainerFileInventoryStats } from "../../inventory/inventoryStats.js";
|
|
46
52
|
import { enhanceBom } from "../../inventory/licenseEnhancer.js";
|
|
47
53
|
import { applyMcpPinningState } from "../../inventory/mcpPinning.js";
|
|
@@ -546,6 +552,13 @@ async function applyIntrospection(bomNSData, options, filePath) {
|
|
|
546
552
|
/**
|
|
547
553
|
* Filter and enhance BOM post generation.
|
|
548
554
|
*
|
|
555
|
+
* At CycloneDX 2.0 the returned `bomNSData` carries two documents:
|
|
556
|
+
* `bomJson` is the rendered 2.0 document (what library users, the server and
|
|
557
|
+
* the writer see), and `internalBomJson` is the 1.x-shaped model the audit,
|
|
558
|
+
* evinse, display and SPDX-export readers use. `internalBomJson` is never
|
|
559
|
+
* serialized; `refreshRenderedBom` re-renders `bomJson` from it after any
|
|
560
|
+
* later mutation. At 1.x `internalBomJson` is unset.
|
|
561
|
+
*
|
|
549
562
|
* @param {Object} bomNSData BOM with namespaces object
|
|
550
563
|
* @param {Object} options CLI options
|
|
551
564
|
* @param {string} [filePath] Source path used for formulation and metadata context
|
|
@@ -615,10 +628,37 @@ export async function postProcess(bomNSData, options, filePath) {
|
|
|
615
628
|
]);
|
|
616
629
|
cleanupEnv(options);
|
|
617
630
|
cleanupTmpDir();
|
|
618
|
-
|
|
631
|
+
// A model read from another 2.0 document keeps that document's originals,
|
|
632
|
+
// keyed by the exact 1.x form of each object, so an unchanged object
|
|
633
|
+
// renders back as it was. Sorting would change those forms, so such a
|
|
634
|
+
// model keeps its order; cdxgen's own BOMs are sorted for determinism.
|
|
635
|
+
if (!bomNSData.bomJson?.[CDX20_INTERNAL_SECTIONS_KEY]?.shadows) {
|
|
636
|
+
sortBomCollections(bomNSData.bomJson);
|
|
637
|
+
}
|
|
619
638
|
// Reflection reads the finished BOM, so it runs after sorting; it returns
|
|
620
639
|
// its verdict alongside the BOM instead of mutating it.
|
|
621
640
|
await applyIntrospection(bomNSData, options, filePath);
|
|
641
|
+
// CycloneDX 2.0: everything above produced the 1.x-shaped model. Keep it on
|
|
642
|
+
// `internalBomJson` for the readers that run after postProcess (audit,
|
|
643
|
+
// evinse, display, SPDX export) and render the 2.0 document once, here.
|
|
644
|
+
// `refreshRenderedBom` re-renders after any later mutation of the model,
|
|
645
|
+
// with the same render context (the optional cdx-hbom hardware mapper,
|
|
646
|
+
// loaded only when the model has hardware components).
|
|
647
|
+
// At 1.x both stay untouched, so those outputs are byte-identical. The
|
|
648
|
+
// document's own specVersion decides when the caller passed none, which is
|
|
649
|
+
// how an evinse run over a 2.0 input stays at 2.0.
|
|
650
|
+
if (
|
|
651
|
+
isCycloneDx20SpecVersion(
|
|
652
|
+
options.specVersion ?? bomNSData.bomJson?.specVersion,
|
|
653
|
+
)
|
|
654
|
+
) {
|
|
655
|
+
bomNSData.renderContext = await hardwareRenderContext(bomNSData.bomJson);
|
|
656
|
+
bomNSData.internalBomJson = bomNSData.bomJson;
|
|
657
|
+
bomNSData.bomJson = renderCycloneDx20(
|
|
658
|
+
bomNSData.bomJson,
|
|
659
|
+
bomNSData.renderContext,
|
|
660
|
+
);
|
|
661
|
+
}
|
|
622
662
|
return bomNSData;
|
|
623
663
|
}
|
|
624
664
|
|
|
@@ -672,16 +672,21 @@ async function interpolateTemplate(template, context, options = {}) {
|
|
|
672
672
|
return template;
|
|
673
673
|
}
|
|
674
674
|
const templateRegex = /\{\{\s*([^}]+)\s*}}/g;
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
675
|
+
// The template is rebuilt from its own slices in one pass, so a value taken
|
|
676
|
+
// from the BOM is never scanned for {{ }} again and never read as a
|
|
677
|
+
// String.replace pattern such as `$&`.
|
|
678
|
+
let result = "";
|
|
679
|
+
let cursor = 0;
|
|
680
|
+
for (const match of template.matchAll(templateRegex)) {
|
|
678
681
|
const [fullMatch, expr] = match;
|
|
682
|
+
let replacement = fullMatch;
|
|
679
683
|
try {
|
|
680
684
|
const expression = jsonata(expr.trim());
|
|
681
685
|
registerCdxHelpers(expression, options);
|
|
682
686
|
const value = await safeEvaluate(expression, context);
|
|
683
|
-
|
|
684
|
-
|
|
687
|
+
if (value !== undefined) {
|
|
688
|
+
replacement = String(value);
|
|
689
|
+
}
|
|
685
690
|
} catch (err) {
|
|
686
691
|
if (DEBUG_MODE) {
|
|
687
692
|
console.warn(
|
|
@@ -690,7 +695,10 @@ async function interpolateTemplate(template, context, options = {}) {
|
|
|
690
695
|
);
|
|
691
696
|
}
|
|
692
697
|
}
|
|
698
|
+
result += template.slice(cursor, match.index) + replacement;
|
|
699
|
+
cursor = match.index + fullMatch.length;
|
|
693
700
|
}
|
|
701
|
+
result += template.slice(cursor);
|
|
694
702
|
return result;
|
|
695
703
|
}
|
|
696
704
|
|