@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
|
@@ -0,0 +1,487 @@
|
|
|
1
|
+
// Bounded PHP build-version reader for unpackaged PHP binaries and
|
|
2
|
+
// libraries. Recovers the version a source-built PHP carries, so a BOM can
|
|
3
|
+
// answer "does this image ship a PHP affected by CVE-2026-109618/109619".
|
|
4
|
+
//
|
|
5
|
+
// The primary marker comes from php-src: SAPI_PHP_VERSION_HEADER is
|
|
6
|
+
// "X-Powered-By: PHP/" PHP_VERSION and is compiled into every SAPI binary and
|
|
7
|
+
// libphp, e.g. the literal `X-Powered-By: PHP/8.4.26`:
|
|
8
|
+
// https://github.com/php/php-src/blob/php-8.4.27/main/SAPI.h#L309
|
|
9
|
+
// The same definition is present in 7.4 through 8.5 (main/SAPI.h at each tag).
|
|
10
|
+
// If a stripped or unusual build lacks it, the installed php_version.h is read
|
|
11
|
+
// from the same prefix. configure.ac generates its PHP_VERSION line:
|
|
12
|
+
// https://github.com/php/php-src/blob/php-8.4.27/configure.ac#L83-L90
|
|
13
|
+
// and install-headers copies it under $(phpincludedir)/main:
|
|
14
|
+
// https://github.com/php/php-src/blob/php-8.4.27/build/Makefile.global#L52
|
|
15
|
+
//
|
|
16
|
+
// Every file in an image is hostile: only regular files inside the extracted
|
|
17
|
+
// root are opened, reads are capped, and a missing/odd file yields no result
|
|
18
|
+
// rather than throwing.
|
|
19
|
+
//
|
|
20
|
+
// The runtime component helpers at the end are the one place a PHP version
|
|
21
|
+
// becomes a component, for the container scan, the OS scan and formulation.
|
|
22
|
+
|
|
23
|
+
import {
|
|
24
|
+
closeSync,
|
|
25
|
+
fstatSync,
|
|
26
|
+
lstatSync,
|
|
27
|
+
openSync,
|
|
28
|
+
readSync,
|
|
29
|
+
realpathSync,
|
|
30
|
+
} from "node:fs";
|
|
31
|
+
import { basename, join, resolve, sep } from "node:path";
|
|
32
|
+
|
|
33
|
+
import { applyPurl, tryBuildPurl } from "./purl.js";
|
|
34
|
+
|
|
35
|
+
// The version grammar the contract accepts: M.m.p, optionally with -dev or an
|
|
36
|
+
// alpha/beta/RC number.
|
|
37
|
+
const VERSION_BODY = "\\d+\\.\\d+\\.\\d+(?:-dev|(?:alpha|beta|RC)\\d+)?";
|
|
38
|
+
const MARKER = Buffer.from("X-Powered-By: PHP/");
|
|
39
|
+
const MAX_VERSION_BYTES = 32;
|
|
40
|
+
// Overlap is at least the marker length plus 32 bytes, per the contract, so a
|
|
41
|
+
// marker split across two reads is seen whole by the second one.
|
|
42
|
+
const OVERLAP_BYTES = MARKER.length + 32;
|
|
43
|
+
const READ_CHUNK_BYTES = 1024 * 1024;
|
|
44
|
+
const MAX_BINARY_BYTES = 256 * 1024 * 1024;
|
|
45
|
+
const MAX_HEADER_BYTES = 64 * 1024;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* The most PHP-named files one scan opens in search of a build version.
|
|
49
|
+
*
|
|
50
|
+
* @type {number}
|
|
51
|
+
*/
|
|
52
|
+
export const MAX_PHP_PROBES = 64;
|
|
53
|
+
|
|
54
|
+
// The trailing lookahead rejects 8.4.26.1 and 8.4.26foo while accepting
|
|
55
|
+
// 8.4.26, 8.4.26-dev and 8.6.0RC3 followed by a non-version byte.
|
|
56
|
+
const VERSION_PREFIX_RE = new RegExp(`^(${VERSION_BODY})(?![0-9A-Za-z.-])`);
|
|
57
|
+
const HEADER_VERSION_RE = new RegExp(
|
|
58
|
+
`^#define\\s+PHP_VERSION\\s+"(${VERSION_BODY})"\\s*$`,
|
|
59
|
+
"m",
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Read the version a text starts with, in the grammar the build-version reader
|
|
64
|
+
* accepts: `8.4.27`, `8.5.0-dev`, `8.6.0RC3`. What follows the version must not
|
|
65
|
+
* continue it, so `8.4.26.1` and `8.4.26foo` parse to nothing. A distro
|
|
66
|
+
* revision such as Ubuntu's `8.1.2-1ubuntu2.14` is not an upstream version
|
|
67
|
+
* either, and parses to nothing rather than to a guess.
|
|
68
|
+
*
|
|
69
|
+
* @param {string} text text that begins with the version
|
|
70
|
+
* @returns {string|undefined} the version, or undefined when the text does not
|
|
71
|
+
* begin with one
|
|
72
|
+
*/
|
|
73
|
+
export function parsePhpVersion(text) {
|
|
74
|
+
if (typeof text !== "string") {
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
// One character past the maximum lets the lookahead see a too-long version
|
|
78
|
+
// instead of treating the end of the slice as a boundary.
|
|
79
|
+
const match = VERSION_PREFIX_RE.exec(text.slice(0, MAX_VERSION_BYTES + 1));
|
|
80
|
+
if (!match || match[1].length > MAX_VERSION_BYTES) {
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
return match[1];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// A distro package can append its revision to PHP_VERSION, as Ubuntu 22.04
|
|
87
|
+
// does. The digit after the hyphen tells it from PHP's own `-dev`.
|
|
88
|
+
const DISTRO_VERSION_RE =
|
|
89
|
+
/^\d+\.\d+\.\d+-\d[0-9A-Za-z.+~-]*(?![0-9A-Za-z.+~-])/;
|
|
90
|
+
const MAX_REPORTED_VERSION_LENGTH = 64;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Read the version a PHP reports about itself, as `php -v` prints it. An
|
|
94
|
+
* upstream version parses as parsePhpVersion does. A version with a distro
|
|
95
|
+
* revision, such as Ubuntu's `8.1.2-1ubuntu2.14`, is kept whole and marked: it
|
|
96
|
+
* is what that PHP reports, but the distro backports fixes without changing the
|
|
97
|
+
* upstream part, so it must not be matched against upstream advisories.
|
|
98
|
+
*
|
|
99
|
+
* @param {string} text text that begins with the version
|
|
100
|
+
* @returns {{version: string, distroRevision: boolean}|undefined} the version,
|
|
101
|
+
* or undefined when the text does not begin with one
|
|
102
|
+
*/
|
|
103
|
+
export function parsePhpReportedVersion(text) {
|
|
104
|
+
const version = parsePhpVersion(text);
|
|
105
|
+
if (version) {
|
|
106
|
+
return { version, distroRevision: false };
|
|
107
|
+
}
|
|
108
|
+
if (typeof text !== "string") {
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
const match = DISTRO_VERSION_RE.exec(
|
|
112
|
+
text.slice(0, MAX_REPORTED_VERSION_LENGTH + 1),
|
|
113
|
+
);
|
|
114
|
+
if (!match || match[0].length > MAX_REPORTED_VERSION_LENGTH) {
|
|
115
|
+
return undefined;
|
|
116
|
+
}
|
|
117
|
+
return { version: match[0], distroRevision: true };
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* The package manager whose store a path lies in. Homebrew (`Cellar/<formula>/
|
|
122
|
+
* <version>/`), Nix (`nix/store/`) and Guix (`gnu/store/`) own everything under
|
|
123
|
+
* their stores, whatever links lead there, and a PHP they own is identified by
|
|
124
|
+
* their package, never as an unpackaged build.
|
|
125
|
+
*
|
|
126
|
+
* @param {string} filePath absolute or root-relative path, either separator
|
|
127
|
+
* @returns {string|undefined} `homebrew`, `nix` or `guix`, or undefined
|
|
128
|
+
*/
|
|
129
|
+
export function packageStoreOf(filePath) {
|
|
130
|
+
if (typeof filePath !== "string" || !filePath) {
|
|
131
|
+
return undefined;
|
|
132
|
+
}
|
|
133
|
+
const parts = filePath.split(/[\\/]+/);
|
|
134
|
+
const cellar = parts.indexOf("Cellar");
|
|
135
|
+
if (cellar !== -1 && parts.length - cellar >= 4) {
|
|
136
|
+
return "homebrew";
|
|
137
|
+
}
|
|
138
|
+
for (let index = 0; index + 2 < parts.length; index++) {
|
|
139
|
+
if (parts[index + 1] !== "store") {
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
if (parts[index] === "nix") {
|
|
143
|
+
return "nix";
|
|
144
|
+
}
|
|
145
|
+
if (parts[index] === "gnu") {
|
|
146
|
+
return "guix";
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return undefined;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Installed names come from the per-SAPI Makefile.frag files at the 8.4.27
|
|
153
|
+
// tag: bin/php, bin/php-cgi, sbin/php-fpm, bin/phpdbg and libs/libphp.so,
|
|
154
|
+
// each with the optional $(program_prefix)/$(program_suffix):
|
|
155
|
+
// https://github.com/php/php-src/blob/php-8.4.27/sapi/cli/Makefile.frag#L9
|
|
156
|
+
// https://github.com/php/php-src/blob/php-8.4.27/sapi/cgi/Makefile.frag#L9
|
|
157
|
+
// https://github.com/php/php-src/blob/php-8.4.27/sapi/fpm/Makefile.frag#L11
|
|
158
|
+
// https://github.com/php/php-src/blob/php-8.4.27/sapi/phpdbg/Makefile.frag#L28
|
|
159
|
+
// The Apache module is libphp.so (libs/libphp.so in build/Makefile.global).
|
|
160
|
+
// FrankenPHP embeds PHP in its own binary.
|
|
161
|
+
const PHP_SAPI_BY_NAME = [
|
|
162
|
+
[/^php(\d+(\.\d+)?)?$/, "cli"],
|
|
163
|
+
[/^php-fpm(\d+(\.\d+)?)?$/, "fpm"],
|
|
164
|
+
[/^php-cgi(\d+(\.\d+)?)?$/, "cgi"],
|
|
165
|
+
[/^phpdbg(\d+(\.\d+)?)?$/, "phpdbg"],
|
|
166
|
+
[/^libphp(\d+(\.\d+)?)?\.so$/, "libphp"],
|
|
167
|
+
[/^frankenphp$/, "frankenphp"],
|
|
168
|
+
];
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Classify a file by its basename into a PHP SAPI, or undefined when the name
|
|
172
|
+
* is not one php-src installs.
|
|
173
|
+
*
|
|
174
|
+
* @param {string} fileName basename or path of the candidate
|
|
175
|
+
* @returns {string|undefined} cli, fpm, cgi, phpdbg, libphp or frankenphp
|
|
176
|
+
*/
|
|
177
|
+
export function classifyPhpSapi(fileName) {
|
|
178
|
+
if (typeof fileName !== "string" || !fileName) {
|
|
179
|
+
return undefined;
|
|
180
|
+
}
|
|
181
|
+
const name = basename(fileName);
|
|
182
|
+
for (const [pattern, sapi] of PHP_SAPI_BY_NAME) {
|
|
183
|
+
if (pattern.test(name)) {
|
|
184
|
+
return sapi;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return undefined;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Open a path only when it is a regular file that does not resolve outside
|
|
192
|
+
* rootDir. lstat runs first so a FIFO is rejected without opening it (an
|
|
193
|
+
* open on a FIFO blocks until a writer appears) and a symlink is never
|
|
194
|
+
* followed.
|
|
195
|
+
*
|
|
196
|
+
* @param {string} absPath absolute path
|
|
197
|
+
* @param {string|undefined} rootDir extracted root the path must stay under
|
|
198
|
+
* @returns {{fd: number, size: number}|undefined}
|
|
199
|
+
*/
|
|
200
|
+
function openRegularFile(absPath, rootDir) {
|
|
201
|
+
let fd;
|
|
202
|
+
try {
|
|
203
|
+
if (typeof absPath !== "string" || !absPath) {
|
|
204
|
+
return undefined;
|
|
205
|
+
}
|
|
206
|
+
const lst = lstatSync(absPath);
|
|
207
|
+
if (!lst.isFile()) {
|
|
208
|
+
return undefined;
|
|
209
|
+
}
|
|
210
|
+
if (rootDir) {
|
|
211
|
+
const root = realpathSync(resolve(rootDir));
|
|
212
|
+
const real = realpathSync(absPath);
|
|
213
|
+
const rootPrefix = root.endsWith(sep) ? root : root + sep;
|
|
214
|
+
if (real !== root && !real.startsWith(rootPrefix)) {
|
|
215
|
+
return undefined;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
fd = openSync(absPath, "r");
|
|
219
|
+
const stats = fstatSync(fd);
|
|
220
|
+
if (!stats.isFile()) {
|
|
221
|
+
closeSync(fd);
|
|
222
|
+
return undefined;
|
|
223
|
+
}
|
|
224
|
+
return { fd, size: stats.size };
|
|
225
|
+
} catch {
|
|
226
|
+
if (fd !== undefined) {
|
|
227
|
+
try {
|
|
228
|
+
closeSync(fd);
|
|
229
|
+
} catch {
|
|
230
|
+
// already closed
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return undefined;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function matchVersionAt(buffer, start, readLength) {
|
|
238
|
+
if (start >= readLength) {
|
|
239
|
+
return undefined;
|
|
240
|
+
}
|
|
241
|
+
// One byte past the maximum lets the lookahead see a too-long version
|
|
242
|
+
// instead of treating the end of the slice as a boundary.
|
|
243
|
+
const end = Math.min(readLength, start + MAX_VERSION_BYTES + 1);
|
|
244
|
+
return parsePhpVersion(buffer.toString("latin1", start, end));
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Scan a bounded prefix of a binary for the compiled-in marker. Files larger
|
|
249
|
+
* than the cap are skipped entirely: the contract treats them as hostile and
|
|
250
|
+
* emits no property.
|
|
251
|
+
*
|
|
252
|
+
* @param {number} fd open file descriptor
|
|
253
|
+
* @param {number} size file size from fstat
|
|
254
|
+
* @returns {string|undefined}
|
|
255
|
+
*/
|
|
256
|
+
function scanBinaryVersion(fd, size) {
|
|
257
|
+
if (size <= 0 || size > MAX_BINARY_BYTES) {
|
|
258
|
+
return undefined;
|
|
259
|
+
}
|
|
260
|
+
const bufferSize = Math.min(size, READ_CHUNK_BYTES) + OVERLAP_BYTES;
|
|
261
|
+
const buffer = Buffer.allocUnsafe(bufferSize);
|
|
262
|
+
for (let position = 0; position < size; position += READ_CHUNK_BYTES) {
|
|
263
|
+
const want = Math.min(bufferSize, size - position);
|
|
264
|
+
const read = readSync(fd, buffer, 0, want, position);
|
|
265
|
+
if (read <= 0) {
|
|
266
|
+
return undefined;
|
|
267
|
+
}
|
|
268
|
+
// Only matches starting inside this window are new; the overlap exists so
|
|
269
|
+
// a version split at the window edge is readable.
|
|
270
|
+
const searchLimit = Math.min(READ_CHUNK_BYTES, read);
|
|
271
|
+
let offset = buffer.indexOf(MARKER);
|
|
272
|
+
while (offset !== -1 && offset < searchLimit) {
|
|
273
|
+
const version = matchVersionAt(buffer, offset + MARKER.length, read);
|
|
274
|
+
if (version) {
|
|
275
|
+
return version;
|
|
276
|
+
}
|
|
277
|
+
offset = buffer.indexOf(MARKER, offset + 1);
|
|
278
|
+
}
|
|
279
|
+
if (read < bufferSize) {
|
|
280
|
+
return undefined;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return undefined;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Derive the install prefix from a path installed under bin, sbin or lib:
|
|
288
|
+
* /usr/local/bin/php -> /usr/local, /usr/lib/apache2/modules/libphp.so -> /usr.
|
|
289
|
+
*
|
|
290
|
+
* @param {string} absPath absolute path
|
|
291
|
+
* @returns {string|undefined}
|
|
292
|
+
*/
|
|
293
|
+
function installPrefix(absPath) {
|
|
294
|
+
const parts = resolve(absPath).split(sep);
|
|
295
|
+
for (let i = parts.length - 2; i >= 0; i--) {
|
|
296
|
+
if (parts[i] === "bin" || parts[i] === "sbin" || parts[i] === "lib") {
|
|
297
|
+
return parts.slice(0, i).join(sep) || sep;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return undefined;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Read PHP_VERSION from <prefix>/include/php/main/php_version.h. Only called
|
|
305
|
+
* for files installed under bin, sbin or lib, and only when the binary marker
|
|
306
|
+
* was absent.
|
|
307
|
+
*
|
|
308
|
+
* @param {string} absPath path of the PHP binary/library
|
|
309
|
+
* @param {string|undefined} rootDir extracted root
|
|
310
|
+
* @returns {string|undefined}
|
|
311
|
+
*/
|
|
312
|
+
function readHeaderVersion(absPath, rootDir) {
|
|
313
|
+
const prefix = installPrefix(absPath);
|
|
314
|
+
if (!prefix) {
|
|
315
|
+
return undefined;
|
|
316
|
+
}
|
|
317
|
+
const headerPath = join(prefix, "include", "php", "main", "php_version.h");
|
|
318
|
+
const opened = openRegularFile(headerPath, rootDir);
|
|
319
|
+
if (!opened) {
|
|
320
|
+
return undefined;
|
|
321
|
+
}
|
|
322
|
+
try {
|
|
323
|
+
const length = Math.min(opened.size, MAX_HEADER_BYTES);
|
|
324
|
+
if (length <= 0) {
|
|
325
|
+
return undefined;
|
|
326
|
+
}
|
|
327
|
+
const buffer = Buffer.allocUnsafe(length);
|
|
328
|
+
const read = readSync(opened.fd, buffer, 0, length, 0);
|
|
329
|
+
if (read <= 0) {
|
|
330
|
+
return undefined;
|
|
331
|
+
}
|
|
332
|
+
const match = HEADER_VERSION_RE.exec(buffer.toString("latin1", 0, read));
|
|
333
|
+
return match ? match[1] : undefined;
|
|
334
|
+
} catch {
|
|
335
|
+
return undefined;
|
|
336
|
+
} finally {
|
|
337
|
+
try {
|
|
338
|
+
closeSync(opened.fd);
|
|
339
|
+
} catch {
|
|
340
|
+
// already closed
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Read the PHP build version of a binary or shared library.
|
|
347
|
+
*
|
|
348
|
+
* @param {string} absPath absolute path
|
|
349
|
+
* @param {string|undefined} rootDir extracted root, when the file came from one
|
|
350
|
+
* @returns {{version: string, source: string}|undefined} source is `binary`
|
|
351
|
+
* or `php_version.h`
|
|
352
|
+
*/
|
|
353
|
+
export function readPhpBuildVersion(absPath, rootDir) {
|
|
354
|
+
const opened = openRegularFile(absPath, rootDir);
|
|
355
|
+
if (!opened) {
|
|
356
|
+
return undefined;
|
|
357
|
+
}
|
|
358
|
+
try {
|
|
359
|
+
const fromBinary = scanBinaryVersion(opened.fd, opened.size);
|
|
360
|
+
if (fromBinary) {
|
|
361
|
+
return { version: fromBinary, source: "binary" };
|
|
362
|
+
}
|
|
363
|
+
} finally {
|
|
364
|
+
try {
|
|
365
|
+
closeSync(opened.fd);
|
|
366
|
+
} catch {
|
|
367
|
+
// already closed
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
const fromHeader = readHeaderVersion(absPath, rootDir);
|
|
371
|
+
return fromHeader
|
|
372
|
+
? { version: fromHeader, source: "php_version.h" }
|
|
373
|
+
: undefined;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* The CPE that lets a downstream scanner match a PHP version. NVD puts a
|
|
378
|
+
* pre-release suffix in the update field, e.g.
|
|
379
|
+
* cpe:2.3:a:php:php:8.5.0:rc1:*:*:*:*:*:* (NVD CPE dictionary).
|
|
380
|
+
*
|
|
381
|
+
* @param {string} version PHP version in the build-version grammar
|
|
382
|
+
* @returns {string} CPE 2.3 string
|
|
383
|
+
*/
|
|
384
|
+
export function phpCpe(version) {
|
|
385
|
+
const match = /^(\d+\.\d+\.\d+)(?:-(dev)|(alpha|beta|RC)(\d+))?$/.exec(
|
|
386
|
+
version,
|
|
387
|
+
);
|
|
388
|
+
if (!match) {
|
|
389
|
+
return `cpe:2.3:a:php:php:${version}:*:*:*:*:*:*:*`;
|
|
390
|
+
}
|
|
391
|
+
let update = "*";
|
|
392
|
+
if (match[2]) {
|
|
393
|
+
update = "dev";
|
|
394
|
+
} else if (match[3]) {
|
|
395
|
+
update = `${match[3].toLowerCase()}${match[4]}`;
|
|
396
|
+
}
|
|
397
|
+
return `cpe:2.3:a:php:php:${match[1]}:${update}:*:*:*:*:*:*`;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* A PHP runtime is one `platform` component per distinct version, like the Go
|
|
402
|
+
* stdlib component. Its identity is `pkg:generic/php`: it is only used where no
|
|
403
|
+
* package manager owns PHP, or where a PATH probe cannot tell which one does.
|
|
404
|
+
*
|
|
405
|
+
* @param {string} version PHP version in the build-version grammar, or as a
|
|
406
|
+
* distro build reports it
|
|
407
|
+
* @param {Object} [options] options
|
|
408
|
+
* @param {boolean} [options.withCpe=true] false for a version with a distro
|
|
409
|
+
* revision, which no upstream CPE describes
|
|
410
|
+
* @returns {Object} component with `purl`, `bom-ref` and, unless left out, `cpe`
|
|
411
|
+
*/
|
|
412
|
+
export function createPhpRuntimeComponent(version, { withCpe = true } = {}) {
|
|
413
|
+
const component = { type: "platform", name: "php", version };
|
|
414
|
+
if (withCpe) {
|
|
415
|
+
component.cpe = phpCpe(version);
|
|
416
|
+
}
|
|
417
|
+
return applyPurl(
|
|
418
|
+
component,
|
|
419
|
+
tryBuildPurl({ type: "generic", name: "php", version }),
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* The bom-ref of the runtime component for a version.
|
|
425
|
+
*
|
|
426
|
+
* @param {string} version PHP version in the build-version grammar
|
|
427
|
+
* @returns {string} bom-ref, which is the runtime's purl
|
|
428
|
+
*/
|
|
429
|
+
export function phpRuntimeRef(version) {
|
|
430
|
+
return createPhpRuntimeComponent(version)["bom-ref"];
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
/**
|
|
434
|
+
* The properties a PHP file component carries once its build version is known.
|
|
435
|
+
* They belong on unpackaged `file` components only: a package-owned PHP is
|
|
436
|
+
* identified by its package, and distro builds carry backported fixes under
|
|
437
|
+
* old version numbers, so the PHP-RCE audit rules that match these properties
|
|
438
|
+
* would raise false positives there.
|
|
439
|
+
*
|
|
440
|
+
* @param {{version: string, source: string}} build result of readPhpBuildVersion
|
|
441
|
+
* @param {string} sapi result of classifyPhpSapi
|
|
442
|
+
* @returns {{name: string, value: string}[]} properties to append
|
|
443
|
+
*/
|
|
444
|
+
export function phpBuildProperties(build, sapi) {
|
|
445
|
+
return [
|
|
446
|
+
{ name: "cdx:php:buildVersion", value: build.version },
|
|
447
|
+
{ name: "cdx:php:buildVersionSource", value: build.source },
|
|
448
|
+
{ name: "cdx:php:sapi", value: sapi },
|
|
449
|
+
];
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* Start collecting the runtime components and edges of one scan.
|
|
454
|
+
*
|
|
455
|
+
* @returns {{runtimeComponents: Object[], dependencies: Object[], runtimeRefs: Set<string>}}
|
|
456
|
+
*/
|
|
457
|
+
export function createPhpRuntimeInventory() {
|
|
458
|
+
return { runtimeComponents: [], dependencies: [], runtimeRefs: new Set() };
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Tag a PHP file component with its build facts and link it to the runtime
|
|
463
|
+
* component of its version, creating that component on first use. Mutates the
|
|
464
|
+
* component in place, as the Go collector does.
|
|
465
|
+
*
|
|
466
|
+
* @param {{runtimeComponents: Object[], dependencies: Object[], runtimeRefs: Set<string>}} inventory
|
|
467
|
+
* accumulator from createPhpRuntimeInventory
|
|
468
|
+
* @param {Object} component file component, with a `properties` array
|
|
469
|
+
* @param {{version: string, source: string}} build result of readPhpBuildVersion
|
|
470
|
+
* @param {string} sapi result of classifyPhpSapi
|
|
471
|
+
*/
|
|
472
|
+
export function attachPhpBuild(inventory, component, build, sapi) {
|
|
473
|
+
component.properties.push(...phpBuildProperties(build, sapi));
|
|
474
|
+
const runtime = createPhpRuntimeComponent(build.version);
|
|
475
|
+
const runtimeRef = runtime["bom-ref"];
|
|
476
|
+
if (!inventory.runtimeRefs.has(runtimeRef)) {
|
|
477
|
+
inventory.runtimeRefs.add(runtimeRef);
|
|
478
|
+
inventory.runtimeComponents.push(runtime);
|
|
479
|
+
inventory.dependencies.push({ ref: runtimeRef, dependsOn: [] });
|
|
480
|
+
}
|
|
481
|
+
if (component["bom-ref"]) {
|
|
482
|
+
inventory.dependencies.push({
|
|
483
|
+
ref: component["bom-ref"],
|
|
484
|
+
dependsOn: [runtimeRef],
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
}
|