@cdxgen/cdxgen 13.2.0 → 13.4.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 +33 -14
- package/bin/cdxgen.js +310 -138
- package/bin/evinse.js +22 -0
- package/bin/repl.js +86 -0
- package/bin/sign.js +119 -15
- package/bin/tracebom.js +69 -5
- package/bin/validate.js +107 -19
- package/bin/verify.js +172 -63
- package/data/helpers/init.gradle +46 -21
- package/data/remediations.json +85 -0
- package/data/rules/dependency-sources.yaml +67 -0
- package/data/rules/scala-evidence.yaml +115 -0
- package/lib/audit/index.js +38 -6
- package/lib/cli/bomAssembly.js +105 -15
- package/lib/cli/cliOptions.js +93 -1
- package/lib/cli/index.js +156 -58
- package/lib/cli/jsBom.js +99 -53
- package/lib/cli/jvmBom.js +708 -147
- package/lib/cli/managedBom.js +415 -224
- package/lib/cli/nativeBom.js +264 -44
- package/lib/core/activity.js +12 -0
- package/lib/core/env.js +22 -15
- package/lib/core/fs.js +176 -7
- package/lib/core/httpClient.js +159 -24
- package/lib/core/metadataProperties.js +97 -0
- package/lib/core/pluginRun.js +184 -0
- package/lib/core/processTree.js +100 -0
- package/lib/core/projectConfig.js +31 -4
- 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 +274 -108
- package/lib/ecosystems/cargoCache.js +231 -8
- package/lib/ecosystems/caxa.js +434 -2
- package/lib/ecosystems/cmakeResolver.js +76 -21
- package/lib/ecosystems/cppBuildContext.js +631 -0
- package/lib/ecosystems/cppEvidence.js +399 -51
- package/lib/ecosystems/cppIncludeResolver.js +294 -0
- package/lib/ecosystems/denoutils.js +93 -66
- package/lib/ecosystems/ecosystems.js +1983 -793
- package/lib/ecosystems/golem.js +28 -12
- package/lib/ecosystems/gradleutils.js +356 -37
- package/lib/ecosystems/jsEvidence.js +104 -44
- package/lib/ecosystems/kosi.js +31 -7
- package/lib/ecosystems/npmutils.js +174 -9
- package/lib/ecosystems/parsers-dotnet.js +616 -159
- package/lib/ecosystems/parsers-elm.js +46 -28
- package/lib/ecosystems/parsers-gleam.js +3 -4
- package/lib/ecosystems/parsers-go.js +371 -70
- package/lib/ecosystems/parsers-js.js +263 -76
- package/lib/ecosystems/parsers-julia.js +2 -3
- package/lib/ecosystems/parsers-jvm.js +204 -12
- package/lib/ecosystems/parsers-misc.js +929 -216
- package/lib/ecosystems/parsers-python.js +167 -24
- package/lib/ecosystems/parsers-rust.js +28 -22
- 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 +1492 -182
- package/lib/ecosystems/rusi.js +54 -10
- package/lib/ecosystems/sbtutils.js +243 -187
- package/lib/ecosystems/scalacliutils.js +342 -0
- package/lib/ecosystems/scalasem.js +2618 -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 +1008 -191
- package/lib/evinser/swiftsem.js +1914 -302
- package/lib/helpers/agenticToolutils.js +2 -2
- package/lib/helpers/bomSigner.js +1101 -222
- package/lib/inventory/aiCollector.js +4 -1
- package/lib/inventory/analyzer.js +110 -127
- package/lib/inventory/atomUtils.js +703 -43
- package/lib/inventory/auditCategories.js +7 -0
- package/lib/inventory/buildToolRateLimit.js +144 -0
- package/lib/inventory/cacheCommands.js +2 -1
- package/lib/inventory/cdxrs.js +103 -12
- package/lib/inventory/cmakeBuildDirs.js +254 -0
- package/lib/inventory/deps.js +501 -124
- package/lib/inventory/depsUtils.js +183 -11
- package/lib/inventory/display.js +4 -5
- package/lib/inventory/dosai.js +798 -57
- package/lib/inventory/dosaiParsers.js +310 -15
- package/lib/inventory/dynamic.js +90 -6
- package/lib/inventory/evidenceUtils.js +166 -113
- package/lib/inventory/fetchBatch.js +690 -55
- package/lib/inventory/fetchDiskCache.js +597 -0
- package/lib/inventory/forgeEnricher.js +14 -5
- package/lib/inventory/jvmLocalRepos.js +917 -0
- package/lib/inventory/mcpConfigParser.js +2 -3
- package/lib/inventory/parentSelection.js +146 -0
- package/lib/inventory/protobom.js +8 -1
- package/lib/inventory/purl.js +152 -3
- package/lib/inventory/rustFormulationParser.js +3 -4
- package/lib/inventory/sbomDocument.js +2 -70
- package/lib/inventory/scalaCoords.js +153 -0
- package/lib/inventory/source.js +45 -27
- package/lib/inventory/spdx.js +101 -0
- package/lib/inventory/traceRunner.js +295 -25
- package/lib/inventory/tracedCrypto.js +294 -0
- package/lib/managers/binary.js +115 -24
- package/lib/managers/docker.js +467 -46
- package/lib/managers/oci.js +63 -3
- package/lib/parsers/cmakeCache.js +69 -0
- package/lib/parsers/cmakeLists.js +466 -0
- package/lib/parsers/cmakePresets.js +400 -0
- package/lib/parsers/compileCommands.js +557 -0
- package/lib/parsers/largeJson.js +454 -0
- package/lib/parsers/npmrc.js +19 -1
- 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 +23 -0
- package/lib/stages/postgen/introspection/markers.js +1 -1
- package/lib/stages/postgen/postgen.js +83 -16
- package/lib/stages/postgen/specVersionCompat.js +32 -0
- package/lib/validator/bomValidator.js +6 -16
- package/lib/validator/index.js +64 -11
- package/lib/validator/reporters/console.js +3 -0
- package/lib/validator/reporters/json.js +2 -0
- package/lib/validator/reporters/sarif.js +7 -0
- package/package.json +23 -23
- package/types/lib/audit/index.d.ts.map +1 -1
- package/types/lib/cli/bomAssembly.d.ts +2 -1
- package/types/lib/cli/bomAssembly.d.ts.map +1 -1
- package/types/lib/cli/cliOptions.d.ts +33 -1
- 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 +24 -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 +9 -0
- package/types/lib/core/env.d.ts.map +1 -1
- package/types/lib/core/fs.d.ts +55 -0
- 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/metadataProperties.d.ts +39 -0
- package/types/lib/core/metadataProperties.d.ts.map +1 -0
- 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 +6 -2
- package/types/lib/core/projectConfig.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 +12 -5
- 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/caxa.d.ts +14 -0
- package/types/lib/ecosystems/caxa.d.ts.map +1 -1
- package/types/lib/ecosystems/cmakeResolver.d.ts +28 -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 +17 -1
- 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.map +1 -1
- package/types/lib/ecosystems/gradleutils.d.ts +70 -4
- package/types/lib/ecosystems/gradleutils.d.ts.map +1 -1
- package/types/lib/ecosystems/jsEvidence.d.ts +5 -2
- package/types/lib/ecosystems/jsEvidence.d.ts.map +1 -1
- package/types/lib/ecosystems/kosi.d.ts +13 -0
- package/types/lib/ecosystems/kosi.d.ts.map +1 -1
- package/types/lib/ecosystems/npmutils.d.ts +57 -0
- package/types/lib/ecosystems/npmutils.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-dotnet.d.ts +118 -4
- 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 +54 -2
- package/types/lib/ecosystems/parsers-go.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-js.d.ts +16 -5
- 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 +46 -1
- package/types/lib/ecosystems/parsers-jvm.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-misc.d.ts +70 -4
- package/types/lib/ecosystems/parsers-misc.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-python.d.ts +53 -3
- 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/parsers-terraform.d.ts +38 -21
- package/types/lib/ecosystems/parsers-terraform.d.ts.map +1 -1
- package/types/lib/ecosystems/pythonutils.d.ts +27 -2
- 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 +164 -3
- package/types/lib/ecosystems/rubyutils.d.ts.map +1 -1
- package/types/lib/ecosystems/rusi.d.ts +13 -0
- 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 +132 -15
- package/types/lib/evinser/evinser.d.ts.map +1 -1
- package/types/lib/evinser/swiftsem.d.ts +280 -15
- package/types/lib/evinser/swiftsem.d.ts.map +1 -1
- package/types/lib/helpers/bomSigner.d.ts +182 -13
- package/types/lib/helpers/bomSigner.d.ts.map +1 -1
- package/types/lib/inventory/aiCollector.d.ts.map +1 -1
- package/types/lib/inventory/analyzer.d.ts.map +1 -1
- package/types/lib/inventory/atomUtils.d.ts +219 -5
- 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/cdxrs.d.ts +8 -3
- package/types/lib/inventory/cdxrs.d.ts.map +1 -1
- package/types/lib/inventory/cmakeBuildDirs.d.ts +58 -0
- package/types/lib/inventory/cmakeBuildDirs.d.ts.map +1 -0
- package/types/lib/inventory/deps.d.ts +59 -1
- package/types/lib/inventory/deps.d.ts.map +1 -1
- package/types/lib/inventory/depsUtils.d.ts +15 -0
- package/types/lib/inventory/depsUtils.d.ts.map +1 -1
- package/types/lib/inventory/display.d.ts.map +1 -1
- package/types/lib/inventory/dosai.d.ts +121 -9
- 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 +10 -0
- package/types/lib/inventory/dynamic.d.ts.map +1 -1
- package/types/lib/inventory/evidenceUtils.d.ts +19 -4
- 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/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/parentSelection.d.ts +34 -0
- package/types/lib/inventory/parentSelection.d.ts.map +1 -0
- package/types/lib/inventory/plugins.d.ts.map +1 -1
- package/types/lib/inventory/protobom.d.ts.map +1 -1
- package/types/lib/inventory/purl.d.ts +71 -2
- package/types/lib/inventory/purl.d.ts.map +1 -1
- package/types/lib/inventory/rustFormulationParser.d.ts.map +1 -1
- package/types/lib/inventory/sbomDocument.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.map +1 -1
- package/types/lib/inventory/spdx.d.ts +9 -0
- package/types/lib/inventory/spdx.d.ts.map +1 -1
- package/types/lib/inventory/traceRunner.d.ts +59 -1
- package/types/lib/inventory/traceRunner.d.ts.map +1 -1
- package/types/lib/inventory/tracedCrypto.d.ts +42 -0
- package/types/lib/inventory/tracedCrypto.d.ts.map +1 -0
- package/types/lib/managers/binary.d.ts +30 -1
- package/types/lib/managers/binary.d.ts.map +1 -1
- package/types/lib/managers/docker.d.ts +29 -0
- package/types/lib/managers/docker.d.ts.map +1 -1
- package/types/lib/managers/oci.d.ts +17 -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 +77 -0
- package/types/lib/parsers/cmakeLists.d.ts.map +1 -0
- 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/largeJson.d.ts +52 -0
- package/types/lib/parsers/largeJson.d.ts.map +1 -0
- package/types/lib/parsers/npmrc.d.ts +5 -0
- package/types/lib/parsers/npmrc.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.map +1 -1
- package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
- package/types/lib/stages/postgen/specVersionCompat.d.ts.map +1 -1
- package/types/lib/validator/bomValidator.d.ts.map +1 -1
- package/types/lib/validator/index.d.ts +18 -1
- package/types/lib/validator/index.d.ts.map +1 -1
- package/types/lib/validator/reporters/console.d.ts.map +1 -1
- package/types/lib/validator/reporters/json.d.ts.map +1 -1
- package/types/lib/validator/reporters/sarif.d.ts.map +1 -1
- package/lib/third-party/arborist/snapshots/calc-dep-flags.test.cjs +0 -462
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
|
|
4
|
+
import { thoughtLog } from "../core/logger.js";
|
|
5
|
+
import { dirNameStr } from "../core/paths.js";
|
|
6
|
+
import { applyAlgorithmProperties } from "./cryptoAlgorithmFamily.js";
|
|
7
|
+
|
|
8
|
+
const cryptoOids = JSON.parse(
|
|
9
|
+
readFileSync(join(dirNameStr, "data", "crypto-oid.json"), "utf-8"),
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
// TLS key-exchange groups by their IANA registry name. A hybrid group pairs a
|
|
13
|
+
// classical curve with ML-KEM: each half has an OID, the pair has none, so the
|
|
14
|
+
// group is recorded as both algorithms.
|
|
15
|
+
const GROUP_ALGORITHMS = {
|
|
16
|
+
X25519MLKEM768: ["x25519", "ml-kem-768"],
|
|
17
|
+
SecP256r1MLKEM768: ["secp256r1", "ml-kem-768"],
|
|
18
|
+
SecP384r1MLKEM1024: ["secp384r1", "ml-kem-1024"],
|
|
19
|
+
X25519Kyber768Draft00: ["x25519"],
|
|
20
|
+
MLKEM512: ["ml-kem-512"],
|
|
21
|
+
MLKEM768: ["ml-kem-768"],
|
|
22
|
+
MLKEM1024: ["ml-kem-1024"],
|
|
23
|
+
x448: ["curveX448"],
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const MLKEM_SECURITY_LEVELS = {
|
|
27
|
+
"ml-kem-512": 1,
|
|
28
|
+
"ml-kem-768": 3,
|
|
29
|
+
"ml-kem-1024": 5,
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// The curve each classical key-exchange algorithm is defined over.
|
|
33
|
+
const KEY_AGREEMENT_CURVES = {
|
|
34
|
+
x25519: "x25519",
|
|
35
|
+
curveX448: "x448",
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// Closed enums of cryptoProperties.algorithmProperties in bom-1.7.schema.json.
|
|
39
|
+
const MODES = new Set(["cbc", "ecb", "ccm", "gcm", "cfb", "ofb", "ctr"]);
|
|
40
|
+
const CRYPTO_FUNCTIONS = new Set([
|
|
41
|
+
"generate",
|
|
42
|
+
"keygen",
|
|
43
|
+
"encrypt",
|
|
44
|
+
"decrypt",
|
|
45
|
+
"digest",
|
|
46
|
+
"tag",
|
|
47
|
+
"keyderive",
|
|
48
|
+
"sign",
|
|
49
|
+
"verify",
|
|
50
|
+
"encapsulate",
|
|
51
|
+
"decapsulate",
|
|
52
|
+
]);
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Names the bulk cipher of a TLS cipher suite as a crypto-oid.json key, from
|
|
56
|
+
* either its IANA name (TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) or its OpenSSL
|
|
57
|
+
* name (ECDHE-RSA-AES128-GCM-SHA256).
|
|
58
|
+
*
|
|
59
|
+
* @param {string} suiteName Cipher suite name
|
|
60
|
+
* @returns {{name: string, bits: number, mode: string|undefined}|undefined} The cipher, when it has an OID
|
|
61
|
+
*/
|
|
62
|
+
export function suiteCipher(suiteName) {
|
|
63
|
+
const tokens = String(suiteName || "")
|
|
64
|
+
.toUpperCase()
|
|
65
|
+
.split(/[-_]/);
|
|
66
|
+
let cipher;
|
|
67
|
+
if (tokens.includes("CHACHA20")) {
|
|
68
|
+
cipher = { name: "chaCha20Poly1305", bits: 256, mode: undefined };
|
|
69
|
+
} else if (tokens.includes("3DES") || tokens.includes("CBC3")) {
|
|
70
|
+
cipher = { name: "des-EDE3-CBC", bits: 112, mode: "cbc" };
|
|
71
|
+
} else {
|
|
72
|
+
const aesIdx = tokens.findIndex((t) => t.startsWith("AES"));
|
|
73
|
+
if (aesIdx < 0) {
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
const bits =
|
|
77
|
+
Number.parseInt(tokens[aesIdx].substring(3), 10) ||
|
|
78
|
+
Number.parseInt(tokens[aesIdx + 1], 10);
|
|
79
|
+
const mode = ["GCM", "CCM"].find((m) => tokens.includes(m)) || "CBC";
|
|
80
|
+
cipher = { name: `aes${bits}-${mode}`, bits, mode: mode.toLowerCase() };
|
|
81
|
+
}
|
|
82
|
+
return cryptoOids[cipher.name]?.oid ? cipher : undefined;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function oidKey(name) {
|
|
86
|
+
if (!name) {
|
|
87
|
+
return undefined;
|
|
88
|
+
}
|
|
89
|
+
if (cryptoOids[name]?.oid) {
|
|
90
|
+
return name;
|
|
91
|
+
}
|
|
92
|
+
const lower = String(name).toLowerCase();
|
|
93
|
+
return cryptoOids[lower]?.oid ? lower : undefined;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function cipherProperties(cipher) {
|
|
97
|
+
const props = {
|
|
98
|
+
primitive: cipher.mode === "cbc" ? "block-cipher" : "ae",
|
|
99
|
+
parameterSetIdentifier: String(cipher.bits),
|
|
100
|
+
cryptoFunctions: ["encrypt", "decrypt"],
|
|
101
|
+
classicalSecurityLevel: cipher.bits,
|
|
102
|
+
};
|
|
103
|
+
if (cipher.mode) {
|
|
104
|
+
props.mode = cipher.mode;
|
|
105
|
+
}
|
|
106
|
+
return props;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function keyExchangeProperties(name) {
|
|
110
|
+
const level = MLKEM_SECURITY_LEVELS[name];
|
|
111
|
+
if (level) {
|
|
112
|
+
return {
|
|
113
|
+
primitive: "kem",
|
|
114
|
+
cryptoFunctions: ["keygen", "encapsulate", "decapsulate"],
|
|
115
|
+
nistQuantumSecurityLevel: level,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
return { primitive: "key-agree", cryptoFunctions: ["keygen"] };
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Keeps the values of an algorithm the traced CBOM described that fit the
|
|
122
|
+
// schema; the primitive itself is checked by applyAlgorithmProperties.
|
|
123
|
+
function knownAlgorithmProperties(props) {
|
|
124
|
+
const known = {};
|
|
125
|
+
if (typeof props?.primitive === "string") {
|
|
126
|
+
known.primitive = props.primitive === "aead" ? "ae" : props.primitive;
|
|
127
|
+
}
|
|
128
|
+
const mode = String(props?.mode || "").toLowerCase();
|
|
129
|
+
if (MODES.has(mode)) {
|
|
130
|
+
known.mode = mode;
|
|
131
|
+
}
|
|
132
|
+
const functions = (props?.cryptoFunctions || []).filter((f) =>
|
|
133
|
+
CRYPTO_FUNCTIONS.has(f),
|
|
134
|
+
);
|
|
135
|
+
if (functions.length) {
|
|
136
|
+
known.cryptoFunctions = functions;
|
|
137
|
+
}
|
|
138
|
+
for (const level of ["classicalSecurityLevel", "nistQuantumSecurityLevel"]) {
|
|
139
|
+
if (Number.isInteger(props?.[level])) {
|
|
140
|
+
known[level] = props[level];
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return known;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Turns the CBOM safer-exec writes for a traced command into components that
|
|
148
|
+
* cdxgen can merge and validate:
|
|
149
|
+
*
|
|
150
|
+
* - every asset gets a bom-ref, without which the assets merge into one
|
|
151
|
+
* - algorithms carry their OID, and those without one are left out
|
|
152
|
+
* - hybrid key-exchange groups become their classical and ML-KEM halves
|
|
153
|
+
* - cipher suites become their bulk cipher, which the protocol's suites refer
|
|
154
|
+
* to by bom-ref
|
|
155
|
+
* - algorithm properties keep only values the schema allows
|
|
156
|
+
* - crypto libraries are left out: they are the traced library components,
|
|
157
|
+
* marked with cdx:dynamic:cryptoLibrary
|
|
158
|
+
*
|
|
159
|
+
* @param {Object[]} cbomComponents Components of the safer-exec CBOM
|
|
160
|
+
* @returns {Object[]} Normalized cryptographic-asset components
|
|
161
|
+
*/
|
|
162
|
+
export function normalizeTracedCryptoComponents(cbomComponents) {
|
|
163
|
+
const byRef = new Map();
|
|
164
|
+
const addAlgorithm = (name, algorithmProperties, curve) => {
|
|
165
|
+
const oid = cryptoOids[name].oid;
|
|
166
|
+
const ref = `crypto/algorithm/${encodeURIComponent(name)}@${oid}`;
|
|
167
|
+
if (!byRef.has(ref)) {
|
|
168
|
+
const component = {
|
|
169
|
+
type: "cryptographic-asset",
|
|
170
|
+
name,
|
|
171
|
+
"bom-ref": ref,
|
|
172
|
+
description: cryptoOids[name].description,
|
|
173
|
+
cryptoProperties: {
|
|
174
|
+
assetType: "algorithm",
|
|
175
|
+
algorithmProperties,
|
|
176
|
+
oid,
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
applyAlgorithmProperties(component, { name, curve });
|
|
180
|
+
byRef.set(ref, component);
|
|
181
|
+
}
|
|
182
|
+
return ref;
|
|
183
|
+
};
|
|
184
|
+
const protocols = [];
|
|
185
|
+
for (const comp of cbomComponents || []) {
|
|
186
|
+
const props = comp?.cryptoProperties;
|
|
187
|
+
if (comp?.type !== "cryptographic-asset" || !props) {
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
if (props.assetType === "protocol") {
|
|
191
|
+
protocols.push(comp);
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
if (props.assetType !== "algorithm") {
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
const groupHalves = GROUP_ALGORITHMS[comp.name];
|
|
198
|
+
if (groupHalves) {
|
|
199
|
+
for (const half of groupHalves) {
|
|
200
|
+
addAlgorithm(
|
|
201
|
+
half,
|
|
202
|
+
keyExchangeProperties(half),
|
|
203
|
+
KEY_AGREEMENT_CURVES[half] ||
|
|
204
|
+
(MLKEM_SECURITY_LEVELS[half] ? "" : half),
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
const name = oidKey(comp.name);
|
|
210
|
+
if (name) {
|
|
211
|
+
addAlgorithm(
|
|
212
|
+
name,
|
|
213
|
+
MLKEM_SECURITY_LEVELS[name] || KEY_AGREEMENT_CURVES[name]
|
|
214
|
+
? keyExchangeProperties(name)
|
|
215
|
+
: knownAlgorithmProperties(props.algorithmProperties),
|
|
216
|
+
KEY_AGREEMENT_CURVES[name] ||
|
|
217
|
+
(/^(secp|brainpool)/.test(name) ? name : ""),
|
|
218
|
+
);
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
const cipher = suiteCipher(comp.name);
|
|
222
|
+
if (cipher) {
|
|
223
|
+
addAlgorithm(cipher.name, cipherProperties(cipher));
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
thoughtLog(`Skipping traced algorithm '${comp.name}' without an OID.`);
|
|
227
|
+
}
|
|
228
|
+
for (const comp of protocols) {
|
|
229
|
+
const ref = `crypto/protocol/${encodeURIComponent(comp.name)}@${encodeURIComponent(comp.version || "unknown")}`;
|
|
230
|
+
const protocolProperties = {
|
|
231
|
+
...comp.cryptoProperties.protocolProperties,
|
|
232
|
+
};
|
|
233
|
+
// The traced suites list algorithm names; the schema wants bom-refs.
|
|
234
|
+
const cipherSuites = (protocolProperties.cipherSuites || []).map(
|
|
235
|
+
({ algorithms: _names, ...suite }) => {
|
|
236
|
+
const cipher = suiteCipher(suite.name);
|
|
237
|
+
return cipher
|
|
238
|
+
? {
|
|
239
|
+
...suite,
|
|
240
|
+
algorithms: [addAlgorithm(cipher.name, cipherProperties(cipher))],
|
|
241
|
+
}
|
|
242
|
+
: suite;
|
|
243
|
+
},
|
|
244
|
+
);
|
|
245
|
+
const existing = byRef.get(ref);
|
|
246
|
+
if (existing) {
|
|
247
|
+
const suites = existing.cryptoProperties.protocolProperties.cipherSuites;
|
|
248
|
+
for (const suite of cipherSuites) {
|
|
249
|
+
if (!suites.some((s) => s.name === suite.name)) {
|
|
250
|
+
suites.push(suite);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
255
|
+
protocolProperties.cipherSuites = cipherSuites;
|
|
256
|
+
const component = {
|
|
257
|
+
type: "cryptographic-asset",
|
|
258
|
+
name: comp.name,
|
|
259
|
+
"bom-ref": ref,
|
|
260
|
+
cryptoProperties: {
|
|
261
|
+
assetType: "protocol",
|
|
262
|
+
protocolProperties,
|
|
263
|
+
},
|
|
264
|
+
};
|
|
265
|
+
if (comp.version) {
|
|
266
|
+
component.version = comp.version;
|
|
267
|
+
}
|
|
268
|
+
byRef.set(ref, component);
|
|
269
|
+
}
|
|
270
|
+
return Array.from(byRef.values());
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Maps the crypto libraries safer-exec reported to the paths they were loaded
|
|
275
|
+
* from.
|
|
276
|
+
*
|
|
277
|
+
* @param {Object[]} cryptoEntries safer-exec crypto-library and crypto-cipher audit entries
|
|
278
|
+
* @returns {Map<string, {name: string, version: string}>} Crypto libraries by path
|
|
279
|
+
*/
|
|
280
|
+
export function cryptoLibrariesByPath(cryptoEntries) {
|
|
281
|
+
const libraries = new Map();
|
|
282
|
+
for (const entry of cryptoEntries || []) {
|
|
283
|
+
if (entry?.type !== "crypto-library" || !entry.path || !entry.name) {
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
if (!libraries.has(entry.path)) {
|
|
287
|
+
libraries.set(entry.path, {
|
|
288
|
+
name: String(entry.name),
|
|
289
|
+
version: entry.version ? String(entry.version) : "",
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
return libraries;
|
|
294
|
+
}
|
package/lib/managers/binary.js
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
} from "node:fs";
|
|
8
8
|
import { platform as _platform, homedir } from "node:os";
|
|
9
9
|
import { basename, dirname, extname, join, relative, resolve } from "node:path";
|
|
10
|
+
import process from "node:process";
|
|
10
11
|
|
|
11
12
|
import { build, Purl } from "@cdxgen/cdx-purl";
|
|
12
13
|
|
|
@@ -54,7 +55,11 @@ import {
|
|
|
54
55
|
resolvePluginBinary,
|
|
55
56
|
setPluginsPathEnv,
|
|
56
57
|
} from "../inventory/plugins.js";
|
|
57
|
-
import {
|
|
58
|
+
import {
|
|
59
|
+
genericPurl,
|
|
60
|
+
parsePurlLoose,
|
|
61
|
+
tryBuildPurl,
|
|
62
|
+
} from "../inventory/purl.js";
|
|
58
63
|
import {
|
|
59
64
|
adjustLicenseInformation,
|
|
60
65
|
findLicenseId,
|
|
@@ -531,28 +536,89 @@ export function getCargoAuditableInfo(src) {
|
|
|
531
536
|
return undefined;
|
|
532
537
|
}
|
|
533
538
|
|
|
539
|
+
/**
|
|
540
|
+
* Check that sourcekitten (bundled plugin or SOURCEKITTEN_CMD) answers a
|
|
541
|
+
* trivial syntax request.
|
|
542
|
+
*
|
|
543
|
+
* @param env {Object} Optional environment overrides merged over process.env
|
|
544
|
+
* @returns {String} `ok`; `unavailable` when there is no bundled plugin and
|
|
545
|
+
* SOURCEKITTEN_CMD is unset; `not-found` when the configured executable does
|
|
546
|
+
* not exist; `failed` when it ran but could not answer
|
|
547
|
+
*/
|
|
548
|
+
export function probeSourcekitten(env) {
|
|
549
|
+
if (!SOURCEKITTEN_BIN) {
|
|
550
|
+
return "unavailable";
|
|
551
|
+
}
|
|
552
|
+
const result = safeSpawnSync(
|
|
553
|
+
SOURCEKITTEN_BIN,
|
|
554
|
+
["syntax", "--text", "import Swift"],
|
|
555
|
+
env ? { env: { ...process.env, ...env } } : undefined,
|
|
556
|
+
);
|
|
557
|
+
if (result?.error?.code === "ENOENT") {
|
|
558
|
+
return "not-found";
|
|
559
|
+
}
|
|
560
|
+
if (result?.status === 0 && result.stdout) {
|
|
561
|
+
try {
|
|
562
|
+
JSON.parse(result.stdout);
|
|
563
|
+
return "ok";
|
|
564
|
+
} catch (_e) {
|
|
565
|
+
// Plain-text errors on stdout are failures
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
if (DEBUG_MODE) {
|
|
569
|
+
console.log(
|
|
570
|
+
"sourcekitten syntax probe failed:",
|
|
571
|
+
`${result?.stderr || result?.error || ""}`
|
|
572
|
+
.split("\n")
|
|
573
|
+
.slice(0, 5)
|
|
574
|
+
.map((l) => l.slice(0, 400))
|
|
575
|
+
.join("\n"),
|
|
576
|
+
);
|
|
577
|
+
}
|
|
578
|
+
return "failed";
|
|
579
|
+
}
|
|
580
|
+
|
|
534
581
|
/**
|
|
535
582
|
* Execute sourcekitten plugin with the given arguments
|
|
536
583
|
*
|
|
537
584
|
* @param args {Array} Arguments
|
|
585
|
+
* @param env {Object} Optional environment overrides merged over process.env,
|
|
586
|
+
* used to align sourcekitten with a specific Swift toolchain
|
|
538
587
|
* @returns {undefined|Object} Command output
|
|
539
588
|
*/
|
|
540
|
-
export function executeSourcekitten(args) {
|
|
541
|
-
if (SOURCEKITTEN_BIN) {
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
589
|
+
export function executeSourcekitten(args, env) {
|
|
590
|
+
if (!SOURCEKITTEN_BIN) {
|
|
591
|
+
return undefined;
|
|
592
|
+
}
|
|
593
|
+
const result = safeSpawnSync(
|
|
594
|
+
SOURCEKITTEN_BIN,
|
|
595
|
+
args,
|
|
596
|
+
env ? { env: { ...process.env, ...env } } : undefined,
|
|
597
|
+
);
|
|
598
|
+
if ((result.status !== 0 || result.error) && DEBUG_MODE) {
|
|
599
|
+
// Failures echo whole clang invocations, so only the first diagnostic
|
|
600
|
+
// lines are worth showing
|
|
601
|
+
const diagnostics = `${result.stderr || ""}`.split("\n").slice(0, 5);
|
|
602
|
+
console.log(
|
|
603
|
+
`sourcekitten ${args?.[0]} failed:`,
|
|
604
|
+
diagnostics.map((l) => l.slice(0, 400)).join("\n"),
|
|
605
|
+
);
|
|
606
|
+
}
|
|
607
|
+
if (!result?.stdout) {
|
|
608
|
+
return undefined;
|
|
609
|
+
}
|
|
610
|
+
try {
|
|
611
|
+
return JSON.parse(result.stdout);
|
|
612
|
+
} catch (_e) {
|
|
613
|
+
// Oversized outputs are truncated at the spawn buffer limit, and
|
|
614
|
+
// sourcekitten prints plain-text errors to stdout on some failures
|
|
615
|
+
if (DEBUG_MODE) {
|
|
616
|
+
console.log(
|
|
617
|
+
`Ignoring unparseable sourcekitten ${args?.[0]} output of ${result.stdout.length} bytes.`,
|
|
618
|
+
);
|
|
553
619
|
}
|
|
620
|
+
return undefined;
|
|
554
621
|
}
|
|
555
|
-
return undefined;
|
|
556
622
|
}
|
|
557
623
|
|
|
558
624
|
/**
|
|
@@ -796,8 +862,16 @@ export async function getOSPackages(src, imageConfig, options = {}) {
|
|
|
796
862
|
);
|
|
797
863
|
}
|
|
798
864
|
}
|
|
799
|
-
|
|
800
|
-
|
|
865
|
+
// trivy-cdxgen only scans a root filesystem; it has no `image` command. The
|
|
866
|
+
// caller hands over the exported image directory, so a missing path means
|
|
867
|
+
// the export failed and there is nothing for trivy to scan.
|
|
868
|
+
const rootfsPresent = TRIVY_BIN ? safeExistsSync(src) : false;
|
|
869
|
+
if (TRIVY_BIN && !rootfsPresent) {
|
|
870
|
+
console.warn(
|
|
871
|
+
`Skipping the trivy OS package scan: the root filesystem ${src} does not exist.`,
|
|
872
|
+
);
|
|
873
|
+
}
|
|
874
|
+
if (TRIVY_BIN && rootfsPresent) {
|
|
801
875
|
const trivyCacheDir = join(homedir(), ".cache", "trivy");
|
|
802
876
|
try {
|
|
803
877
|
safeMkdirSync(join(trivyCacheDir, "db"), { recursive: true });
|
|
@@ -805,13 +879,10 @@ export async function getOSPackages(src, imageConfig, options = {}) {
|
|
|
805
879
|
} catch (_err) {
|
|
806
880
|
// ignore errors
|
|
807
881
|
}
|
|
808
|
-
if (safeExistsSync(src)) {
|
|
809
|
-
imageType = "rootfs";
|
|
810
|
-
}
|
|
811
882
|
const tempDir = safeMkdtempSync(join(getTmpDir(), "trivy-cdxgen-"));
|
|
812
883
|
const bomJsonFile = join(tempDir, "trivy-bom.json");
|
|
813
884
|
const args = [
|
|
814
|
-
|
|
885
|
+
"rootfs",
|
|
815
886
|
"--cache-dir",
|
|
816
887
|
trivyCacheDir,
|
|
817
888
|
"--output",
|
|
@@ -932,7 +1003,7 @@ export async function getOSPackages(src, imageConfig, options = {}) {
|
|
|
932
1003
|
? tmpBom.metadata.tools
|
|
933
1004
|
: tmpBom?.metadata?.tools?.components || []
|
|
934
1005
|
).filter((tool) => tool?.["bom-ref"] && tool?.name !== "cdxgen"),
|
|
935
|
-
["trivy"
|
|
1006
|
+
["trivy", "trustinspector"],
|
|
936
1007
|
);
|
|
937
1008
|
const toolRefs = extractToolRefs(
|
|
938
1009
|
{ components: tools },
|
|
@@ -2977,7 +3048,20 @@ function detectSdksRuntimes(comp, bundledSdks, bundledRuntimes) {
|
|
|
2977
3048
|
}
|
|
2978
3049
|
}
|
|
2979
3050
|
|
|
2980
|
-
|
|
3051
|
+
/**
|
|
3052
|
+
* Collect the dependency edges trivy recorded for one OS package component.
|
|
3053
|
+
*
|
|
3054
|
+
* Trivy keys its `dependencies` by its own bom-refs, which may leave the `+` of
|
|
3055
|
+
* an rpm or deb version unescaped (`...libstdc%2B%2B6@14.2.0+git10526-...`), so
|
|
3056
|
+
* each ref is read structurally and re-rendered in cdxgen's decoded bom-ref
|
|
3057
|
+
* form with the component's type, namespace and distro qualifiers.
|
|
3058
|
+
*
|
|
3059
|
+
* @param {Object<string, string[]>} tmpDependencies Trivy's refs mapped to the refs they depend on
|
|
3060
|
+
* @param {string} origBomRef The component's bom-ref as trivy wrote it
|
|
3061
|
+
* @param {object} comp The component after cdxgen rewrote its purl and bom-ref
|
|
3062
|
+
* @returns {{ref: string, dependsOn: string[]}|undefined} Dependency entry for the component
|
|
3063
|
+
*/
|
|
3064
|
+
export const retrieveDependencies = (tmpDependencies, origBomRef, comp) => {
|
|
2981
3065
|
try {
|
|
2982
3066
|
const tmpDependsOn =
|
|
2983
3067
|
tmpDependencies[origBomRef] || tmpDependencies[comp["bom-ref"]] || [];
|
|
@@ -2985,7 +3069,14 @@ const retrieveDependencies = (tmpDependencies, origBomRef, comp) => {
|
|
|
2985
3069
|
tmpDependsOn.forEach((d) => {
|
|
2986
3070
|
try {
|
|
2987
3071
|
const compPurl = Purl.parse(comp.purl);
|
|
2988
|
-
|
|
3072
|
+
// Trivy's dependency refs are its bom-refs, which can leave the `+` of
|
|
3073
|
+
// an rpm or deb version unescaped; read them structurally so the edge
|
|
3074
|
+
// survives.
|
|
3075
|
+
const depParts = parsePurlLoose(d.replace("none", compPurl.type));
|
|
3076
|
+
if (!depParts) {
|
|
3077
|
+
return;
|
|
3078
|
+
}
|
|
3079
|
+
const tmpPurl = new Purl(depParts);
|
|
2989
3080
|
tmpPurl.type = compPurl.type;
|
|
2990
3081
|
// FIXME: Check if this hack is still needed with the latest trivy
|
|
2991
3082
|
if (OS_PURL_TYPES.includes(compPurl.type)) {
|