@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
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
|
-
import { readFileSync } from "node:fs";
|
|
2
|
+
import { readdirSync, readFileSync } from "node:fs";
|
|
3
3
|
import {
|
|
4
4
|
sep as _sep,
|
|
5
5
|
basename,
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
hasDangerousUnicode,
|
|
19
19
|
readEnvironmentVariable,
|
|
20
20
|
} from "../core/activity.js";
|
|
21
|
+
import { readRegularTextFile } from "../core/boundedFile.js";
|
|
21
22
|
import { recordDegradation } from "../core/buildLedger.js";
|
|
22
23
|
import { deferFailOnError } from "../core/deferredExit.js";
|
|
23
24
|
import { shouldFetchLicense } from "../core/env.js";
|
|
@@ -52,7 +53,12 @@ import {
|
|
|
52
53
|
tryBuildPurl,
|
|
53
54
|
} from "../inventory/purl.js";
|
|
54
55
|
import { getLicenses, spdxLicenses } from "../inventory/spdx.js";
|
|
55
|
-
import {
|
|
56
|
+
import {
|
|
57
|
+
cmakeFetchDependencies,
|
|
58
|
+
cmakeSetVariables,
|
|
59
|
+
expandCmakeVariables,
|
|
60
|
+
parseCmakeCommands,
|
|
61
|
+
} from "../parsers/cmakeLists.js";
|
|
56
62
|
import { isValidIdnEmail } from "../parsers/email.js";
|
|
57
63
|
import { submodulePurlCoordinates } from "../parsers/gitmodules.js";
|
|
58
64
|
import { getDartMetadata } from "./ecosystems.js";
|
|
@@ -2784,6 +2790,130 @@ export function cmakeFetchDependencyComponent(dep, srcFile) {
|
|
|
2784
2790
|
return component;
|
|
2785
2791
|
}
|
|
2786
2792
|
|
|
2793
|
+
const MAX_MESON_WRAPS = 256;
|
|
2794
|
+
const MAX_MESON_WRAP_BYTES = 64 * 1024;
|
|
2795
|
+
|
|
2796
|
+
function upstreamVersionOf(text) {
|
|
2797
|
+
if (typeof text !== "string") {
|
|
2798
|
+
return undefined;
|
|
2799
|
+
}
|
|
2800
|
+
const value = text.trim().replace(/^v(?=\d)/, "");
|
|
2801
|
+
return /^\d+(\.\d+)*([-+._~][0-9A-Za-z.]+)?$/.test(value) ? value : undefined;
|
|
2802
|
+
}
|
|
2803
|
+
|
|
2804
|
+
// `brotli-1.1.0`, `brotli-1.1.0.tar.gz`: the version after the last `-` that
|
|
2805
|
+
// starts a number.
|
|
2806
|
+
function versionFromArchiveName(name) {
|
|
2807
|
+
if (typeof name !== "string") {
|
|
2808
|
+
return undefined;
|
|
2809
|
+
}
|
|
2810
|
+
const stem = name.replace(/\.(tar\.gz|tar\.xz|tar\.bz2|tgz|zip|tar)$/i, "");
|
|
2811
|
+
const dash = stem.search(/-\d[^-]*$/);
|
|
2812
|
+
return dash === -1 ? undefined : upstreamVersionOf(stem.slice(dash + 1));
|
|
2813
|
+
}
|
|
2814
|
+
|
|
2815
|
+
/**
|
|
2816
|
+
* Read the wrap files of a meson project's subprojects directory: which
|
|
2817
|
+
* dependency names each wrap provides, and the version it pins.
|
|
2818
|
+
* https://mesonbuild.com/Wrap-dependency-system-manual.html
|
|
2819
|
+
*
|
|
2820
|
+
* A WrapDB wrap records `wrapdb_version = <upstream>-<wrap revision>`; any wrap
|
|
2821
|
+
* names its unpacked `directory` and its archive, which carry the upstream
|
|
2822
|
+
* version; a git wrap pins a `revision` that is often a version tag.
|
|
2823
|
+
*
|
|
2824
|
+
* @param {string} subprojectsDir path of the subprojects directory
|
|
2825
|
+
* @returns {Map<string, {wrap: string, version: string, source: string, revision?: string}>}
|
|
2826
|
+
* by provided dependency name, lower-case
|
|
2827
|
+
*/
|
|
2828
|
+
export function readMesonWraps(subprojectsDir) {
|
|
2829
|
+
const provided = new Map();
|
|
2830
|
+
let wrapFiles = [];
|
|
2831
|
+
try {
|
|
2832
|
+
wrapFiles = readdirSync(subprojectsDir)
|
|
2833
|
+
.filter((name) => name.endsWith(".wrap"))
|
|
2834
|
+
.sort()
|
|
2835
|
+
.slice(0, MAX_MESON_WRAPS);
|
|
2836
|
+
} catch {
|
|
2837
|
+
return provided;
|
|
2838
|
+
}
|
|
2839
|
+
for (const wrapFile of wrapFiles) {
|
|
2840
|
+
// A regular file only: a FIFO named *.wrap would block a plain read.
|
|
2841
|
+
const text = readRegularTextFile(
|
|
2842
|
+
join(subprojectsDir, wrapFile),
|
|
2843
|
+
MAX_MESON_WRAP_BYTES,
|
|
2844
|
+
);
|
|
2845
|
+
if (text === undefined) {
|
|
2846
|
+
continue;
|
|
2847
|
+
}
|
|
2848
|
+
const sections = {};
|
|
2849
|
+
let section = "";
|
|
2850
|
+
for (const rawLine of text.split(/\r?\n/)) {
|
|
2851
|
+
const line = rawLine.trim();
|
|
2852
|
+
if (!line || line.startsWith("#") || line.startsWith(";")) {
|
|
2853
|
+
continue;
|
|
2854
|
+
}
|
|
2855
|
+
if (line.startsWith("[") && line.endsWith("]")) {
|
|
2856
|
+
section = line.slice(1, -1).trim();
|
|
2857
|
+
sections[section] = sections[section] || {};
|
|
2858
|
+
continue;
|
|
2859
|
+
}
|
|
2860
|
+
const equals = line.indexOf("=");
|
|
2861
|
+
if (equals <= 0 || !section) {
|
|
2862
|
+
continue;
|
|
2863
|
+
}
|
|
2864
|
+
sections[section][line.slice(0, equals).trim()] = line
|
|
2865
|
+
.slice(equals + 1)
|
|
2866
|
+
.trim();
|
|
2867
|
+
}
|
|
2868
|
+
const body = sections["wrap-file"] || sections["wrap-git"] || {};
|
|
2869
|
+
let version;
|
|
2870
|
+
let source;
|
|
2871
|
+
let revision;
|
|
2872
|
+
if (body.wrapdb_version) {
|
|
2873
|
+
const dash = body.wrapdb_version.lastIndexOf("-");
|
|
2874
|
+
version = upstreamVersionOf(
|
|
2875
|
+
dash > 0 ? body.wrapdb_version.slice(0, dash) : body.wrapdb_version,
|
|
2876
|
+
);
|
|
2877
|
+
revision = dash > 0 ? body.wrapdb_version.slice(dash + 1) : undefined;
|
|
2878
|
+
source = "wrapdb_version";
|
|
2879
|
+
}
|
|
2880
|
+
if (!version && sections["wrap-file"]) {
|
|
2881
|
+
version =
|
|
2882
|
+
versionFromArchiveName(body.directory) ||
|
|
2883
|
+
versionFromArchiveName(body.source_filename);
|
|
2884
|
+
source = version ? "directory" : undefined;
|
|
2885
|
+
}
|
|
2886
|
+
if (!version && sections["wrap-git"]) {
|
|
2887
|
+
version = upstreamVersionOf(body.revision);
|
|
2888
|
+
source = version ? "revision" : undefined;
|
|
2889
|
+
}
|
|
2890
|
+
if (!version) {
|
|
2891
|
+
continue;
|
|
2892
|
+
}
|
|
2893
|
+
const wrap = wrapFile.slice(0, -".wrap".length);
|
|
2894
|
+
const entry = { wrap, version, source, ...(revision ? { revision } : {}) };
|
|
2895
|
+
const names = new Set([wrap.toLowerCase()]);
|
|
2896
|
+
const provide = sections.provide || {};
|
|
2897
|
+
for (const [key, value] of Object.entries(provide)) {
|
|
2898
|
+
if (key === "dependency_names" || key === "program_names") {
|
|
2899
|
+
for (const name of value.split(",")) {
|
|
2900
|
+
if (name.trim()) {
|
|
2901
|
+
names.add(name.trim().toLowerCase());
|
|
2902
|
+
}
|
|
2903
|
+
}
|
|
2904
|
+
} else {
|
|
2905
|
+
names.add(key.toLowerCase());
|
|
2906
|
+
}
|
|
2907
|
+
}
|
|
2908
|
+
for (const name of names) {
|
|
2909
|
+
if (!provided.has(name)) {
|
|
2910
|
+
provided.set(name, entry);
|
|
2911
|
+
}
|
|
2912
|
+
}
|
|
2913
|
+
}
|
|
2914
|
+
return provided;
|
|
2915
|
+
}
|
|
2916
|
+
|
|
2787
2917
|
/**
|
|
2788
2918
|
* Parse a CMake-like build file (CMakeLists.txt, meson.build, etc.) and extract the
|
|
2789
2919
|
* parent component and list of dependency packages.
|
|
@@ -2801,6 +2931,11 @@ export function cmakeFetchDependencyComponent(dep, srcFile) {
|
|
|
2801
2931
|
*/
|
|
2802
2932
|
export function parseCmakeLikeFile(cmakeListFile, pkgType, options = {}) {
|
|
2803
2933
|
const rawData = readFileSync(cmakeListFile, { encoding: "utf-8" });
|
|
2934
|
+
// The wraps a meson project ships pin the versions of the subprojects its
|
|
2935
|
+
// dependency() calls fall back to.
|
|
2936
|
+
const mesonWraps = basename(cmakeListFile).startsWith("meson")
|
|
2937
|
+
? readMesonWraps(join(dirname(cmakeListFile), "subprojects"))
|
|
2938
|
+
: new Map();
|
|
2804
2939
|
let cmakeListData = rawData;
|
|
2805
2940
|
const pkgList = [];
|
|
2806
2941
|
const pkgAddedMap = {};
|
|
@@ -2808,6 +2943,25 @@ export function parseCmakeLikeFile(cmakeListFile, pkgType, options = {}) {
|
|
|
2808
2943
|
const versionsMap = {};
|
|
2809
2944
|
let parentComponent = {};
|
|
2810
2945
|
const templateValues = {};
|
|
2946
|
+
// The parent component is built the same way whether its name and version
|
|
2947
|
+
// came from the parsed project() command or from the line loop below.
|
|
2948
|
+
const toParentComponent = (parentName, parentVersion) => {
|
|
2949
|
+
const component = {
|
|
2950
|
+
group: options.projectGroup || "",
|
|
2951
|
+
name: parentName,
|
|
2952
|
+
version: parentVersion || options.projectVersion || "",
|
|
2953
|
+
type: "application",
|
|
2954
|
+
};
|
|
2955
|
+
component["purl"] = build({
|
|
2956
|
+
type: pkgType,
|
|
2957
|
+
namespace: component.group || null,
|
|
2958
|
+
name: component.name,
|
|
2959
|
+
version: component.version || null,
|
|
2960
|
+
subpath: null,
|
|
2961
|
+
});
|
|
2962
|
+
component["bom-ref"] = decodeURIComponent(component["purl"]);
|
|
2963
|
+
return component;
|
|
2964
|
+
};
|
|
2811
2965
|
// A dependency fetched at configure time is the same package a find_package()
|
|
2812
2966
|
// of the same name asks for: the fetched component, with its source and pin,
|
|
2813
2967
|
// stands for both.
|
|
@@ -2823,6 +2977,38 @@ export function parseCmakeLikeFile(cmakeListFile, pkgType, options = {}) {
|
|
|
2823
2977
|
fetchedNames.add(dep.name.toLowerCase());
|
|
2824
2978
|
pkgList.push(component);
|
|
2825
2979
|
}
|
|
2980
|
+
// A project() call may span several lines, which the line loop below
|
|
2981
|
+
// cannot rejoin, so the parent name and version are read from the parsed
|
|
2982
|
+
// commands instead. The first argument is the project name and the
|
|
2983
|
+
// VERSION keyword is followed by the version.
|
|
2984
|
+
const commands = parseCmakeCommands(rawData);
|
|
2985
|
+
const variables = cmakeSetVariables(commands);
|
|
2986
|
+
const projectCommand = commands.find(
|
|
2987
|
+
(command) => command.name === "project",
|
|
2988
|
+
);
|
|
2989
|
+
if (projectCommand?.args.length) {
|
|
2990
|
+
const args = projectCommand.args.map((arg) =>
|
|
2991
|
+
expandCmakeVariables(arg, variables),
|
|
2992
|
+
);
|
|
2993
|
+
const parentName = args[0].replace(":", "").trim();
|
|
2994
|
+
let parentVersion;
|
|
2995
|
+
const versionIndex = args.findIndex(
|
|
2996
|
+
(arg) => arg.toLowerCase() === "version",
|
|
2997
|
+
);
|
|
2998
|
+
if (versionIndex > -1 && args.length > versionIndex + 1) {
|
|
2999
|
+
parentVersion = args[versionIndex + 1];
|
|
3000
|
+
}
|
|
3001
|
+
// A `${VAR}` that no `set()` in this file defines stays literal. It is
|
|
3002
|
+
// not a version, and percent-encoding it into a purl publishes the
|
|
3003
|
+
// variable name as the version, so the field is left empty instead.
|
|
3004
|
+
// CMakeCache.txt carries the evaluated value when a build tree exists.
|
|
3005
|
+
if (parentVersion?.includes("$")) {
|
|
3006
|
+
parentVersion = undefined;
|
|
3007
|
+
}
|
|
3008
|
+
if (parentName.length && !parentName.includes("$")) {
|
|
3009
|
+
parentComponent = toParentComponent(parentName, parentVersion);
|
|
3010
|
+
}
|
|
3011
|
+
}
|
|
2826
3012
|
}
|
|
2827
3013
|
cmakeListData = cmakeListData
|
|
2828
3014
|
.replace(/^ {2}/g, "")
|
|
@@ -2883,23 +3069,7 @@ export function parseCmakeLikeFile(cmakeListFile, pkgType, options = {}) {
|
|
|
2883
3069
|
parentVersion = undefined;
|
|
2884
3070
|
}
|
|
2885
3071
|
if (parentName?.length && !parentName.includes("$")) {
|
|
2886
|
-
parentComponent =
|
|
2887
|
-
group: options.projectGroup || "",
|
|
2888
|
-
name: parentName,
|
|
2889
|
-
version: parentVersion || options.projectVersion || "",
|
|
2890
|
-
type: "application",
|
|
2891
|
-
};
|
|
2892
|
-
const safePath = path ? path.replace(/^\/+/, "") : null;
|
|
2893
|
-
parentComponent["purl"] = build({
|
|
2894
|
-
type: pkgType,
|
|
2895
|
-
namespace: parentComponent.group || null,
|
|
2896
|
-
name: parentComponent.name,
|
|
2897
|
-
version: parentComponent.version || null,
|
|
2898
|
-
subpath: safePath,
|
|
2899
|
-
});
|
|
2900
|
-
parentComponent["bom-ref"] = decodeURIComponent(
|
|
2901
|
-
parentComponent["purl"],
|
|
2902
|
-
);
|
|
3072
|
+
parentComponent = toParentComponent(parentName, parentVersion);
|
|
2903
3073
|
}
|
|
2904
3074
|
} else if (CMAKE_FIND_COMMANDS.has(command)) {
|
|
2905
3075
|
let tmpB = commandArgs.split(")")[0].split(" ");
|
|
@@ -3041,7 +3211,26 @@ export function parseCmakeLikeFile(cmakeListFile, pkgType, options = {}) {
|
|
|
3041
3211
|
// wrap match has since replaced, so the scraped name is the fallback.
|
|
3042
3212
|
const versionSpecifier =
|
|
3043
3213
|
versionSpecifiersMap[n] || versionSpecifiersMap[scrapedName];
|
|
3044
|
-
|
|
3214
|
+
let version = versionsMap[n] || versionsMap[scrapedName] || "";
|
|
3215
|
+
const localWrap =
|
|
3216
|
+
mesonWraps.get(scrapedName.toLowerCase()) ||
|
|
3217
|
+
mesonWraps.get(n.toLowerCase());
|
|
3218
|
+
if (localWrap && !version) {
|
|
3219
|
+
version = localWrap.version;
|
|
3220
|
+
props.push({ name: "cdx:meson:wrap", value: localWrap.wrap });
|
|
3221
|
+
props.push({
|
|
3222
|
+
name: "cdx:meson:wrap:versionSource",
|
|
3223
|
+
value: localWrap.source,
|
|
3224
|
+
});
|
|
3225
|
+
if (localWrap.revision) {
|
|
3226
|
+
props.push({
|
|
3227
|
+
name: "cdx:meson:wrap:revision",
|
|
3228
|
+
value: localWrap.revision,
|
|
3229
|
+
});
|
|
3230
|
+
}
|
|
3231
|
+
// A pinned wrap is a stronger identity than a name match alone.
|
|
3232
|
+
confidence = Math.max(confidence, 0.7);
|
|
3233
|
+
}
|
|
3045
3234
|
if (versionSpecifier) {
|
|
3046
3235
|
props.push({
|
|
3047
3236
|
name: "cdx:build:versionSpecifiers",
|
|
@@ -8,6 +8,7 @@ import { parse as _load } from "yaml";
|
|
|
8
8
|
import { DEBUG_MODE } from "../core/activity.js";
|
|
9
9
|
import { recordDegradation } from "../core/buildLedger.js";
|
|
10
10
|
import { getAllFiles, safeExistsSync, safeSpawnSync } from "../core/fs.js";
|
|
11
|
+
import { sanitizeBomUrl } from "../core/propertySanitizer.js";
|
|
11
12
|
import { PYTHON_STD_MODULES } from "../core/state.js";
|
|
12
13
|
import { parseToml } from "../core/toml.js";
|
|
13
14
|
import { tryBuildPurl } from "../inventory/purl.js";
|
|
@@ -888,6 +889,61 @@ export function enrichFromInstalledMetadata(pkgList, installedMetadata) {
|
|
|
888
889
|
return enriched;
|
|
889
890
|
}
|
|
890
891
|
|
|
892
|
+
// The interpreter cdxgen assumes for a lock file's environment. A marker that
|
|
893
|
+
// tests the implementation against it is decidable without a target machine.
|
|
894
|
+
const IMPLEMENTATION_CLAUSE_RE =
|
|
895
|
+
/^(platform_python_implementation|implementation_name)\s*(==|!=)\s*(['"])([A-Za-z]+)\3$/;
|
|
896
|
+
|
|
897
|
+
function implementationClauseIsFalse(clause) {
|
|
898
|
+
const match = IMPLEMENTATION_CLAUSE_RE.exec(clause.trim());
|
|
899
|
+
if (!match) {
|
|
900
|
+
return false;
|
|
901
|
+
}
|
|
902
|
+
const expected = match[1] === "implementation_name" ? "cpython" : "CPython";
|
|
903
|
+
const equal = match[4] === expected;
|
|
904
|
+
return match[2] === "==" ? !equal : equal;
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
/**
|
|
908
|
+
* Whether an environment marker is false for every CPython interpreter. Only
|
|
909
|
+
* `platform_python_implementation` and `implementation_name` clauses are
|
|
910
|
+
* decided; anything else, or a marker with parentheses, is treated as possibly
|
|
911
|
+
* true, so the answer errs towards keeping a package.
|
|
912
|
+
*
|
|
913
|
+
* @param {string} marker PEP 508 environment marker
|
|
914
|
+
* @returns {boolean} true when no CPython environment satisfies the marker
|
|
915
|
+
*/
|
|
916
|
+
export function markerExcludesCPython(marker) {
|
|
917
|
+
if (typeof marker !== "string" || !marker.trim() || /[()]/.test(marker)) {
|
|
918
|
+
return false;
|
|
919
|
+
}
|
|
920
|
+
return marker
|
|
921
|
+
.split(/\s+or\s+/)
|
|
922
|
+
.every((disjunct) =>
|
|
923
|
+
disjunct.split(/\s+and\s+/).some(implementationClauseIsFalse),
|
|
924
|
+
);
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
function recordMarkerEdge(markerEdges, depKey, apkgDep) {
|
|
928
|
+
if (!depKey) {
|
|
929
|
+
return;
|
|
930
|
+
}
|
|
931
|
+
const edge = markerEdges.get(depKey) || {
|
|
932
|
+
total: 0,
|
|
933
|
+
cpythonExcluded: 0,
|
|
934
|
+
markers: new Set(),
|
|
935
|
+
};
|
|
936
|
+
edge.total += 1;
|
|
937
|
+
const marker = typeof apkgDep === "object" ? apkgDep?.marker : undefined;
|
|
938
|
+
if (typeof marker === "string" && marker.trim()) {
|
|
939
|
+
edge.markers.add(marker.trim());
|
|
940
|
+
if (markerExcludesCPython(marker)) {
|
|
941
|
+
edge.cpythonExcluded += 1;
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
markerEdges.set(depKey, edge);
|
|
945
|
+
}
|
|
946
|
+
|
|
891
947
|
/**
|
|
892
948
|
* Method to parse python lock files such as poetry.lock, pdm.lock, uv.lock, and pylock.toml.
|
|
893
949
|
*
|
|
@@ -911,6 +967,8 @@ export async function parsePyLockData(
|
|
|
911
967
|
const depsMap = {};
|
|
912
968
|
const existingPkgMap = {};
|
|
913
969
|
const pkgBomRefMap = {};
|
|
970
|
+
// Incoming edges per dependency, with the environment markers they carry.
|
|
971
|
+
const markerEdges = new Map();
|
|
914
972
|
let directDepsKeys = {};
|
|
915
973
|
let groupDepsKeys = {};
|
|
916
974
|
let dependencySourceMap = {};
|
|
@@ -1080,10 +1138,22 @@ export async function parsePyLockData(
|
|
|
1080
1138
|
hasWorkspaces = true;
|
|
1081
1139
|
}
|
|
1082
1140
|
for (const amember of workspaceMembers) {
|
|
1083
|
-
if (amember === parentComponent
|
|
1141
|
+
if (amember === parentComponent?.name) {
|
|
1142
|
+
continue;
|
|
1143
|
+
}
|
|
1144
|
+
// a lock file read without its pyproject.toml has no parent to hold
|
|
1145
|
+
// the members, which is said once for the whole lock file
|
|
1146
|
+
if (!parentComponent) {
|
|
1147
|
+
if (!workspaceWarningShown) {
|
|
1148
|
+
console.log(
|
|
1149
|
+
`The workspace members in ${lockFile || "the lock file"} are read without a pyproject.toml, so there is no project to list them under.`,
|
|
1150
|
+
);
|
|
1151
|
+
workspaceWarningShown = true;
|
|
1152
|
+
}
|
|
1084
1153
|
continue;
|
|
1085
1154
|
}
|
|
1086
1155
|
if (workspaceComponentMap[amember]) {
|
|
1156
|
+
parentComponent.components = parentComponent.components || [];
|
|
1087
1157
|
parentComponent.components.push(workspaceComponentMap[amember]);
|
|
1088
1158
|
} else {
|
|
1089
1159
|
if (!workspaceWarningShown) {
|
|
@@ -1334,9 +1404,16 @@ export async function parsePyLockData(
|
|
|
1334
1404
|
devDependencies.length ||
|
|
1335
1405
|
optionalDependencies.length
|
|
1336
1406
|
) {
|
|
1337
|
-
|
|
1407
|
+
// A package whose only dependencies are optional (urllib3 has no
|
|
1408
|
+
// required ones, only the `brotli`, `socks` and `zstd` extras) has no
|
|
1409
|
+
// `dependencies` key in uv.lock, but its extras are still edges.
|
|
1410
|
+
if (
|
|
1411
|
+
Array.isArray(apkg.dependencies) ||
|
|
1412
|
+
(!apkg.dependencies &&
|
|
1413
|
+
(devDependencies.length || optionalDependencies.length))
|
|
1414
|
+
) {
|
|
1338
1415
|
// pdm.lock files
|
|
1339
|
-
let allDeps = apkg.dependencies;
|
|
1416
|
+
let allDeps = apkg.dependencies || [];
|
|
1340
1417
|
allDeps = allDeps.concat(devDependencies);
|
|
1341
1418
|
allDeps = allDeps.concat(optionalDependencies);
|
|
1342
1419
|
for (const apkgDep of allDeps) {
|
|
@@ -1348,6 +1425,7 @@ export async function parsePyLockData(
|
|
|
1348
1425
|
const depPkgRef =
|
|
1349
1426
|
existingPkgMap[nameLower] || existingPkgMap[nameStr];
|
|
1350
1427
|
depsMap[pkg["bom-ref"]].add(depPkgRef || nameStr);
|
|
1428
|
+
recordMarkerEdge(markerEdges, depPkgRef || nameLower, apkgDep);
|
|
1351
1429
|
// Propagate the workspace properties to the child components
|
|
1352
1430
|
if (depPkgRef && pkgBomRefMap[depPkgRef]) {
|
|
1353
1431
|
const dependentPkg = pkgBomRefMap[depPkgRef];
|
|
@@ -1421,6 +1499,28 @@ export async function parsePyLockData(
|
|
|
1421
1499
|
}
|
|
1422
1500
|
}
|
|
1423
1501
|
}
|
|
1502
|
+
// A package reached only through edges whose environment marker excludes
|
|
1503
|
+
// CPython (brotlicffi is `platform_python_implementation != 'CPython'`) is
|
|
1504
|
+
// not installed by a CPython environment built from this lock, so it is
|
|
1505
|
+
// optional rather than part of the CPython closure. A direct dependency of
|
|
1506
|
+
// the project is left alone: the manifest asked for it.
|
|
1507
|
+
for (const [depRef, edge] of markerEdges) {
|
|
1508
|
+
const dependentPkg = pkgBomRefMap[depRef];
|
|
1509
|
+
if (
|
|
1510
|
+
!dependentPkg ||
|
|
1511
|
+
!edge.total ||
|
|
1512
|
+
edge.cpythonExcluded !== edge.total ||
|
|
1513
|
+
directDepsKeys[normalizePythonDependencyKey(dependentPkg.name)]
|
|
1514
|
+
) {
|
|
1515
|
+
continue;
|
|
1516
|
+
}
|
|
1517
|
+
dependentPkg.scope = "optional";
|
|
1518
|
+
dependentPkg.properties = dependentPkg.properties || [];
|
|
1519
|
+
dependentPkg.properties.push({
|
|
1520
|
+
name: "cdx:pip:markers",
|
|
1521
|
+
value: Array.from(edge.markers).sort().join(" or "),
|
|
1522
|
+
});
|
|
1523
|
+
}
|
|
1424
1524
|
// Seed the parent component's first-level edges from the manifest. Lock
|
|
1425
1525
|
// files describe the resolved closure but do not say which of the locked
|
|
1426
1526
|
// packages the root project directly depends on; parsePyProjectTomlFile
|
|
@@ -1542,14 +1642,40 @@ export async function parsePyLockData(
|
|
|
1542
1642
|
}
|
|
1543
1643
|
|
|
1544
1644
|
/**
|
|
1545
|
-
*
|
|
1546
|
-
*
|
|
1645
|
+
* An exact PEP 440 version clause: `==` or `===` and a version with no
|
|
1646
|
+
* wildcard.
|
|
1547
1647
|
*
|
|
1548
|
-
*
|
|
1549
|
-
*
|
|
1550
|
-
* or a local version label (`2.1.0+cpu`).
|
|
1648
|
+
* Whitespace may separate the operator from the version, and a version may
|
|
1649
|
+
* carry a PEP 440 epoch (`1!2.0`) or a local version label (`2.1.0+cpu`).
|
|
1551
1650
|
*/
|
|
1552
|
-
const
|
|
1651
|
+
const PEP440_EXACT_CLAUSE = /^(===?)\s*([0-9A-Za-z._+!-]+)$/;
|
|
1652
|
+
|
|
1653
|
+
/**
|
|
1654
|
+
* Version a PEP 508 requirement pins: the version of its only exact clause.
|
|
1655
|
+
*
|
|
1656
|
+
* A requirement with no exact clause, a wildcard (`==1.2.*`) or more than one
|
|
1657
|
+
* exact clause pins no version, so a range such as `>=1.0,<2` gives null
|
|
1658
|
+
* rather than one of its bounds. Per-requirement options such as
|
|
1659
|
+
* `--config-settings` are not clauses.
|
|
1660
|
+
*
|
|
1661
|
+
* @param {String} versionSpecifiers Version specifiers of the requirement
|
|
1662
|
+
* @returns {String|null} The pinned version, or null
|
|
1663
|
+
*/
|
|
1664
|
+
function pinnedRequirementVersion(versionSpecifiers) {
|
|
1665
|
+
const specifiers = versionSpecifiers || "";
|
|
1666
|
+
const optionsIndex = specifiers.indexOf(" --");
|
|
1667
|
+
const clausesSource =
|
|
1668
|
+
optionsIndex === -1 ? specifiers : specifiers.substring(0, optionsIndex);
|
|
1669
|
+
let trimmed = clausesSource.trim();
|
|
1670
|
+
if (trimmed.startsWith("(") && trimmed.endsWith(")")) {
|
|
1671
|
+
trimmed = trimmed.substring(1, trimmed.length - 1);
|
|
1672
|
+
}
|
|
1673
|
+
const exactClauses = trimmed
|
|
1674
|
+
.split(",")
|
|
1675
|
+
.map((clause) => clause.trim().match(PEP440_EXACT_CLAUSE))
|
|
1676
|
+
.filter(Boolean);
|
|
1677
|
+
return exactClauses.length === 1 ? exactClauses[0][2] : null;
|
|
1678
|
+
}
|
|
1553
1679
|
|
|
1554
1680
|
/**
|
|
1555
1681
|
* Method to parse requirements.txt file. This must be replaced with atom parsedeps.
|
|
@@ -1738,7 +1864,7 @@ async function parseReqData(
|
|
|
1738
1864
|
|
|
1739
1865
|
// Handle extras (e.g., package[extra1,extra2])
|
|
1740
1866
|
let extras = null;
|
|
1741
|
-
const extrasMatch = l.match(/^([a-zA-Z0-9_\-.]+)(\[([^\]]+)])?(.*)$/);
|
|
1867
|
+
const extrasMatch = l.match(/^([a-zA-Z0-9_\-.]+)(\s*\[([^\]]+)])?(.*)$/);
|
|
1742
1868
|
if (extrasMatch) {
|
|
1743
1869
|
const [, packageName, , extrasStr, versionSpecifiers] = extrasMatch;
|
|
1744
1870
|
const name = packageName;
|
|
@@ -1749,14 +1875,7 @@ async function parseReqData(
|
|
|
1749
1875
|
if (PYTHON_STD_MODULES.includes(name)) {
|
|
1750
1876
|
continue;
|
|
1751
1877
|
}
|
|
1752
|
-
const
|
|
1753
|
-
let version = null;
|
|
1754
|
-
if (versionMatch) {
|
|
1755
|
-
version = versionMatch[2].replaceAll("*", "0") || null;
|
|
1756
|
-
if (version === "0") {
|
|
1757
|
-
version = null;
|
|
1758
|
-
}
|
|
1759
|
-
}
|
|
1878
|
+
const version = pinnedRequirementVersion(versionSpecifiers);
|
|
1760
1879
|
const apkg = {
|
|
1761
1880
|
name,
|
|
1762
1881
|
version,
|
|
@@ -1776,7 +1895,10 @@ async function parseReqData(
|
|
|
1776
1895
|
value: extras.join(","),
|
|
1777
1896
|
});
|
|
1778
1897
|
}
|
|
1779
|
-
if (
|
|
1898
|
+
if (
|
|
1899
|
+
versionSpecifiers?.trim() &&
|
|
1900
|
+
(!version || !versionSpecifiers.trim().startsWith("=="))
|
|
1901
|
+
) {
|
|
1780
1902
|
properties.push({
|
|
1781
1903
|
name: "cdx:pypi:versionSpecifiers",
|
|
1782
1904
|
value: versionSpecifiers.trim(),
|
|
@@ -1813,12 +1935,7 @@ async function parseReqData(
|
|
|
1813
1935
|
if (PYTHON_STD_MODULES.includes(name)) {
|
|
1814
1936
|
continue;
|
|
1815
1937
|
}
|
|
1816
|
-
const
|
|
1817
|
-
let version = null;
|
|
1818
|
-
if (versionMatch) {
|
|
1819
|
-
version = versionMatch[2].replaceAll("*", "0") || null;
|
|
1820
|
-
if (version === "0") version = null;
|
|
1821
|
-
}
|
|
1938
|
+
const version = pinnedRequirementVersion(versionSpecifiers);
|
|
1822
1939
|
const apkg = {
|
|
1823
1940
|
name,
|
|
1824
1941
|
version,
|
|
@@ -1829,7 +1946,10 @@ async function parseReqData(
|
|
|
1829
1946
|
if (licenses) {
|
|
1830
1947
|
apkg.licenses = licenses;
|
|
1831
1948
|
}
|
|
1832
|
-
if (
|
|
1949
|
+
if (
|
|
1950
|
+
versionSpecifiers?.trim() &&
|
|
1951
|
+
(!version || !versionSpecifiers.trim().startsWith("=="))
|
|
1952
|
+
) {
|
|
1833
1953
|
properties.push({
|
|
1834
1954
|
name: "cdx:pypi:versionSpecifiers",
|
|
1835
1955
|
value: versionSpecifiers.trim(),
|
|
@@ -1977,6 +2097,33 @@ function createPixiBomRef(packageData) {
|
|
|
1977
2097
|
return `library:${packageData["name"]}:${packageData["version"] || ""}`;
|
|
1978
2098
|
}
|
|
1979
2099
|
|
|
2100
|
+
/**
|
|
2101
|
+
* Return the download url of a pixi.lock package, without credentials, query
|
|
2102
|
+
* or fragment. A private conda channel can carry its access token in a
|
|
2103
|
+
* `/t/<token>/` path segment, so such a url is left out.
|
|
2104
|
+
*
|
|
2105
|
+
* @param {unknown} url Package url from pixi.lock
|
|
2106
|
+
* @returns {string|undefined} Distribution url
|
|
2107
|
+
*/
|
|
2108
|
+
function pixiDistributionUrl(url) {
|
|
2109
|
+
if (typeof url !== "string" || !url.trim()) {
|
|
2110
|
+
return undefined;
|
|
2111
|
+
}
|
|
2112
|
+
const sanitized = sanitizeBomUrl(url);
|
|
2113
|
+
try {
|
|
2114
|
+
const parsed = new URL(sanitized);
|
|
2115
|
+
if (
|
|
2116
|
+
!["http:", "https:"].includes(parsed.protocol) ||
|
|
2117
|
+
parsed.pathname.split("/").includes("t")
|
|
2118
|
+
) {
|
|
2119
|
+
return undefined;
|
|
2120
|
+
}
|
|
2121
|
+
} catch {
|
|
2122
|
+
return undefined;
|
|
2123
|
+
}
|
|
2124
|
+
return sanitized;
|
|
2125
|
+
}
|
|
2126
|
+
|
|
1980
2127
|
/**
|
|
1981
2128
|
* Method to parse pixi.lock data
|
|
1982
2129
|
*
|
|
@@ -2066,10 +2213,13 @@ export function parsePixiLockFile(pixiLockFileName, path) {
|
|
|
2066
2213
|
*
|
|
2067
2214
|
*/
|
|
2068
2215
|
const purlTemplate = createPurlTemplate(packageData);
|
|
2216
|
+
const distributionUrl = pixiDistributionUrl(packageData["url"]);
|
|
2069
2217
|
return {
|
|
2070
2218
|
name: packageData["name"],
|
|
2071
2219
|
version: packageData["version"],
|
|
2072
2220
|
...(purlTemplate ? { purl: purlTemplate } : {}),
|
|
2221
|
+
// The package download url becomes a distribution external reference.
|
|
2222
|
+
...(distributionUrl ? { distribution: { url: distributionUrl } } : {}),
|
|
2073
2223
|
type: "library",
|
|
2074
2224
|
"bom-ref": createPixiBomRef(packageData),
|
|
2075
2225
|
// "licenses": [
|
|
@@ -2077,10 +2227,8 @@ export function parsePixiLockFile(pixiLockFileName, path) {
|
|
|
2077
2227
|
// "id": packageData["license"]
|
|
2078
2228
|
// }]
|
|
2079
2229
|
// ],
|
|
2080
|
-
supplier
|
|
2081
|
-
|
|
2082
|
-
url: packageData["url"],
|
|
2083
|
-
},
|
|
2230
|
+
// The conda build string is not a supplier, so it stays in
|
|
2231
|
+
// cdx:pixi:build below.
|
|
2084
2232
|
// "hashes": [
|
|
2085
2233
|
// {"md5": packageData["md5"]},
|
|
2086
2234
|
// {"sha256": packageData["sha256"]}
|