@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,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether the frontmatter of a SKILL.md satisfies the open Agent Skills
|
|
3
|
+
* constraints (agentskills.io): a name of 1-64 lowercase letters, digits and
|
|
4
|
+
* hyphens, and a description of 1-1024 characters.
|
|
5
|
+
*
|
|
6
|
+
* @param {{name?: unknown, description?: unknown}|undefined} metadata Frontmatter values
|
|
7
|
+
* @returns {boolean} true when both constraints hold
|
|
8
|
+
*/
|
|
9
|
+
export function isAgentSkillSpecValid(metadata) {
|
|
10
|
+
return (
|
|
11
|
+
typeof metadata?.name === "string" &&
|
|
12
|
+
/^[a-z0-9-]{1,64}$/u.test(metadata.name) &&
|
|
13
|
+
typeof metadata?.description === "string" &&
|
|
14
|
+
metadata.description.length >= 1 &&
|
|
15
|
+
metadata.description.length <= 1024
|
|
16
|
+
);
|
|
17
|
+
}
|
|
@@ -90,8 +90,11 @@ const isVendoredArtifactPath = (filePath) => {
|
|
|
90
90
|
};
|
|
91
91
|
const GGUF_MIN_ALIGNMENT = 4;
|
|
92
92
|
const GGUF_MAX_ALIGNMENT = 1024 * 1024;
|
|
93
|
+
// Tested against full paths. The config exceptions follow IGNORE_FILE_PATTERN
|
|
94
|
+
// in analyzer.js, with the app exception anchored to a path separator instead
|
|
95
|
+
// of the start of a file name.
|
|
93
96
|
const IGNORE_SOURCE_FILE_PATTERN =
|
|
94
|
-
/(^|\/|\\)(__tests__|fixtures?|examples?|samples?)($|\/|\\)|(^|\/|\\)(test|spec|mock|setup-jest|conftest|sitecustomize)\.(
|
|
97
|
+
/(^|\/|\\)(__tests__|fixtures?|examples?|samples?)($|\/|\\)|(^|\/|\\)(test|spec|mock|setup-jest|conftest|sitecustomize)\.([cm]?[jt]sx?|py)$|(?<!vite\.|vue\.|svelte\.|astro\.|(?:^|\/|\\)app\.)(conf|config)\.[cm]?[jt]sx?$/iu;
|
|
95
98
|
const HOST_PROVIDER_PATTERNS = [
|
|
96
99
|
["openai", /(?:^|\.)openai\.com$/iu],
|
|
97
100
|
["anthropic", /(?:^|\.)anthropic\.com$/iu],
|
|
@@ -68,9 +68,19 @@ const IGNORE_DIRS = readEnvironmentVariable("ASTGEN_IGNORE_DIRS")
|
|
|
68
68
|
"coverage",
|
|
69
69
|
];
|
|
70
70
|
|
|
71
|
+
// The pattern is tested against file names. Config files are skipped because
|
|
72
|
+
// their imports are mostly build and test tooling. The exceptions hold code the
|
|
73
|
+
// application is built from: the Vite, Vue CLI, Svelte, and Astro configs name
|
|
74
|
+
// the build plugins and integrations the app needs, and app.config.* holds
|
|
75
|
+
// application code, such as the root providers of an Angular app. The app
|
|
76
|
+
// exception is anchored to the start of the name, so names such as
|
|
77
|
+
// webapp.config.ts are still skipped. [cm]?[jt]sx? covers every JavaScript and
|
|
78
|
+
// TypeScript module extension, as the default test globs of Jest and Vitest do.
|
|
79
|
+
// Keep the config exceptions in step with IGNORE_SOURCE_FILE_PATTERN in
|
|
80
|
+
// aiCollector.js.
|
|
71
81
|
const IGNORE_FILE_PATTERN = new RegExp(
|
|
72
82
|
readEnvironmentVariable("ASTGEN_IGNORE_FILE_PATTERN") ||
|
|
73
|
-
"(test|spec|mock|setup-jest|\\.d)\\.(
|
|
83
|
+
"(test|spec|mock|setup-jest|\\.d)\\.[cm]?[jt]sx?$|(?<!vite\\.|vue\\.|svelte\\.|astro\\.|^app\\.)(conf|config)\\.[cm]?[jt]sx?$",
|
|
74
84
|
"i",
|
|
75
85
|
);
|
|
76
86
|
|
|
@@ -210,6 +220,46 @@ const getAllFiles = (
|
|
|
210
220
|
return result;
|
|
211
221
|
};
|
|
212
222
|
|
|
223
|
+
/**
|
|
224
|
+
* Walk a directory tree once and return the files whose names end with any of
|
|
225
|
+
* the given extensions.
|
|
226
|
+
*
|
|
227
|
+
* Files are grouped by extension in the order of `extensions`, and each group
|
|
228
|
+
* keeps the walk order. That is the order one walk per extension produced, and
|
|
229
|
+
* occurrences reach the BOM in it.
|
|
230
|
+
*
|
|
231
|
+
* @param {string} dir Directory to walk
|
|
232
|
+
* @param {string[]} extensions File extensions, each with its leading dot
|
|
233
|
+
* @param {boolean|Object} deepOrOptions Deep flag, or `{ deep, exclude, noIgnore }`
|
|
234
|
+
* @returns {string[]} Matching file paths
|
|
235
|
+
*/
|
|
236
|
+
const getAllFilesByExtensions = (dir, extensions, deepOrOptions) => {
|
|
237
|
+
const searchOptions = normalizeAnalyzerSearchOptions(deepOrOptions);
|
|
238
|
+
const files = getAllFiles(
|
|
239
|
+
searchOptions.deep,
|
|
240
|
+
dir,
|
|
241
|
+
undefined,
|
|
242
|
+
undefined,
|
|
243
|
+
undefined,
|
|
244
|
+
new RegExp(
|
|
245
|
+
`(?:${extensions.map((extension) => `\\${extension}`).join("|")})$`,
|
|
246
|
+
),
|
|
247
|
+
dir,
|
|
248
|
+
searchOptions.exclude,
|
|
249
|
+
searchOptions.noIgnore,
|
|
250
|
+
);
|
|
251
|
+
const filesByExtension = extensions.map(() => []);
|
|
252
|
+
for (const file of files) {
|
|
253
|
+
const extensionIndex = extensions.findIndex((extension) =>
|
|
254
|
+
file.endsWith(extension),
|
|
255
|
+
);
|
|
256
|
+
if (extensionIndex !== -1) {
|
|
257
|
+
filesByExtension[extensionIndex].push(file);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return filesByExtension.flat();
|
|
261
|
+
};
|
|
262
|
+
|
|
213
263
|
const babelParserOptions = {
|
|
214
264
|
sourceType: "unambiguous",
|
|
215
265
|
allowImportExportEverywhere: true,
|
|
@@ -1752,37 +1802,29 @@ export const parseFileASTTreeCollected = (src, file) => {
|
|
|
1752
1802
|
return { imports, exports };
|
|
1753
1803
|
};
|
|
1754
1804
|
|
|
1805
|
+
const JS_TS_SOURCE_EXTENSIONS = [
|
|
1806
|
+
".js",
|
|
1807
|
+
".jsx",
|
|
1808
|
+
".cjs",
|
|
1809
|
+
".mjs",
|
|
1810
|
+
".ts",
|
|
1811
|
+
".tsx",
|
|
1812
|
+
".mts",
|
|
1813
|
+
".cts",
|
|
1814
|
+
".vue",
|
|
1815
|
+
".svelte",
|
|
1816
|
+
];
|
|
1817
|
+
|
|
1755
1818
|
/**
|
|
1756
|
-
* Return paths to all
|
|
1819
|
+
* Return paths to all JavaScript, TypeScript, Vue, and Svelte source files,
|
|
1820
|
+
* found in one walk of the tree.
|
|
1821
|
+
*
|
|
1822
|
+
* @param {string} src Directory to walk
|
|
1823
|
+
* @param {boolean|Object} deep Deep flag, or `{ deep, exclude, noIgnore }`
|
|
1824
|
+
* @returns {string[]} Source file paths, grouped by extension
|
|
1757
1825
|
*/
|
|
1758
1826
|
const getAllSrcJSAndTSFiles = (src, deep) =>
|
|
1759
|
-
|
|
1760
|
-
[
|
|
1761
|
-
".js",
|
|
1762
|
-
".jsx",
|
|
1763
|
-
".cjs",
|
|
1764
|
-
".mjs",
|
|
1765
|
-
".ts",
|
|
1766
|
-
".tsx",
|
|
1767
|
-
".mts",
|
|
1768
|
-
".cts",
|
|
1769
|
-
".vue",
|
|
1770
|
-
".svelte",
|
|
1771
|
-
].map((extension) => {
|
|
1772
|
-
const searchOptions = normalizeAnalyzerSearchOptions(deep);
|
|
1773
|
-
return getAllFiles(
|
|
1774
|
-
searchOptions.deep,
|
|
1775
|
-
src,
|
|
1776
|
-
extension,
|
|
1777
|
-
undefined,
|
|
1778
|
-
undefined,
|
|
1779
|
-
undefined,
|
|
1780
|
-
src,
|
|
1781
|
-
searchOptions.exclude,
|
|
1782
|
-
searchOptions.noIgnore,
|
|
1783
|
-
);
|
|
1784
|
-
}),
|
|
1785
|
-
);
|
|
1827
|
+
getAllFilesByExtensions(src, JS_TS_SOURCE_EXTENSIONS, deep);
|
|
1786
1828
|
|
|
1787
1829
|
const getAngularWorkspaceManifestFiles = (
|
|
1788
1830
|
dir,
|
|
@@ -2139,51 +2181,42 @@ const parseAngularStyleFiles = (
|
|
|
2139
2181
|
excludePatterns,
|
|
2140
2182
|
noIgnore = false,
|
|
2141
2183
|
) => {
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
for (const
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
continue;
|
|
2160
|
-
}
|
|
2161
|
-
for (const referencePattern of STYLE_PACKAGE_REFERENCE_PATTERNS) {
|
|
2162
|
-
for (const match of content.matchAll(referencePattern)) {
|
|
2163
|
-
const reference = match[1];
|
|
2164
|
-
if (!reference) {
|
|
2165
|
-
continue;
|
|
2166
|
-
}
|
|
2167
|
-
if (
|
|
2168
|
-
match[0]?.trim().startsWith("url") &&
|
|
2169
|
-
!isPackageStyleUrlReference(reference)
|
|
2170
|
-
) {
|
|
2171
|
-
continue;
|
|
2172
|
-
}
|
|
2173
|
-
const prefix = content.slice(0, match.index || 0);
|
|
2174
|
-
const lineNumber = prefix.split(/\r?\n/).length;
|
|
2175
|
-
const lineStart = prefix.lastIndexOf("\n");
|
|
2176
|
-
const columnNumber =
|
|
2177
|
-
lineStart >= 0 ? prefix.length - lineStart - 1 : 0;
|
|
2178
|
-
setAngularPackageRef(
|
|
2179
|
-
allImports,
|
|
2180
|
-
allExports,
|
|
2181
|
-
src,
|
|
2182
|
-
styleFile,
|
|
2183
|
-
reference,
|
|
2184
|
-
{ column: columnNumber, line: lineNumber },
|
|
2185
|
-
);
|
|
2184
|
+
const styleFiles = getAllFilesByExtensions(
|
|
2185
|
+
src,
|
|
2186
|
+
ANGULAR_STYLE_FILE_EXTENSIONS,
|
|
2187
|
+
{ deep, exclude: excludePatterns, noIgnore },
|
|
2188
|
+
);
|
|
2189
|
+
for (const styleFile of styleFiles) {
|
|
2190
|
+
let content;
|
|
2191
|
+
try {
|
|
2192
|
+
content = readFileSync(styleFile, "utf-8");
|
|
2193
|
+
} catch {
|
|
2194
|
+
continue;
|
|
2195
|
+
}
|
|
2196
|
+
for (const referencePattern of STYLE_PACKAGE_REFERENCE_PATTERNS) {
|
|
2197
|
+
for (const match of content.matchAll(referencePattern)) {
|
|
2198
|
+
const reference = match[1];
|
|
2199
|
+
if (!reference) {
|
|
2200
|
+
continue;
|
|
2186
2201
|
}
|
|
2202
|
+
if (
|
|
2203
|
+
match[0]?.trim().startsWith("url") &&
|
|
2204
|
+
!isPackageStyleUrlReference(reference)
|
|
2205
|
+
) {
|
|
2206
|
+
continue;
|
|
2207
|
+
}
|
|
2208
|
+
const prefix = content.slice(0, match.index || 0);
|
|
2209
|
+
const lineNumber = prefix.split(/\r?\n/).length;
|
|
2210
|
+
const lineStart = prefix.lastIndexOf("\n");
|
|
2211
|
+
const columnNumber = lineStart >= 0 ? prefix.length - lineStart - 1 : 0;
|
|
2212
|
+
setAngularPackageRef(
|
|
2213
|
+
allImports,
|
|
2214
|
+
allExports,
|
|
2215
|
+
src,
|
|
2216
|
+
styleFile,
|
|
2217
|
+
reference,
|
|
2218
|
+
{ column: columnNumber, line: lineNumber },
|
|
2219
|
+
);
|
|
2187
2220
|
}
|
|
2188
2221
|
}
|
|
2189
2222
|
}
|
|
@@ -3478,8 +3511,7 @@ export const findJSImportsExports = async (src, deep) => {
|
|
|
3478
3511
|
// scope of astWorker.js. Absence is silent — tier 1 covers all scope
|
|
3479
3512
|
// evidence.
|
|
3480
3513
|
await primeSvelteParser();
|
|
3481
|
-
const
|
|
3482
|
-
const srcFiles = promiseMap.flat();
|
|
3514
|
+
const srcFiles = getAllSrcJSAndTSFiles(src, deep);
|
|
3483
3515
|
const tasks = srcFiles.map((file) => ({ src, file }));
|
|
3484
3516
|
const parallelWorthwhile =
|
|
3485
3517
|
totalSourceBytes(srcFiles) >= MIN_PARALLEL_PARSE_BYTES;
|
|
@@ -4580,8 +4612,7 @@ export const analyzeJsCryptoFile = (filePath) => {
|
|
|
4580
4612
|
export const detectJsCryptoInventory = async (src, deep = false) => {
|
|
4581
4613
|
let srcFiles = [];
|
|
4582
4614
|
try {
|
|
4583
|
-
|
|
4584
|
-
srcFiles = promiseMap.flat();
|
|
4615
|
+
srcFiles = getAllSrcJSAndTSFiles(src, deep);
|
|
4585
4616
|
} catch {
|
|
4586
4617
|
return { algorithms: [], libraries: [] };
|
|
4587
4618
|
}
|
|
@@ -4626,31 +4657,7 @@ export const detectExtensionCapabilities = (src, deep = false) => {
|
|
|
4626
4657
|
}
|
|
4627
4658
|
let srcFiles = [];
|
|
4628
4659
|
try {
|
|
4629
|
-
|
|
4630
|
-
srcFiles = [
|
|
4631
|
-
".js",
|
|
4632
|
-
".jsx",
|
|
4633
|
-
".cjs",
|
|
4634
|
-
".mjs",
|
|
4635
|
-
".ts",
|
|
4636
|
-
".tsx",
|
|
4637
|
-
".mts",
|
|
4638
|
-
".cts",
|
|
4639
|
-
".vue",
|
|
4640
|
-
".svelte",
|
|
4641
|
-
].flatMap((extension) =>
|
|
4642
|
-
getAllFiles(
|
|
4643
|
-
searchOptions.deep,
|
|
4644
|
-
src,
|
|
4645
|
-
extension,
|
|
4646
|
-
undefined,
|
|
4647
|
-
undefined,
|
|
4648
|
-
undefined,
|
|
4649
|
-
src,
|
|
4650
|
-
searchOptions.exclude,
|
|
4651
|
-
searchOptions.noIgnore,
|
|
4652
|
-
),
|
|
4653
|
-
);
|
|
4660
|
+
srcFiles = getAllSrcJSAndTSFiles(src, deep);
|
|
4654
4661
|
} catch (_err) {
|
|
4655
4662
|
return { capabilities: [], indicators: {} };
|
|
4656
4663
|
}
|
|
@@ -5857,31 +5864,7 @@ export const detectMcpInventory = (src, deep = false) => {
|
|
|
5857
5864
|
const servicesByKey = new Map();
|
|
5858
5865
|
let srcFiles = [];
|
|
5859
5866
|
try {
|
|
5860
|
-
|
|
5861
|
-
srcFiles = [
|
|
5862
|
-
".js",
|
|
5863
|
-
".jsx",
|
|
5864
|
-
".cjs",
|
|
5865
|
-
".mjs",
|
|
5866
|
-
".ts",
|
|
5867
|
-
".tsx",
|
|
5868
|
-
".mts",
|
|
5869
|
-
".cts",
|
|
5870
|
-
".vue",
|
|
5871
|
-
".svelte",
|
|
5872
|
-
].flatMap((extension) =>
|
|
5873
|
-
getAllFiles(
|
|
5874
|
-
searchOptions.deep,
|
|
5875
|
-
src,
|
|
5876
|
-
extension,
|
|
5877
|
-
undefined,
|
|
5878
|
-
undefined,
|
|
5879
|
-
undefined,
|
|
5880
|
-
src,
|
|
5881
|
-
searchOptions.exclude,
|
|
5882
|
-
searchOptions.noIgnore,
|
|
5883
|
-
),
|
|
5884
|
-
);
|
|
5867
|
+
srcFiles = getAllSrcJSAndTSFiles(src, deep);
|
|
5885
5868
|
} catch {
|
|
5886
5869
|
return { components: [], dependencies: [], services: [] };
|
|
5887
5870
|
}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
// Bounded, read-only reader of the apk installed database.
|
|
2
|
+
//
|
|
3
|
+
// osquery has no apk table, so an Alpine, Wolfi or Chainguard host would have no
|
|
4
|
+
// OS package inventory in an OBOM, and the PHP host probe needs the same
|
|
5
|
+
// database to tell which PHP files a package owns. Both read it through here, so
|
|
6
|
+
// what the OBOM lists and what the probe treats as owned follow one parser: the
|
|
7
|
+
// same file, location order, caps and record rules.
|
|
8
|
+
//
|
|
9
|
+
// The database is `/lib/apk/db/installed`. A usr-merged system keeps it at
|
|
10
|
+
// `/usr/lib/apk/db/installed` (and `/lib` is a link to `/usr/lib`, so the two
|
|
11
|
+
// names are one file), and Alpaquita keeps it under `/var/lib/apk/db`. The first
|
|
12
|
+
// of those that exists is the database. One that exists but cannot be read
|
|
13
|
+
// leaves the packages unknown: it is reported as unreadable, never read in part
|
|
14
|
+
// and never skipped for the next name.
|
|
15
|
+
//
|
|
16
|
+
// A record is a run of `<letter>:<value>` lines ended by a blank line. P: names
|
|
17
|
+
// the package, V: its version, A: its architecture, o: its origin (the source
|
|
18
|
+
// package), m: its maintainer, L: its licence, U: its home page and T: its
|
|
19
|
+
// description. F: names a directory and each R: after it a file in that
|
|
20
|
+
// directory. A record may start with C: (Alpine) or P: (Wolfi).
|
|
21
|
+
|
|
22
|
+
import { statSync } from "node:fs";
|
|
23
|
+
import { join } from "node:path";
|
|
24
|
+
import process from "node:process";
|
|
25
|
+
|
|
26
|
+
import { isDryRun, recordActivity } from "../core/activity.js";
|
|
27
|
+
import { safeExistsSync, safeReadFileSync } from "../core/fs.js";
|
|
28
|
+
import { thoughtLog } from "../core/logger.js";
|
|
29
|
+
|
|
30
|
+
/** The database, or the packages it lists, past these is unreadable rather than read in part. */
|
|
31
|
+
export const MAX_APK_DATABASE_BYTES = 64 * 1024 * 1024;
|
|
32
|
+
export const MAX_APK_PACKAGES = 100000;
|
|
33
|
+
|
|
34
|
+
/** Where apk keeps the installed database, relative to the root, in the order they are tried. */
|
|
35
|
+
export const APK_INSTALLED_DB_PATHS = [
|
|
36
|
+
"lib/apk/db/installed",
|
|
37
|
+
"usr/lib/apk/db/installed",
|
|
38
|
+
"var/lib/apk/db/installed",
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
// No field of a package record is longer than this once read.
|
|
42
|
+
const MAX_FIELD_LENGTH = 4096;
|
|
43
|
+
|
|
44
|
+
const FIELD_NAMES = {
|
|
45
|
+
P: "name",
|
|
46
|
+
V: "version",
|
|
47
|
+
A: "arch",
|
|
48
|
+
o: "origin",
|
|
49
|
+
m: "maintainer",
|
|
50
|
+
L: "license",
|
|
51
|
+
U: "url",
|
|
52
|
+
T: "description",
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
function readBounded(file, maxBytes) {
|
|
56
|
+
try {
|
|
57
|
+
const stats = statSync(file);
|
|
58
|
+
if (!stats.isFile() || stats.size > maxBytes) {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
} catch {
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
const text = safeReadFileSync(file, "utf-8");
|
|
65
|
+
// A file that grew between the stat and the read is over the cap too.
|
|
66
|
+
return typeof text === "string" && text.length <= maxBytes ? text : undefined;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function newRecord() {
|
|
70
|
+
return { fields: {}, fileCount: 0, files: [], touched: false };
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Parse the text of an installed database.
|
|
75
|
+
*
|
|
76
|
+
* @param {string} text Database text
|
|
77
|
+
* @param {Set<string>|undefined} wantedFiles Absolute paths whose owner is wanted
|
|
78
|
+
* @param {number} maxPackages Most packages to accept
|
|
79
|
+
* @returns {{packages: Object[], malformed: number, overflow: boolean}}
|
|
80
|
+
*/
|
|
81
|
+
function parseDatabase(text, wantedFiles, maxPackages) {
|
|
82
|
+
const packages = [];
|
|
83
|
+
let malformed = 0;
|
|
84
|
+
let overflow = false;
|
|
85
|
+
let record = newRecord();
|
|
86
|
+
let directory = "";
|
|
87
|
+
const finishRecord = () => {
|
|
88
|
+
const { fields, fileCount, files, touched } = record;
|
|
89
|
+
record = newRecord();
|
|
90
|
+
directory = "";
|
|
91
|
+
if (!touched) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
// A package with no name or no version cannot be named by a purl.
|
|
95
|
+
if (!fields.name || !fields.version) {
|
|
96
|
+
malformed++;
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
packages.push({ ...fields, fileCount, files });
|
|
100
|
+
if (packages.length > maxPackages) {
|
|
101
|
+
overflow = true;
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
let position = 0;
|
|
105
|
+
while (position <= text.length && !overflow) {
|
|
106
|
+
let end = text.indexOf("\n", position);
|
|
107
|
+
if (end === -1) {
|
|
108
|
+
end = text.length;
|
|
109
|
+
}
|
|
110
|
+
let line = text.slice(position, end);
|
|
111
|
+
position = end + 1;
|
|
112
|
+
if (line.endsWith("\r")) {
|
|
113
|
+
line = line.slice(0, -1);
|
|
114
|
+
}
|
|
115
|
+
if (line === "") {
|
|
116
|
+
finishRecord();
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
if (line.length < 2 || line[1] !== ":") {
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
const letter = line[0];
|
|
123
|
+
const value = line.slice(2);
|
|
124
|
+
if (Object.hasOwn(FIELD_NAMES, letter)) {
|
|
125
|
+
record.touched = true;
|
|
126
|
+
if (value) {
|
|
127
|
+
record.fields[FIELD_NAMES[letter]] =
|
|
128
|
+
value.length > MAX_FIELD_LENGTH
|
|
129
|
+
? value.slice(0, MAX_FIELD_LENGTH)
|
|
130
|
+
: value;
|
|
131
|
+
}
|
|
132
|
+
} else if (letter === "F") {
|
|
133
|
+
record.touched = true;
|
|
134
|
+
directory = value;
|
|
135
|
+
} else if (letter === "R") {
|
|
136
|
+
record.touched = true;
|
|
137
|
+
record.fileCount++;
|
|
138
|
+
if (wantedFiles) {
|
|
139
|
+
const file = `/${directory ? `${directory}/` : ""}${value}`;
|
|
140
|
+
if (wantedFiles.has(file)) {
|
|
141
|
+
record.files.push(file);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (!overflow) {
|
|
147
|
+
finishRecord();
|
|
148
|
+
}
|
|
149
|
+
return { packages, malformed, overflow };
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Read the packages of the apk installed database.
|
|
154
|
+
*
|
|
155
|
+
* @param {Object} [options] Read options
|
|
156
|
+
* @param {string} [options.rootPath="/"] Directory the database paths hang off;
|
|
157
|
+
* tests point it at a built tree
|
|
158
|
+
* @param {string} [options.databaseFile] Read this file instead of looking
|
|
159
|
+
* under `rootPath`
|
|
160
|
+
* @param {Set<string>} [options.wantedFiles] Absolute paths whose owner is
|
|
161
|
+
* wanted. A package comes back with the ones it owns in `files`; the other
|
|
162
|
+
* files of a package are only counted, so a large database stays small.
|
|
163
|
+
* @param {number} [options.maxBytes] Largest database to read, 64 MiB by default
|
|
164
|
+
* @param {number} [options.maxPackages] Most packages to accept, 100000 by default
|
|
165
|
+
* @param {string} [options.platform] `linux` by default for the process; an apk
|
|
166
|
+
* database exists on Linux only
|
|
167
|
+
* @returns {{state: string, path?: string, packages: Object[], malformed: number}}
|
|
168
|
+
* `state` is `ok`, `absent` (no database, or not Linux), `unreadable` (a
|
|
169
|
+
* database that could not be read in full) or `skipped` (a dry run).
|
|
170
|
+
* `malformed` counts the records left out for having no name or version.
|
|
171
|
+
* Each package has `name`, `version` and `fileCount`, `files`, and, when the
|
|
172
|
+
* record has them, `arch`, `origin`, `maintainer`, `license`, `url` and
|
|
173
|
+
* `description`.
|
|
174
|
+
*/
|
|
175
|
+
export function readApkInstalledDb(options = {}) {
|
|
176
|
+
const result = (state, extra = {}) => ({
|
|
177
|
+
state,
|
|
178
|
+
packages: [],
|
|
179
|
+
malformed: 0,
|
|
180
|
+
...extra,
|
|
181
|
+
});
|
|
182
|
+
const platform = options.platform || process.platform;
|
|
183
|
+
if (platform !== "linux") {
|
|
184
|
+
return result("absent");
|
|
185
|
+
}
|
|
186
|
+
const rootPath = options.rootPath || "/";
|
|
187
|
+
if (isDryRun) {
|
|
188
|
+
recordActivity({
|
|
189
|
+
capability: "apk-installed-db",
|
|
190
|
+
kind: "read",
|
|
191
|
+
reason:
|
|
192
|
+
"Dry run mode blocks reading the apk installed database, which lives outside the project.",
|
|
193
|
+
status: "blocked",
|
|
194
|
+
target: options.databaseFile || rootPath,
|
|
195
|
+
});
|
|
196
|
+
return result("skipped");
|
|
197
|
+
}
|
|
198
|
+
const candidates = options.databaseFile
|
|
199
|
+
? [options.databaseFile]
|
|
200
|
+
: APK_INSTALLED_DB_PATHS.map((location) => join(rootPath, location));
|
|
201
|
+
const file = candidates.find((candidate) => safeExistsSync(candidate));
|
|
202
|
+
if (!file) {
|
|
203
|
+
return result("absent");
|
|
204
|
+
}
|
|
205
|
+
const unreadable = (reason) => {
|
|
206
|
+
thoughtLog(`The apk installed database ${file} was not read: ${reason}.`);
|
|
207
|
+
recordActivity({
|
|
208
|
+
capability: "apk-installed-db",
|
|
209
|
+
kind: "read",
|
|
210
|
+
reason: `The apk installed database ${file} could not be read: ${reason}.`,
|
|
211
|
+
status: "failed",
|
|
212
|
+
target: file,
|
|
213
|
+
});
|
|
214
|
+
return result("unreadable", { path: file });
|
|
215
|
+
};
|
|
216
|
+
const maxBytes = options.maxBytes ?? MAX_APK_DATABASE_BYTES;
|
|
217
|
+
const text = readBounded(file, maxBytes);
|
|
218
|
+
if (text === undefined) {
|
|
219
|
+
return unreadable(`it is not a file of at most ${maxBytes} bytes`);
|
|
220
|
+
}
|
|
221
|
+
const maxPackages = options.maxPackages ?? MAX_APK_PACKAGES;
|
|
222
|
+
const { packages, malformed, overflow } = parseDatabase(
|
|
223
|
+
text,
|
|
224
|
+
options.wantedFiles,
|
|
225
|
+
maxPackages,
|
|
226
|
+
);
|
|
227
|
+
if (overflow) {
|
|
228
|
+
return unreadable(`it lists more than ${maxPackages} packages`);
|
|
229
|
+
}
|
|
230
|
+
if (malformed) {
|
|
231
|
+
thoughtLog(
|
|
232
|
+
`${malformed} record(s) of the apk installed database ${file} have no name or no version and were left out.`,
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
recordActivity({
|
|
236
|
+
capability: "apk-installed-db",
|
|
237
|
+
kind: "read",
|
|
238
|
+
reason: `Read ${packages.length} package(s) from the apk installed database ${file}.`,
|
|
239
|
+
status: "completed",
|
|
240
|
+
target: file,
|
|
241
|
+
});
|
|
242
|
+
return result("ok", { path: file, packages, malformed });
|
|
243
|
+
}
|