@cdxgen/cdxgen 13.3.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 +9 -6
- package/bin/cdxgen.js +90 -26
- package/bin/evinse.js +18 -1
- package/bin/repl.js +86 -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/helpers/init.gradle +46 -21
- package/data/remediations.json +61 -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/index.js +113 -54
- package/lib/cli/jsBom.js +50 -29
- package/lib/cli/jvmBom.js +665 -138
- package/lib/cli/managedBom.js +320 -200
- package/lib/cli/nativeBom.js +139 -30
- package/lib/core/activity.js +12 -0
- package/lib/core/env.js +17 -9
- package/lib/core/fs.js +3 -2
- package/lib/core/httpClient.js +159 -24
- package/lib/core/pluginRun.js +184 -0
- package/lib/core/processTree.js +100 -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 +28 -12
- package/lib/ecosystems/gradleutils.js +314 -30
- 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 +567 -151
- package/lib/ecosystems/parsers-elm.js +46 -28
- package/lib/ecosystems/parsers-gleam.js +3 -4
- package/lib/ecosystems/parsers-go.js +324 -61
- package/lib/ecosystems/parsers-js.js +92 -26
- package/lib/ecosystems/parsers-julia.js +2 -3
- package/lib/ecosystems/parsers-jvm.js +204 -12
- package/lib/ecosystems/parsers-misc.js +182 -55
- package/lib/ecosystems/parsers-python.js +141 -10
- 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 +67 -17
- package/lib/ecosystems/rusi.js +22 -9
- 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 +578 -69
- package/lib/helpers/agenticToolutils.js +2 -2
- package/lib/helpers/bomSigner.js +576 -128
- package/lib/inventory/aiCollector.js +4 -1
- package/lib/inventory/analyzer.js +110 -127
- package/lib/inventory/atomUtils.js +171 -48
- package/lib/inventory/auditCategories.js +7 -0
- package/lib/inventory/buildToolRateLimit.js +144 -0
- package/lib/inventory/cacheCommands.js +2 -1
- package/lib/inventory/cmakeBuildDirs.js +254 -0
- package/lib/inventory/deps.js +501 -124
- package/lib/inventory/dosai.js +248 -44
- package/lib/inventory/dosaiParsers.js +310 -15
- package/lib/inventory/dynamic.js +52 -6
- package/lib/inventory/evidenceUtils.js +154 -109
- package/lib/inventory/fetchBatch.js +574 -38
- 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/rustFormulationParser.js +3 -4
- package/lib/inventory/scalaCoords.js +153 -0
- package/lib/inventory/source.js +8 -8
- package/lib/inventory/spdx.js +101 -0
- package/lib/inventory/traceRunner.js +88 -7
- package/lib/inventory/tracedCrypto.js +294 -0
- package/lib/managers/docker.js +33 -32
- 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/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 +15 -1
- package/lib/stages/postgen/specVersionCompat.js +32 -0
- package/lib/validator/index.js +25 -10
- package/lib/validator/reporters/json.js +1 -0
- package/package.json +21 -21
- package/types/lib/audit/index.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.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/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 +18 -2
- 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 +50 -0
- 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 +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 +44 -2
- 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 +46 -1
- package/types/lib/ecosystems/parsers-jvm.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-misc.d.ts +3 -1
- 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-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 +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 +75 -8
- package/types/lib/evinser/evinser.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/aiCollector.d.ts.map +1 -1
- package/types/lib/inventory/analyzer.d.ts.map +1 -1
- package/types/lib/inventory/atomUtils.d.ts +82 -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/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/dosai.d.ts +57 -8
- 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/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.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 +12 -0
- 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/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/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/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
package/README.md
CHANGED
|
@@ -216,7 +216,7 @@ Common asset names:
|
|
|
216
216
|
#### Linux
|
|
217
217
|
|
|
218
218
|
```bash
|
|
219
|
-
VERSION="v13.
|
|
219
|
+
VERSION="v13.4.0"
|
|
220
220
|
ASSET="cdx-audit-linux-amd64"
|
|
221
221
|
BASE_URL="https://github.com/cdxgen/cdxgen/releases/download/${VERSION}"
|
|
222
222
|
|
|
@@ -230,7 +230,7 @@ chmod +x "${ASSET}"
|
|
|
230
230
|
#### macOS
|
|
231
231
|
|
|
232
232
|
```bash
|
|
233
|
-
VERSION="v13.
|
|
233
|
+
VERSION="v13.4.0"
|
|
234
234
|
ASSET="cdx-audit-darwin-arm64"
|
|
235
235
|
BASE_URL="https://github.com/cdxgen/cdxgen/releases/download/${VERSION}"
|
|
236
236
|
|
|
@@ -244,7 +244,7 @@ chmod +x "${ASSET}"
|
|
|
244
244
|
#### Windows (PowerShell)
|
|
245
245
|
|
|
246
246
|
```powershell
|
|
247
|
-
$Version = "v13.
|
|
247
|
+
$Version = "v13.4.0"
|
|
248
248
|
$Asset = "cdx-audit-windows-amd64.exe"
|
|
249
249
|
$BaseUrl = "https://github.com/cdxgen/cdxgen/releases/download/$Version"
|
|
250
250
|
|
|
@@ -269,7 +269,7 @@ steps:
|
|
|
269
269
|
env:
|
|
270
270
|
GH_TOKEN: ${{ github.token }}
|
|
271
271
|
run: |
|
|
272
|
-
gh release download v13.
|
|
272
|
+
gh release download v13.4.0 \
|
|
273
273
|
--repo cdxgen/cdxgen \
|
|
274
274
|
--pattern 'cdx-audit-linux-amd64' \
|
|
275
275
|
--pattern 'cdx-audit-linux-amd64.sha256'
|
|
@@ -759,9 +759,9 @@ BOMs signed with cdxgen 13.2.0 or earlier must be re-signed with the current `cd
|
|
|
759
759
|
For complex supply chain orchestration, use the bundled `cdx-sign` CLI. This tool allows multiple entities (e.g., a Builder and an Auditor) to co-sign an existing BOM without modifying its original data.
|
|
760
760
|
|
|
761
761
|
```shell
|
|
762
|
-
# Append a parallel multi-signature (Auditor co-signing)
|
|
762
|
+
# Append a parallel multi-signature (Auditor co-signing) after checking the Builder's signature
|
|
763
763
|
# Note: Granular component signing is disabled to preserve the Builder's original signature payload.
|
|
764
|
-
cdx-sign -i bom.json -k auditor_private.pem -a ES256 --key-id "auditor-qa" --mode signers --no-sign-components
|
|
764
|
+
cdx-sign -i bom.json -k auditor_private.pem -a ES256 --key-id "auditor-qa" --mode signers --no-sign-components --verify-existing-with builder_public.pem
|
|
765
765
|
```
|
|
766
766
|
|
|
767
767
|
### Validating CycloneDX BOMs
|
|
@@ -780,6 +780,9 @@ cdx-verify -i bom.json --public-key public.key
|
|
|
780
780
|
|
|
781
781
|
# Verify ONLY the top-level root signature (useful for verifying a multi-signer who didn't sign nested components)
|
|
782
782
|
cdx-verify -i bom.json --public-key auditor_public.key --no-deep
|
|
783
|
+
|
|
784
|
+
# Require every co-signer
|
|
785
|
+
cdx-verify -i bom.json --public-key builder_public.key --public-key auditor_public.key --require-all
|
|
783
786
|
```
|
|
784
787
|
|
|
785
788
|
### Verifying the signature (pnpm)
|
package/bin/cdxgen.js
CHANGED
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
isDeferredFailOnError,
|
|
35
35
|
} from "../lib/core/deferredExit.js";
|
|
36
36
|
import { TRACE_MODE, thoughtEnd, thoughtLog } from "../lib/core/logger.js";
|
|
37
|
+
import { resolveSourcePathArgument } from "../lib/core/pluginRun.js";
|
|
37
38
|
import {
|
|
38
39
|
PROJECT_CONFIG_FILENAMES,
|
|
39
40
|
sanitizeProjectConfig,
|
|
@@ -263,12 +264,12 @@ const args = _yargs
|
|
|
263
264
|
.option("cmake-cache", {
|
|
264
265
|
type: "string",
|
|
265
266
|
description:
|
|
266
|
-
"Path to the CMakeCache.txt of a configured C/C++ build. Overrides the lookup
|
|
267
|
+
"Path to the CMakeCache.txt of a configured C/C++ build. Overrides the lookup in the build directories of the CMake presets, build*/, out/, builddir/ and cmake-build-*/.",
|
|
267
268
|
})
|
|
268
269
|
.option("compile-commands", {
|
|
269
270
|
type: "string",
|
|
270
271
|
description:
|
|
271
|
-
"Path to the compile_commands.json of a C/C++ build, or a directory holding one. atom then parses each file with its build's include paths, macros and language. Overrides the lookup in the project root, build
|
|
272
|
+
"Path to the compile_commands.json of a C/C++ build, or a directory holding one. atom then parses each file with its build's include paths, macros and language. Overrides the lookup in the project root and its build directories (those of the CMake presets, build*/, out/, builddir/, cmake-build-*/), which is skipped in secure mode.",
|
|
272
273
|
})
|
|
273
274
|
.option("git-branch", {
|
|
274
275
|
description: "Git branch to clone when the source is a git URL or purl",
|
|
@@ -456,6 +457,23 @@ const args = _yargs
|
|
|
456
457
|
default: false,
|
|
457
458
|
description: "Generate SBOM with evidence for supported languages.",
|
|
458
459
|
})
|
|
460
|
+
.option("scalasem", {
|
|
461
|
+
type: "boolean",
|
|
462
|
+
default: true,
|
|
463
|
+
description:
|
|
464
|
+
"Run the Scala semantic analyzer for the evidence of Scala projects. Use --no-scalasem to skip it.",
|
|
465
|
+
})
|
|
466
|
+
.option("scalasem-command", {
|
|
467
|
+
type: "string",
|
|
468
|
+
description:
|
|
469
|
+
"Use a specific scalasem script for the Scala evidence. Defaults to SCALASEM_CMD.",
|
|
470
|
+
})
|
|
471
|
+
.option("scalasem-include-tests", {
|
|
472
|
+
type: "boolean",
|
|
473
|
+
default: false,
|
|
474
|
+
description:
|
|
475
|
+
"Include test sources in the Scala evidence, tagged with their usage scope.",
|
|
476
|
+
})
|
|
459
477
|
.option("deps-slices-file", {
|
|
460
478
|
description: "Path for the parsedeps slice file created by atom.",
|
|
461
479
|
default: "deps.slices.json",
|
|
@@ -893,7 +911,7 @@ const args = _yargs
|
|
|
893
911
|
type: "boolean",
|
|
894
912
|
default: true,
|
|
895
913
|
description:
|
|
896
|
-
"Use the on-disk metadata cache for registry lookups. Pass --no-cache to bypass it for this run.",
|
|
914
|
+
"Use the on-disk metadata cache for registry lookups. Pass --no-cache to bypass it for this run; answers are still remembered within the run.",
|
|
897
915
|
})
|
|
898
916
|
.option("cache-ttl", {
|
|
899
917
|
type: "number",
|
|
@@ -1013,9 +1031,24 @@ if (!readEnvironmentVariable("NODE_USE_SYSTEM_CA")) {
|
|
|
1013
1031
|
process.env.NODE_USE_SYSTEM_CA = "1";
|
|
1014
1032
|
}
|
|
1015
1033
|
|
|
1016
|
-
|
|
1034
|
+
let filePath = args._[0] || process.cwd();
|
|
1017
1035
|
const sourceInputIsRemoteOrPurl =
|
|
1018
1036
|
maybeRemotePath(filePath) || maybePurlSource(filePath);
|
|
1037
|
+
// Resolve the source argument once, before anything uses it. With the working
|
|
1038
|
+
// directory already set to the project and the argument relative to a
|
|
1039
|
+
// repository root (depscan's launch shape), every later resolve would produce
|
|
1040
|
+
// <project>/<argument>, a directory that does not exist: the BOM came out
|
|
1041
|
+
// empty and the plugins analyzed nothing, while the run still exited 0.
|
|
1042
|
+
if (!sourceInputIsRemoteOrPurl && args._?.[0]) {
|
|
1043
|
+
const sourceResolution = resolveSourcePathArgument(filePath);
|
|
1044
|
+
if (sourceResolution.rewritten) {
|
|
1045
|
+
console.warn(
|
|
1046
|
+
`Source path '${filePath}' does not exist relative to the working directory, which is itself the directory it names; using '${sourceResolution.path}'.`,
|
|
1047
|
+
);
|
|
1048
|
+
filePath = sourceResolution.path;
|
|
1049
|
+
args._[0] = filePath;
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1019
1052
|
if (!args.projectName) {
|
|
1020
1053
|
if (filePath !== ".") {
|
|
1021
1054
|
args.projectName = basename(filePath);
|
|
@@ -2137,30 +2170,61 @@ const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
|
|
|
2137
2170
|
sourcePath: filePath,
|
|
2138
2171
|
});
|
|
2139
2172
|
const evinserModule = await import("../lib/evinser/evinser.js");
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2173
|
+
if (!options.projectType) {
|
|
2174
|
+
const evidenceLanguage = evinserModule.defaultEvidenceLanguage(
|
|
2175
|
+
filePath,
|
|
2176
|
+
bomNSData?.bomJson,
|
|
2177
|
+
options,
|
|
2178
|
+
);
|
|
2179
|
+
if (evidenceLanguage) {
|
|
2180
|
+
options.projectType = [evidenceLanguage];
|
|
2181
|
+
}
|
|
2182
|
+
}
|
|
2183
|
+
if (!options.projectType) {
|
|
2184
|
+
console.log(
|
|
2185
|
+
"Skipping the evidence analysis since the BOM lists no package in a language it supports. Pass -t to choose the language.",
|
|
2151
2186
|
);
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2187
|
+
if (bomNSData) {
|
|
2188
|
+
bomNSData.bomJson = applyEvidenceBasedFilter(
|
|
2189
|
+
bomNSData.bomJson,
|
|
2190
|
+
options,
|
|
2191
|
+
);
|
|
2192
|
+
}
|
|
2193
|
+
} else {
|
|
2194
|
+
const evinseOptions = evinserModule.buildEvinseOptions(
|
|
2195
|
+
options,
|
|
2196
|
+
args,
|
|
2197
|
+
internalCycloneDxInputPath || options.output,
|
|
2155
2198
|
);
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2199
|
+
try {
|
|
2200
|
+
const dbObjMap = await evinserModule.prepareDB(evinseOptions);
|
|
2201
|
+
if (dbObjMap) {
|
|
2202
|
+
const sliceArtefacts = await evinserModule.analyzeProject(
|
|
2203
|
+
dbObjMap,
|
|
2204
|
+
evinseOptions,
|
|
2205
|
+
);
|
|
2206
|
+
const evinseJson = await evinserModule.createEvinseFile(
|
|
2207
|
+
sliceArtefacts,
|
|
2208
|
+
evinseOptions,
|
|
2209
|
+
);
|
|
2210
|
+
// The scope filter is deferred until here so the analyzers get to
|
|
2211
|
+
// prove that an optional dependency is actually used.
|
|
2212
|
+
bomNSData.bomJson = applyEvidenceBasedFilter(evinseJson, options);
|
|
2213
|
+
if (options.print && evinseJson) {
|
|
2214
|
+
printOccurrences(evinseJson);
|
|
2215
|
+
printCallStack(evinseJson);
|
|
2216
|
+
printReachables(sliceArtefacts);
|
|
2217
|
+
printServices(evinseJson);
|
|
2218
|
+
}
|
|
2219
|
+
}
|
|
2220
|
+
} catch (err) {
|
|
2221
|
+
// A rusi/golem analysis failure under --fail-on-error on an
|
|
2222
|
+
// introspected run defers its exit so the BOM and the reports are
|
|
2223
|
+
// still written; the run continues here without the reachability
|
|
2224
|
+
// evidence, exactly as the deferral contract describes.
|
|
2225
|
+
if (!isDeferredFailOnError(err)) {
|
|
2226
|
+
throw err;
|
|
2227
|
+
}
|
|
2164
2228
|
}
|
|
2165
2229
|
}
|
|
2166
2230
|
}
|
package/bin/evinse.js
CHANGED
|
@@ -91,7 +91,7 @@ const args = yargs(hideBin(process.argv))
|
|
|
91
91
|
})
|
|
92
92
|
.option("compile-commands", {
|
|
93
93
|
description:
|
|
94
|
-
"Path to the compile_commands.json of a C/C++ build, or a directory holding one, for atom to parse each file as its build does. Overrides the lookup in the project root, build
|
|
94
|
+
"Path to the compile_commands.json of a C/C++ build, or a directory holding one, for atom to parse each file as its build does. Overrides the lookup in the project root and its build directories (those of the CMake presets, build*/, out/, builddir/, cmake-build-*/), which is skipped in secure mode.",
|
|
95
95
|
type: "string",
|
|
96
96
|
})
|
|
97
97
|
.option("golem-command", {
|
|
@@ -264,6 +264,23 @@ const args = yargs(hideBin(process.argv))
|
|
|
264
264
|
description: "Use an existing usages slices file.",
|
|
265
265
|
default: "usages.slices.json",
|
|
266
266
|
})
|
|
267
|
+
.option("scalasem-command", {
|
|
268
|
+
description:
|
|
269
|
+
"Use a specific scalasem script for Scala evidence analysis. Defaults to SCALASEM_CMD.",
|
|
270
|
+
default: readEnvironmentVariable("SCALASEM_CMD"),
|
|
271
|
+
})
|
|
272
|
+
.option("scalasem-include-tests", {
|
|
273
|
+
description:
|
|
274
|
+
"Include test sources in the Scala semantic evidence, tagged with their usage scope.",
|
|
275
|
+
default: false,
|
|
276
|
+
type: "boolean",
|
|
277
|
+
})
|
|
278
|
+
.option("scalasem", {
|
|
279
|
+
description:
|
|
280
|
+
"Run the Scala semantic analyzer for Scala projects. Use --no-scalasem to skip it and keep the plain BOM.",
|
|
281
|
+
default: true,
|
|
282
|
+
type: "boolean",
|
|
283
|
+
})
|
|
267
284
|
.option("data-flow-slices-file", {
|
|
268
285
|
description: "Use an existing data-flow slices file.",
|
|
269
286
|
default: "data-flow.slices.json",
|
package/bin/repl.js
CHANGED
|
@@ -1741,6 +1741,92 @@ cdxgenRepl.defineCommand("golemcoverage", {
|
|
|
1741
1741
|
this.displayPrompt();
|
|
1742
1742
|
},
|
|
1743
1743
|
});
|
|
1744
|
+
function hasScalasemProperties(component) {
|
|
1745
|
+
return Boolean(
|
|
1746
|
+
component?.properties?.some((property) =>
|
|
1747
|
+
property?.name?.startsWith("cdx:scalasem:"),
|
|
1748
|
+
),
|
|
1749
|
+
);
|
|
1750
|
+
}
|
|
1751
|
+
|
|
1752
|
+
cdxgenRepl.defineCommand("scalasemsummary", {
|
|
1753
|
+
help: "summarize Scala Evinse/scalasem metadata and evidence coverage",
|
|
1754
|
+
action() {
|
|
1755
|
+
const interactiveBom = getInteractiveBom();
|
|
1756
|
+
if (!interactiveBom) {
|
|
1757
|
+
console.log("⚠ No BOM is loaded. Use .import command to import an SBOM");
|
|
1758
|
+
this.displayPrompt();
|
|
1759
|
+
return;
|
|
1760
|
+
}
|
|
1761
|
+
if (!hasScalasemProperties(interactiveBom.metadata?.component)) {
|
|
1762
|
+
console.log(
|
|
1763
|
+
"No scalasem properties found. Generate an evidence BOM with evinse -l scala or cdxgen --evidence to use this view.",
|
|
1764
|
+
);
|
|
1765
|
+
this.displayPrompt();
|
|
1766
|
+
return;
|
|
1767
|
+
}
|
|
1768
|
+
const rootComponent = interactiveBom.metadata?.component || {};
|
|
1769
|
+
const components = interactiveBom.components || [];
|
|
1770
|
+
const occurrences = components.reduce(
|
|
1771
|
+
(total, component) =>
|
|
1772
|
+
total + (component?.evidence?.occurrences?.length || 0),
|
|
1773
|
+
0,
|
|
1774
|
+
);
|
|
1775
|
+
const occurrencesWithLine = components.reduce(
|
|
1776
|
+
(total, component) =>
|
|
1777
|
+
total +
|
|
1778
|
+
(component?.evidence?.occurrences || []).filter(
|
|
1779
|
+
(occurrence) => occurrence?.line,
|
|
1780
|
+
).length,
|
|
1781
|
+
0,
|
|
1782
|
+
);
|
|
1783
|
+
const callstacks = components.filter(
|
|
1784
|
+
(component) => component?.evidence?.callstack?.frames?.length,
|
|
1785
|
+
).length;
|
|
1786
|
+
const cryptoAssets = components.filter(
|
|
1787
|
+
(component) => component?.type === "cryptographic-asset",
|
|
1788
|
+
).length;
|
|
1789
|
+
printKeyValueTable("Scala Evinse / scalasem summary", [
|
|
1790
|
+
[
|
|
1791
|
+
"Schema version",
|
|
1792
|
+
getPropertyValue(rootComponent, "cdx:scalasem:schemaVersion"),
|
|
1793
|
+
],
|
|
1794
|
+
[
|
|
1795
|
+
"Facts source",
|
|
1796
|
+
getPropertyValue(rootComponent, "cdx:scalasem:factsSource"),
|
|
1797
|
+
],
|
|
1798
|
+
[
|
|
1799
|
+
"Scala versions",
|
|
1800
|
+
getPropertyValue(rootComponent, "cdx:scalasem:scalaVersions"),
|
|
1801
|
+
],
|
|
1802
|
+
["Platforms", getPropertyValue(rootComponent, "cdx:scalasem:platforms")],
|
|
1803
|
+
[
|
|
1804
|
+
"Files analyzed",
|
|
1805
|
+
getPropertyValue(rootComponent, "cdx:scalasem:filesAnalyzed"),
|
|
1806
|
+
],
|
|
1807
|
+
["Degraded", getPropertyValue(rootComponent, "cdx:scalasem:degraded")],
|
|
1808
|
+
...(rootComponent.properties || [])
|
|
1809
|
+
.filter((property) =>
|
|
1810
|
+
property?.name?.startsWith("cdx:scalasem:diagnostic:"),
|
|
1811
|
+
)
|
|
1812
|
+
.map((property) => [
|
|
1813
|
+
`Diagnostic ${property.name.slice("cdx:scalasem:diagnostic:".length)}`,
|
|
1814
|
+
property.value,
|
|
1815
|
+
]),
|
|
1816
|
+
[
|
|
1817
|
+
"Components with occurrences",
|
|
1818
|
+
components.filter((c) => c?.evidence?.occurrences?.length).length,
|
|
1819
|
+
],
|
|
1820
|
+
["Occurrences", occurrences],
|
|
1821
|
+
["Occurrences with line", occurrencesWithLine],
|
|
1822
|
+
["Components with call stacks", callstacks],
|
|
1823
|
+
["Crypto assets", cryptoAssets],
|
|
1824
|
+
["Services", (interactiveBom.services || []).length],
|
|
1825
|
+
]);
|
|
1826
|
+
this.displayPrompt();
|
|
1827
|
+
},
|
|
1828
|
+
});
|
|
1829
|
+
|
|
1744
1830
|
cdxgenRepl.defineCommand("auditfindings", {
|
|
1745
1831
|
help: "summarize cdx-audit and bom-audit annotations from the loaded BOM",
|
|
1746
1832
|
action() {
|
package/bin/sign.js
CHANGED
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
getNonCycloneDxErrorMessage,
|
|
21
21
|
isCycloneDxBom,
|
|
22
22
|
} from "../lib/inventory/bomUtils.js";
|
|
23
|
+
import { parseStrictJson } from "../lib/parsers/strictJson.js";
|
|
23
24
|
|
|
24
25
|
const _yargs = yargs(hideBin(process.argv));
|
|
25
26
|
|
|
@@ -55,13 +56,19 @@ const args = _yargs
|
|
|
55
56
|
type: "array",
|
|
56
57
|
string: true,
|
|
57
58
|
description:
|
|
58
|
-
"Public key (PEM) of an earlier signer.
|
|
59
|
+
"Public key (PEM) of an earlier signer. Before a new entry is appended, every existing chain entry (--mode chain), or at least one existing entry (--mode signers), must verify with one of these keys.",
|
|
59
60
|
})
|
|
60
61
|
.option("allow-unverified-history", {
|
|
61
62
|
type: "boolean",
|
|
62
63
|
default: false,
|
|
63
64
|
description:
|
|
64
|
-
"With --mode chain, append even when existing
|
|
65
|
+
"With --mode chain or signers, append even when the existing signature entries cannot be verified with --verify-existing-with.",
|
|
66
|
+
})
|
|
67
|
+
.option("embed-public-key", {
|
|
68
|
+
type: "boolean",
|
|
69
|
+
default: true,
|
|
70
|
+
description:
|
|
71
|
+
"Embed the signer's public key in the root signature, which binds the signature to that key. Not used for HMAC (HS*) algorithms. Pass --no-embed-public-key to leave it out.",
|
|
65
72
|
})
|
|
66
73
|
.option("key-id", {
|
|
67
74
|
description:
|
|
@@ -173,16 +180,19 @@ function describeEntry(result) {
|
|
|
173
180
|
: `entry ${result.index}`;
|
|
174
181
|
}
|
|
175
182
|
|
|
176
|
-
// A new chain entry covers every earlier entry, so the signer vouches for
|
|
177
|
-
//
|
|
178
|
-
|
|
183
|
+
// A new chain entry covers every earlier entry, so the signer vouches for that
|
|
184
|
+
// history, and every entry must verify. A new signers entry covers the same
|
|
185
|
+
// content as the existing entries, so at least one must verify to show the
|
|
186
|
+
// content is still what an earlier signer signed.
|
|
187
|
+
function checkExistingSignatures(bomJson) {
|
|
179
188
|
const existing = bomJson.signature;
|
|
189
|
+
const otherForm = args.mode === "chain" ? "signers" : "chain";
|
|
180
190
|
if (
|
|
181
|
-
args.mode
|
|
191
|
+
args.mode === "replace" ||
|
|
182
192
|
existing === undefined ||
|
|
183
193
|
(existing !== null &&
|
|
184
194
|
typeof existing === "object" &&
|
|
185
|
-
Object.hasOwn(existing,
|
|
195
|
+
Object.hasOwn(existing, otherForm))
|
|
186
196
|
) {
|
|
187
197
|
return;
|
|
188
198
|
}
|
|
@@ -192,10 +202,10 @@ function checkChainHistory(bomJson) {
|
|
|
192
202
|
}
|
|
193
203
|
return fs.readFileSync(keyFile, "utf8");
|
|
194
204
|
});
|
|
195
|
-
const
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
if (!unverified.length) {
|
|
205
|
+
const results = checkSignatureEntries(bomJson, keys);
|
|
206
|
+
const unverified = results.filter((result) => !result.verified);
|
|
207
|
+
const chain = args.mode === "chain";
|
|
208
|
+
if (chain ? !unverified.length : unverified.length < results.length) {
|
|
199
209
|
return;
|
|
200
210
|
}
|
|
201
211
|
const details = unverified.map(
|
|
@@ -205,7 +215,9 @@ function checkChainHistory(bomJson) {
|
|
|
205
215
|
if (args.allowUnverifiedHistory) {
|
|
206
216
|
console.warn(
|
|
207
217
|
[
|
|
208
|
-
|
|
218
|
+
chain
|
|
219
|
+
? `Warning: appending to a chain with ${unverified.length} unverified entry(s):`
|
|
220
|
+
: `Warning: appending a signers entry although none of the ${unverified.length} existing entry(s) verified:`,
|
|
209
221
|
...details,
|
|
210
222
|
].join("\n"),
|
|
211
223
|
);
|
|
@@ -213,7 +225,9 @@ function checkChainHistory(bomJson) {
|
|
|
213
225
|
}
|
|
214
226
|
throw new Error(
|
|
215
227
|
[
|
|
216
|
-
|
|
228
|
+
chain
|
|
229
|
+
? `the new chain entry would vouch for ${unverified.length} existing entry(s) that could not be verified:`
|
|
230
|
+
: `none of the ${unverified.length} existing signature entry(s) could be verified, so the content may have changed since it was signed:`,
|
|
217
231
|
...details,
|
|
218
232
|
"Pass --verify-existing-with <public key> for each earlier signer, or --allow-unverified-history to sign anyway.",
|
|
219
233
|
].join("\n"),
|
|
@@ -221,7 +235,7 @@ function checkChainHistory(bomJson) {
|
|
|
221
235
|
}
|
|
222
236
|
|
|
223
237
|
try {
|
|
224
|
-
const bomJson =
|
|
238
|
+
const bomJson = parseStrictJson(fs.readFileSync(args.input));
|
|
225
239
|
if (!isCycloneDxBom(bomJson)) {
|
|
226
240
|
console.error(getNonCycloneDxErrorMessage(bomJson, "cdx-sign"));
|
|
227
241
|
process.exit(1);
|
|
@@ -229,10 +243,12 @@ try {
|
|
|
229
243
|
|
|
230
244
|
let signedBom = bomJson;
|
|
231
245
|
if (hasPrivateKey && privateKeyContent) {
|
|
232
|
-
|
|
246
|
+
checkExistingSignatures(bomJson);
|
|
233
247
|
signedBom = signBom(bomJson, {
|
|
234
248
|
privateKey: privateKeyContent,
|
|
235
249
|
algorithm: args.algorithm,
|
|
250
|
+
embedPublicKey: args.embedPublicKey,
|
|
251
|
+
embedPublicKeyNested: false,
|
|
236
252
|
keyId: args.keyId,
|
|
237
253
|
mode: args.mode,
|
|
238
254
|
signComponents: args.signComponents,
|
|
@@ -247,6 +263,20 @@ try {
|
|
|
247
263
|
console.log(
|
|
248
264
|
`Mode: ${args.mode} | Algorithm: ${args.algorithm}${args.keyId ? ` | KeyId: ${args.keyId}` : ""}`,
|
|
249
265
|
);
|
|
266
|
+
const rootSignature = signedBom.signature;
|
|
267
|
+
const newEntry =
|
|
268
|
+
rootSignature?.signers?.at(-1) ??
|
|
269
|
+
rootSignature?.chain?.at(-1) ??
|
|
270
|
+
rootSignature;
|
|
271
|
+
if (
|
|
272
|
+
args.embedPublicKey &&
|
|
273
|
+
!String(args.algorithm).startsWith("HS") &&
|
|
274
|
+
newEntry?.publicKey === undefined
|
|
275
|
+
) {
|
|
276
|
+
console.warn(
|
|
277
|
+
"Warning: this key type has no JWK form, so the public key was not embedded in the signature.",
|
|
278
|
+
);
|
|
279
|
+
}
|
|
250
280
|
} else {
|
|
251
281
|
if (!hasAnySignature(bomJson)) {
|
|
252
282
|
console.error(
|
package/bin/tracebom.js
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
safeWriteSync,
|
|
15
15
|
} from "../lib/ecosystems/utils.js";
|
|
16
16
|
import { DEFAULT_CDX_SPEC_VERSION } from "../lib/inventory/bomUtils.js";
|
|
17
|
+
import { applySpecVersionCompatibility } from "../lib/stages/postgen/specVersionCompat.js";
|
|
17
18
|
|
|
18
19
|
const _yargs = yargs(hideBin(process.argv));
|
|
19
20
|
|
|
@@ -166,7 +167,7 @@ const args = _yargs
|
|
|
166
167
|
})
|
|
167
168
|
.option("trace-crypto", {
|
|
168
169
|
description:
|
|
169
|
-
"
|
|
170
|
+
"Trace cryptographic libraries and TLS parameters: eBPF on Linux, crypto DLLs on Windows (elevated prompt), and TLS handshakes through --proxy-egress on every platform.",
|
|
170
171
|
default: true,
|
|
171
172
|
type: "boolean",
|
|
172
173
|
})
|
|
@@ -337,6 +338,9 @@ const options = {
|
|
|
337
338
|
console.error("Dynamic SBOM generation failed: no output was produced.");
|
|
338
339
|
process.exit(1);
|
|
339
340
|
}
|
|
341
|
+
// tracebom skips postProcess, so the downgrade to an older --spec-version
|
|
342
|
+
// (for example dropping the 1.7 algorithmFamily of traced crypto) runs here.
|
|
343
|
+
applySpecVersionCompatibility(bomJson, options);
|
|
340
344
|
|
|
341
345
|
const jsonPayload = JSON.stringify(bomJson, null, DEBUG_MODE ? 2 : null);
|
|
342
346
|
|