@cdxgen/cdxgen 13.4.0 → 13.6.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 +9 -9
- package/bin/cdxgen-secure.js +15 -0
- package/bin/cdxgen.js +29 -5
- package/bin/evinse.js +8 -0
- package/bin/hbom.js +15 -7
- package/bin/repl.js +29 -0
- package/bin/validate.js +6 -0
- package/data/cbomosdb-queries.json +13 -1
- package/data/component-tags.json +8 -0
- package/data/license-aliases.json +24 -2
- package/data/queries-darwin.json +25 -1
- package/data/queries-win.json +19 -1
- package/data/queries.json +41 -0
- package/data/remediations.json +407 -1
- package/data/rules/ai-bom.yaml +1 -1
- package/data/rules/brotli-decoder.yaml +107 -0
- package/data/rules/cbom-security.yaml +235 -4
- 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/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 +14 -0
- package/lib/cli/bomAssembly.js +120 -6
- package/lib/cli/cliOptions.js +110 -3
- package/lib/cli/index.js +182 -6
- package/lib/cli/jsBom.js +153 -64
- package/lib/cli/jvmBom.js +363 -66
- package/lib/cli/managedBom.js +853 -87
- package/lib/cli/nativeBom.js +267 -33
- package/lib/core/boundedFile.js +344 -0
- package/lib/core/brotliProbe.js +182 -0
- package/lib/core/env.js +38 -8
- package/lib/core/fs.js +40 -19
- package/lib/core/httpClient.js +172 -46
- package/lib/core/lockPaths.js +38 -0
- package/lib/core/paths.js +24 -1
- package/lib/core/processTree.js +5 -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/toolRegistry.js +170 -0
- package/lib/ecosystems/cppEvidence.js +263 -106
- package/lib/ecosystems/cppIncludeResolver.js +16 -5
- package/lib/ecosystems/ecosystems.js +25 -10
- package/lib/ecosystems/gemHostProbe.js +301 -0
- package/lib/ecosystems/golem.js +550 -6
- package/lib/ecosystems/gradleutils.js +858 -244
- package/lib/ecosystems/parsers-bazel.js +107 -6
- package/lib/ecosystems/parsers-dotnet.js +117 -18
- package/lib/ecosystems/parsers-go.js +1090 -367
- package/lib/ecosystems/parsers-js.js +505 -22
- package/lib/ecosystems/parsers-jvm.js +259 -17
- package/lib/ecosystems/parsers-misc.js +438 -64
- package/lib/ecosystems/parsers-python.js +100 -12
- package/lib/ecosystems/pythonutils.js +128 -2
- package/lib/ecosystems/rubyutils.js +544 -34
- package/lib/ecosystems/rusi.js +10 -0
- package/lib/ecosystems/scalacliutils.js +4 -1
- package/lib/ecosystems/scalasem.js +798 -151
- package/lib/ecosystems/vendoredCode.js +237 -3
- package/lib/ecosystems/venvProbe.js +360 -0
- package/lib/evinser/evinser.js +472 -61
- package/lib/evinser/swiftsem.js +68 -5
- package/lib/helpers/agenticToolutils.js +413 -93
- package/lib/helpers/vsixutils.js +1574 -315
- package/lib/inventory/agentSkillSpec.js +17 -0
- package/lib/inventory/apkInstalledDb.js +243 -0
- package/lib/inventory/atomUtils.js +110 -0
- package/lib/inventory/auditCategories.js +3 -3
- package/lib/inventory/brotliDecoder.js +142 -0
- package/lib/inventory/buildToolRateLimit.js +1 -1
- package/lib/inventory/cacheDir.js +52 -9
- package/lib/inventory/cbomutils.js +56 -7
- package/lib/inventory/certificates.js +2371 -0
- package/lib/inventory/communityAiConfigParser.js +4 -9
- package/lib/inventory/deps.js +41 -4
- package/lib/inventory/display.js +200 -3
- package/lib/inventory/dosai.js +639 -63
- package/lib/inventory/dotnetRuntime.js +217 -0
- package/lib/inventory/dynamic.js +45 -3
- package/lib/inventory/envcontext.js +475 -18
- package/lib/inventory/evidenceUtils.js +447 -23
- package/lib/inventory/fetchBatch.js +1 -1
- package/lib/inventory/formulationParsers.js +32 -3
- package/lib/inventory/goBuildInfo.js +140 -0
- package/lib/inventory/gtfobins.js +13 -0
- package/lib/inventory/hbom.js +67 -7
- package/lib/inventory/hbomAnalysis.js +16 -0
- package/lib/inventory/hostRuntimeProbe.js +686 -0
- package/lib/inventory/hostTopology.js +21 -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/nodeBuildInfo.js +218 -0
- package/lib/inventory/nodeHostProbe.js +202 -0
- package/lib/inventory/osPackagePurl.js +244 -0
- package/lib/inventory/osPackageResolver.js +271 -87
- package/lib/inventory/osinfo.js +79 -31
- package/lib/inventory/osqueryTransform.js +114 -5
- package/lib/inventory/phpBuildInfo.js +438 -0
- package/lib/inventory/phpHostProbe.js +185 -0
- package/lib/inventory/rootfsCerts.js +426 -0
- package/lib/inventory/rubyBuildInfo.js +972 -0
- package/lib/inventory/rubyHostProbe.js +218 -0
- package/lib/inventory/scalaCoords.js +4 -3
- package/lib/inventory/scalaDedupe.js +440 -0
- package/lib/inventory/source.js +256 -5
- package/lib/inventory/spdx.js +144 -0
- package/lib/inventory/traceRunner.js +5 -1
- package/lib/inventory/tracedCrypto.js +129 -0
- package/lib/managers/binary.js +866 -186
- package/lib/managers/docker.js +245 -12
- package/lib/parsers/email.js +277 -0
- package/lib/parsers/largeJson.js +62 -13
- package/lib/parsers/vscodeExtensionId.js +183 -0
- package/lib/server/server.js +198 -2
- package/lib/stages/postgen/annotator.js +17 -1
- package/lib/stages/postgen/introspection/reflect.js +4 -1
- package/lib/stages/postgen/postgen.js +5 -5
- package/lib/stages/postgen/ruleEngine.js +71 -6
- package/lib/stages/postgen/specVersionCompat.js +30 -0
- package/lib/stages/pregen/envAudit.js +1 -0
- package/lib/stages/pregen/pregen.js +231 -62
- package/lib/validator/bomValidator.js +32 -6
- package/lib/validator/generated/runtime.mjs +13 -0
- package/lib/validator/generated/validate-1.6.mjs +27 -8
- package/lib/validator/generated/validate-1.7.mjs +32 -13
- package/lib/validator/generated/validate-2.0.mjs +31 -12
- package/lib/validator/index.js +1 -1
- package/package.json +19 -18
- 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 +22 -3
- 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 +1 -17
- package/types/lib/cli/jsBom.d.ts.map +1 -1
- package/types/lib/cli/jvmBom.d.ts +20 -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 +70 -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 +22 -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 +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/processTree.d.ts +2 -0
- package/types/lib/core/processTree.d.ts.map +1 -1
- 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/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 +81 -1
- package/types/lib/ecosystems/golem.d.ts.map +1 -1
- package/types/lib/ecosystems/gradleutils.d.ts +57 -21
- package/types/lib/ecosystems/gradleutils.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-bazel.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-dotnet.d.ts +40 -4
- package/types/lib/ecosystems/parsers-dotnet.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-go.d.ts +85 -13
- package/types/lib/ecosystems/parsers-go.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-jvm.d.ts +28 -2
- package/types/lib/ecosystems/parsers-jvm.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-misc.d.ts +37 -58
- package/types/lib/ecosystems/parsers-misc.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-python.d.ts +14 -3
- package/types/lib/ecosystems/parsers-python.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/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.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 +88 -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/inventory/agentSkillSpec.d.ts +13 -0
- package/types/lib/inventory/agentSkillSpec.d.ts.map +1 -0
- 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 +33 -0
- package/types/lib/inventory/atomUtils.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/cacheDir.d.ts +12 -4
- package/types/lib/inventory/cacheDir.d.ts.map +1 -1
- package/types/lib/inventory/cbomutils.d.ts +17 -0
- package/types/lib/inventory/cbomutils.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/communityAiConfigParser.d.ts.map +1 -1
- package/types/lib/inventory/deps.d.ts +2 -1
- 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 +162 -7
- package/types/lib/inventory/dosai.d.ts.map +1 -1
- package/types/lib/inventory/dotnetRuntime.d.ts +44 -0
- package/types/lib/inventory/dotnetRuntime.d.ts.map +1 -0
- package/types/lib/inventory/dynamic.d.ts +6 -1
- package/types/lib/inventory/dynamic.d.ts.map +1 -1
- package/types/lib/inventory/envcontext.d.ts +92 -8
- package/types/lib/inventory/envcontext.d.ts.map +1 -1
- package/types/lib/inventory/evidenceUtils.d.ts +29 -10
- package/types/lib/inventory/evidenceUtils.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/gtfobins.d.ts.map +1 -1
- 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/hostRuntimeProbe.d.ts +44 -0
- package/types/lib/inventory/hostRuntimeProbe.d.ts.map +1 -0
- package/types/lib/inventory/hostTopology.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/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/osPackagePurl.d.ts +99 -0
- package/types/lib/inventory/osPackagePurl.d.ts.map +1 -0
- package/types/lib/inventory/osPackageResolver.d.ts +44 -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/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/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/source.d.ts +38 -0
- package/types/lib/inventory/source.d.ts.map +1 -1
- package/types/lib/inventory/spdx.d.ts +15 -0
- package/types/lib/inventory/spdx.d.ts.map +1 -1
- package/types/lib/inventory/traceRunner.d.ts +4 -1
- package/types/lib/inventory/traceRunner.d.ts.map +1 -1
- package/types/lib/inventory/tracedCrypto.d.ts +22 -0
- package/types/lib/inventory/tracedCrypto.d.ts.map +1 -1
- 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 +24 -0
- package/types/lib/managers/docker.d.ts.map +1 -1
- 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 +17 -3
- package/types/lib/parsers/largeJson.d.ts.map +1 -1
- 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/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/envAudit.d.ts.map +1 -1
- package/types/lib/stages/pregen/pregen.d.ts +26 -9
- package/types/lib/stages/pregen/pregen.d.ts.map +1 -1
- package/types/lib/validator/bomValidator.d.ts.map +1 -1
|
@@ -5,6 +5,7 @@ import { parse as loadYaml } from "yaml";
|
|
|
5
5
|
|
|
6
6
|
import { safeExistsSync } from "../core/fs.js";
|
|
7
7
|
import { sanitizeBomPropertyValue } from "../core/propertySanitizer.js";
|
|
8
|
+
import { isAgentSkillSpecValid } from "./agentSkillSpec.js";
|
|
8
9
|
import { parseJsonLike } from "./jsonLike.js";
|
|
9
10
|
import {
|
|
10
11
|
credentialIndicatorsForText,
|
|
@@ -279,18 +280,12 @@ function parseSkillFile(filePath, raw) {
|
|
|
279
280
|
);
|
|
280
281
|
}
|
|
281
282
|
// Record whether the frontmatter satisfies the open Agent Skills constraints
|
|
282
|
-
//
|
|
283
|
-
//
|
|
284
|
-
const specValid =
|
|
285
|
-
typeof metadata?.name === "string" &&
|
|
286
|
-
/^[a-z0-9-]{1,64}$/u.test(metadata.name) &&
|
|
287
|
-
typeof metadata?.description === "string" &&
|
|
288
|
-
metadata.description.length >= 1 &&
|
|
289
|
-
metadata.description.length <= 1024;
|
|
283
|
+
// as a single reviewer-friendly boolean rather than copying the raw values
|
|
284
|
+
// twice.
|
|
290
285
|
addUniqueProperty(
|
|
291
286
|
component.properties,
|
|
292
287
|
"cdx:skill:specValid",
|
|
293
|
-
|
|
288
|
+
isAgentSkillSpecValid(metadata) ? "true" : "false",
|
|
294
289
|
);
|
|
295
290
|
const skillDir = dirname(filePath);
|
|
296
291
|
for (const [subdir, property] of [
|
package/lib/inventory/deps.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { lstatSync, readFileSync, statSync } from "node:fs";
|
|
2
|
-
import { homedir
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
3
|
import { delimiter as _delimiter, basename, dirname, join } from "node:path";
|
|
4
4
|
|
|
5
5
|
import { build, Purl } from "@cdxgen/cdx-purl";
|
|
@@ -10,6 +10,7 @@ import { commandOutputText } from "../core/buildLedger.js";
|
|
|
10
10
|
import { parseMavenArgs } from "../core/env.js";
|
|
11
11
|
import {
|
|
12
12
|
getAllFiles,
|
|
13
|
+
getTmpDir,
|
|
13
14
|
multiChecksumFile,
|
|
14
15
|
safeExistsSync,
|
|
15
16
|
safeMkdtempSync,
|
|
@@ -24,6 +25,10 @@ import {
|
|
|
24
25
|
mavenLocalRepositories,
|
|
25
26
|
splitArtifactFileName,
|
|
26
27
|
} from "./jvmLocalRepos.js";
|
|
28
|
+
import {
|
|
29
|
+
mavenMirrorSettingsArgs,
|
|
30
|
+
mavenWrapperMirrorEnv,
|
|
31
|
+
} from "./mavenCentralMirror.js";
|
|
27
32
|
import { pypiBomRef } from "./purl.js";
|
|
28
33
|
import { findLicenseId, spdxLicenses } from "./spdx.js";
|
|
29
34
|
|
|
@@ -99,7 +104,8 @@ function jarPurl(group, name, version, classifier = undefined) {
|
|
|
99
104
|
* Collect maven dependencies
|
|
100
105
|
*
|
|
101
106
|
* @param {string} mavenCmd Maven command to use
|
|
102
|
-
* @param {string} basePath Path to the maven project
|
|
107
|
+
* @param {string} basePath Path to the maven project. Without it Maven is not
|
|
108
|
+
* run, and only the local repository is read when includeCacheDir is set.
|
|
103
109
|
* @param {boolean} cleanup Remove temporary directories
|
|
104
110
|
* @param {boolean} includeCacheDir Include maven and gradle cache directories
|
|
105
111
|
*/
|
|
@@ -118,7 +124,7 @@ export async function collectMvnDependencies(
|
|
|
118
124
|
safeExistsSync(repo),
|
|
119
125
|
) ||
|
|
120
126
|
join(homedir(), ".m2", "repository");
|
|
121
|
-
const tempDir = safeMkdtempSync(join(
|
|
127
|
+
const tempDir = safeMkdtempSync(join(getTmpDir(), "mvn-deps-"));
|
|
122
128
|
// No -U: forcing update checks re-requests every maven-metadata.xml and
|
|
123
129
|
// every artifact Maven already knows is missing, once per module.
|
|
124
130
|
let copyArgs = [
|
|
@@ -134,11 +140,13 @@ export async function collectMvnDependencies(
|
|
|
134
140
|
const addArgs = parseMavenArgs(readEnvironmentVariable("MVN_ARGS"));
|
|
135
141
|
copyArgs = copyArgs.concat(addArgs);
|
|
136
142
|
}
|
|
143
|
+
copyArgs = copyArgs.concat(mavenMirrorSettingsArgs());
|
|
137
144
|
if (basePath && basePath !== MAVEN_CACHE_DIR) {
|
|
138
145
|
console.log(`Executing '${mavenCmd} in ${basePath}`);
|
|
139
146
|
const result = safeSpawnSync(mavenCmd, copyArgs, {
|
|
140
147
|
cwd: basePath,
|
|
141
148
|
shell: isWin,
|
|
149
|
+
env: { ...process.env, ...mavenWrapperMirrorEnv() },
|
|
142
150
|
});
|
|
143
151
|
const rateLimited = noteBuildToolRateLimit(
|
|
144
152
|
"maven",
|
|
@@ -178,7 +186,7 @@ export async function collectMvnDependencies(
|
|
|
178
186
|
}
|
|
179
187
|
|
|
180
188
|
// Clean up
|
|
181
|
-
if (cleanup && tempDir?.startsWith(
|
|
189
|
+
if (cleanup && tempDir?.startsWith(getTmpDir())) {
|
|
182
190
|
safeRmSync(tempDir, { recursive: true, force: true });
|
|
183
191
|
}
|
|
184
192
|
return jarNSMapping;
|
|
@@ -334,6 +342,35 @@ export async function collectJarNS(jarPath, pomPathMap = {}) {
|
|
|
334
342
|
return jarNSMapping;
|
|
335
343
|
}
|
|
336
344
|
|
|
345
|
+
/**
|
|
346
|
+
* The jar namespace map entries of components a jar scan produced, in the
|
|
347
|
+
* shape {@link collectJarNS} writes (`{ namespaces: string[] }`), from their
|
|
348
|
+
* `internal:Namespaces` properties. The scan reads each jar from a temporary
|
|
349
|
+
* copy, so no `jarFile` is recorded. Purls `existing` already maps keep the
|
|
350
|
+
* entry they have, which names the jar it was read from.
|
|
351
|
+
*
|
|
352
|
+
* @param {Object[]} components Components with `internal:Namespaces` properties
|
|
353
|
+
* @param {Object} [existing] Jar namespace map already collected
|
|
354
|
+
* @returns {Object} New entries keyed by purl
|
|
355
|
+
*/
|
|
356
|
+
export function namespaceMappingOfComponents(components, existing = {}) {
|
|
357
|
+
const mapping = {};
|
|
358
|
+
for (const component of components || []) {
|
|
359
|
+
if (!component?.purl || existing[component.purl]) {
|
|
360
|
+
continue;
|
|
361
|
+
}
|
|
362
|
+
const namespaces = (component.properties || [])
|
|
363
|
+
.filter((property) => property.name === "internal:Namespaces")
|
|
364
|
+
.flatMap((property) => String(property.value || "").split("\n"))
|
|
365
|
+
.map((namespace) => namespace.trim())
|
|
366
|
+
.filter(Boolean);
|
|
367
|
+
if (namespaces.length) {
|
|
368
|
+
mapping[component.purl] = { namespaces: [...new Set(namespaces)] };
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
return mapping;
|
|
372
|
+
}
|
|
373
|
+
|
|
337
374
|
/**
|
|
338
375
|
* Convert a JAR namespace mapping (produced by {@link collectJarNS}) into an array
|
|
339
376
|
* of CycloneDX package component objects.
|
package/lib/inventory/display.js
CHANGED
|
@@ -14,6 +14,7 @@ import { readReachablesSlices } from "./atomUtils.js";
|
|
|
14
14
|
import { formatOccurrenceEvidence } from "./evidenceUtils.js";
|
|
15
15
|
import {
|
|
16
16
|
formatHbomHardwareClassSummary,
|
|
17
|
+
getHbomPrivilegeGuidance,
|
|
17
18
|
getHbomSummary,
|
|
18
19
|
isHbomLikeBom,
|
|
19
20
|
} from "./hbomAnalysis.js";
|
|
@@ -475,7 +476,9 @@ export const buildTableSummaryLines = (
|
|
|
475
476
|
);
|
|
476
477
|
if (hbomSummary.requiresPrivilegedEnrichment) {
|
|
477
478
|
summaryLines.push(
|
|
478
|
-
|
|
479
|
+
hbomSummary.platform === "windows"
|
|
480
|
+
? getHbomPrivilegeGuidance(hbomSummary.platform)
|
|
481
|
+
: "Permission-sensitive enrichments were skipped or blocked. Re-run with --privileged where policy allows.",
|
|
479
482
|
);
|
|
480
483
|
}
|
|
481
484
|
}
|
|
@@ -526,6 +529,7 @@ const HBOM_COLUMN_PRIORITY = Object.freeze([
|
|
|
526
529
|
["cdx:hbom:securityMode", "securityMode"],
|
|
527
530
|
["cdx:hbom:health", "health"],
|
|
528
531
|
["cdx:hbom:smartStatus", "smartStatus"],
|
|
532
|
+
["cdx:hbom:healthStatus", "healthStatus"],
|
|
529
533
|
["cdx:hbom:powerSource", "powerSource"],
|
|
530
534
|
["cdx:hbom:maximumCapacity", "maximumCapacity"],
|
|
531
535
|
["cdx:hbom:chargePercent", "chargePercent"],
|
|
@@ -546,6 +550,7 @@ const HBOM_COLUMN_PRIORITY = Object.freeze([
|
|
|
546
550
|
["cdx:hostview:kernel_modules:count", "kernelMods"],
|
|
547
551
|
["cdx:hostview:mount_hardening:count", "runtimeMounts"],
|
|
548
552
|
["cdx:hostview:runtime-storage:count", "runtimeStorage"],
|
|
553
|
+
["cdx:hostview:logical_drives:count", "runtimeDrives"],
|
|
549
554
|
["cdx:hostview:linkedRuntimeCategoryCount", "runtimeLinks"],
|
|
550
555
|
]);
|
|
551
556
|
|
|
@@ -616,6 +621,7 @@ const HBOM_CLASS_PROPERTY_PRIORITY = Object.freeze({
|
|
|
616
621
|
storage: Object.freeze([
|
|
617
622
|
["cdx:hbom:capacity", "capacity"],
|
|
618
623
|
["cdx:hbom:smartStatus", "smart"],
|
|
624
|
+
["cdx:hbom:healthStatus", "healthStatus"],
|
|
619
625
|
["cdx:hbom:wearPercentageUsed", "wearUsed"],
|
|
620
626
|
["cdx:hbom:transport", "transport"],
|
|
621
627
|
["cdx:hbom:firmwareVersion", "firmware"],
|
|
@@ -630,6 +636,7 @@ const HBOM_CLASS_PROPERTY_PRIORITY = Object.freeze({
|
|
|
630
636
|
["cdx:hbom:isRemovable", "removable"],
|
|
631
637
|
["cdx:hostview:mount_hardening:count", "runtimeMounts"],
|
|
632
638
|
["cdx:hostview:runtime-storage:count", "runtimeStorage"],
|
|
639
|
+
["cdx:hostview:logical_drives:count", "runtimeDrives"],
|
|
633
640
|
]),
|
|
634
641
|
sensor: Object.freeze([
|
|
635
642
|
["cdx:hbom:temperatureCelsius", "tempC"],
|
|
@@ -870,8 +877,13 @@ export function printTable(
|
|
|
870
877
|
}
|
|
871
878
|
if (
|
|
872
879
|
bomJson.metadata?.component &&
|
|
873
|
-
["operating-system", "platform"].includes(
|
|
880
|
+
["operating-system", "platform"].includes(
|
|
881
|
+
bomJson.metadata.component.type,
|
|
882
|
+
) &&
|
|
883
|
+
!filterTypes?.includes("cryptographic-asset")
|
|
874
884
|
) {
|
|
885
|
+
// A filtered crypto view stays a crypto view even on an OS BOM; only the
|
|
886
|
+
// unfiltered component listing falls through to the OS table.
|
|
875
887
|
return printOSTable(bomJson);
|
|
876
888
|
}
|
|
877
889
|
if (isHbomLikeBom(bomJson) && !filterTypes?.includes("cryptographic-asset")) {
|
|
@@ -1037,7 +1049,13 @@ const locationComparator = (a, b) => {
|
|
|
1037
1049
|
const tmpB = b.split("#");
|
|
1038
1050
|
if (tmpA.length === 2 && tmpB.length === 2) {
|
|
1039
1051
|
if (tmpA[0] === tmpB[0]) {
|
|
1040
|
-
|
|
1052
|
+
// Line numbers sort numerically; other fragments (a secret key such
|
|
1053
|
+
// as data.tls.crt) by text, never NaN.
|
|
1054
|
+
const lineA = Number(tmpA[1]);
|
|
1055
|
+
const lineB = Number(tmpB[1]);
|
|
1056
|
+
return Number.isNaN(lineA) || Number.isNaN(lineB)
|
|
1057
|
+
? tmpA[1].localeCompare(tmpB[1])
|
|
1058
|
+
: lineA - lineB;
|
|
1041
1059
|
}
|
|
1042
1060
|
}
|
|
1043
1061
|
}
|
|
@@ -2125,3 +2143,182 @@ export function displaySelfThreatModel(
|
|
|
2125
2143
|
process.exit(1);
|
|
2126
2144
|
}
|
|
2127
2145
|
}
|
|
2146
|
+
|
|
2147
|
+
function certificateComponents(bomJson) {
|
|
2148
|
+
return (bomJson?.components || []).filter(
|
|
2149
|
+
(component) => component?.cryptoProperties?.assetType === "certificate",
|
|
2150
|
+
);
|
|
2151
|
+
}
|
|
2152
|
+
|
|
2153
|
+
function auditedBomRefs(bomJson) {
|
|
2154
|
+
// Audit findings land as document annotations whose location names the
|
|
2155
|
+
// component; a certificate listed there is flagged in the table. The
|
|
2156
|
+
// annotation text is rendered as a markdown property table, so the rows
|
|
2157
|
+
// are parsed back out of it (the same way the REPL's audit view does).
|
|
2158
|
+
const refs = new Set();
|
|
2159
|
+
for (const annotation of bomJson?.annotations || []) {
|
|
2160
|
+
const text = typeof annotation?.text === "string" ? annotation.text : "";
|
|
2161
|
+
for (const line of text.split(/\r?\n/)) {
|
|
2162
|
+
if (!line.includes("cdx:audit:location:bomRef")) {
|
|
2163
|
+
continue;
|
|
2164
|
+
}
|
|
2165
|
+
const cells = line.split("|").map((cell) => cell.trim());
|
|
2166
|
+
if (
|
|
2167
|
+
cells.length >= 2 &&
|
|
2168
|
+
cells[1] === "cdx:audit:location:bomRef" &&
|
|
2169
|
+
cells[2]
|
|
2170
|
+
) {
|
|
2171
|
+
refs.add(cells[2]);
|
|
2172
|
+
}
|
|
2173
|
+
}
|
|
2174
|
+
}
|
|
2175
|
+
return refs;
|
|
2176
|
+
}
|
|
2177
|
+
|
|
2178
|
+
/**
|
|
2179
|
+
* Print a table of the BOM's certificate components: role, name, issuer,
|
|
2180
|
+
* expiry, the SPKI prefix and how many locations each certificate appears
|
|
2181
|
+
* in, with a marker when the audit flagged it.
|
|
2182
|
+
*
|
|
2183
|
+
* @param {Object} bomJson CycloneDX BOM JSON object
|
|
2184
|
+
* @returns {void}
|
|
2185
|
+
*/
|
|
2186
|
+
export function printCertificatesTable(bomJson) {
|
|
2187
|
+
const certificates = certificateComponents(bomJson);
|
|
2188
|
+
if (!certificates.length) {
|
|
2189
|
+
console.log(
|
|
2190
|
+
"No certificate components found. Generate a CBOM with --include-crypto to use this view.",
|
|
2191
|
+
);
|
|
2192
|
+
return;
|
|
2193
|
+
}
|
|
2194
|
+
const flagged = auditedBomRefs(bomJson);
|
|
2195
|
+
const stream = createStream({
|
|
2196
|
+
columnDefault: { width: 24 },
|
|
2197
|
+
columnCount: 6,
|
|
2198
|
+
columns: [
|
|
2199
|
+
{ width: 13 },
|
|
2200
|
+
{ width: 30 },
|
|
2201
|
+
{ width: 30 },
|
|
2202
|
+
{ width: 21 },
|
|
2203
|
+
{ width: 18 },
|
|
2204
|
+
{ width: 5, alignment: "center" },
|
|
2205
|
+
],
|
|
2206
|
+
});
|
|
2207
|
+
stream.write([
|
|
2208
|
+
"Role",
|
|
2209
|
+
"Name",
|
|
2210
|
+
"Issuer CN",
|
|
2211
|
+
"Not valid after",
|
|
2212
|
+
"SPKI (first 16)",
|
|
2213
|
+
"Locs",
|
|
2214
|
+
]);
|
|
2215
|
+
for (const certificate of certificates) {
|
|
2216
|
+
const issuerCn = commonNameFromIssuer(certificate);
|
|
2217
|
+
stream.write([
|
|
2218
|
+
getPropertyValue(certificate, "cdx:crypto:certRole") || "?",
|
|
2219
|
+
certificate.name || "",
|
|
2220
|
+
issuerCn ||
|
|
2221
|
+
certificate.cryptoProperties?.certificateProperties?.issuerName ||
|
|
2222
|
+
"",
|
|
2223
|
+
certificate.cryptoProperties?.certificateProperties?.notValidAfter || "",
|
|
2224
|
+
(getPropertyValue(certificate, "cdx:crypto:spkiSha256") || "").slice(
|
|
2225
|
+
0,
|
|
2226
|
+
16,
|
|
2227
|
+
),
|
|
2228
|
+
`${certificate.evidence?.occurrences?.length || 0}${flagged.has(certificate["bom-ref"]) ? " ⚠" : ""}`,
|
|
2229
|
+
]);
|
|
2230
|
+
}
|
|
2231
|
+
stream.end();
|
|
2232
|
+
console.log();
|
|
2233
|
+
console.log(`Found ${certificates.length} certificate component(s).`);
|
|
2234
|
+
}
|
|
2235
|
+
|
|
2236
|
+
function commonNameFromIssuer(certificate) {
|
|
2237
|
+
const issuer =
|
|
2238
|
+
certificate.cryptoProperties?.certificateProperties?.issuerName || "";
|
|
2239
|
+
const parts = issuer.split(",").map((part) => part.trim());
|
|
2240
|
+
const cn = parts.find((part) => part.startsWith("CN="));
|
|
2241
|
+
return cn ? cn.slice(3) : parts[0];
|
|
2242
|
+
}
|
|
2243
|
+
|
|
2244
|
+
/**
|
|
2245
|
+
* Print the issuer chain above a certificate and the certificates issued
|
|
2246
|
+
* under it, walking the verified `dependsOn` edges.
|
|
2247
|
+
*
|
|
2248
|
+
* @param {Object} bomJson CycloneDX BOM JSON object
|
|
2249
|
+
* @param {string} selector bom-ref, SPKI hex prefix or certificate ref prefix
|
|
2250
|
+
* @returns {void}
|
|
2251
|
+
*/
|
|
2252
|
+
export function printCertificateChain(bomJson, selector) {
|
|
2253
|
+
const query = String(selector || "").trim();
|
|
2254
|
+
if (!query) {
|
|
2255
|
+
console.log("Usage: .certchain <bom-ref|spki-prefix|cert-prefix>");
|
|
2256
|
+
return;
|
|
2257
|
+
}
|
|
2258
|
+
const certificates = certificateComponents(bomJson);
|
|
2259
|
+
const byRef = new Map(certificates.map((c) => [c["bom-ref"], c]));
|
|
2260
|
+
const edges = new Map(
|
|
2261
|
+
(bomJson?.dependencies || []).map((dep) => [
|
|
2262
|
+
dep.ref,
|
|
2263
|
+
(dep.dependsOn || []).filter((ref) => byRef.has(ref)),
|
|
2264
|
+
]),
|
|
2265
|
+
);
|
|
2266
|
+
const issuersOf = new Map();
|
|
2267
|
+
for (const [ref, issuerRefs] of edges) {
|
|
2268
|
+
for (const issuerRef of issuerRefs) {
|
|
2269
|
+
if (!issuersOf.has(issuerRef)) {
|
|
2270
|
+
issuersOf.set(issuerRef, []);
|
|
2271
|
+
}
|
|
2272
|
+
issuersOf.get(issuerRef).push(ref);
|
|
2273
|
+
}
|
|
2274
|
+
}
|
|
2275
|
+
let target;
|
|
2276
|
+
if (byRef.has(query)) {
|
|
2277
|
+
target = byRef.get(query);
|
|
2278
|
+
} else {
|
|
2279
|
+
target = certificates.find(
|
|
2280
|
+
(certificate) =>
|
|
2281
|
+
certificate["bom-ref"].includes(query) ||
|
|
2282
|
+
(
|
|
2283
|
+
getPropertyValue(certificate, "cdx:crypto:spkiSha256") || ""
|
|
2284
|
+
).startsWith(query.toLowerCase()),
|
|
2285
|
+
);
|
|
2286
|
+
}
|
|
2287
|
+
if (!target) {
|
|
2288
|
+
console.log(`No certificate matches '${query}'.`);
|
|
2289
|
+
return;
|
|
2290
|
+
}
|
|
2291
|
+
const describe = (certificate) =>
|
|
2292
|
+
`${getPropertyValue(certificate, "cdx:crypto:certRole") || "?"} ${certificate.name} (${(getPropertyValue(certificate, "cdx:crypto:spkiSha256") || "").slice(0, 16)}…)`;
|
|
2293
|
+
const chain = [];
|
|
2294
|
+
let cursor = target["bom-ref"];
|
|
2295
|
+
const seen = new Set([cursor]);
|
|
2296
|
+
while (edges.has(cursor)) {
|
|
2297
|
+
const next = (edges.get(cursor) || []).filter((ref) => !seen.has(ref));
|
|
2298
|
+
if (!next.length) {
|
|
2299
|
+
break;
|
|
2300
|
+
}
|
|
2301
|
+
cursor = next[0];
|
|
2302
|
+
seen.add(cursor);
|
|
2303
|
+
chain.push(byRef.get(cursor));
|
|
2304
|
+
}
|
|
2305
|
+
console.log(`Chain above ${describe(target)}:`);
|
|
2306
|
+
if (chain.length) {
|
|
2307
|
+
chain.forEach((certificate, index) => {
|
|
2308
|
+
console.log(`${" ".repeat(index + 1)}← ${describe(certificate)}`);
|
|
2309
|
+
});
|
|
2310
|
+
} else {
|
|
2311
|
+
console.log(" (no verified issuer in this BOM)");
|
|
2312
|
+
}
|
|
2313
|
+
const issued = (issuersOf.get(target["bom-ref"]) || []).filter((ref) =>
|
|
2314
|
+
byRef.has(ref),
|
|
2315
|
+
);
|
|
2316
|
+
console.log(`Issued under ${describe(target)}:`);
|
|
2317
|
+
if (issued.length) {
|
|
2318
|
+
for (const ref of issued) {
|
|
2319
|
+
console.log(` → ${describe(byRef.get(ref))}`);
|
|
2320
|
+
}
|
|
2321
|
+
} else {
|
|
2322
|
+
console.log(" (none in this BOM)");
|
|
2323
|
+
}
|
|
2324
|
+
}
|