@cdxgen/cdxgen 13.3.0 → 13.5.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 +12 -9
- package/bin/cdxgen-secure.js +15 -0
- package/bin/cdxgen.js +115 -31
- package/bin/evinse.js +23 -1
- package/bin/hbom.js +15 -7
- package/bin/repl.js +115 -0
- package/bin/sign.js +45 -15
- package/bin/tracebom.js +5 -1
- package/bin/validate.js +84 -18
- package/bin/verify.js +155 -86
- package/data/cbomosdb-queries.json +13 -1
- package/data/component-tags.json +8 -0
- package/data/helpers/init.gradle +46 -21
- package/data/queries-darwin.json +25 -1
- package/data/queries-win.json +19 -1
- package/data/queries.json +41 -0
- package/data/remediations.json +344 -1
- package/data/rules/cbom-security.yaml +235 -4
- package/data/rules/dependency-sources.yaml +67 -0
- package/data/rules/go-binaries.yaml +46 -0
- package/data/rules/golem-go.yaml +80 -0
- package/data/rules/hbom-compliance.yaml +40 -22
- package/data/rules/hbom-performance.yaml +7 -1
- package/data/rules/host-topology.yaml +1 -1
- package/data/rules/obom-runtime.yaml +31 -2
- package/data/rules/php-runtime.yaml +143 -0
- package/data/rules/scala-evidence.yaml +115 -0
- package/lib/audit/index.js +52 -6
- package/lib/cli/bomAssembly.js +28 -3
- package/lib/cli/cliOptions.js +110 -3
- package/lib/cli/index.js +186 -58
- package/lib/cli/jsBom.js +50 -29
- package/lib/cli/jvmBom.js +779 -146
- package/lib/cli/managedBom.js +1021 -261
- package/lib/cli/nativeBom.js +364 -58
- package/lib/core/activity.js +12 -0
- package/lib/core/env.js +47 -17
- package/lib/core/fs.js +31 -21
- package/lib/core/httpClient.js +233 -69
- package/lib/core/pluginRun.js +184 -0
- package/lib/core/processTree.js +100 -0
- package/lib/core/projectConfig.js +1 -0
- package/lib/core/projectTooling.js +97 -0
- package/lib/core/propertySanitizer.js +72 -0
- package/lib/core/runState.js +39 -0
- package/lib/core/toml.js +72 -0
- package/lib/ecosystems/asarutils.js +4 -2
- package/lib/ecosystems/bunutils.js +5 -7
- package/lib/ecosystems/cargoCache.js +231 -8
- package/lib/ecosystems/cmakeResolver.js +10 -21
- package/lib/ecosystems/cppBuildContext.js +631 -0
- package/lib/ecosystems/cppEvidence.js +337 -22
- package/lib/ecosystems/cppIncludeResolver.js +294 -0
- package/lib/ecosystems/denoutils.js +93 -66
- package/lib/ecosystems/ecosystems.js +1967 -788
- package/lib/ecosystems/golem.js +578 -18
- package/lib/ecosystems/gradleutils.js +340 -46
- package/lib/ecosystems/jsEvidence.js +85 -24
- package/lib/ecosystems/kosi.js +21 -4
- package/lib/ecosystems/npmutils.js +64 -0
- package/lib/ecosystems/parsers-dotnet.js +668 -153
- package/lib/ecosystems/parsers-elm.js +46 -28
- package/lib/ecosystems/parsers-gleam.js +3 -4
- package/lib/ecosystems/parsers-go.js +1283 -297
- package/lib/ecosystems/parsers-js.js +92 -26
- package/lib/ecosystems/parsers-julia.js +2 -3
- package/lib/ecosystems/parsers-jvm.js +463 -29
- package/lib/ecosystems/parsers-misc.js +405 -93
- package/lib/ecosystems/parsers-python.js +152 -20
- package/lib/ecosystems/parsers-rust.js +4 -4
- package/lib/ecosystems/parsers-terraform.js +1573 -19
- package/lib/ecosystems/pythonutils.js +102 -6
- package/lib/ecosystems/remote/huggingface.js +3 -0
- package/lib/ecosystems/rubyutils.js +73 -20
- package/lib/ecosystems/rusi.js +32 -9
- package/lib/ecosystems/sbtutils.js +243 -187
- package/lib/ecosystems/scalacliutils.js +343 -0
- package/lib/ecosystems/scalasem.js +2620 -0
- package/lib/ecosystems/terraformRegistry.js +288 -0
- package/lib/ecosystems/utils.js +2 -0
- package/lib/ecosystems/vendoredCode.js +156 -0
- package/lib/evinser/evinser.js +695 -78
- package/lib/evinser/swiftsem.js +68 -5
- package/lib/helpers/agenticToolutils.js +2 -2
- package/lib/helpers/bomSigner.js +576 -128
- package/lib/inventory/agentSkillSpec.js +17 -0
- package/lib/inventory/aiCollector.js +4 -1
- package/lib/inventory/analyzer.js +110 -127
- package/lib/inventory/apkInstalledDb.js +243 -0
- package/lib/inventory/atomUtils.js +204 -48
- package/lib/inventory/auditCategories.js +10 -3
- package/lib/inventory/buildToolRateLimit.js +144 -0
- package/lib/inventory/cacheCommands.js +2 -1
- package/lib/inventory/cacheDir.js +52 -9
- package/lib/inventory/certificates.js +2371 -0
- package/lib/inventory/cmakeBuildDirs.js +254 -0
- package/lib/inventory/communityAiConfigParser.js +4 -9
- package/lib/inventory/deps.js +507 -128
- package/lib/inventory/display.js +200 -3
- package/lib/inventory/dosai.js +747 -101
- package/lib/inventory/dosaiParsers.js +310 -15
- package/lib/inventory/dynamic.js +96 -8
- package/lib/inventory/envcontext.js +168 -5
- package/lib/inventory/evidenceUtils.js +590 -132
- package/lib/inventory/fetchBatch.js +574 -38
- package/lib/inventory/fetchDiskCache.js +597 -0
- package/lib/inventory/forgeEnricher.js +14 -5
- package/lib/inventory/formulationParsers.js +3 -2
- package/lib/inventory/goBuildInfo.js +140 -0
- package/lib/inventory/hbom.js +67 -7
- package/lib/inventory/hbomAnalysis.js +16 -0
- package/lib/inventory/hostTopology.js +21 -0
- package/lib/inventory/jvmLocalRepos.js +917 -0
- package/lib/inventory/mcpConfigParser.js +2 -3
- package/lib/inventory/osPackagePurl.js +244 -0
- package/lib/inventory/osPackageResolver.js +89 -87
- package/lib/inventory/osinfo.js +79 -31
- package/lib/inventory/osqueryTransform.js +114 -5
- package/lib/inventory/parentSelection.js +146 -0
- package/lib/inventory/phpBuildInfo.js +487 -0
- package/lib/inventory/phpHostProbe.js +641 -0
- package/lib/inventory/rootfsCerts.js +426 -0
- package/lib/inventory/rustFormulationParser.js +3 -4
- package/lib/inventory/scalaCoords.js +153 -0
- package/lib/inventory/source.js +215 -11
- package/lib/inventory/spdx.js +245 -0
- package/lib/inventory/traceRunner.js +93 -8
- package/lib/inventory/tracedCrypto.js +423 -0
- package/lib/managers/binary.js +529 -183
- package/lib/managers/docker.js +199 -44
- package/lib/managers/oci.js +24 -2
- package/lib/parsers/cmakeCache.js +69 -0
- package/lib/parsers/cmakeLists.js +16 -2
- package/lib/parsers/cmakePresets.js +400 -0
- package/lib/parsers/compileCommands.js +557 -0
- package/lib/parsers/email.js +277 -0
- package/lib/parsers/largeJson.js +34 -2
- package/lib/parsers/strictJson.js +322 -0
- package/lib/parsers/terraformConfig.js +1073 -0
- package/lib/parsers/terraformSource.js +652 -0
- package/lib/server/server.js +209 -1
- package/lib/stages/postgen/annotator.js +17 -1
- package/lib/stages/postgen/introspection/markers.js +1 -1
- package/lib/stages/postgen/introspection/reflect.js +4 -1
- package/lib/stages/postgen/postgen.js +20 -6
- package/lib/stages/postgen/ruleEngine.js +58 -1
- package/lib/stages/postgen/specVersionCompat.js +62 -0
- package/lib/stages/pregen/pregen.js +117 -5
- package/lib/validator/bomValidator.js +26 -5
- package/lib/validator/generated/runtime.mjs +13 -0
- package/lib/validator/generated/validate-1.6.mjs +26 -7
- package/lib/validator/generated/validate-1.7.mjs +31 -12
- package/lib/validator/generated/validate-2.0.mjs +30 -11
- package/lib/validator/index.js +25 -10
- package/lib/validator/reporters/json.js +1 -0
- package/package.json +23 -23
- package/types/bin/cdxgen-secure.d.ts +3 -0
- package/types/bin/cdxgen-secure.d.ts.map +1 -0
- package/types/bin/repl.d.ts.map +1 -1
- package/types/lib/audit/index.d.ts.map +1 -1
- package/types/lib/cli/bomAssembly.d.ts +9 -2
- package/types/lib/cli/bomAssembly.d.ts.map +1 -1
- package/types/lib/cli/cliOptions.d.ts +43 -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.map +1 -1
- package/types/lib/cli/jvmBom.d.ts +44 -1
- package/types/lib/cli/jvmBom.d.ts.map +1 -1
- package/types/lib/cli/managedBom.d.ts +7 -4
- package/types/lib/cli/managedBom.d.ts.map +1 -1
- package/types/lib/cli/nativeBom.d.ts +3 -1
- package/types/lib/cli/nativeBom.d.ts.map +1 -1
- package/types/lib/core/activity.d.ts.map +1 -1
- package/types/lib/core/env.d.ts +27 -2
- package/types/lib/core/env.d.ts.map +1 -1
- package/types/lib/core/fs.d.ts.map +1 -1
- package/types/lib/core/httpClient.d.ts +13 -8
- package/types/lib/core/httpClient.d.ts.map +1 -1
- package/types/lib/core/pluginRun.d.ts +97 -0
- package/types/lib/core/pluginRun.d.ts.map +1 -0
- package/types/lib/core/processTree.d.ts +36 -0
- package/types/lib/core/processTree.d.ts.map +1 -0
- package/types/lib/core/projectConfig.d.ts.map +1 -1
- package/types/lib/core/projectTooling.d.ts +41 -0
- package/types/lib/core/projectTooling.d.ts.map +1 -0
- package/types/lib/core/propertySanitizer.d.ts +26 -0
- package/types/lib/core/propertySanitizer.d.ts.map +1 -1
- package/types/lib/core/runState.d.ts +29 -0
- package/types/lib/core/runState.d.ts.map +1 -0
- package/types/lib/core/toml.d.ts +20 -0
- package/types/lib/core/toml.d.ts.map +1 -0
- package/types/lib/ecosystems/asarutils.d.ts.map +1 -1
- package/types/lib/ecosystems/bunutils.d.ts.map +1 -1
- package/types/lib/ecosystems/cargoCache.d.ts +12 -0
- package/types/lib/ecosystems/cargoCache.d.ts.map +1 -1
- package/types/lib/ecosystems/cmakeResolver.d.ts +5 -3
- package/types/lib/ecosystems/cmakeResolver.d.ts.map +1 -1
- package/types/lib/ecosystems/cppBuildContext.d.ts +55 -0
- package/types/lib/ecosystems/cppBuildContext.d.ts.map +1 -0
- package/types/lib/ecosystems/cppEvidence.d.ts +19 -3
- package/types/lib/ecosystems/cppEvidence.d.ts.map +1 -1
- package/types/lib/ecosystems/cppIncludeResolver.d.ts +92 -0
- package/types/lib/ecosystems/cppIncludeResolver.d.ts.map +1 -0
- package/types/lib/ecosystems/denoutils.d.ts +9 -3
- package/types/lib/ecosystems/denoutils.d.ts.map +1 -1
- package/types/lib/ecosystems/ecosystems.d.ts +62 -13
- package/types/lib/ecosystems/ecosystems.d.ts.map +1 -1
- package/types/lib/ecosystems/golem.d.ts +81 -1
- package/types/lib/ecosystems/golem.d.ts.map +1 -1
- package/types/lib/ecosystems/gradleutils.d.ts +59 -7
- package/types/lib/ecosystems/gradleutils.d.ts.map +1 -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/npmutils.d.ts +15 -0
- package/types/lib/ecosystems/npmutils.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-dotnet.d.ts +155 -5
- package/types/lib/ecosystems/parsers-dotnet.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-elm.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-gleam.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-go.d.ts +119 -5
- package/types/lib/ecosystems/parsers-go.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-js.d.ts +6 -1
- package/types/lib/ecosystems/parsers-js.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-julia.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-jvm.d.ts +74 -3
- package/types/lib/ecosystems/parsers-jvm.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-misc.d.ts +21 -59
- package/types/lib/ecosystems/parsers-misc.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-python.d.ts +57 -6
- package/types/lib/ecosystems/parsers-python.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-terraform.d.ts +38 -21
- package/types/lib/ecosystems/parsers-terraform.d.ts.map +1 -1
- package/types/lib/ecosystems/pythonutils.d.ts +26 -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 +21 -1
- package/types/lib/ecosystems/rubyutils.d.ts.map +1 -1
- package/types/lib/ecosystems/rusi.d.ts.map +1 -1
- package/types/lib/ecosystems/sbtutils.d.ts +88 -2
- package/types/lib/ecosystems/sbtutils.d.ts.map +1 -1
- package/types/lib/ecosystems/scalacliutils.d.ts +56 -0
- package/types/lib/ecosystems/scalacliutils.d.ts.map +1 -0
- package/types/lib/ecosystems/scalasem.d.ts +311 -0
- package/types/lib/ecosystems/scalasem.d.ts.map +1 -0
- package/types/lib/ecosystems/terraformRegistry.d.ts +9 -0
- package/types/lib/ecosystems/terraformRegistry.d.ts.map +1 -0
- package/types/lib/ecosystems/utils.d.ts +2 -2
- package/types/lib/ecosystems/utils.d.ts.map +1 -1
- package/types/lib/ecosystems/vendoredCode.d.ts +32 -0
- package/types/lib/ecosystems/vendoredCode.d.ts.map +1 -0
- package/types/lib/evinser/evinser.d.ts +100 -8
- package/types/lib/evinser/evinser.d.ts.map +1 -1
- package/types/lib/evinser/swiftsem.d.ts +10 -0
- package/types/lib/evinser/swiftsem.d.ts.map +1 -1
- package/types/lib/helpers/bomSigner.d.ts +80 -4
- package/types/lib/helpers/bomSigner.d.ts.map +1 -1
- package/types/lib/inventory/agentSkillSpec.d.ts +13 -0
- package/types/lib/inventory/agentSkillSpec.d.ts.map +1 -0
- package/types/lib/inventory/aiCollector.d.ts.map +1 -1
- package/types/lib/inventory/analyzer.d.ts.map +1 -1
- package/types/lib/inventory/apkInstalledDb.d.ts +42 -0
- package/types/lib/inventory/apkInstalledDb.d.ts.map +1 -0
- package/types/lib/inventory/atomUtils.d.ts +96 -10
- package/types/lib/inventory/atomUtils.d.ts.map +1 -1
- package/types/lib/inventory/auditCategories.d.ts +3 -0
- package/types/lib/inventory/auditCategories.d.ts.map +1 -1
- package/types/lib/inventory/buildToolRateLimit.d.ts +38 -0
- package/types/lib/inventory/buildToolRateLimit.d.ts.map +1 -0
- package/types/lib/inventory/cacheCommands.d.ts +2 -1
- package/types/lib/inventory/cacheCommands.d.ts.map +1 -1
- package/types/lib/inventory/cacheDir.d.ts +12 -4
- package/types/lib/inventory/cacheDir.d.ts.map +1 -1
- package/types/lib/inventory/certificates.d.ts +205 -0
- package/types/lib/inventory/certificates.d.ts.map +1 -0
- package/types/lib/inventory/cmakeBuildDirs.d.ts +58 -0
- package/types/lib/inventory/cmakeBuildDirs.d.ts.map +1 -0
- package/types/lib/inventory/communityAiConfigParser.d.ts.map +1 -1
- package/types/lib/inventory/deps.d.ts +61 -2
- package/types/lib/inventory/deps.d.ts.map +1 -1
- package/types/lib/inventory/display.d.ts +18 -0
- package/types/lib/inventory/display.d.ts.map +1 -1
- package/types/lib/inventory/dosai.d.ts +202 -14
- package/types/lib/inventory/dosai.d.ts.map +1 -1
- package/types/lib/inventory/dosaiParsers.d.ts +53 -7
- package/types/lib/inventory/dosaiParsers.d.ts.map +1 -1
- package/types/lib/inventory/dynamic.d.ts +16 -1
- package/types/lib/inventory/dynamic.d.ts.map +1 -1
- package/types/lib/inventory/envcontext.d.ts +40 -2
- package/types/lib/inventory/envcontext.d.ts.map +1 -1
- package/types/lib/inventory/evidenceUtils.d.ts +48 -14
- package/types/lib/inventory/evidenceUtils.d.ts.map +1 -1
- package/types/lib/inventory/fetchBatch.d.ts +83 -14
- package/types/lib/inventory/fetchBatch.d.ts.map +1 -1
- package/types/lib/inventory/fetchDiskCache.d.ts +169 -0
- package/types/lib/inventory/fetchDiskCache.d.ts.map +1 -0
- package/types/lib/inventory/forgeEnricher.d.ts.map +1 -1
- package/types/lib/inventory/formulationParsers.d.ts.map +1 -1
- package/types/lib/inventory/goBuildInfo.d.ts +10 -0
- package/types/lib/inventory/goBuildInfo.d.ts.map +1 -0
- package/types/lib/inventory/hbom.d.ts.map +1 -1
- package/types/lib/inventory/hbomAnalysis.d.ts +10 -0
- package/types/lib/inventory/hbomAnalysis.d.ts.map +1 -1
- package/types/lib/inventory/hostTopology.d.ts.map +1 -1
- package/types/lib/inventory/jvmLocalRepos.d.ts +178 -0
- package/types/lib/inventory/jvmLocalRepos.d.ts.map +1 -0
- package/types/lib/inventory/mcpConfigParser.d.ts.map +1 -1
- package/types/lib/inventory/osPackagePurl.d.ts +99 -0
- package/types/lib/inventory/osPackagePurl.d.ts.map +1 -0
- package/types/lib/inventory/osPackageResolver.d.ts +6 -2
- package/types/lib/inventory/osPackageResolver.d.ts.map +1 -1
- package/types/lib/inventory/osinfo.d.ts +31 -6
- package/types/lib/inventory/osinfo.d.ts.map +1 -1
- package/types/lib/inventory/osqueryTransform.d.ts +51 -0
- package/types/lib/inventory/osqueryTransform.d.ts.map +1 -1
- package/types/lib/inventory/parentSelection.d.ts +34 -0
- package/types/lib/inventory/parentSelection.d.ts.map +1 -0
- package/types/lib/inventory/phpBuildInfo.d.ts +142 -0
- package/types/lib/inventory/phpBuildInfo.d.ts.map +1 -0
- package/types/lib/inventory/phpHostProbe.d.ts +35 -0
- package/types/lib/inventory/phpHostProbe.d.ts.map +1 -0
- package/types/lib/inventory/rootfsCerts.d.ts +27 -0
- package/types/lib/inventory/rootfsCerts.d.ts.map +1 -0
- package/types/lib/inventory/rustFormulationParser.d.ts.map +1 -1
- package/types/lib/inventory/scalaCoords.d.ts +80 -0
- package/types/lib/inventory/scalaCoords.d.ts.map +1 -0
- package/types/lib/inventory/source.d.ts +28 -0
- package/types/lib/inventory/source.d.ts.map +1 -1
- package/types/lib/inventory/spdx.d.ts +24 -0
- package/types/lib/inventory/spdx.d.ts.map +1 -1
- package/types/lib/inventory/traceRunner.d.ts +16 -1
- package/types/lib/inventory/traceRunner.d.ts.map +1 -1
- package/types/lib/inventory/tracedCrypto.d.ts +64 -0
- package/types/lib/inventory/tracedCrypto.d.ts.map +1 -0
- package/types/lib/managers/binary.d.ts +10 -0
- 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/managers/oci.d.ts +3 -1
- package/types/lib/managers/oci.d.ts.map +1 -1
- package/types/lib/parsers/cmakeCache.d.ts +16 -0
- package/types/lib/parsers/cmakeCache.d.ts.map +1 -1
- package/types/lib/parsers/cmakeLists.d.ts +2 -1
- package/types/lib/parsers/cmakeLists.d.ts.map +1 -1
- package/types/lib/parsers/cmakePresets.d.ts +78 -0
- package/types/lib/parsers/cmakePresets.d.ts.map +1 -0
- package/types/lib/parsers/compileCommands.d.ts +115 -0
- package/types/lib/parsers/compileCommands.d.ts.map +1 -0
- package/types/lib/parsers/email.d.ts +19 -0
- package/types/lib/parsers/email.d.ts.map +1 -0
- package/types/lib/parsers/largeJson.d.ts +13 -0
- package/types/lib/parsers/largeJson.d.ts.map +1 -1
- package/types/lib/parsers/strictJson.d.ts +46 -0
- package/types/lib/parsers/strictJson.d.ts.map +1 -0
- package/types/lib/parsers/terraformConfig.d.ts +70 -0
- package/types/lib/parsers/terraformConfig.d.ts.map +1 -0
- package/types/lib/parsers/terraformSource.d.ts +66 -0
- package/types/lib/parsers/terraformSource.d.ts.map +1 -0
- package/types/lib/server/server.d.ts +8 -0
- package/types/lib/server/server.d.ts.map +1 -1
- package/types/lib/stages/postgen/annotator.d.ts.map +1 -1
- package/types/lib/stages/postgen/introspection/reflect.d.ts.map +1 -1
- package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
- package/types/lib/stages/postgen/ruleEngine.d.ts +7 -4
- package/types/lib/stages/postgen/ruleEngine.d.ts.map +1 -1
- package/types/lib/stages/postgen/specVersionCompat.d.ts.map +1 -1
- package/types/lib/stages/pregen/pregen.d.ts +14 -1
- package/types/lib/stages/pregen/pregen.d.ts.map +1 -1
- package/types/lib/validator/bomValidator.d.ts.map +1 -1
- package/types/lib/validator/index.d.ts +8 -0
- package/types/lib/validator/index.d.ts.map +1 -1
- package/types/lib/validator/reporters/json.d.ts.map +1 -1
- package/lib/third-party/arborist/snapshots/calc-dep-flags.test.cjs +0 -462
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
sep as _sep,
|
|
5
5
|
basename,
|
|
6
6
|
dirname,
|
|
7
|
+
isAbsolute,
|
|
7
8
|
join,
|
|
8
9
|
relative,
|
|
9
10
|
resolve,
|
|
@@ -13,14 +14,15 @@ import { build, Purl } from "@cdxgen/cdx-purl";
|
|
|
13
14
|
import { parse as _load } from "yaml";
|
|
14
15
|
|
|
15
16
|
import {
|
|
16
|
-
cdxgenAgent,
|
|
17
17
|
DEBUG_MODE,
|
|
18
|
+
hasDangerousUnicode,
|
|
18
19
|
readEnvironmentVariable,
|
|
19
20
|
} from "../core/activity.js";
|
|
20
21
|
import { recordDegradation } from "../core/buildLedger.js";
|
|
21
22
|
import { deferFailOnError } from "../core/deferredExit.js";
|
|
22
23
|
import { shouldFetchLicense } from "../core/env.js";
|
|
23
24
|
import {
|
|
25
|
+
getTmpDir,
|
|
24
26
|
safeExistsSync,
|
|
25
27
|
safeSpawnSync,
|
|
26
28
|
safeWriteSync,
|
|
@@ -28,10 +30,16 @@ import {
|
|
|
28
30
|
} from "../core/fs.js";
|
|
29
31
|
import { thoughtLog } from "../core/logger.js";
|
|
30
32
|
import { isWin } from "../core/paths.js";
|
|
33
|
+
import {
|
|
34
|
+
isProjectToolingAllowed,
|
|
35
|
+
reportProjectToolingSkipped,
|
|
36
|
+
} from "../core/projectTooling.js";
|
|
37
|
+
import { registerRunReset } from "../core/runState.js";
|
|
31
38
|
import { mesonWrapDB } from "../core/state.js";
|
|
32
39
|
import { isGitHubUrl } from "../core/urls.js";
|
|
33
40
|
import { parseWorkflowFile } from "../inventory/ciParsers/githubActions.js";
|
|
34
41
|
import {
|
|
42
|
+
gatedGet,
|
|
35
43
|
prefetchEnabled,
|
|
36
44
|
prefetchedResponse,
|
|
37
45
|
prefetchJson,
|
|
@@ -45,6 +53,7 @@ import {
|
|
|
45
53
|
} from "../inventory/purl.js";
|
|
46
54
|
import { getLicenses, spdxLicenses } from "../inventory/spdx.js";
|
|
47
55
|
import { cmakeFetchDependencies } from "../parsers/cmakeLists.js";
|
|
56
|
+
import { isValidIdnEmail } from "../parsers/email.js";
|
|
48
57
|
import { submodulePurlCoordinates } from "../parsers/gitmodules.js";
|
|
49
58
|
import { getDartMetadata } from "./ecosystems.js";
|
|
50
59
|
import { parsePkgJson } from "./parsers-js.js";
|
|
@@ -59,6 +68,22 @@ import { parsePkgJson } from "./parsers-js.js";
|
|
|
59
68
|
*/
|
|
60
69
|
const MAX_FLAKE_INPUTS_BLOCK_LENGTH = 16 * 1024;
|
|
61
70
|
|
|
71
|
+
/**
|
|
72
|
+
* Whether a package registry can hold a pubspec.lock entry.
|
|
73
|
+
*
|
|
74
|
+
* The entry's `source` names where the package comes from. `sdk` packages ship
|
|
75
|
+
* with the Dart or Flutter SDK, `path` packages live in the working tree, and
|
|
76
|
+
* `git` packages come from a repository. None is published on a registry, and
|
|
77
|
+
* asking about them leaks their names and imports a look-alike's metadata.
|
|
78
|
+
*
|
|
79
|
+
* @param {Object} packageData One pubspec.lock `packages` entry.
|
|
80
|
+
* @returns {boolean}
|
|
81
|
+
*/
|
|
82
|
+
function canPubRegistryServe(packageData) {
|
|
83
|
+
const source = packageData?.source;
|
|
84
|
+
return source === undefined || source === "hosted";
|
|
85
|
+
}
|
|
86
|
+
|
|
62
87
|
/**
|
|
63
88
|
* Method to parse pubspec.lock files.
|
|
64
89
|
*
|
|
@@ -71,10 +96,11 @@ export async function parsePubLockData(pubLockData, lockFile) {
|
|
|
71
96
|
if (!pubLockData) {
|
|
72
97
|
return [];
|
|
73
98
|
}
|
|
74
|
-
|
|
99
|
+
const pkgList = [];
|
|
75
100
|
const rootList = [];
|
|
76
101
|
const data = _load(pubLockData);
|
|
77
102
|
const packages = data.packages;
|
|
103
|
+
const lookupList = [];
|
|
78
104
|
for (const [packageName, packageData] of Object.entries(packages)) {
|
|
79
105
|
const pkg = {
|
|
80
106
|
name: packageName,
|
|
@@ -131,9 +157,15 @@ export async function parsePubLockData(pubLockData, lockFile) {
|
|
|
131
157
|
};
|
|
132
158
|
}
|
|
133
159
|
pkgList.push(pkg);
|
|
160
|
+
if (canPubRegistryServe(packageData)) {
|
|
161
|
+
lookupList.push(pkg);
|
|
162
|
+
}
|
|
134
163
|
}
|
|
135
164
|
if (shouldFetchLicense()) {
|
|
136
|
-
|
|
165
|
+
// getDartMetadata enriches in place, so the sdk, path and git packages
|
|
166
|
+
// stay in pkgList with the lockfile's answers and are simply not handed
|
|
167
|
+
// to it.
|
|
168
|
+
await getDartMetadata(lookupList);
|
|
137
169
|
}
|
|
138
170
|
return { rootList, pkgList };
|
|
139
171
|
}
|
|
@@ -1533,11 +1565,146 @@ export function parseComposerJson(composerJsonFile) {
|
|
|
1533
1565
|
return { rootRequires, moduleParent };
|
|
1534
1566
|
}
|
|
1535
1567
|
|
|
1568
|
+
// Composer's platform packages stand for what the runtime provides, and none
|
|
1569
|
+
// is installable, so none has a purl or an edge in the dependency graph. These
|
|
1570
|
+
// are the ones that describe PHP: PHP and its build flavours, HHVM, and the
|
|
1571
|
+
// extensions and system libraries PHP was built with. composer,
|
|
1572
|
+
// composer-plugin-api and composer-runtime-api are platform packages too, but
|
|
1573
|
+
// they describe Composer, so they are left out.
|
|
1574
|
+
// https://github.com/composer/composer/blob/2.10.3/src/Composer/Repository/PlatformRepository.php#L39
|
|
1575
|
+
const COMPOSER_PLATFORM_NAMES = new Set([
|
|
1576
|
+
"php",
|
|
1577
|
+
"php-64bit",
|
|
1578
|
+
"php-ipv6",
|
|
1579
|
+
"php-zts",
|
|
1580
|
+
"php-debug",
|
|
1581
|
+
"hhvm",
|
|
1582
|
+
]);
|
|
1583
|
+
|
|
1584
|
+
function isComposerPlatformRequirement(name) {
|
|
1585
|
+
return (
|
|
1586
|
+
COMPOSER_PLATFORM_NAMES.has(name) ||
|
|
1587
|
+
name.startsWith("ext-") ||
|
|
1588
|
+
name.startsWith("lib-")
|
|
1589
|
+
);
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1592
|
+
// What the lock records about the platform is a constraint, or the version a
|
|
1593
|
+
// project told Composer to assume. It is a fact about the project's
|
|
1594
|
+
// requirements, never the version of anything that runs, so it is kept as a
|
|
1595
|
+
// property and never becomes a component.
|
|
1596
|
+
const COMPOSER_PLATFORM_SECTIONS = [
|
|
1597
|
+
["platform", "cdx:composer:platform:"],
|
|
1598
|
+
["platform-dev", "cdx:composer:platformDev:"],
|
|
1599
|
+
["platform-overrides", "cdx:composer:platformOverride:"],
|
|
1600
|
+
];
|
|
1601
|
+
const COMPOSER_REQUIRE_PREFIX = "cdx:composer:require:";
|
|
1602
|
+
const MAX_COMPOSER_PLATFORM_VALUE_LENGTH = 256;
|
|
1603
|
+
// A real lock names a few dozen platform packages per map at most; the cap
|
|
1604
|
+
// keeps a crafted one from turning each map into thousands of properties.
|
|
1605
|
+
const MAX_COMPOSER_PLATFORM_ENTRIES = 128;
|
|
1606
|
+
|
|
1607
|
+
function isComposerPlatformKey(key) {
|
|
1608
|
+
return /^[A-Za-z0-9._-]{1,100}$/.test(key);
|
|
1609
|
+
}
|
|
1610
|
+
|
|
1611
|
+
/**
|
|
1612
|
+
* The value a platform entry carries as a property: a constraint or version
|
|
1613
|
+
* string, or `false`, which `config.platform` uses to disable a package:
|
|
1614
|
+
* https://github.com/composer/composer/blob/2.10.3/src/Composer/Repository/PlatformRepository.php#L125
|
|
1615
|
+
*
|
|
1616
|
+
* @param {unknown} value value from the lock
|
|
1617
|
+
* @returns {string|undefined} property value, or undefined when it is not one
|
|
1618
|
+
*/
|
|
1619
|
+
function composerPlatformValue(value) {
|
|
1620
|
+
if (value === false) {
|
|
1621
|
+
return "false";
|
|
1622
|
+
}
|
|
1623
|
+
if (typeof value !== "string") {
|
|
1624
|
+
return undefined;
|
|
1625
|
+
}
|
|
1626
|
+
const trimmed = value.trim();
|
|
1627
|
+
if (
|
|
1628
|
+
!trimmed ||
|
|
1629
|
+
trimmed.length > MAX_COMPOSER_PLATFORM_VALUE_LENGTH ||
|
|
1630
|
+
hasDangerousUnicode(trimmed) ||
|
|
1631
|
+
/[\t\n\r]/.test(trimmed)
|
|
1632
|
+
) {
|
|
1633
|
+
return undefined;
|
|
1634
|
+
}
|
|
1635
|
+
return trimmed;
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1638
|
+
/**
|
|
1639
|
+
* Turn a map of platform entries into properties named `<prefix><name>`, in
|
|
1640
|
+
* name order, at most MAX_COMPOSER_PLATFORM_ENTRIES of them. Over the cap the
|
|
1641
|
+
* PHP and HHVM entries are kept first, since `ext-*` sorts before `php`. An
|
|
1642
|
+
* array (Composer writes an empty section as `[]`) or any other shape holds no
|
|
1643
|
+
* entries.
|
|
1644
|
+
*
|
|
1645
|
+
* @param {unknown} entries map of requirement name to constraint
|
|
1646
|
+
* @param {string} prefix property name prefix
|
|
1647
|
+
* @param {function(string): boolean} [keep] which names to keep
|
|
1648
|
+
* @returns {{name: string, value: string}[]} properties
|
|
1649
|
+
*/
|
|
1650
|
+
function composerPlatformProperties(entries, prefix, keep = () => true) {
|
|
1651
|
+
if (!entries || typeof entries !== "object" || Array.isArray(entries)) {
|
|
1652
|
+
return [];
|
|
1653
|
+
}
|
|
1654
|
+
const kept = [];
|
|
1655
|
+
for (const key of Object.keys(entries).sort()) {
|
|
1656
|
+
const value = composerPlatformValue(entries[key]);
|
|
1657
|
+
if (value !== undefined && isComposerPlatformKey(key) && keep(key)) {
|
|
1658
|
+
kept.push({ key, value });
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1661
|
+
let selected = kept;
|
|
1662
|
+
if (kept.length > MAX_COMPOSER_PLATFORM_ENTRIES) {
|
|
1663
|
+
const runtimes = kept.filter(({ key }) => COMPOSER_PLATFORM_NAMES.has(key));
|
|
1664
|
+
const others = kept
|
|
1665
|
+
.filter(({ key }) => !COMPOSER_PLATFORM_NAMES.has(key))
|
|
1666
|
+
.slice(0, MAX_COMPOSER_PLATFORM_ENTRIES - runtimes.length);
|
|
1667
|
+
const chosen = new Set([...runtimes, ...others]);
|
|
1668
|
+
selected = kept.filter((entry) => chosen.has(entry));
|
|
1669
|
+
}
|
|
1670
|
+
return selected.map(({ key, value }) => ({ name: `${prefix}${key}`, value }));
|
|
1671
|
+
}
|
|
1672
|
+
|
|
1673
|
+
/**
|
|
1674
|
+
* A CycloneDX `organizationalContact` from an author record in package
|
|
1675
|
+
* metadata. The schema asserts `idn-email` on the address, so one that is not
|
|
1676
|
+
* a valid address is dropped rather than failing BOM validation; an author with
|
|
1677
|
+
* neither a name nor a valid address yields nothing.
|
|
1678
|
+
*
|
|
1679
|
+
* @param {{name?: string, email?: unknown}} author Author as the manifest has it
|
|
1680
|
+
* @returns {Array<{name?: string, email?: string}>} Zero or one contact
|
|
1681
|
+
*/
|
|
1682
|
+
function contactFromAuthor(author) {
|
|
1683
|
+
const contact = {};
|
|
1684
|
+
if (typeof author?.name === "string" && author.name.trim()) {
|
|
1685
|
+
contact.name = author.name;
|
|
1686
|
+
}
|
|
1687
|
+
const email = typeof author?.email === "string" ? author.email.trim() : "";
|
|
1688
|
+
if (isValidIdnEmail(email)) {
|
|
1689
|
+
contact.email = email;
|
|
1690
|
+
}
|
|
1691
|
+
return Object.keys(contact).length ? [contact] : [];
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1536
1694
|
/**
|
|
1537
1695
|
* Parse composer lock file
|
|
1538
1696
|
*
|
|
1539
1697
|
* @param {string} pkgLockFile composer.lock file
|
|
1540
1698
|
* @param {array} rootRequires require section from composer.json
|
|
1699
|
+
* @returns {{pkgList: Object[], dependenciesList: Object[], rootList: Object[], platformProperties: {name: string, value: string}[]}|Array}
|
|
1700
|
+
* The locked packages, the dependency edges between them, the packages the
|
|
1701
|
+
* root requires, and the lock's `platform`, `platform-dev` and
|
|
1702
|
+
* `platform-overrides` entries as `cdx:composer:*` properties. The platform
|
|
1703
|
+
* entries are constraints and assumed versions, not the PHP that runs; the
|
|
1704
|
+
* caller puts them on the module component. Every locked package carries its
|
|
1705
|
+
* own `php`, `hhvm`, `ext-*` and `lib-*` requirements as
|
|
1706
|
+
* `cdx:composer:require:<name>` properties. A lock that is not valid JSON
|
|
1707
|
+
* gives an empty array.
|
|
1541
1708
|
*/
|
|
1542
1709
|
export function parseComposerLock(pkgLockFile, rootRequires) {
|
|
1543
1710
|
const pkgList = [];
|
|
@@ -1546,16 +1713,12 @@ export function parseComposerLock(pkgLockFile, rootRequires) {
|
|
|
1546
1713
|
const pkgNamePurlMap = {};
|
|
1547
1714
|
const rootList = [];
|
|
1548
1715
|
const rootRequiresMap = {};
|
|
1716
|
+
let platformProperties = [];
|
|
1549
1717
|
if (rootRequires) {
|
|
1550
1718
|
for (const rr of Object.keys(rootRequires)) {
|
|
1551
1719
|
// Skip platform requirements (php, hhvm, ext-*, lib-*) — they are never
|
|
1552
1720
|
// Composer package names and must not be used to identify root packages.
|
|
1553
|
-
if (
|
|
1554
|
-
rr === "php" ||
|
|
1555
|
-
rr === "hhvm" ||
|
|
1556
|
-
rr.startsWith("ext-") ||
|
|
1557
|
-
rr.startsWith("lib-")
|
|
1558
|
-
) {
|
|
1721
|
+
if (isComposerPlatformRequirement(rr)) {
|
|
1559
1722
|
continue;
|
|
1560
1723
|
}
|
|
1561
1724
|
rootRequiresMap[rr] = true;
|
|
@@ -1570,6 +1733,11 @@ export function parseComposerLock(pkgLockFile, rootRequires) {
|
|
|
1570
1733
|
return [];
|
|
1571
1734
|
}
|
|
1572
1735
|
if (lockData) {
|
|
1736
|
+
for (const [section, prefix] of COMPOSER_PLATFORM_SECTIONS) {
|
|
1737
|
+
platformProperties = platformProperties.concat(
|
|
1738
|
+
composerPlatformProperties(lockData[section], prefix),
|
|
1739
|
+
);
|
|
1740
|
+
}
|
|
1573
1741
|
const packages = {};
|
|
1574
1742
|
if (lockData["packages"]) {
|
|
1575
1743
|
packages["required"] = lockData["packages"];
|
|
@@ -1642,9 +1810,10 @@ export function parseComposerLock(pkgLockFile, rootRequires) {
|
|
|
1642
1810
|
apkg.distribution = { url: distUrl };
|
|
1643
1811
|
}
|
|
1644
1812
|
if (pkg?.authors?.length) {
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1813
|
+
const authors = pkg.authors.flatMap(contactFromAuthor);
|
|
1814
|
+
if (authors.length) {
|
|
1815
|
+
apkg.authors = authors;
|
|
1816
|
+
}
|
|
1648
1817
|
}
|
|
1649
1818
|
if (pkg?.keywords?.length) {
|
|
1650
1819
|
apkg.tags = pkg.keywords;
|
|
@@ -1665,6 +1834,13 @@ export function parseComposerLock(pkgLockFile, rootRequires) {
|
|
|
1665
1834
|
});
|
|
1666
1835
|
}
|
|
1667
1836
|
}
|
|
1837
|
+
apkg.properties.push(
|
|
1838
|
+
...composerPlatformProperties(
|
|
1839
|
+
pkg.require,
|
|
1840
|
+
COMPOSER_REQUIRE_PREFIX,
|
|
1841
|
+
isComposerPlatformRequirement,
|
|
1842
|
+
),
|
|
1843
|
+
);
|
|
1668
1844
|
pkgList.push(apkg);
|
|
1669
1845
|
dependenciesMap[purl] = new Set();
|
|
1670
1846
|
pkgNamePurlMap[pkg.name] = purl;
|
|
@@ -1704,6 +1880,7 @@ export function parseComposerLock(pkgLockFile, rootRequires) {
|
|
|
1704
1880
|
pkgList,
|
|
1705
1881
|
dependenciesList,
|
|
1706
1882
|
rootList,
|
|
1883
|
+
platformProperties,
|
|
1707
1884
|
};
|
|
1708
1885
|
}
|
|
1709
1886
|
|
|
@@ -3002,14 +3179,67 @@ export function parseMakeDFile(dfile) {
|
|
|
3002
3179
|
return pkgFilesMap;
|
|
3003
3180
|
}
|
|
3004
3181
|
|
|
3182
|
+
/**
|
|
3183
|
+
* Resolve a path a lockfile names against the lockfile's directory, refusing
|
|
3184
|
+
* absolute paths and any that leave the scanned directory. The value comes
|
|
3185
|
+
* from the scanned project, so it must not steer the scan at files outside
|
|
3186
|
+
* it. The bound is the scan root, not the lockfile's directory: a React
|
|
3187
|
+
* Native `ios/Podfile` names its pods as `../node_modules/...`.
|
|
3188
|
+
*
|
|
3189
|
+
* @param {String} projectPath Directory of the Podfile.lock
|
|
3190
|
+
* @param {String} value Path as the lockfile writes it
|
|
3191
|
+
* @param {String} [scanRoot] Directory the scan was asked for; the lockfile's
|
|
3192
|
+
* directory when not given
|
|
3193
|
+
* @returns {String|undefined} The resolved path, or undefined when refused
|
|
3194
|
+
*/
|
|
3195
|
+
function resolveInsideScan(projectPath, value, scanRoot = projectPath) {
|
|
3196
|
+
if (typeof value !== "string" || !value.length) {
|
|
3197
|
+
return undefined;
|
|
3198
|
+
}
|
|
3199
|
+
if (
|
|
3200
|
+
isAbsolute(value) ||
|
|
3201
|
+
/^[a-zA-Z]:[\\/]/.test(value) ||
|
|
3202
|
+
value.startsWith("\\\\")
|
|
3203
|
+
) {
|
|
3204
|
+
return undefined;
|
|
3205
|
+
}
|
|
3206
|
+
const resolved = resolve(projectPath, value);
|
|
3207
|
+
const back = relative(resolve(scanRoot), resolved);
|
|
3208
|
+
if (back.startsWith("..") || isAbsolute(back)) {
|
|
3209
|
+
return undefined;
|
|
3210
|
+
}
|
|
3211
|
+
return resolved;
|
|
3212
|
+
}
|
|
3213
|
+
|
|
3214
|
+
/**
|
|
3215
|
+
* Whether a pod name can be used as a file name. Pod names come from the
|
|
3216
|
+
* lockfile and are joined onto directories.
|
|
3217
|
+
*
|
|
3218
|
+
* @param {String} podName Root pod name
|
|
3219
|
+
* @returns {Boolean}
|
|
3220
|
+
*/
|
|
3221
|
+
function isSafePodFileName(podName) {
|
|
3222
|
+
return (
|
|
3223
|
+
typeof podName === "string" &&
|
|
3224
|
+
podName.length > 0 &&
|
|
3225
|
+
!podName.includes("/") &&
|
|
3226
|
+
!podName.includes("\\") &&
|
|
3227
|
+
!podName.includes("\0") &&
|
|
3228
|
+
podName !== "." &&
|
|
3229
|
+
podName !== ".."
|
|
3230
|
+
);
|
|
3231
|
+
}
|
|
3232
|
+
|
|
3005
3233
|
/**
|
|
3006
3234
|
* Parse the contents of a 'Podfile.lock'
|
|
3007
3235
|
*
|
|
3008
3236
|
* @param {Object} podfileLock The content of the podfile.lock as an Object
|
|
3009
3237
|
* @param {String} projectPath The path to the project root
|
|
3238
|
+
* @param {String} [scanRoot] Directory the scan was asked for. Local `:path`
|
|
3239
|
+
* and `:podspec` sources outside it are not read. Defaults to projectPath.
|
|
3010
3240
|
* @returns {Map} Map of all dependencies with their direct dependencies
|
|
3011
3241
|
*/
|
|
3012
|
-
export async function parsePodfileLock(podfileLock, projectPath) {
|
|
3242
|
+
export async function parsePodfileLock(podfileLock, projectPath, scanRoot) {
|
|
3013
3243
|
const dependencies = new Map();
|
|
3014
3244
|
for (const pod of podfileLock["PODS"]) {
|
|
3015
3245
|
const dependency = {};
|
|
@@ -3031,58 +3261,103 @@ export async function parsePodfileLock(podfileLock, projectPath) {
|
|
|
3031
3261
|
dependency.metadata.name.indexOf("/"),
|
|
3032
3262
|
)
|
|
3033
3263
|
: dependency.metadata.name;
|
|
3034
|
-
if (
|
|
3264
|
+
if (
|
|
3265
|
+
podfileLock["EXTERNAL SOURCES"]?.[podName] &&
|
|
3266
|
+
isSafePodFileName(podName)
|
|
3267
|
+
) {
|
|
3035
3268
|
const externalPod = podfileLock["EXTERNAL SOURCES"][podName];
|
|
3036
3269
|
if (externalPod[":git"]) {
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3270
|
+
// The podspec of a checked out pod, which `pod install` writes
|
|
3271
|
+
// alongside the sources it downloaded. Reading it needs no request,
|
|
3272
|
+
// so it answers before any raw repository URL.
|
|
3273
|
+
const localPodspec = join(
|
|
3274
|
+
projectPath,
|
|
3275
|
+
"Pods",
|
|
3276
|
+
"Local Podspecs",
|
|
3277
|
+
`${podName}.podspec.json`,
|
|
3278
|
+
);
|
|
3279
|
+
if (safeExistsSync(localPodspec)) {
|
|
3280
|
+
dependency.metadata.properties = [
|
|
3281
|
+
{
|
|
3282
|
+
name: "cdx:pods:podspecLocation",
|
|
3283
|
+
value: localPodspec,
|
|
3284
|
+
},
|
|
3285
|
+
];
|
|
3286
|
+
} else {
|
|
3287
|
+
let projectRepo = externalPod[":git"];
|
|
3288
|
+
if (isGitHubUrl(projectRepo)) {
|
|
3289
|
+
projectRepo = projectRepo.replace(
|
|
3290
|
+
"github.com",
|
|
3291
|
+
"raw.githubusercontent.com",
|
|
3292
|
+
);
|
|
3293
|
+
}
|
|
3294
|
+
if (projectRepo.endsWith(".git")) {
|
|
3295
|
+
projectRepo = projectRepo.substring(0, projectRepo.length - 4);
|
|
3296
|
+
}
|
|
3297
|
+
// The commit the lockfile recorded in CHECKOUT OPTIONS names the
|
|
3298
|
+
// exact revision CocoaPods checked out, so its podspec is asked
|
|
3299
|
+
// for directly instead of probing the default branch names. It
|
|
3300
|
+
// wins over a branch, whose head may have moved since.
|
|
3301
|
+
const checkoutCommit =
|
|
3302
|
+
podfileLock["CHECKOUT OPTIONS"]?.[podName]?.[":commit"];
|
|
3303
|
+
const projectRepoBranchOrTag =
|
|
3304
|
+
typeof checkoutCommit === "string" &&
|
|
3305
|
+
/^[0-9a-f]{7,64}$/i.test(checkoutCommit)
|
|
3306
|
+
? checkoutCommit
|
|
3307
|
+
: externalPod[":tag"]
|
|
3308
|
+
? `refs/tags/${externalPod[":tag"]}`
|
|
3309
|
+
: externalPod[":branch"]
|
|
3310
|
+
? `refs/heads/${externalPod[":branch"]}`
|
|
3311
|
+
: "refs/heads/<DEFAULT>";
|
|
3312
|
+
dependency.metadata.properties = [
|
|
3313
|
+
{
|
|
3314
|
+
name: "cdx:pods:podspecLocation",
|
|
3315
|
+
value: `${projectRepo}/${projectRepoBranchOrTag}/${podName}.podspec`,
|
|
3316
|
+
},
|
|
3317
|
+
];
|
|
3046
3318
|
}
|
|
3047
|
-
const projectRepoBranchOrTag = externalPod[":tag"]
|
|
3048
|
-
? `tags/${externalPod[":tag"]}`
|
|
3049
|
-
: `heads/${externalPod[":branch"] ? externalPod[":branch"] : "<DEFAULT>"}`;
|
|
3050
|
-
dependency.metadata.properties = [
|
|
3051
|
-
{
|
|
3052
|
-
name: "cdx:pods:podspecLocation",
|
|
3053
|
-
value: `${projectRepo}/refs/${projectRepoBranchOrTag}/${podName}.podspec`,
|
|
3054
|
-
},
|
|
3055
|
-
];
|
|
3056
3319
|
} else if (externalPod[":path"]) {
|
|
3057
|
-
const projectLocation =
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
}
|
|
3320
|
+
const projectLocation = resolveInsideScan(
|
|
3321
|
+
projectPath,
|
|
3322
|
+
externalPod[":path"],
|
|
3323
|
+
scanRoot,
|
|
3324
|
+
);
|
|
3325
|
+
if (projectLocation) {
|
|
3326
|
+
dependency.metadata.properties = [
|
|
3327
|
+
{
|
|
3328
|
+
name: "cdx:pods:projectDir",
|
|
3329
|
+
value: projectLocation,
|
|
3330
|
+
},
|
|
3331
|
+
];
|
|
3332
|
+
let podspec = join(projectLocation, `${podName}.podspec`);
|
|
3333
|
+
if (!safeExistsSync(podspec)) {
|
|
3334
|
+
podspec = `${podspec}.json`;
|
|
3335
|
+
}
|
|
3336
|
+
if (safeExistsSync(podspec)) {
|
|
3337
|
+
dependency.metadata.properties.push({
|
|
3338
|
+
name: "cdx:pods:podspecLocation",
|
|
3339
|
+
value: podspec,
|
|
3340
|
+
});
|
|
3341
|
+
}
|
|
3073
3342
|
}
|
|
3074
3343
|
} else if (externalPod[":podspec"]) {
|
|
3075
|
-
const podspecLocation =
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3344
|
+
const podspecLocation = resolveInsideScan(
|
|
3345
|
+
projectPath,
|
|
3346
|
+
externalPod[":podspec"],
|
|
3347
|
+
scanRoot,
|
|
3348
|
+
);
|
|
3349
|
+
if (podspecLocation) {
|
|
3350
|
+
dependency.metadata.properties = [
|
|
3351
|
+
{
|
|
3352
|
+
name: "cdx:pods:projectDir",
|
|
3353
|
+
value: dirname(podspecLocation),
|
|
3354
|
+
},
|
|
3355
|
+
{
|
|
3356
|
+
name: "cdx:pods:podspecLocation",
|
|
3357
|
+
value: podspecLocation,
|
|
3358
|
+
},
|
|
3359
|
+
];
|
|
3360
|
+
}
|
|
3086
3361
|
}
|
|
3087
3362
|
}
|
|
3088
3363
|
dependencies.set(dependency.metadata.name, dependency);
|
|
@@ -3408,6 +3683,8 @@ export function resetCocoaPodspecPrefetch() {
|
|
|
3408
3683
|
cocoaPodspecPrefetch = new Map();
|
|
3409
3684
|
}
|
|
3410
3685
|
|
|
3686
|
+
registerRunReset("cocoapods:podspecs", resetCocoaPodspecPrefetch);
|
|
3687
|
+
|
|
3411
3688
|
/**
|
|
3412
3689
|
* Prefetch the remote podspecs a full CocoaPods scan is about to read.
|
|
3413
3690
|
*
|
|
@@ -3486,6 +3763,12 @@ async function fullScanCocoaPod(dependency, component, options) {
|
|
|
3486
3763
|
value: podspecLocation,
|
|
3487
3764
|
});
|
|
3488
3765
|
}
|
|
3766
|
+
// A Ruby podspec is a program that only `pod` can read, and it comes from
|
|
3767
|
+
// the scanned project or a repository its lockfile names. Without
|
|
3768
|
+
// permission to run the project's tooling, only JSON podspecs are read,
|
|
3769
|
+
// directly and without `pod`.
|
|
3770
|
+
const toolingAllowed = isProjectToolingAllowed(options);
|
|
3771
|
+
const isRemote = podspecLocation.startsWith("http");
|
|
3489
3772
|
let replacements = [];
|
|
3490
3773
|
if (
|
|
3491
3774
|
podspecLocation.endsWith(".podspec") &&
|
|
@@ -3502,29 +3785,50 @@ async function fullScanCocoaPod(dependency, component, options) {
|
|
|
3502
3785
|
"COCOA_PODSPEC_JSON_REPLACEMENTS",
|
|
3503
3786
|
).split(";");
|
|
3504
3787
|
}
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
httpResult =
|
|
3512
|
-
prefetchedResponse(cocoaPodspecPrefetch, candidate) ||
|
|
3513
|
-
(await cdxgenAgent.get(candidate));
|
|
3514
|
-
podspecLocation = candidate;
|
|
3515
|
-
} catch (_err) {
|
|
3516
|
-
continue;
|
|
3517
|
-
}
|
|
3518
|
-
component.properties.find(
|
|
3519
|
-
({ name }) => name === "cdx:pods:podspecLocation",
|
|
3520
|
-
).value = podspecLocation;
|
|
3521
|
-
podspecLocation = `${randomUUID()}.${podspecLocation.substring(podspecLocation.lastIndexOf(".") + 1)}`;
|
|
3522
|
-
podspecContent = httpResult.body;
|
|
3523
|
-
break;
|
|
3788
|
+
let podspecContent;
|
|
3789
|
+
if (isRemote) {
|
|
3790
|
+
let httpResult;
|
|
3791
|
+
for (const candidate of podspecCandidates(podspecLocation)) {
|
|
3792
|
+
if (!toolingAllowed && !candidate.endsWith(".json")) {
|
|
3793
|
+
continue;
|
|
3524
3794
|
}
|
|
3525
|
-
|
|
3526
|
-
|
|
3795
|
+
try {
|
|
3796
|
+
httpResult =
|
|
3797
|
+
prefetchedResponse(cocoaPodspecPrefetch, candidate) ||
|
|
3798
|
+
(await gatedGet(candidate, { responseType: "text" }));
|
|
3799
|
+
podspecLocation = candidate;
|
|
3800
|
+
} catch (_err) {
|
|
3801
|
+
continue;
|
|
3802
|
+
}
|
|
3803
|
+
component.properties.find(
|
|
3804
|
+
({ name }) => name === "cdx:pods:podspecLocation",
|
|
3805
|
+
).value = podspecLocation;
|
|
3806
|
+
podspecContent = httpResult.body;
|
|
3807
|
+
break;
|
|
3527
3808
|
}
|
|
3809
|
+
// A location none of the candidates served contributes nothing: the
|
|
3810
|
+
// component keeps what the lockfile already said about the pod.
|
|
3811
|
+
if (podspecContent === undefined) {
|
|
3812
|
+
return;
|
|
3813
|
+
}
|
|
3814
|
+
} else if (!toolingAllowed && !podspecLocation.endsWith(".json")) {
|
|
3815
|
+
reportProjectToolingSkipped(
|
|
3816
|
+
options,
|
|
3817
|
+
"cocoa.podspec.tooling-disabled",
|
|
3818
|
+
"Skipping 'pod ipc spec' for Ruby podspecs since dependency installation is disabled. Their pods keep the details from Podfile.lock.",
|
|
3819
|
+
{
|
|
3820
|
+
ecosystem: "cocoa",
|
|
3821
|
+
tool: "pod",
|
|
3822
|
+
impact: "licenses",
|
|
3823
|
+
detail:
|
|
3824
|
+
"Dependency installation is disabled, so Ruby podspecs were not evaluated and their pods lack license and author details.",
|
|
3825
|
+
},
|
|
3826
|
+
);
|
|
3827
|
+
return;
|
|
3828
|
+
} else if (replacements.length || !toolingAllowed) {
|
|
3829
|
+
podspecContent = readFileSync(podspecLocation, "utf-8");
|
|
3830
|
+
}
|
|
3831
|
+
if (podspecContent !== undefined) {
|
|
3528
3832
|
for (const replacement of replacements) {
|
|
3529
3833
|
const replacementPair = replacement.split("=");
|
|
3530
3834
|
let match = replacementPair[0].replaceAll("<NEWLINE>", "\n");
|
|
@@ -3534,18 +3838,28 @@ async function fullScanCocoaPod(dependency, component, options) {
|
|
|
3534
3838
|
const repl = replacementPair[1].replaceAll("<NEWLINE>", "\n");
|
|
3535
3839
|
podspecContent = podspecContent.replaceAll(match, repl);
|
|
3536
3840
|
}
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3841
|
+
}
|
|
3842
|
+
if (!toolingAllowed) {
|
|
3843
|
+
// Only JSON podspecs reach this point, and they need no `pod`
|
|
3844
|
+
result = { stdout: podspecContent };
|
|
3845
|
+
} else {
|
|
3846
|
+
if (podspecContent !== undefined) {
|
|
3847
|
+
// A downloaded podspec goes to the temporary directory; a local one
|
|
3848
|
+
// with replacements stays beside the original, whose relative paths
|
|
3849
|
+
// its Ruby may read.
|
|
3850
|
+
podspecLocation = join(
|
|
3851
|
+
isRemote ? getTmpDir() : dirname(podspecLocation),
|
|
3852
|
+
`${randomUUID()}.${podspecLocation.substring(podspecLocation.lastIndexOf(".") + 1)}`,
|
|
3853
|
+
);
|
|
3854
|
+
safeWriteSync(podspecLocation, podspecContent);
|
|
3855
|
+
temporaryFiles.add(podspecLocation);
|
|
3856
|
+
}
|
|
3857
|
+
result = executePodCommand(
|
|
3858
|
+
["ipc", "spec", "--silent", podspecLocation],
|
|
3859
|
+
undefined,
|
|
3860
|
+
options,
|
|
3540
3861
|
);
|
|
3541
|
-
safeWriteSync(podspecLocation, podspecContent);
|
|
3542
|
-
temporaryFiles.add(podspecLocation);
|
|
3543
3862
|
}
|
|
3544
|
-
result = executePodCommand(
|
|
3545
|
-
["ipc", "spec", "--silent", podspecLocation],
|
|
3546
|
-
undefined,
|
|
3547
|
-
options,
|
|
3548
|
-
);
|
|
3549
3863
|
} else {
|
|
3550
3864
|
let dependencyName = dependency.name;
|
|
3551
3865
|
if (dependencyName.includes("/")) {
|
|
@@ -3610,9 +3924,7 @@ async function fullScanCocoaPod(dependency, component, options) {
|
|
|
3610
3924
|
component.authors = [];
|
|
3611
3925
|
if (podspec.authors.constructor === Object) {
|
|
3612
3926
|
Object.entries(podspec.authors).forEach(([name, email]) => {
|
|
3613
|
-
|
|
3614
|
-
? component.authors.push({ name, email })
|
|
3615
|
-
: component.authors.push({ name });
|
|
3927
|
+
component.authors.push(...contactFromAuthor({ name, email }));
|
|
3616
3928
|
});
|
|
3617
3929
|
} else if (podspec.authors.constructor === Array) {
|
|
3618
3930
|
podspec.authors.forEach((name) => {
|