@cdxgen/cdxgen 13.5.0 → 13.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -10
- package/bin/audit.js +7 -4
- package/bin/cdxgen.js +260 -37
- package/bin/convert.js +146 -22
- package/bin/evinse.js +28 -3
- package/bin/repl.js +47 -3
- package/bin/sign.js +211 -34
- package/bin/tracebom.js +18 -6
- package/bin/validate.js +24 -3
- package/bin/verify.js +113 -5
- package/data/behavior-taxonomy.schema.json +1491 -0
- package/data/cyclonedx-2.0-bundled.schema.json +18606 -5528
- package/data/cyclonedx-2.0-cryptography-defs.schema.json +857 -0
- package/data/license-aliases.json +24 -2
- package/data/pqc-migration.json +239 -0
- package/data/remediations.json +176 -0
- package/data/rules/ai-bom.yaml +1 -1
- package/data/rules/brotli-decoder.yaml +107 -0
- package/data/rules/cbom-security.yaml +4 -3
- package/data/rules/package-integrity.yaml +28 -0
- package/data/rules/vscode-extensions.yaml +75 -0
- package/data/spdx-license-list.json +121 -7
- package/data/spdx-licenses.json +69 -0
- package/data/spdx.schema.json +845 -2
- package/lib/audit/index.js +25 -3
- package/lib/cli/bomAssembly.js +172 -4
- package/lib/cli/cliOptions.js +121 -17
- package/lib/cli/index.js +720 -902
- package/lib/cli/jsBom.js +156 -64
- package/lib/cli/jvmBom.js +602 -86
- package/lib/cli/managedBom.js +161 -19
- package/lib/cli/nativeBom.js +52 -5
- package/lib/core/boundedFile.js +344 -0
- package/lib/core/brotliProbe.js +182 -0
- package/lib/core/env.js +34 -0
- package/lib/core/fs.js +138 -3
- package/lib/core/globPatterns.js +218 -0
- package/lib/core/httpClient.js +98 -1
- package/lib/core/lockPaths.js +38 -0
- package/lib/core/paths.js +24 -1
- package/lib/core/processTree.js +100 -8
- package/lib/core/projectConfig.js +332 -25
- package/lib/core/toolRegistry.js +184 -0
- package/lib/ecosystems/cppEvidence.js +263 -106
- package/lib/ecosystems/cppIncludeResolver.js +16 -5
- package/lib/ecosystems/denoutils.js +2 -2
- package/lib/ecosystems/ecosystems.js +25 -10
- package/lib/ecosystems/gemHostProbe.js +301 -0
- package/lib/ecosystems/golem.js +3 -8
- package/lib/ecosystems/gradleutils.js +1909 -229
- package/lib/ecosystems/jsEvidence.js +90 -38
- package/lib/ecosystems/kosi.js +3 -5
- package/lib/ecosystems/npmVersionResolution.js +376 -0
- package/lib/ecosystems/parsers-bazel.js +107 -6
- package/lib/ecosystems/parsers-js.js +505 -22
- package/lib/ecosystems/parsers-misc.js +209 -20
- package/lib/ecosystems/parsers-python.js +178 -30
- package/lib/ecosystems/parsers-rust.js +117 -15
- package/lib/ecosystems/pythonutils.js +128 -2
- package/lib/ecosystems/remote/huggingface.js +22 -0
- package/lib/ecosystems/rubyutils.js +538 -31
- package/lib/ecosystems/rusi.js +2 -4
- package/lib/ecosystems/scalacliutils.js +2 -0
- package/lib/ecosystems/scalasem.js +798 -152
- package/lib/ecosystems/vendoredCode.js +237 -3
- package/lib/ecosystems/venvProbe.js +360 -0
- package/lib/evinser/evinser.js +536 -71
- package/lib/evinser/scalasem.js +5 -1
- package/lib/helpers/agenticToolutils.js +525 -94
- package/lib/helpers/bomSigner.js +43 -9
- package/lib/helpers/jssSigner.js +1276 -0
- package/lib/helpers/vsixutils.js +1574 -315
- package/lib/inventory/agentBlueprint.js +193 -0
- package/lib/inventory/agentToolNames.js +145 -0
- package/lib/inventory/aiCollector.js +153 -7
- package/lib/inventory/aiInventory.js +44 -8
- package/lib/inventory/aiProviders.js +324 -0
- package/lib/inventory/atomUtils.js +77 -0
- package/lib/inventory/bomUtils.js +8 -1
- package/lib/inventory/brotliDecoder.js +142 -0
- package/lib/inventory/buildToolRateLimit.js +1 -1
- package/lib/inventory/cbomutils.js +56 -7
- package/lib/inventory/ciParsers/githubActionsLock.js +821 -0
- package/lib/inventory/citations.js +31 -2
- package/lib/inventory/communityAiConfigParser.js +978 -80
- package/lib/inventory/cyclonedx20.js +152 -0
- package/lib/inventory/cyclonedx20Common.js +286 -0
- package/lib/inventory/cyclonedx20Derived.js +159 -0
- package/lib/inventory/cyclonedx20Parties.js +552 -0
- package/lib/inventory/cyclonedx20Read.js +768 -0
- package/lib/inventory/cyclonedx20ReadCommon.js +374 -0
- package/lib/inventory/cyclonedx20ReadComponents.js +692 -0
- package/lib/inventory/cyclonedx20ReadContext.js +380 -0
- package/lib/inventory/cyclonedx20ReadEvidence.js +466 -0
- package/lib/inventory/cyclonedx20ReadSections.js +599 -0
- package/lib/inventory/cyclonedx20Render.js +766 -0
- package/lib/inventory/cyclonedx20RenderComponents.js +716 -0
- package/lib/inventory/cyclonedx20RenderDefinitions.js +405 -0
- package/lib/inventory/cyclonedx20RenderEvidence.js +726 -0
- package/lib/inventory/cyclonedx20RenderHardware.js +203 -0
- package/lib/inventory/cyclonedx20RenderPatents.js +174 -0
- package/lib/inventory/cyclonedx20RenderRefIds.js +314 -0
- package/lib/inventory/cyclonedx20RenderSections.js +499 -0
- package/lib/inventory/cyclonedx20Tables.js +594 -0
- package/lib/inventory/deps.js +141 -13
- package/lib/inventory/dosai.js +375 -6
- package/lib/inventory/dosaiParsers.js +3 -6
- package/lib/inventory/dotnetRuntime.js +367 -0
- package/lib/inventory/ecosystemFormulationParsers.js +979 -0
- package/lib/inventory/envcontext.js +436 -48
- package/lib/inventory/evidenceUtils.js +13 -1
- package/lib/inventory/fetchBatch.js +1 -1
- package/lib/inventory/formulationParsers.js +124 -14
- package/lib/inventory/gtfobins.js +13 -0
- package/lib/inventory/hbom.js +45 -6
- package/lib/inventory/hbomLoader.js +166 -0
- package/lib/inventory/hostRuntimeProbe.js +686 -0
- package/lib/inventory/jvmLocalRepos.js +9 -2
- package/lib/inventory/jvmToolEnv.js +29 -0
- package/lib/inventory/licenseEnhancer.js +12 -0
- package/lib/inventory/mavenCentralMirror.js +534 -0
- package/lib/inventory/mcpConfigParser.js +5 -0
- package/lib/inventory/nodeBuildInfo.js +218 -0
- package/lib/inventory/nodeHostProbe.js +202 -0
- package/lib/inventory/occurrenceKey.js +90 -0
- package/lib/inventory/osPackageResolver.js +182 -0
- package/lib/inventory/phpBuildInfo.js +10 -59
- package/lib/inventory/phpHostProbe.js +32 -488
- package/lib/inventory/pqcMigration.js +426 -0
- package/lib/inventory/rubyBuildInfo.js +972 -0
- package/lib/inventory/rubyHostProbe.js +218 -0
- package/lib/inventory/rustFormulationParser.js +21 -10
- package/lib/inventory/scalaCoords.js +4 -3
- package/lib/inventory/scalaDedupe.js +440 -0
- package/lib/inventory/source.js +114 -8
- package/lib/managers/binary.js +337 -3
- package/lib/managers/docker.js +79 -0
- package/lib/parsers/huggingfaceManifest.js +9 -1
- package/lib/parsers/huggingfaceUtils.js +18 -0
- package/lib/parsers/kiroPermissions.js +166 -0
- package/lib/parsers/largeJson.js +28 -11
- package/lib/parsers/vscodeExtensionId.js +183 -0
- package/lib/server/server.js +48 -35
- package/lib/stages/postgen/postgen.js +41 -1
- package/lib/stages/postgen/ruleEngine.js +13 -5
- package/lib/stages/postgen/specVersionCompat.js +76 -0
- package/lib/stages/pregen/envAudit.js +1 -0
- package/lib/stages/pregen/pregen.js +114 -57
- package/lib/validator/bomValidator.js +14 -2
- package/lib/validator/complianceEngine.js +30 -3
- package/lib/validator/complianceRules.js +1416 -4
- package/lib/validator/generated/validate-1.6.mjs +1 -1
- package/lib/validator/generated/validate-1.7.mjs +1 -1
- package/lib/validator/generated/validate-2.0.mjs +57554 -13851
- package/lib/validator/index.js +49 -8
- package/lib/validator/reporters/json.js +6 -0
- package/package.json +11 -10
- package/types/bin/repl.d.ts.map +1 -1
- package/types/lib/audit/index.d.ts +6 -2
- package/types/lib/audit/index.d.ts.map +1 -1
- package/types/lib/cli/bomAssembly.d.ts +29 -1
- package/types/lib/cli/bomAssembly.d.ts.map +1 -1
- package/types/lib/cli/cliOptions.d.ts +6 -0
- package/types/lib/cli/cliOptions.d.ts.map +1 -1
- package/types/lib/cli/index.d.ts.map +1 -1
- package/types/lib/cli/jsBom.d.ts +3 -18
- package/types/lib/cli/jsBom.d.ts.map +1 -1
- package/types/lib/cli/jvmBom.d.ts +15 -0
- package/types/lib/cli/jvmBom.d.ts.map +1 -1
- package/types/lib/cli/managedBom.d.ts.map +1 -1
- package/types/lib/cli/nativeBom.d.ts.map +1 -1
- package/types/lib/core/boundedFile.d.ts +100 -0
- package/types/lib/core/boundedFile.d.ts.map +1 -0
- package/types/lib/core/brotliProbe.d.ts +37 -0
- package/types/lib/core/brotliProbe.d.ts.map +1 -0
- package/types/lib/core/env.d.ts +14 -0
- package/types/lib/core/env.d.ts.map +1 -1
- package/types/lib/core/fs.d.ts +4 -0
- package/types/lib/core/fs.d.ts.map +1 -1
- package/types/lib/core/globPatterns.d.ts +70 -0
- package/types/lib/core/globPatterns.d.ts.map +1 -0
- package/types/lib/core/httpClient.d.ts +24 -0
- package/types/lib/core/httpClient.d.ts.map +1 -1
- package/types/lib/core/lockPaths.d.ts +19 -0
- package/types/lib/core/lockPaths.d.ts.map +1 -0
- package/types/lib/core/paths.d.ts +9 -0
- package/types/lib/core/paths.d.ts.map +1 -1
- package/types/lib/core/processTree.d.ts +17 -4
- package/types/lib/core/processTree.d.ts.map +1 -1
- package/types/lib/core/projectConfig.d.ts +47 -8
- package/types/lib/core/projectConfig.d.ts.map +1 -1
- package/types/lib/core/toolRegistry.d.ts +36 -0
- package/types/lib/core/toolRegistry.d.ts.map +1 -0
- package/types/lib/ecosystems/cppEvidence.d.ts +40 -13
- package/types/lib/ecosystems/cppEvidence.d.ts.map +1 -1
- package/types/lib/ecosystems/cppIncludeResolver.d.ts +2 -1
- package/types/lib/ecosystems/cppIncludeResolver.d.ts.map +1 -1
- package/types/lib/ecosystems/ecosystems.d.ts.map +1 -1
- package/types/lib/ecosystems/gemHostProbe.d.ts +28 -0
- package/types/lib/ecosystems/gemHostProbe.d.ts.map +1 -0
- package/types/lib/ecosystems/golem.d.ts.map +1 -1
- package/types/lib/ecosystems/gradleutils.d.ts +294 -20
- package/types/lib/ecosystems/gradleutils.d.ts.map +1 -1
- package/types/lib/ecosystems/jsEvidence.d.ts +14 -1
- package/types/lib/ecosystems/jsEvidence.d.ts.map +1 -1
- package/types/lib/ecosystems/kosi.d.ts.map +1 -1
- package/types/lib/ecosystems/npmVersionResolution.d.ts +119 -0
- package/types/lib/ecosystems/npmVersionResolution.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-bazel.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-js.d.ts +17 -20
- package/types/lib/ecosystems/parsers-js.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-misc.d.ts +19 -0
- package/types/lib/ecosystems/parsers-misc.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-python.d.ts +10 -0
- package/types/lib/ecosystems/parsers-python.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-rust.d.ts.map +1 -1
- package/types/lib/ecosystems/pythonutils.d.ts +19 -1
- package/types/lib/ecosystems/pythonutils.d.ts.map +1 -1
- package/types/lib/ecosystems/remote/huggingface.d.ts.map +1 -1
- package/types/lib/ecosystems/rubyutils.d.ts +144 -12
- package/types/lib/ecosystems/rubyutils.d.ts.map +1 -1
- package/types/lib/ecosystems/rusi.d.ts.map +1 -1
- package/types/lib/ecosystems/scalacliutils.d.ts.map +1 -1
- package/types/lib/ecosystems/scalasem.d.ts +58 -16
- package/types/lib/ecosystems/scalasem.d.ts.map +1 -1
- package/types/lib/ecosystems/vendoredCode.d.ts +26 -0
- package/types/lib/ecosystems/vendoredCode.d.ts.map +1 -1
- package/types/lib/ecosystems/venvProbe.d.ts +40 -0
- package/types/lib/ecosystems/venvProbe.d.ts.map +1 -0
- package/types/lib/evinser/evinser.d.ts +120 -13
- package/types/lib/evinser/evinser.d.ts.map +1 -1
- package/types/lib/evinser/scalasem.d.ts.map +1 -1
- package/types/lib/helpers/agenticToolutils.d.ts +53 -19
- package/types/lib/helpers/agenticToolutils.d.ts.map +1 -1
- package/types/lib/helpers/bomSigner.d.ts +20 -3
- package/types/lib/helpers/bomSigner.d.ts.map +1 -1
- package/types/lib/helpers/jssSigner.d.ts +288 -0
- package/types/lib/helpers/jssSigner.d.ts.map +1 -0
- package/types/lib/helpers/vsixutils.d.ts +303 -19
- package/types/lib/helpers/vsixutils.d.ts.map +1 -1
- package/types/lib/inventory/agentBlueprint.d.ts +70 -0
- package/types/lib/inventory/agentBlueprint.d.ts.map +1 -0
- package/types/lib/inventory/agentToolNames.d.ts +51 -0
- package/types/lib/inventory/agentToolNames.d.ts.map +1 -0
- package/types/lib/inventory/aiCollector.d.ts.map +1 -1
- package/types/lib/inventory/aiInventory.d.ts.map +1 -1
- package/types/lib/inventory/aiProviders.d.ts +85 -0
- package/types/lib/inventory/aiProviders.d.ts.map +1 -0
- package/types/lib/inventory/atomUtils.d.ts +19 -0
- package/types/lib/inventory/atomUtils.d.ts.map +1 -1
- package/types/lib/inventory/bomUtils.d.ts.map +1 -1
- package/types/lib/inventory/brotliDecoder.d.ts +58 -0
- package/types/lib/inventory/brotliDecoder.d.ts.map +1 -0
- package/types/lib/inventory/cbomutils.d.ts +17 -0
- package/types/lib/inventory/cbomutils.d.ts.map +1 -1
- package/types/lib/inventory/ciParsers/githubActionsLock.d.ts +101 -0
- package/types/lib/inventory/ciParsers/githubActionsLock.d.ts.map +1 -0
- package/types/lib/inventory/citations.d.ts +5 -0
- package/types/lib/inventory/citations.d.ts.map +1 -1
- package/types/lib/inventory/communityAiConfigParser.d.ts.map +1 -1
- package/types/lib/inventory/cyclonedx20.d.ts +99 -0
- package/types/lib/inventory/cyclonedx20.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Common.d.ts +102 -0
- package/types/lib/inventory/cyclonedx20Common.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Derived.d.ts +74 -0
- package/types/lib/inventory/cyclonedx20Derived.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Parties.d.ts +91 -0
- package/types/lib/inventory/cyclonedx20Parties.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Read.d.ts +51 -0
- package/types/lib/inventory/cyclonedx20Read.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20ReadCommon.d.ts +69 -0
- package/types/lib/inventory/cyclonedx20ReadCommon.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20ReadComponents.d.ts +77 -0
- package/types/lib/inventory/cyclonedx20ReadComponents.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20ReadContext.d.ts +118 -0
- package/types/lib/inventory/cyclonedx20ReadContext.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20ReadEvidence.d.ts +40 -0
- package/types/lib/inventory/cyclonedx20ReadEvidence.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20ReadSections.d.ts +45 -0
- package/types/lib/inventory/cyclonedx20ReadSections.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Render.d.ts +53 -0
- package/types/lib/inventory/cyclonedx20Render.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderComponents.d.ts +73 -0
- package/types/lib/inventory/cyclonedx20RenderComponents.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderDefinitions.d.ts +29 -0
- package/types/lib/inventory/cyclonedx20RenderDefinitions.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderEvidence.d.ts +110 -0
- package/types/lib/inventory/cyclonedx20RenderEvidence.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderHardware.d.ts +42 -0
- package/types/lib/inventory/cyclonedx20RenderHardware.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderPatents.d.ts +26 -0
- package/types/lib/inventory/cyclonedx20RenderPatents.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderRefIds.d.ts +55 -0
- package/types/lib/inventory/cyclonedx20RenderRefIds.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderSections.d.ts +45 -0
- package/types/lib/inventory/cyclonedx20RenderSections.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Tables.d.ts +134 -0
- package/types/lib/inventory/cyclonedx20Tables.d.ts.map +1 -0
- package/types/lib/inventory/deps.d.ts +35 -2
- package/types/lib/inventory/deps.d.ts.map +1 -1
- package/types/lib/inventory/dosai.d.ts +36 -1
- package/types/lib/inventory/dosai.d.ts.map +1 -1
- package/types/lib/inventory/dosaiParsers.d.ts.map +1 -1
- package/types/lib/inventory/dotnetRuntime.d.ts +91 -0
- package/types/lib/inventory/dotnetRuntime.d.ts.map +1 -0
- package/types/lib/inventory/ecosystemFormulationParsers.d.ts +73 -0
- package/types/lib/inventory/ecosystemFormulationParsers.d.ts.map +1 -0
- package/types/lib/inventory/envcontext.d.ts +74 -12
- package/types/lib/inventory/envcontext.d.ts.map +1 -1
- package/types/lib/inventory/evidenceUtils.d.ts.map +1 -1
- package/types/lib/inventory/formulationParsers.d.ts.map +1 -1
- package/types/lib/inventory/gtfobins.d.ts.map +1 -1
- package/types/lib/inventory/hbom.d.ts +11 -0
- package/types/lib/inventory/hbom.d.ts.map +1 -1
- package/types/lib/inventory/hbomLoader.d.ts +54 -0
- package/types/lib/inventory/hbomLoader.d.ts.map +1 -1
- package/types/lib/inventory/hostRuntimeProbe.d.ts +44 -0
- package/types/lib/inventory/hostRuntimeProbe.d.ts.map +1 -0
- package/types/lib/inventory/jvmLocalRepos.d.ts +5 -1
- package/types/lib/inventory/jvmLocalRepos.d.ts.map +1 -1
- package/types/lib/inventory/jvmToolEnv.d.ts +12 -0
- package/types/lib/inventory/jvmToolEnv.d.ts.map +1 -1
- package/types/lib/inventory/licenseEnhancer.d.ts.map +1 -1
- package/types/lib/inventory/mavenCentralMirror.d.ts +170 -0
- package/types/lib/inventory/mavenCentralMirror.d.ts.map +1 -0
- package/types/lib/inventory/mcpConfigParser.d.ts.map +1 -1
- package/types/lib/inventory/nodeBuildInfo.d.ts +95 -0
- package/types/lib/inventory/nodeBuildInfo.d.ts.map +1 -0
- package/types/lib/inventory/nodeHostProbe.d.ts +15 -0
- package/types/lib/inventory/nodeHostProbe.d.ts.map +1 -0
- package/types/lib/inventory/occurrenceKey.d.ts +52 -0
- package/types/lib/inventory/occurrenceKey.d.ts.map +1 -0
- package/types/lib/inventory/osPackageResolver.d.ts +38 -0
- package/types/lib/inventory/osPackageResolver.d.ts.map +1 -1
- package/types/lib/inventory/phpBuildInfo.d.ts.map +1 -1
- package/types/lib/inventory/phpHostProbe.d.ts.map +1 -1
- package/types/lib/inventory/pqcMigration.d.ts +84 -0
- package/types/lib/inventory/pqcMigration.d.ts.map +1 -0
- package/types/lib/inventory/rubyBuildInfo.d.ts +271 -0
- package/types/lib/inventory/rubyBuildInfo.d.ts.map +1 -0
- package/types/lib/inventory/rubyHostProbe.d.ts +47 -0
- package/types/lib/inventory/rubyHostProbe.d.ts.map +1 -0
- package/types/lib/inventory/rustFormulationParser.d.ts +7 -2
- package/types/lib/inventory/rustFormulationParser.d.ts.map +1 -1
- package/types/lib/inventory/scalaCoords.d.ts.map +1 -1
- package/types/lib/inventory/scalaDedupe.d.ts +43 -0
- package/types/lib/inventory/scalaDedupe.d.ts.map +1 -0
- package/types/lib/inventory/source.d.ts +25 -0
- package/types/lib/inventory/source.d.ts.map +1 -1
- package/types/lib/managers/binary.d.ts.map +1 -1
- package/types/lib/managers/docker.d.ts +12 -0
- package/types/lib/managers/docker.d.ts.map +1 -1
- package/types/lib/parsers/huggingfaceManifest.d.ts +10 -1
- package/types/lib/parsers/huggingfaceManifest.d.ts.map +1 -1
- package/types/lib/parsers/huggingfaceUtils.d.ts +12 -0
- package/types/lib/parsers/huggingfaceUtils.d.ts.map +1 -1
- package/types/lib/parsers/kiroPermissions.d.ts +62 -0
- package/types/lib/parsers/kiroPermissions.d.ts.map +1 -0
- package/types/lib/parsers/largeJson.d.ts +4 -3
- package/types/lib/parsers/largeJson.d.ts.map +1 -1
- package/types/lib/parsers/vscodeExtensionId.d.ts +48 -0
- package/types/lib/parsers/vscodeExtensionId.d.ts.map +1 -0
- package/types/lib/server/server.d.ts.map +1 -1
- package/types/lib/stages/postgen/postgen.d.ts +7 -0
- package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
- package/types/lib/stages/postgen/ruleEngine.d.ts.map +1 -1
- package/types/lib/stages/postgen/specVersionCompat.d.ts +25 -0
- package/types/lib/stages/postgen/specVersionCompat.d.ts.map +1 -1
- package/types/lib/stages/pregen/envAudit.d.ts.map +1 -1
- package/types/lib/stages/pregen/pregen.d.ts +12 -8
- package/types/lib/stages/pregen/pregen.d.ts.map +1 -1
- package/types/lib/validator/bomValidator.d.ts +5 -1
- package/types/lib/validator/bomValidator.d.ts.map +1 -1
- package/types/lib/validator/complianceEngine.d.ts +4 -4
- package/types/lib/validator/complianceEngine.d.ts.map +1 -1
- package/types/lib/validator/complianceRules.d.ts +14 -2
- package/types/lib/validator/complianceRules.d.ts.map +1 -1
- package/types/lib/validator/index.d.ts +10 -0
- package/types/lib/validator/index.d.ts.map +1 -1
- package/types/lib/validator/reporters/json.d.ts.map +1 -1
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
// Bounded, read-only access to files inside an extracted image or a live host.
|
|
2
|
+
//
|
|
3
|
+
// Every file a scan opens may be hostile: only regular files that stay inside
|
|
4
|
+
// the extracted root are opened, a symlink is never followed, a FIFO is never
|
|
5
|
+
// opened, and reads are capped. A missing or odd file yields no result rather
|
|
6
|
+
// than throwing.
|
|
7
|
+
|
|
8
|
+
import { createHash } from "node:crypto";
|
|
9
|
+
import {
|
|
10
|
+
closeSync,
|
|
11
|
+
constants,
|
|
12
|
+
fstatSync,
|
|
13
|
+
lstatSync,
|
|
14
|
+
openSync,
|
|
15
|
+
readSync,
|
|
16
|
+
realpathSync,
|
|
17
|
+
} from "node:fs";
|
|
18
|
+
import { resolve, sep } from "node:path";
|
|
19
|
+
import process from "node:process";
|
|
20
|
+
|
|
21
|
+
const READ_CHUNK_BYTES = 1024 * 1024;
|
|
22
|
+
|
|
23
|
+
// O_NOFOLLOW refuses a symlink swapped in after lstat, and O_NONBLOCK keeps a
|
|
24
|
+
// FIFO swapped in the same way from blocking the open. Neither exists on
|
|
25
|
+
// Windows, where neither race applies.
|
|
26
|
+
const OPEN_FLAGS =
|
|
27
|
+
constants.O_RDONLY |
|
|
28
|
+
(constants.O_NOFOLLOW || 0) |
|
|
29
|
+
(constants.O_NONBLOCK || 0);
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The largest file scanFileMarkers reads. Larger files are skipped whole
|
|
33
|
+
* rather than read in part, so a marker past the cap is never mistaken for an
|
|
34
|
+
* absent one; the result says the file was skipped.
|
|
35
|
+
*
|
|
36
|
+
* @type {number}
|
|
37
|
+
*/
|
|
38
|
+
export const MAX_MARKER_SCAN_BYTES = 2 * 1024 * 1024 * 1024;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Open a path only when it is a regular file that does not resolve outside
|
|
42
|
+
* rootDir. lstat runs first so a FIFO is rejected without opening it (an open
|
|
43
|
+
* on a FIFO blocks until a writer appears) and a symlink is never followed.
|
|
44
|
+
*
|
|
45
|
+
* @param {string} absPath absolute path
|
|
46
|
+
* @param {string|undefined} rootDir extracted root the path must stay under
|
|
47
|
+
* @returns {{fd: number, size: number}|undefined} an open descriptor the
|
|
48
|
+
* caller closes, or undefined
|
|
49
|
+
*/
|
|
50
|
+
export function openRegularFile(absPath, rootDir) {
|
|
51
|
+
let fd;
|
|
52
|
+
try {
|
|
53
|
+
if (typeof absPath !== "string" || !absPath) {
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
const lst = lstatSync(absPath);
|
|
57
|
+
if (!lst.isFile()) {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
if (rootDir) {
|
|
61
|
+
const root = realpathSync(resolve(rootDir));
|
|
62
|
+
const real = realpathSync(absPath);
|
|
63
|
+
const rootPrefix = root.endsWith(sep) ? root : root + sep;
|
|
64
|
+
if (real !== root && !real.startsWith(rootPrefix)) {
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
fd = openSync(absPath, OPEN_FLAGS);
|
|
69
|
+
const stats = fstatSync(fd);
|
|
70
|
+
if (!stats.isFile()) {
|
|
71
|
+
closeSync(fd);
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
return { fd, size: stats.size };
|
|
75
|
+
} catch {
|
|
76
|
+
if (fd !== undefined) {
|
|
77
|
+
try {
|
|
78
|
+
closeSync(fd);
|
|
79
|
+
} catch {
|
|
80
|
+
// already closed
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Read a small text file in full, only when it is a regular file no larger
|
|
89
|
+
* than maxBytes. A FIFO, a directory, a symlink or an oversized file reads as
|
|
90
|
+
* undefined.
|
|
91
|
+
*
|
|
92
|
+
* @param {string} absPath absolute path
|
|
93
|
+
* @param {number} maxBytes largest size read
|
|
94
|
+
* @param {string|undefined} [rootDir] root the path must stay under
|
|
95
|
+
* @returns {string|undefined} the text, or undefined
|
|
96
|
+
*/
|
|
97
|
+
export function readRegularTextFile(absPath, maxBytes, rootDir) {
|
|
98
|
+
const opened = openRegularFile(absPath, rootDir);
|
|
99
|
+
if (!opened) {
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
try {
|
|
103
|
+
if (opened.size > maxBytes) {
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
const buffer = Buffer.alloc(opened.size);
|
|
107
|
+
let total = 0;
|
|
108
|
+
while (total < opened.size) {
|
|
109
|
+
const read = readSync(
|
|
110
|
+
opened.fd,
|
|
111
|
+
buffer,
|
|
112
|
+
total,
|
|
113
|
+
opened.size - total,
|
|
114
|
+
total,
|
|
115
|
+
);
|
|
116
|
+
if (read <= 0) {
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
total += read;
|
|
120
|
+
}
|
|
121
|
+
return buffer.toString("utf8", 0, total);
|
|
122
|
+
} catch {
|
|
123
|
+
return undefined;
|
|
124
|
+
} finally {
|
|
125
|
+
try {
|
|
126
|
+
closeSync(opened.fd);
|
|
127
|
+
} catch {
|
|
128
|
+
// already closed
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Find byte markers in a file with bounded chunked reads.
|
|
135
|
+
*
|
|
136
|
+
* Each hit records up to `beforeBytes` bytes before the marker and up to
|
|
137
|
+
* `contextBytes` bytes after it, so a caller can read a version that follows a
|
|
138
|
+
* marker or check what a string is part of. Consecutive reads overlap by the
|
|
139
|
+
* longest marker plus the context length, so a marker split across two reads
|
|
140
|
+
* is seen whole once. Only bytes that were read are searched.
|
|
141
|
+
*
|
|
142
|
+
* @param {string} absPath absolute path of the file
|
|
143
|
+
* @param {string|undefined} rootDir extracted root the file must stay under
|
|
144
|
+
* @param {Buffer[]} markers byte markers to look for
|
|
145
|
+
* @param {Object} [options] options
|
|
146
|
+
* @param {number} [options.maxBytes] files larger than this are not read
|
|
147
|
+
* @param {number} [options.contextBytes=64] bytes kept after each hit
|
|
148
|
+
* @param {number} [options.beforeBytes=1] bytes kept before each hit
|
|
149
|
+
* @param {number} [options.maxHits=16] hits kept per marker
|
|
150
|
+
* @returns {{hits: {before: Buffer, after: Buffer, offset: number}[][], size: number, skipped?: string}|undefined}
|
|
151
|
+
* hits per marker, in marker order, and the file size; `skipped` is
|
|
152
|
+
* `too-large` when the file is over the cap and was not read. Undefined when
|
|
153
|
+
* the file cannot be opened.
|
|
154
|
+
*/
|
|
155
|
+
export function scanFileMarkers(
|
|
156
|
+
absPath,
|
|
157
|
+
rootDir,
|
|
158
|
+
markers,
|
|
159
|
+
{
|
|
160
|
+
maxBytes = MAX_MARKER_SCAN_BYTES,
|
|
161
|
+
contextBytes = 64,
|
|
162
|
+
beforeBytes = 1,
|
|
163
|
+
maxHits = 16,
|
|
164
|
+
} = {},
|
|
165
|
+
) {
|
|
166
|
+
if (!Array.isArray(markers) || !markers.length) {
|
|
167
|
+
return undefined;
|
|
168
|
+
}
|
|
169
|
+
const opened = openRegularFile(absPath, rootDir);
|
|
170
|
+
if (!opened) {
|
|
171
|
+
return undefined;
|
|
172
|
+
}
|
|
173
|
+
const hits = markers.map(() => []);
|
|
174
|
+
try {
|
|
175
|
+
const { fd, size } = opened;
|
|
176
|
+
if (size > maxBytes) {
|
|
177
|
+
return { hits, size, skipped: "too-large" };
|
|
178
|
+
}
|
|
179
|
+
if (size <= 0) {
|
|
180
|
+
return { hits, size };
|
|
181
|
+
}
|
|
182
|
+
const longest = Math.max(...markers.map((marker) => marker.length));
|
|
183
|
+
const overlap = longest + contextBytes;
|
|
184
|
+
const bufferSize = Math.min(size, READ_CHUNK_BYTES) + overlap;
|
|
185
|
+
const buffer = Buffer.allocUnsafe(bufferSize);
|
|
186
|
+
// The bytes just before the current window, for a hit near its start.
|
|
187
|
+
let previousTail = Buffer.alloc(0);
|
|
188
|
+
for (let position = 0; position < size; position += READ_CHUNK_BYTES) {
|
|
189
|
+
const want = Math.min(bufferSize, size - position);
|
|
190
|
+
const read = readSync(fd, buffer, 0, want, position);
|
|
191
|
+
if (read <= 0) {
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
194
|
+
// What a previous, longer read left in the buffer past `read` is never
|
|
195
|
+
// searched.
|
|
196
|
+
const window = buffer.subarray(0, read);
|
|
197
|
+
// Only hits starting inside this window are new; the overlap lets the
|
|
198
|
+
// next window see a marker and its context that cross the edge. The
|
|
199
|
+
// last window has no next one, so everything it read is searched.
|
|
200
|
+
const isLast = position + read >= size;
|
|
201
|
+
const searchLimit = isLast ? read : Math.min(READ_CHUNK_BYTES, read);
|
|
202
|
+
for (let index = 0; index < markers.length; index++) {
|
|
203
|
+
const marker = markers[index];
|
|
204
|
+
const found = hits[index];
|
|
205
|
+
let offset = window.indexOf(marker);
|
|
206
|
+
while (
|
|
207
|
+
offset !== -1 &&
|
|
208
|
+
offset < searchLimit &&
|
|
209
|
+
found.length < maxHits
|
|
210
|
+
) {
|
|
211
|
+
const afterStart = offset + marker.length;
|
|
212
|
+
const before =
|
|
213
|
+
offset >= beforeBytes
|
|
214
|
+
? window.subarray(offset - beforeBytes, offset)
|
|
215
|
+
: Buffer.concat([
|
|
216
|
+
previousTail,
|
|
217
|
+
window.subarray(0, offset),
|
|
218
|
+
]).subarray(-beforeBytes);
|
|
219
|
+
found.push({
|
|
220
|
+
offset: position + offset,
|
|
221
|
+
before: Buffer.from(before),
|
|
222
|
+
after: Buffer.from(
|
|
223
|
+
window.subarray(
|
|
224
|
+
Math.min(afterStart, read),
|
|
225
|
+
Math.min(read, afterStart + contextBytes),
|
|
226
|
+
),
|
|
227
|
+
),
|
|
228
|
+
});
|
|
229
|
+
offset = window.indexOf(marker, offset + 1);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
if (read < bufferSize) {
|
|
233
|
+
break;
|
|
234
|
+
}
|
|
235
|
+
previousTail = Buffer.from(
|
|
236
|
+
window.subarray(
|
|
237
|
+
Math.max(0, READ_CHUNK_BYTES - beforeBytes),
|
|
238
|
+
READ_CHUNK_BYTES,
|
|
239
|
+
),
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
return { hits, size };
|
|
243
|
+
} catch {
|
|
244
|
+
return undefined;
|
|
245
|
+
} finally {
|
|
246
|
+
try {
|
|
247
|
+
closeSync(opened.fd);
|
|
248
|
+
} catch {
|
|
249
|
+
// already closed
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Compute the digest of a regular file with bounded chunked reads, under the
|
|
256
|
+
* same rules as readRegularTextFile: a FIFO, a directory, a symlink, a file
|
|
257
|
+
* that resolves outside rootDir or one larger than maxBytes yields undefined.
|
|
258
|
+
*
|
|
259
|
+
* @param {string} absPath absolute path
|
|
260
|
+
* @param {number} maxBytes largest size hashed
|
|
261
|
+
* @param {string|undefined} [rootDir] root the path must stay under
|
|
262
|
+
* @param {string} [algorithm="sha256"] node:crypto hash algorithm
|
|
263
|
+
* @returns {string|undefined} the hex digest, or undefined
|
|
264
|
+
*/
|
|
265
|
+
export function hashRegularFile(
|
|
266
|
+
absPath,
|
|
267
|
+
maxBytes,
|
|
268
|
+
rootDir,
|
|
269
|
+
algorithm = "sha256",
|
|
270
|
+
) {
|
|
271
|
+
const opened = openRegularFile(absPath, rootDir);
|
|
272
|
+
if (!opened) {
|
|
273
|
+
return undefined;
|
|
274
|
+
}
|
|
275
|
+
try {
|
|
276
|
+
if (opened.size > maxBytes) {
|
|
277
|
+
return undefined;
|
|
278
|
+
}
|
|
279
|
+
const hash = createHash(algorithm);
|
|
280
|
+
const buffer = Buffer.alloc(Math.min(READ_CHUNK_BYTES, opened.size || 1));
|
|
281
|
+
let total = 0;
|
|
282
|
+
while (total < opened.size) {
|
|
283
|
+
const read = readSync(
|
|
284
|
+
opened.fd,
|
|
285
|
+
buffer,
|
|
286
|
+
0,
|
|
287
|
+
Math.min(buffer.length, opened.size - total),
|
|
288
|
+
total,
|
|
289
|
+
);
|
|
290
|
+
if (read <= 0) {
|
|
291
|
+
break;
|
|
292
|
+
}
|
|
293
|
+
hash.update(buffer.subarray(0, read));
|
|
294
|
+
total += read;
|
|
295
|
+
}
|
|
296
|
+
return hash.digest("hex");
|
|
297
|
+
} catch {
|
|
298
|
+
return undefined;
|
|
299
|
+
} finally {
|
|
300
|
+
try {
|
|
301
|
+
closeSync(opened.fd);
|
|
302
|
+
} catch {
|
|
303
|
+
// already closed
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* True when the process runs as root, where a symlink planted in a user's
|
|
310
|
+
* home could point a scan at files only root can read.
|
|
311
|
+
*
|
|
312
|
+
* @returns {boolean} true for uid 0
|
|
313
|
+
*/
|
|
314
|
+
export function isRunningAsRoot() {
|
|
315
|
+
return typeof process.getuid === "function" && process.getuid() === 0;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Read a small text file a user keeps in their home, such as an editor's or an
|
|
320
|
+
* agent's configuration. Dotfile managers often make these symlinks, so a
|
|
321
|
+
* symlink to a regular file is followed, except when the process runs as root.
|
|
322
|
+
* The target must still be a regular file no larger than maxBytes.
|
|
323
|
+
*
|
|
324
|
+
* @param {string} absPath absolute path
|
|
325
|
+
* @param {number} maxBytes largest size read
|
|
326
|
+
* @returns {string|undefined} the text, or undefined
|
|
327
|
+
*/
|
|
328
|
+
export function readUserFileText(absPath, maxBytes) {
|
|
329
|
+
if (typeof absPath !== "string" || !absPath) {
|
|
330
|
+
return undefined;
|
|
331
|
+
}
|
|
332
|
+
let target = absPath;
|
|
333
|
+
try {
|
|
334
|
+
if (lstatSync(absPath).isSymbolicLink()) {
|
|
335
|
+
if (isRunningAsRoot()) {
|
|
336
|
+
return undefined;
|
|
337
|
+
}
|
|
338
|
+
target = realpathSync(absPath);
|
|
339
|
+
}
|
|
340
|
+
} catch {
|
|
341
|
+
return undefined;
|
|
342
|
+
}
|
|
343
|
+
return readRegularTextFile(target, maxBytes);
|
|
344
|
+
}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
// Bounded probe for a Brotli decoder compiled into a native file, and for
|
|
2
|
+
// whether that copy carries the CVE-2026-111497 fix.
|
|
3
|
+
//
|
|
4
|
+
// Node.js, the Python Brotli and brotlicffi wheels, the PHP and Ruby
|
|
5
|
+
// extensions, the .NET runtime and many static binaries carry a private copy of
|
|
6
|
+
// Google's C decoder. No package manager names that copy, and its version is
|
|
7
|
+
// not stored as a string anywhere in the file, so a BOM has to read the file
|
|
8
|
+
// to say whether a vulnerable decoder ships in it.
|
|
9
|
+
//
|
|
10
|
+
// Three kinds of evidence are read, each classified by the bytes around it:
|
|
11
|
+
//
|
|
12
|
+
// - The names of the decoder's error codes, which BrotliDecoderErrorString()
|
|
13
|
+
// returns (EXUBERANT_NIBBLE is one). Upstream 1.1+ stores them prefixed,
|
|
14
|
+
// `_ERROR_FORMAT_EXUBERANT_NIBBLE`; 1.0.x and Debian's backport store the
|
|
15
|
+
// bare name between NULs. The fix, google/brotli 0ed4268, added the name
|
|
16
|
+
// BLOCK_SWITCH, so a decoder whose table has it is patched.
|
|
17
|
+
// https://github.com/google/brotli/blob/v1.2.0/c/include/brotli/decode.h#L72
|
|
18
|
+
// https://github.com/google/brotli/commit/0ed4268a4401abcb4472096340477cf4af7d1a2b
|
|
19
|
+
// - Two decoder tables, kCodeLengthCodeOrder and kCodeLengthPrefixValue
|
|
20
|
+
// (c/dec/decode.c). They stay when a linker drops the error-name table
|
|
21
|
+
// because nothing calls BrotliDecoderErrorString (--gc-sections, LTO,
|
|
22
|
+
// -dead_strip). The encoder keeps the first table but not the second. With
|
|
23
|
+
// the tables alone the decoder is present but its fix state is unknown.
|
|
24
|
+
// - Node.js's zlib.constants table, BROTLI_DECODER_ERROR_FORMAT_*. It mirrors
|
|
25
|
+
// the brotli headers Node.js was built with, and a linker that merges string
|
|
26
|
+
// tails (lld -O2, lld-link /OPT:ICF) can leave only it in place of the
|
|
27
|
+
// decoder's own names. Next to the decoder tables it stands for them; alone,
|
|
28
|
+
// as in a Node.js linked to a shared libbrotlidec, it is no decoder.
|
|
29
|
+
//
|
|
30
|
+
// The ports are told apart. The Go port (andybalholm/brotli, fixed in v1.2.7)
|
|
31
|
+
// keeps the same names in Go's undelimited string table, so a Go binary can
|
|
32
|
+
// hold both a cgo-linked C decoder and the Go port, and each gets its own
|
|
33
|
+
// fix state. The Rust port (brotli-decompressor) keeps `ERROR_FORMAT_...`
|
|
34
|
+
// strings and the same tables but is not affected; its crate name in symbols
|
|
35
|
+
// or panic paths marks it, and its evidence is ignored.
|
|
36
|
+
//
|
|
37
|
+
// Nothing is executed. A file over the read cap is reported as skipped, never
|
|
38
|
+
// as free of a decoder.
|
|
39
|
+
//
|
|
40
|
+
// The component helpers that put the answer into a BOM are in
|
|
41
|
+
// lib/inventory/brotliDecoder.js; this half lives in the core layer so the HTTP
|
|
42
|
+
// client can ask it about its own runtime.
|
|
43
|
+
|
|
44
|
+
import { scanFileMarkers } from "./boundedFile.js";
|
|
45
|
+
|
|
46
|
+
const NAME = Buffer.from("EXUBERANT_NIBBLE");
|
|
47
|
+
const FIX_NAME = Buffer.from("BLOCK_SWITCH");
|
|
48
|
+
// The Go linker writes this magic at the start of the buildinfo section.
|
|
49
|
+
// https://github.com/golang/go/blob/go1.25.0/src/debug/buildinfo/buildinfo.go#L58
|
|
50
|
+
const GO_BUILDINFO_MAGIC = Buffer.from("\xff Go buildinf:", "latin1");
|
|
51
|
+
// static const uint8_t kCodeLengthCodeOrder[18] and
|
|
52
|
+
// kCodeLengthPrefixValue[16], c/dec/decode.c.
|
|
53
|
+
const CODE_LENGTH_CODE_ORDER = Buffer.from([
|
|
54
|
+
1, 2, 3, 4, 0, 5, 17, 6, 16, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
|
55
|
+
]);
|
|
56
|
+
const CODE_LENGTH_PREFIX_VALUE = Buffer.from([
|
|
57
|
+
0, 4, 3, 2, 0, 4, 3, 1, 0, 4, 3, 2, 0, 4, 3, 5,
|
|
58
|
+
]);
|
|
59
|
+
// Legacy and v0 Rust mangling length-prefix the crate name; panic messages
|
|
60
|
+
// name the crate's source path.
|
|
61
|
+
const RUST_CRATE_SYMBOL = Buffer.from("19brotli_decompressor");
|
|
62
|
+
const RUST_CRATE_PATH = Buffer.from("brotli-decompressor-");
|
|
63
|
+
|
|
64
|
+
const CONSTANT_PREFIX = Buffer.from("BROTLI_DECODER_ERROR_FORMAT_");
|
|
65
|
+
const C_PREFIX = Buffer.from("_ERROR_FORMAT_");
|
|
66
|
+
const RUST_PREFIX = Buffer.from("ERROR_FORMAT_");
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* The most files of one kind (executables and libraries, or extension
|
|
70
|
+
* modules) one scan opens in search of a Brotli decoder.
|
|
71
|
+
*
|
|
72
|
+
* @type {number}
|
|
73
|
+
*/
|
|
74
|
+
export const MAX_BROTLI_PROBES = 4096;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* The most bytes one scan reads in search of Brotli decoders.
|
|
78
|
+
*
|
|
79
|
+
* @type {number}
|
|
80
|
+
*/
|
|
81
|
+
export const MAX_BROTLI_PROBE_BYTES = 16 * 1024 * 1024 * 1024;
|
|
82
|
+
|
|
83
|
+
function endsWith(buffer, suffix) {
|
|
84
|
+
return (
|
|
85
|
+
buffer.length >= suffix.length &&
|
|
86
|
+
buffer.subarray(buffer.length - suffix.length).equals(suffix)
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Classify one hit of an error name by what it is part of.
|
|
92
|
+
*
|
|
93
|
+
* @param {{before: Buffer, after: Buffer}} hit marker hit
|
|
94
|
+
* @returns {string} `constant`, `c`, `rust` or `other`
|
|
95
|
+
*/
|
|
96
|
+
function classify(hit) {
|
|
97
|
+
if (endsWith(hit.before, CONSTANT_PREFIX)) {
|
|
98
|
+
return "constant";
|
|
99
|
+
}
|
|
100
|
+
if (endsWith(hit.before, C_PREFIX)) {
|
|
101
|
+
return "c";
|
|
102
|
+
}
|
|
103
|
+
if (endsWith(hit.before, RUST_PREFIX)) {
|
|
104
|
+
return "rust";
|
|
105
|
+
}
|
|
106
|
+
const previous = hit.before.length ? hit.before[hit.before.length - 1] : 0;
|
|
107
|
+
if (previous === 0 && hit.after.length && hit.after[0] === 0) {
|
|
108
|
+
return "c";
|
|
109
|
+
}
|
|
110
|
+
return "other";
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Read which Brotli decoders a native file embeds and whether each carries
|
|
115
|
+
* the CVE-2026-111497 fix.
|
|
116
|
+
*
|
|
117
|
+
* @param {string} absPath absolute path of the file
|
|
118
|
+
* @param {string|undefined} rootDir extracted root the file must stay under
|
|
119
|
+
* @returns {{c?: {blockSwitchFix: string, evidence: string}, go?: {blockSwitchFix: string}, skipped?: string, size: number}|undefined}
|
|
120
|
+
* undefined when the file cannot be read or holds no decoder. `c` is
|
|
121
|
+
* Google's C decoder, with blockSwitchFix `true`, `false` or `unknown` and
|
|
122
|
+
* the evidence it rests on (`error-names`, `constant-names` or `tables`);
|
|
123
|
+
* `go` is the Go port. `skipped` is `too-large` for a file over the read cap.
|
|
124
|
+
*/
|
|
125
|
+
export function readBrotliDecoder(absPath, rootDir) {
|
|
126
|
+
const scan = scanFileMarkers(
|
|
127
|
+
absPath,
|
|
128
|
+
rootDir,
|
|
129
|
+
[
|
|
130
|
+
NAME,
|
|
131
|
+
FIX_NAME,
|
|
132
|
+
GO_BUILDINFO_MAGIC,
|
|
133
|
+
CODE_LENGTH_CODE_ORDER,
|
|
134
|
+
CODE_LENGTH_PREFIX_VALUE,
|
|
135
|
+
RUST_CRATE_SYMBOL,
|
|
136
|
+
RUST_CRATE_PATH,
|
|
137
|
+
],
|
|
138
|
+
{ contextBytes: 1, beforeBytes: CONSTANT_PREFIX.length, maxHits: 256 },
|
|
139
|
+
);
|
|
140
|
+
if (!scan) {
|
|
141
|
+
return undefined;
|
|
142
|
+
}
|
|
143
|
+
if (scan.skipped) {
|
|
144
|
+
return { skipped: scan.skipped, size: scan.size };
|
|
145
|
+
}
|
|
146
|
+
const [
|
|
147
|
+
names,
|
|
148
|
+
fixNames,
|
|
149
|
+
goMagic,
|
|
150
|
+
codeOrder,
|
|
151
|
+
prefixValue,
|
|
152
|
+
rustSymbol,
|
|
153
|
+
rustPath,
|
|
154
|
+
] = scan.hits;
|
|
155
|
+
const kinds = (hits) => new Set(hits.map(classify));
|
|
156
|
+
const nameKinds = kinds(names);
|
|
157
|
+
const fixKinds = kinds(fixNames);
|
|
158
|
+
const isGo = goMagic.length > 0;
|
|
159
|
+
const isRust = rustSymbol.length > 0 || rustPath.length > 0;
|
|
160
|
+
const hasTables = codeOrder.length > 0 && prefixValue.length > 0;
|
|
161
|
+
const result = { size: scan.size };
|
|
162
|
+
// Go strings are not delimited, so a name that is neither C-shaped nor a
|
|
163
|
+
// constant is the Go port's, in a Go binary.
|
|
164
|
+
const hasGoPort = isGo && nameKinds.has("other");
|
|
165
|
+
if (hasGoPort) {
|
|
166
|
+
result.go = { blockSwitchFix: fixKinds.has("other") ? "true" : "false" };
|
|
167
|
+
}
|
|
168
|
+
if (nameKinds.has("c")) {
|
|
169
|
+
result.c = {
|
|
170
|
+
blockSwitchFix: fixKinds.has("c") ? "true" : "false",
|
|
171
|
+
evidence: "error-names",
|
|
172
|
+
};
|
|
173
|
+
} else if (hasTables && !hasGoPort && !isRust) {
|
|
174
|
+
result.c = nameKinds.has("constant")
|
|
175
|
+
? {
|
|
176
|
+
blockSwitchFix: fixKinds.has("constant") ? "true" : "false",
|
|
177
|
+
evidence: "constant-names",
|
|
178
|
+
}
|
|
179
|
+
: { blockSwitchFix: "unknown", evidence: "tables" };
|
|
180
|
+
}
|
|
181
|
+
return result.c || result.go ? result : undefined;
|
|
182
|
+
}
|
package/lib/core/env.js
CHANGED
|
@@ -301,6 +301,13 @@ export const SWIFT_CMD = readEnvironmentVariable("SWIFT_CMD") || "swift";
|
|
|
301
301
|
/** Resolved Ruby executable command (RUBY_CMD env var, or "ruby"). */
|
|
302
302
|
export const RUBY_CMD = readEnvironmentVariable("RUBY_CMD") || "ruby";
|
|
303
303
|
|
|
304
|
+
/** Resolved RubyGems executable command (CDXGEN_GEM_CMD env var, or "gem"). */
|
|
305
|
+
export const GEM_CMD = readEnvironmentVariable("CDXGEN_GEM_CMD") || "gem";
|
|
306
|
+
|
|
307
|
+
/** Resolved Bundler executable command (CDXGEN_BUNDLE_CMD env var, or "bundle"). */
|
|
308
|
+
export const BUNDLE_CMD =
|
|
309
|
+
readEnvironmentVariable("CDXGEN_BUNDLE_CMD") || "bundle";
|
|
310
|
+
|
|
304
311
|
/** Resolved PHP executable command (PHP_CMD env var, or "php"). */
|
|
305
312
|
export const PHP_CMD = readEnvironmentVariable("PHP_CMD") || "php";
|
|
306
313
|
|
|
@@ -520,6 +527,7 @@ export const PROJECT_TYPE_ALIASES = {
|
|
|
520
527
|
"vscode",
|
|
521
528
|
"openvsx",
|
|
522
529
|
"vscode-extensions",
|
|
530
|
+
"ide",
|
|
523
531
|
"ide-extension",
|
|
524
532
|
"ide-extensions",
|
|
525
533
|
],
|
|
@@ -533,6 +541,32 @@ export const PROJECT_TYPE_ALIASES = {
|
|
|
533
541
|
"ai-provenance": ["ai-provenance", "ai-authorship", "aicode", "ai-codegen"],
|
|
534
542
|
};
|
|
535
543
|
|
|
544
|
+
/**
|
|
545
|
+
* Project types, with their aliases, that inventory the host cdxgen runs on
|
|
546
|
+
* rather than the scan path: installed packages, users, shell history, IDE
|
|
547
|
+
* and browser extensions, or the Maven, Gradle, sbt, Cargo and Helm caches in
|
|
548
|
+
* the user's home directory. Only the operator may select them; neither a
|
|
549
|
+
* server request nor a config file in the scanned directory can.
|
|
550
|
+
*
|
|
551
|
+
* @type {Set<string>}
|
|
552
|
+
*/
|
|
553
|
+
export const HOST_SCOPE_PROJECT_TYPES = new Set(
|
|
554
|
+
[
|
|
555
|
+
"os",
|
|
556
|
+
"hbom",
|
|
557
|
+
"cargo-cache",
|
|
558
|
+
"helm-index",
|
|
559
|
+
"gradle-index",
|
|
560
|
+
"sbt-index",
|
|
561
|
+
"maven-index",
|
|
562
|
+
"vscode-extension",
|
|
563
|
+
"chrome-extension",
|
|
564
|
+
"agentic",
|
|
565
|
+
]
|
|
566
|
+
.flatMap((key) => PROJECT_TYPE_ALIASES[key] || [key])
|
|
567
|
+
.concat(["maven-repo"]),
|
|
568
|
+
);
|
|
569
|
+
|
|
536
570
|
/** Map of base package manager to the array of accepted alias strings. */
|
|
537
571
|
export const PACKAGE_MANAGER_ALIASES = {
|
|
538
572
|
scala: ["sbt"],
|