@cdxgen/cdxgen 13.2.0 → 13.3.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 +28 -12
- package/bin/cdxgen.js +227 -119
- package/bin/evinse.js +5 -0
- package/bin/sign.js +88 -14
- package/bin/tracebom.js +64 -4
- package/bin/validate.js +29 -7
- package/bin/verify.js +79 -39
- package/data/remediations.json +24 -0
- package/lib/cli/bomAssembly.js +105 -15
- package/lib/cli/cliOptions.js +93 -1
- package/lib/cli/index.js +43 -4
- package/lib/cli/jsBom.js +49 -24
- package/lib/cli/jvmBom.js +46 -12
- package/lib/cli/managedBom.js +112 -41
- package/lib/cli/nativeBom.js +125 -14
- package/lib/core/env.js +5 -6
- package/lib/core/fs.js +174 -6
- package/lib/core/metadataProperties.js +97 -0
- package/lib/core/projectConfig.js +31 -4
- package/lib/ecosystems/bunutils.js +269 -101
- package/lib/ecosystems/caxa.js +434 -2
- package/lib/ecosystems/cmakeResolver.js +66 -0
- package/lib/ecosystems/cppEvidence.js +64 -31
- package/lib/ecosystems/ecosystems.js +19 -8
- package/lib/ecosystems/gradleutils.js +42 -7
- package/lib/ecosystems/jsEvidence.js +19 -20
- package/lib/ecosystems/kosi.js +10 -3
- package/lib/ecosystems/npmutils.js +110 -9
- package/lib/ecosystems/parsers-dotnet.js +51 -10
- package/lib/ecosystems/parsers-go.js +47 -9
- package/lib/ecosystems/parsers-js.js +171 -50
- package/lib/ecosystems/parsers-misc.js +747 -161
- package/lib/ecosystems/parsers-python.js +26 -14
- package/lib/ecosystems/parsers-rust.js +24 -18
- package/lib/ecosystems/rubyutils.js +1426 -166
- package/lib/ecosystems/rusi.js +32 -1
- package/lib/evinser/evinser.js +436 -128
- package/lib/evinser/swiftsem.js +1914 -302
- package/lib/helpers/bomSigner.js +652 -221
- package/lib/inventory/atomUtils.js +568 -31
- package/lib/inventory/cdxrs.js +103 -12
- package/lib/inventory/depsUtils.js +183 -11
- package/lib/inventory/display.js +4 -5
- package/lib/inventory/dosai.js +550 -13
- package/lib/inventory/dynamic.js +39 -1
- package/lib/inventory/evidenceUtils.js +14 -6
- package/lib/inventory/fetchBatch.js +116 -17
- package/lib/inventory/protobom.js +8 -1
- package/lib/inventory/purl.js +152 -3
- package/lib/inventory/sbomDocument.js +2 -70
- package/lib/inventory/source.js +37 -19
- package/lib/inventory/traceRunner.js +210 -21
- package/lib/managers/binary.js +115 -24
- package/lib/managers/docker.js +440 -20
- package/lib/managers/oci.js +39 -1
- package/lib/parsers/cmakeLists.js +452 -0
- package/lib/parsers/largeJson.js +454 -0
- package/lib/parsers/npmrc.js +19 -1
- package/lib/stages/postgen/postgen.js +68 -15
- package/lib/validator/bomValidator.js +6 -16
- package/lib/validator/index.js +48 -10
- package/lib/validator/reporters/console.js +3 -0
- package/lib/validator/reporters/json.js +1 -0
- package/lib/validator/reporters/sarif.js +7 -0
- package/package.json +20 -20
- 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.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/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/metadataProperties.d.ts +39 -0
- package/types/lib/core/metadataProperties.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/ecosystems/bunutils.d.ts +12 -5
- package/types/lib/ecosystems/bunutils.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 +23 -0
- package/types/lib/ecosystems/cmakeResolver.d.ts.map +1 -1
- package/types/lib/ecosystems/cppEvidence.d.ts +1 -1
- package/types/lib/ecosystems/cppEvidence.d.ts.map +1 -1
- 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 +20 -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 +42 -0
- package/types/lib/ecosystems/npmutils.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-dotnet.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-go.d.ts +10 -0
- package/types/lib/ecosystems/parsers-go.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-js.d.ts +10 -4
- package/types/lib/ecosystems/parsers-js.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-misc.d.ts +67 -3
- package/types/lib/ecosystems/parsers-misc.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-python.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-rust.d.ts.map +1 -1
- package/types/lib/ecosystems/pythonutils.d.ts +1 -1
- package/types/lib/ecosystems/rubyutils.d.ts +143 -2
- 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/evinser/evinser.d.ts +59 -9
- 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 +106 -13
- package/types/lib/helpers/bomSigner.d.ts.map +1 -1
- package/types/lib/inventory/atomUtils.d.ts +145 -3
- package/types/lib/inventory/atomUtils.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/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 +64 -1
- package/types/lib/inventory/dosai.d.ts.map +1 -1
- package/types/lib/inventory/dynamic.d.ts.map +1 -1
- package/types/lib/inventory/evidenceUtils.d.ts.map +1 -1
- package/types/lib/inventory/fetchBatch.d.ts.map +1 -1
- 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/sbomDocument.d.ts.map +1 -1
- package/types/lib/inventory/source.d.ts.map +1 -1
- package/types/lib/inventory/traceRunner.d.ts +47 -1
- package/types/lib/inventory/traceRunner.d.ts.map +1 -1
- 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 +14 -0
- package/types/lib/managers/oci.d.ts.map +1 -1
- package/types/lib/parsers/cmakeLists.d.ts +76 -0
- package/types/lib/parsers/cmakeLists.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/stages/postgen/postgen.d.ts.map +1 -1
- package/types/lib/validator/bomValidator.d.ts.map +1 -1
- package/types/lib/validator/index.d.ts +10 -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/README.md
CHANGED
|
@@ -41,7 +41,7 @@ Supported output document formats:
|
|
|
41
41
|
| **Build engineers** | Grade how completely the SBOM captured the project, and get ranked fixes when the build environment degraded it | `cdxgen --profile introspect --introspect-fail-below 70 -o bom.json .` | [Build Introspection](docs/INTROSPECTION.md), [Fidelity loop skill](.agents/skills/sbom-fidelity-loop/SKILL.md) |
|
|
42
42
|
| **SOC analysts** | Build OBOM inventories for live hosts and triage runtime posture issues | `obom -o obom.json --deep --bom-audit --bom-audit-categories obom-runtime` | [OBOM lessons](docs/OBOM_LESSONS.md), [Server Usage][docs-server] |
|
|
43
43
|
| **Compliance teams** | Validate BOM quality, check SCVS/CRA posture, and export SPDX deliverables | `cdx-validate -i bom.json --benchmark scvs-l2,cra` | [cdx-validate](docs/CDX_VALIDATE.md), [cdx-convert](docs/CDX_CONVERT.md), [Permissions][docs-permissions] |
|
|
44
|
-
| **Security Teams** | Dynamically trace executions to capture cryptographic activities, CBOM properties, software components, and services | `tracebom --
|
|
44
|
+
| **Security Teams** | Dynamically trace executions to capture cryptographic activities, CBOM properties, software components, and services | `tracebom --cmd "npm test" --trace-crypto -o cbom.json` | [Threat Model](docs/THREAT_MODEL.md) |
|
|
45
45
|
|
|
46
46
|
### Role-based quick starts
|
|
47
47
|
|
|
@@ -216,7 +216,7 @@ Common asset names:
|
|
|
216
216
|
#### Linux
|
|
217
217
|
|
|
218
218
|
```bash
|
|
219
|
-
VERSION="v13.
|
|
219
|
+
VERSION="v13.3.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.3.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.3.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.3.0 \
|
|
273
273
|
--repo cdxgen/cdxgen \
|
|
274
274
|
--pattern 'cdx-audit-linux-amd64' \
|
|
275
275
|
--pattern 'cdx-audit-linux-amd64.sha256'
|
|
@@ -391,7 +391,7 @@ import { createBom, submitBom } from "npm:@cdxgen/cdxgen@^13";
|
|
|
391
391
|
| Generate a BOM from the current repository | `cdxgen -o bom.json .` | [CLI Usage][docs-cli] |
|
|
392
392
|
| Generate a BOM from a git URL | `cdxgen -o bom.json https://github.com/example/project.git` | [CLI Usage][docs-cli] |
|
|
393
393
|
| Generate a BOM from a package URL | `cdxgen -o bom.json "pkg:npm/lodash@4.17.21"` | [CLI Usage][docs-cli] |
|
|
394
|
-
| Generate a dynamically traced CBOM for an application | `tracebom --
|
|
394
|
+
| Generate a dynamically traced CBOM for an application | `tracebom --cmd "npm test" --trace-crypto -o cbom.json` | [Threat Model](docs/THREAT_MODEL.md) |
|
|
395
395
|
| Generate and audit an AI-BOM from the current repository | `cdxgen -r --include-formulation -o aibom.json --bom-audit --bom-audit-categories ai-bom .` | [AI-BOM Guide](docs/AI_BOM.md) |
|
|
396
396
|
| Scan a container image | `cdxgen ghcr.io/owasp-dep-scan/depscan:nightly -o bom.json -t docker` | [Server Usage][docs-server] |
|
|
397
397
|
| Audit a generated BOM for built-in supply-chain findings | `cdxgen -o bom.json --bom-audit .` | [BOM Audit](docs/BOM_AUDIT.md) |
|
|
@@ -683,6 +683,17 @@ systemctl --user start podman.socket
|
|
|
683
683
|
podman system service -t 0 &
|
|
684
684
|
```
|
|
685
685
|
|
|
686
|
+
### WSL Containers (wslc) on Windows
|
|
687
|
+
|
|
688
|
+
On Windows, Docker Desktop is optional when [WSL Containers][wsl-containers-docs] is available. cdxgen automatically uses the `wslc` CLI (included with WSL 2.9.3 or higher) to pull, inspect, and export images whenever the docker CLI is not installed, so image scans such as the below work with just WSL:
|
|
689
|
+
|
|
690
|
+
```shell
|
|
691
|
+
wsl --update
|
|
692
|
+
cdxgen alpine:latest -t oci -o bom.json
|
|
693
|
+
```
|
|
694
|
+
|
|
695
|
+
Set `DOCKER_CMD=wslc` to prefer wslc even when a docker CLI is installed. See [Generating container SBOM on Windows](./ADVANCED.md#generating-container-sbom-on-windows) for requirements, including the nested virtualization needed when Windows itself runs inside a VM.
|
|
696
|
+
|
|
686
697
|
## Generate OBOM for a live system
|
|
687
698
|
|
|
688
699
|
You can use the `obom` command to generate an OBOM for a live system or a VM for compliance and vulnerability management purposes. Linux, Windows, and macOS are supported in this mode, though some macOS tables require elevated privileges and Full Disk Access.
|
|
@@ -732,12 +743,16 @@ cdxgen features a best-in-class, native **JSON Signature Format (JSF)** implemen
|
|
|
732
743
|
|
|
733
744
|
To enable automatic signing during BOM generation, set the following environment variables:
|
|
734
745
|
|
|
735
|
-
- `SBOM_SIGN_ALGORITHM`: JSF Algorithm. Examples: `RS512`, `ES256`, `Ed25519`, `HS256
|
|
736
|
-
- `SBOM_SIGN_PRIVATE_KEY`: Location of the private key (PEM format)
|
|
737
|
-
- `SBOM_SIGN_PUBLIC_KEY`: Optional. Location of the public key
|
|
746
|
+
- `SBOM_SIGN_ALGORITHM`: JSF Algorithm. Examples: `RS512`, `ES256`, `Ed25519`, `HS256`. It must match the key type.
|
|
747
|
+
- `SBOM_SIGN_PRIVATE_KEY`: Location of the private key (PEM format), or of the shared secret for `HS256`, `HS384`, and `HS512`
|
|
748
|
+
- `SBOM_SIGN_PUBLIC_KEY`: Optional. Location of the public key to embed. It must belong to the private key.
|
|
738
749
|
- `SBOM_SIGN_MODE`: Optional. Signature mode (`replace`, `signers`, `chain`). Default is `replace`.
|
|
739
750
|
|
|
740
|
-
To quickly generate test
|
|
751
|
+
To quickly generate a test key pair for `SBOM_SIGN_ALGORITHM` and sign your first BOM, you can run cdxgen with the `--generate-key-and-sign` argument.
|
|
752
|
+
|
|
753
|
+
When signing is configured (`SBOM_SIGN_ALGORITHM` plus a private key), cdxgen signs the BOM it writes, prints, or submits to Dependency-Track, and exits with status 1 if it cannot sign it, including when the key file is missing. A private key without `SBOM_SIGN_ALGORITHM` leaves the BOM unsigned and prints a warning; set `SBOM_SIGN_ALGORITHM=none` to opt out explicitly.
|
|
754
|
+
|
|
755
|
+
BOMs signed with cdxgen 13.2.0 or earlier must be re-signed with the current `cdx-sign` before they verify. See [cdx-sign](docs/CDX_SIGN.md#re-signing-boms-from-earlier-releases).
|
|
741
756
|
|
|
742
757
|
### Advanced Signing with `cdx-sign`
|
|
743
758
|
|
|
@@ -785,7 +800,7 @@ pnpm dlx @cdxgen/cdxgen cdx-sign -i bom.json -k private.key
|
|
|
785
800
|
|
|
786
801
|
## Automatic usage detection
|
|
787
802
|
|
|
788
|
-
For node.js projects, lock files are parsed initially, so the SBOM would include all dependencies, including dev ones. An AST parser powered by babel-parser is then used to detect packages that are imported and used by non-test code. Such imported packages would automatically set their scope property to `required` in the resulting SBOM. You can turn off this analysis by passing the argument `--no-babel`. Scope property would then be set based on the `dev` attribute in the lock file.
|
|
803
|
+
For node.js projects, lock files are parsed initially, so the SBOM would include all dependencies, including dev ones. An AST parser powered by babel-parser is then used to detect packages that are imported and used by non-test code. Such imported packages would automatically set their scope property to `required` in the resulting SBOM. A package with no observed usage keeps the scope from the lock file, since packages loaded from configuration, bundler entrypoints, stylesheets, or plugins are invisible to import analysis. A package imported only for its TypeScript types is scoped `excluded`, and a package that only such packages depend on is scoped `optional`. You can turn off this analysis by passing the argument `--no-babel`. Scope property would then be set based on the `dev` attribute in the lock file.
|
|
789
804
|
|
|
790
805
|
Single-file component frameworks are handled natively by this analysis: `.vue` and `.svelte` templates are segmented position-preservingly so script imports recover with correct file and line evidence. For Svelte and SvelteKit, framework usage signals are additionally collected — SvelteKit virtual modules such as `$app/stores` are attributed to `@sveltejs/kit`, `$lib/*` imports resolve through `kit.alias`, `svelte.config.js` adapters and preprocessors, CSS preprocessor packages implied by `<style lang="...">` blocks together with their `@use`/`@import` package references, npm script executables such as `svelte-kit sync` and `svelte-check`, and rune usage (`$state`, `$derived`, ...) which marks `svelte` required even in components that never import it. This works in every installation; when the optional `@appthreat/atom-parsetools` package is present, template expressions also contribute usage occurrences.
|
|
791
806
|
|
|
@@ -793,7 +808,7 @@ This attribute can be later used for various purposes. For example, [dep-scan][d
|
|
|
793
808
|
|
|
794
809
|
With the argument `--required-only`, you can limit the SBOM only to include packages with the scope "required", commonly called production or non-dev dependencies. Combine with `--no-babel` to limit this list to only non-dev dependencies based on the `dev` attribute being false in the lock files.
|
|
795
810
|
|
|
796
|
-
For go, `go mod
|
|
811
|
+
For go, `go list -deps` lists the modules the project's packages import, and a module is scoped `required` when go.mod requires it directly and `optional` when the requirement is `// indirect`. With `USE_GOSUM=true`, `go mod why` scopes each go.sum module instead: `required` when the main module needs it, and `optional` when go reports that it does not. If `go mod why` fails, no module is scoped `optional`. For php, composer lock file is parsed to distinguish required (packages) from optional (packages-dev).
|
|
797
812
|
|
|
798
813
|
## Automatic services detection
|
|
799
814
|
|
|
@@ -981,4 +996,5 @@ Copy the below block to your markdown files to show your ❤️ for cdxgen.
|
|
|
981
996
|
[npmjs-cdxgen-v12]: https://www.npmjs.com/package/@cyclonedx/cdxgen
|
|
982
997
|
[podman-github-rootless]: https://github.com/containers/podman/blob/master/docs/tutorials/rootless_tutorial.md
|
|
983
998
|
[podman-github-remote]: https://github.com/containers/podman/blob/master/docs/tutorials/mac_win_client.md
|
|
999
|
+
[wsl-containers-docs]: https://learn.microsoft.com/en-us/windows/wsl/wsl-container
|
|
984
1000
|
[swh-cdxgen]: https://archive.softwareheritage.org/browse/origin/?origin_url=https://github.com/cdxgen/cdxgen
|
package/bin/cdxgen.js
CHANGED
|
@@ -72,7 +72,11 @@ import {
|
|
|
72
72
|
setDryRunMode,
|
|
73
73
|
shouldRunPredictiveBomAudit,
|
|
74
74
|
} from "../lib/ecosystems/utils.js";
|
|
75
|
-
import {
|
|
75
|
+
import {
|
|
76
|
+
generateSigningKeyPair,
|
|
77
|
+
signBom,
|
|
78
|
+
verifyBom,
|
|
79
|
+
} from "../lib/helpers/bomSigner.js";
|
|
76
80
|
import {
|
|
77
81
|
createOutputPlan,
|
|
78
82
|
getOutputDirectory,
|
|
@@ -81,7 +85,6 @@ import {
|
|
|
81
85
|
DEFAULT_CDX_SPEC_VERSION,
|
|
82
86
|
getSupportedCycloneDxComponentTypes,
|
|
83
87
|
isCycloneDxBom,
|
|
84
|
-
isCycloneDxComponentTypeEnabled,
|
|
85
88
|
normalizeCycloneDxComponentTypeFilter,
|
|
86
89
|
toCycloneDxSpecVersionString,
|
|
87
90
|
} from "../lib/inventory/bomUtils.js";
|
|
@@ -164,6 +167,11 @@ for (const configPattern of PROJECT_CONFIG_FILENAMES) {
|
|
|
164
167
|
`Config file '${configPath}' sets '${foundKey}'. Verify this is intentional.`,
|
|
165
168
|
);
|
|
166
169
|
}
|
|
170
|
+
for (const propertyName of sanitized.reservedProperties) {
|
|
171
|
+
console.warn(
|
|
172
|
+
`\x1b[1;35mConfig file '${configPath}' sets the metadata property '${propertyName}', whose namespace cdxgen reserves for its own findings. Ignoring it. Pass the property with --metadata-property if this is intentional.\x1b[0m`,
|
|
173
|
+
);
|
|
174
|
+
}
|
|
167
175
|
} catch (_e) {
|
|
168
176
|
console.log("Invalid config file", configPath);
|
|
169
177
|
}
|
|
@@ -252,6 +260,16 @@ const args = _yargs
|
|
|
252
260
|
description:
|
|
253
261
|
"Perform deep searches for components. Useful while scanning C/C++ apps, live OS and oci images.",
|
|
254
262
|
})
|
|
263
|
+
.option("cmake-cache", {
|
|
264
|
+
type: "string",
|
|
265
|
+
description:
|
|
266
|
+
"Path to the CMakeCache.txt of a configured C/C++ build. Overrides the lookup under build/, out/ and cmake-build-*/.",
|
|
267
|
+
})
|
|
268
|
+
.option("compile-commands", {
|
|
269
|
+
type: "string",
|
|
270
|
+
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/, out/, builddir/ and cmake-build-*/, which is skipped in secure mode.",
|
|
272
|
+
})
|
|
255
273
|
.option("git-branch", {
|
|
256
274
|
description: "Git branch to clone when the source is a git URL or purl",
|
|
257
275
|
type: "string",
|
|
@@ -399,7 +417,7 @@ const args = _yargs
|
|
|
399
417
|
.option("generate-key-and-sign", {
|
|
400
418
|
type: "boolean",
|
|
401
419
|
description:
|
|
402
|
-
"Generate
|
|
420
|
+
"Generate a public/private key pair for SBOM_SIGN_ALGORITHM (RS512 by default) and then sign the generated SBOM using the JSON Signature Format (JSF).",
|
|
403
421
|
})
|
|
404
422
|
.option("server", {
|
|
405
423
|
type: "boolean",
|
|
@@ -565,6 +583,11 @@ const args = _yargs
|
|
|
565
583
|
default: false,
|
|
566
584
|
description: "Disable default ignore lists during scanning.",
|
|
567
585
|
})
|
|
586
|
+
.option("caxa-app-dir", {
|
|
587
|
+
type: "string",
|
|
588
|
+
description:
|
|
589
|
+
"Directory of the app a caxa binary extracts. With -t caxa, also records the native tools, the vendored PHP, Ruby and Java packages, and the npm integrity hashes found there.",
|
|
590
|
+
})
|
|
568
591
|
.option("export-proto", {
|
|
569
592
|
type: "boolean",
|
|
570
593
|
default: false,
|
|
@@ -605,6 +628,12 @@ const args = _yargs
|
|
|
605
628
|
default: false,
|
|
606
629
|
description: "Synthesize custom LicenseRef IDs for unresolved licenses.",
|
|
607
630
|
})
|
|
631
|
+
.option("metadata-property", {
|
|
632
|
+
description:
|
|
633
|
+
"Custom property to add to the BOM metadata, as name=value. Repeat the flag for several properties. Combined with the properties of the CDXGEN_METADATA_PROPERTIES environment variable and of a config file.",
|
|
634
|
+
nargs: 1,
|
|
635
|
+
type: "array",
|
|
636
|
+
})
|
|
608
637
|
.option("standard", {
|
|
609
638
|
description:
|
|
610
639
|
"The list of standards which may consist of regulations, industry or organizational-specific standards, maturity models, best practices, or any other requirements which can be evaluated against or attested to.",
|
|
@@ -1047,6 +1076,7 @@ const { options, warnings: phase3Warnings } = buildOptionsFromArgs(args, {
|
|
|
1047
1076
|
userSetSpecVersion,
|
|
1048
1077
|
isDryRun,
|
|
1049
1078
|
isSecureMode,
|
|
1079
|
+
projectConfig: config,
|
|
1050
1080
|
});
|
|
1051
1081
|
// Exit status reserved for the introspection CI gate: the BOM was generated
|
|
1052
1082
|
// and written, but its introspection score missed the configured threshold.
|
|
@@ -1410,6 +1440,8 @@ const checkPermissions = (filePath, options) => {
|
|
|
1410
1440
|
return true;
|
|
1411
1441
|
};
|
|
1412
1442
|
|
|
1443
|
+
let warnedAboutSigningAlgorithm = false;
|
|
1444
|
+
|
|
1413
1445
|
const needsBomSigning = ({ generateKeyAndSign }) =>
|
|
1414
1446
|
generateKeyAndSign ||
|
|
1415
1447
|
(() => {
|
|
@@ -1427,11 +1459,19 @@ const needsBomSigning = ({ generateKeyAndSign }) =>
|
|
|
1427
1459
|
sensitive: true,
|
|
1428
1460
|
},
|
|
1429
1461
|
);
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1462
|
+
const keyConfigured = Boolean(
|
|
1463
|
+
sbomSignPrivateKey || sbomSignPrivateKeyBase64,
|
|
1464
|
+
);
|
|
1465
|
+
if (keyConfigured && !sbomSignAlgorithm && !warnedAboutSigningAlgorithm) {
|
|
1466
|
+
warnedAboutSigningAlgorithm = true;
|
|
1467
|
+
console.warn(
|
|
1468
|
+
"SBOM_SIGN_PRIVATE_KEY is set without SBOM_SIGN_ALGORITHM, so the BOM is not signed. Set SBOM_SIGN_ALGORITHM (for example RS512) to sign it, or SBOM_SIGN_ALGORITHM=none to silence this warning.",
|
|
1469
|
+
);
|
|
1470
|
+
}
|
|
1471
|
+
// A configured key file that is missing counts as a signing request, so
|
|
1472
|
+
// that signing fails loudly instead of being skipped.
|
|
1473
|
+
return Boolean(
|
|
1474
|
+
sbomSignAlgorithm && sbomSignAlgorithm !== "none" && keyConfigured,
|
|
1435
1475
|
);
|
|
1436
1476
|
})();
|
|
1437
1477
|
|
|
@@ -1440,28 +1480,20 @@ const stringifyJson = (jsonPayload, jsonPretty) =>
|
|
|
1440
1480
|
? jsonPayload
|
|
1441
1481
|
: JSON.stringify(jsonPayload, null, jsonPretty ? 2 : null);
|
|
1442
1482
|
|
|
1443
|
-
const
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
recordActivity({
|
|
1458
|
-
kind: "sign",
|
|
1459
|
-
reason: "Dry run mode skips BOM signing and key generation.",
|
|
1460
|
-
status: "blocked",
|
|
1461
|
-
target: jsonFile,
|
|
1462
|
-
});
|
|
1463
|
-
return jsonPayload;
|
|
1464
|
-
}
|
|
1483
|
+
const SIGNING_HINT =
|
|
1484
|
+
"Check that the private key is in PEM format and that SBOM_SIGN_ALGORITHM matches its key type.";
|
|
1485
|
+
|
|
1486
|
+
/**
|
|
1487
|
+
* Signs a CycloneDX payload with the configured or generated key.
|
|
1488
|
+
*
|
|
1489
|
+
* @param {string} jsonPayload Serialized CycloneDX BOM
|
|
1490
|
+
* @param {string|undefined} keyDir Directory for --generate-key-and-sign keys
|
|
1491
|
+
* @param {string} target Output the signed BOM is written to (for the activity log)
|
|
1492
|
+
* @param {Object} options CLI options
|
|
1493
|
+
* @returns {Object} Signed BOM
|
|
1494
|
+
* @throws {Error} When signing was requested but cannot be completed
|
|
1495
|
+
*/
|
|
1496
|
+
const signCycloneDxPayload = (jsonPayload, keyDir, target, options) => {
|
|
1465
1497
|
const sbomSignAlgorithm = readEnvironmentVariable("SBOM_SIGN_ALGORITHM");
|
|
1466
1498
|
const sbomSignPrivateKey = readEnvironmentVariable("SBOM_SIGN_PRIVATE_KEY", {
|
|
1467
1499
|
sensitive: true,
|
|
@@ -1476,29 +1508,20 @@ const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
|
|
|
1476
1508
|
const sbomSignPublicKeyBase64 = readEnvironmentVariable(
|
|
1477
1509
|
"SBOM_SIGN_PUBLIC_KEY_BASE64",
|
|
1478
1510
|
);
|
|
1479
|
-
|
|
1480
|
-
if (alg.includes("none")) {
|
|
1481
|
-
alg = "RS512";
|
|
1482
|
-
}
|
|
1511
|
+
const alg = sbomSignAlgorithm || "RS512";
|
|
1483
1512
|
let privateKeyToUse;
|
|
1484
1513
|
let jwkPublicKey;
|
|
1485
1514
|
let publicKeyFile;
|
|
1486
1515
|
if (options.generateKeyAndSign) {
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
},
|
|
1497
|
-
privateKeyEncoding: {
|
|
1498
|
-
type: "pkcs8",
|
|
1499
|
-
format: "pem",
|
|
1500
|
-
},
|
|
1501
|
-
});
|
|
1516
|
+
if (!keyDir) {
|
|
1517
|
+
throw new Error(
|
|
1518
|
+
"--generate-key-and-sign needs a file output (-o) to write the generated keys next to.",
|
|
1519
|
+
);
|
|
1520
|
+
}
|
|
1521
|
+
publicKeyFile = join(keyDir, "public.key");
|
|
1522
|
+
const privateKeyFile = join(keyDir, "private.key");
|
|
1523
|
+
const privateKeyB64File = join(keyDir, "private.key.base64");
|
|
1524
|
+
const { privateKey, publicKey } = generateSigningKeyPair(alg);
|
|
1502
1525
|
safeWriteSync(publicKeyFile, publicKey);
|
|
1503
1526
|
safeWriteSync(privateKeyFile, privateKey);
|
|
1504
1527
|
safeWriteSync(
|
|
@@ -1515,69 +1538,129 @@ const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
|
|
|
1515
1538
|
jwkPublicKey = crypto.createPublicKey(publicKey).export({ format: "jwk" });
|
|
1516
1539
|
} else {
|
|
1517
1540
|
if (sbomSignPrivateKey) {
|
|
1541
|
+
if (!safeExistsSync(sbomSignPrivateKey)) {
|
|
1542
|
+
throw new Error(
|
|
1543
|
+
`The SBOM_SIGN_PRIVATE_KEY file '${sbomSignPrivateKey}' was not found.`,
|
|
1544
|
+
);
|
|
1545
|
+
}
|
|
1518
1546
|
recordSensitiveFileRead(sbomSignPrivateKey, {
|
|
1519
1547
|
label: "SBOM signing private key",
|
|
1520
1548
|
});
|
|
1521
|
-
privateKeyToUse = fs.readFileSync(sbomSignPrivateKey
|
|
1549
|
+
privateKeyToUse = fs.readFileSync(sbomSignPrivateKey);
|
|
1522
1550
|
} else if (sbomSignPrivateKeyBase64) {
|
|
1523
|
-
privateKeyToUse = Buffer.from(
|
|
1524
|
-
sbomSignPrivateKeyBase64,
|
|
1525
|
-
"base64",
|
|
1526
|
-
).toString("utf8");
|
|
1551
|
+
privateKeyToUse = Buffer.from(sbomSignPrivateKeyBase64, "base64");
|
|
1527
1552
|
}
|
|
1528
1553
|
if (sbomSignPublicKey && safeExistsSync(sbomSignPublicKey)) {
|
|
1529
1554
|
jwkPublicKey = crypto
|
|
1530
1555
|
.createPublicKey(fs.readFileSync(sbomSignPublicKey, "utf8"))
|
|
1531
1556
|
.export({ format: "jwk" });
|
|
1532
1557
|
} else if (sbomSignPublicKeyBase64) {
|
|
1533
|
-
jwkPublicKey =
|
|
1534
|
-
"
|
|
1558
|
+
jwkPublicKey = crypto
|
|
1559
|
+
.createPublicKey(Buffer.from(sbomSignPublicKeyBase64, "base64"))
|
|
1560
|
+
.export({ format: "jwk" });
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
thoughtLog(`Signing the BOM for "${target}".`);
|
|
1564
|
+
const signedBom = signBom(JSON.parse(jsonPayload), {
|
|
1565
|
+
privateKey: privateKeyToUse,
|
|
1566
|
+
algorithm: alg,
|
|
1567
|
+
publicKeyJwk: jwkPublicKey,
|
|
1568
|
+
mode: readEnvironmentVariable("SBOM_SIGN_MODE") || "replace",
|
|
1569
|
+
signComponents: true,
|
|
1570
|
+
signServices: true,
|
|
1571
|
+
signAnnotations: true,
|
|
1572
|
+
});
|
|
1573
|
+
if (publicKeyFile) {
|
|
1574
|
+
if (!verifyBom(signedBom, fs.readFileSync(publicKeyFile, "utf8"))) {
|
|
1575
|
+
throw new Error(
|
|
1576
|
+
`The new signature does not verify with ${publicKeyFile}.`,
|
|
1535
1577
|
);
|
|
1536
1578
|
}
|
|
1579
|
+
console.log(
|
|
1580
|
+
"SBOM signature is verifiable natively with the public key and the algorithm",
|
|
1581
|
+
publicKeyFile,
|
|
1582
|
+
alg,
|
|
1583
|
+
);
|
|
1584
|
+
}
|
|
1585
|
+
recordActivity({
|
|
1586
|
+
kind: "sign",
|
|
1587
|
+
status: "completed",
|
|
1588
|
+
target,
|
|
1589
|
+
});
|
|
1590
|
+
return signedBom;
|
|
1591
|
+
};
|
|
1592
|
+
|
|
1593
|
+
/**
|
|
1594
|
+
* Signs the BOM for an output when signing is configured. A failure is
|
|
1595
|
+
* recorded and returned so that the caller can stop with a non-zero exit
|
|
1596
|
+
* instead of publishing an unsigned BOM.
|
|
1597
|
+
*
|
|
1598
|
+
* @returns {{ bomJson: Object, jsonPayload: string, signingError?: Error }}
|
|
1599
|
+
*/
|
|
1600
|
+
const signForOutput = (bomJson, jsonPayload, keyDir, target, options) => {
|
|
1601
|
+
if (!jsonPayload || !needsBomSigning(options)) {
|
|
1602
|
+
return { bomJson, jsonPayload };
|
|
1603
|
+
}
|
|
1604
|
+
if (isDryRun) {
|
|
1605
|
+
recordActivity({
|
|
1606
|
+
kind: "sign",
|
|
1607
|
+
reason: "Dry run mode skips BOM signing and key generation.",
|
|
1608
|
+
status: "blocked",
|
|
1609
|
+
target,
|
|
1610
|
+
});
|
|
1611
|
+
return { bomJson, jsonPayload };
|
|
1537
1612
|
}
|
|
1538
1613
|
try {
|
|
1539
|
-
const
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1614
|
+
const signedBom = signCycloneDxPayload(
|
|
1615
|
+
jsonPayload,
|
|
1616
|
+
keyDir,
|
|
1617
|
+
target,
|
|
1618
|
+
options,
|
|
1619
|
+
);
|
|
1620
|
+
return {
|
|
1621
|
+
bomJson: signedBom,
|
|
1622
|
+
jsonPayload: JSON.stringify(
|
|
1623
|
+
signedBom,
|
|
1624
|
+
null,
|
|
1625
|
+
options.jsonPretty ? 2 : null,
|
|
1626
|
+
),
|
|
1548
1627
|
};
|
|
1549
|
-
|
|
1628
|
+
} catch (err) {
|
|
1550
1629
|
recordActivity({
|
|
1551
1630
|
kind: "sign",
|
|
1552
|
-
|
|
1553
|
-
|
|
1631
|
+
reason: err.message,
|
|
1632
|
+
status: "failed",
|
|
1633
|
+
target,
|
|
1554
1634
|
});
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1635
|
+
return { bomJson, jsonPayload, signingError: err };
|
|
1636
|
+
}
|
|
1637
|
+
};
|
|
1638
|
+
|
|
1639
|
+
const reportSigningFailure = (signingError, target) => {
|
|
1640
|
+
console.error(`SBOM signing was unsuccessful: ${signingError.message}`);
|
|
1641
|
+
console.error(SIGNING_HINT);
|
|
1642
|
+
if (target !== "stdout") {
|
|
1643
|
+
console.error(`The BOM at '${target}' was written without a signature.`);
|
|
1644
|
+
}
|
|
1645
|
+
};
|
|
1646
|
+
|
|
1647
|
+
const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
|
|
1648
|
+
const result = signForOutput(
|
|
1649
|
+
bomJson,
|
|
1650
|
+
stringifyJson(bomJson, options.jsonPretty),
|
|
1651
|
+
dirname(jsonFile),
|
|
1652
|
+
jsonFile,
|
|
1653
|
+
options,
|
|
1654
|
+
);
|
|
1655
|
+
safeWriteSync(jsonFile, result.jsonPayload);
|
|
1656
|
+
if (jsonFile.endsWith("bom.json")) {
|
|
1657
|
+
thoughtLog(
|
|
1658
|
+
`Let's save the file to "${jsonFile}". Should I suggest the '.cdx.json' file extension for better semantics?`,
|
|
1578
1659
|
);
|
|
1660
|
+
} else {
|
|
1661
|
+
thoughtLog(`Let's save the file to "${jsonFile}".`);
|
|
1579
1662
|
}
|
|
1580
|
-
return
|
|
1663
|
+
return result;
|
|
1581
1664
|
};
|
|
1582
1665
|
|
|
1583
1666
|
/**
|
|
@@ -2055,27 +2138,11 @@ const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
|
|
|
2055
2138
|
});
|
|
2056
2139
|
const evinserModule = await import("../lib/evinser/evinser.js");
|
|
2057
2140
|
options.projectType = options.projectType || ["java"];
|
|
2058
|
-
const evinseOptions =
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
skipMavenCollector: false,
|
|
2064
|
-
force: false,
|
|
2065
|
-
withReachables: options.deep,
|
|
2066
|
-
usagesSlicesFile: options.usagesSlicesFile,
|
|
2067
|
-
dataFlowSlicesFile: options.dataFlowSlicesFile,
|
|
2068
|
-
reachablesSlicesFile: options.reachablesSlicesFile,
|
|
2069
|
-
semanticsSlicesFile: options.semanticsSlicesFile,
|
|
2070
|
-
openapiSpecFile: options.openapiSpecFile,
|
|
2071
|
-
componentType: options.componentType,
|
|
2072
|
-
includeCrypto:
|
|
2073
|
-
options.includeCrypto &&
|
|
2074
|
-
isCycloneDxComponentTypeEnabled("cryptographic-asset", options),
|
|
2075
|
-
specVersion: options.specVersion,
|
|
2076
|
-
profile: options.profile,
|
|
2077
|
-
jsonPretty: options.jsonPretty,
|
|
2078
|
-
};
|
|
2141
|
+
const evinseOptions = evinserModule.buildEvinseOptions(
|
|
2142
|
+
options,
|
|
2143
|
+
args,
|
|
2144
|
+
internalCycloneDxInputPath || options.output,
|
|
2145
|
+
);
|
|
2079
2146
|
const dbObjMap = await evinserModule.prepareDB(evinseOptions);
|
|
2080
2147
|
if (dbObjMap) {
|
|
2081
2148
|
const sliceArtefacts = await evinserModule.analyzeProject(
|
|
@@ -2164,10 +2231,27 @@ const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
|
|
|
2164
2231
|
}
|
|
2165
2232
|
if (outputIsStdout) {
|
|
2166
2233
|
if (!isDryRun && bomNSData.bomJson) {
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2234
|
+
let payload;
|
|
2235
|
+
if (outputPlan.formats.has("spdx") && bomNSData.spdxJson) {
|
|
2236
|
+
payload = stringifyJson(bomNSData.spdxJson, options.jsonPretty);
|
|
2237
|
+
} else {
|
|
2238
|
+
const result = signForOutput(
|
|
2239
|
+
bomNSData.bomJson,
|
|
2240
|
+
stringifyJson(bomNSData.bomJson, options.jsonPretty),
|
|
2241
|
+
undefined,
|
|
2242
|
+
"stdout",
|
|
2243
|
+
options,
|
|
2244
|
+
);
|
|
2245
|
+
if (result.signingError) {
|
|
2246
|
+
reportSigningFailure(result.signingError, "stdout");
|
|
2247
|
+
if (cleanup) {
|
|
2248
|
+
cleanupSourceDir(srcDir);
|
|
2249
|
+
}
|
|
2250
|
+
process.exit(1);
|
|
2251
|
+
}
|
|
2252
|
+
bomNSData.bomJson = result.bomJson;
|
|
2253
|
+
payload = result.jsonPayload;
|
|
2254
|
+
}
|
|
2171
2255
|
process.stdout.write(payload);
|
|
2172
2256
|
} else if (isDryRun) {
|
|
2173
2257
|
recordActivity({
|
|
@@ -2182,11 +2266,20 @@ const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
|
|
|
2182
2266
|
(typeof options.output === "string" || options.output instanceof String)
|
|
2183
2267
|
) {
|
|
2184
2268
|
if (!isDryRun && outputPlan.outputs.cyclonedx && bomNSData.bomJson) {
|
|
2185
|
-
writeCycloneDxOutput(
|
|
2269
|
+
const result = writeCycloneDxOutput(
|
|
2186
2270
|
outputPlan.outputs.cyclonedx,
|
|
2187
2271
|
bomNSData.bomJson,
|
|
2188
2272
|
options,
|
|
2189
2273
|
);
|
|
2274
|
+
if (result.signingError) {
|
|
2275
|
+
reportSigningFailure(result.signingError, outputPlan.outputs.cyclonedx);
|
|
2276
|
+
if (cleanup) {
|
|
2277
|
+
cleanupSourceDir(srcDir);
|
|
2278
|
+
}
|
|
2279
|
+
process.exit(1);
|
|
2280
|
+
}
|
|
2281
|
+
// Later consumers, such as the Dependency-Track upload, get the signed BOM.
|
|
2282
|
+
bomNSData.bomJson = result.bomJson;
|
|
2190
2283
|
if (bomNSData.nsMapping && Object.keys(bomNSData.nsMapping).length) {
|
|
2191
2284
|
const nsFile = `${outputPlan.outputs.cyclonedx}.map`;
|
|
2192
2285
|
safeWriteSync(nsFile, JSON.stringify(bomNSData.nsMapping));
|
|
@@ -2217,7 +2310,22 @@ const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
|
|
|
2217
2310
|
if (outputPlan.formats.has("spdx") && bomNSData?.spdxJson) {
|
|
2218
2311
|
console.log(stringifyJson(bomNSData.spdxJson, options.jsonPretty));
|
|
2219
2312
|
} else if (bomNSData.bomJson) {
|
|
2220
|
-
|
|
2313
|
+
const result = signForOutput(
|
|
2314
|
+
bomNSData.bomJson,
|
|
2315
|
+
stringifyJson(bomNSData.bomJson, options.jsonPretty),
|
|
2316
|
+
undefined,
|
|
2317
|
+
"stdout",
|
|
2318
|
+
options,
|
|
2319
|
+
);
|
|
2320
|
+
if (result.signingError) {
|
|
2321
|
+
reportSigningFailure(result.signingError, "stdout");
|
|
2322
|
+
if (cleanup) {
|
|
2323
|
+
cleanupSourceDir(srcDir);
|
|
2324
|
+
}
|
|
2325
|
+
process.exit(1);
|
|
2326
|
+
}
|
|
2327
|
+
bomNSData.bomJson = result.bomJson;
|
|
2328
|
+
console.log(result.jsonPayload);
|
|
2221
2329
|
} else {
|
|
2222
2330
|
console.log("Unable to produce BOM for", filePath);
|
|
2223
2331
|
console.log("Try running the command with -t <type> or -r argument");
|
package/bin/evinse.js
CHANGED
|
@@ -89,6 +89,11 @@ const args = yargs(hideBin(process.argv))
|
|
|
89
89
|
default: false,
|
|
90
90
|
type: "boolean",
|
|
91
91
|
})
|
|
92
|
+
.option("compile-commands", {
|
|
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/, out/, builddir/ and cmake-build-*/, which is skipped in secure mode.",
|
|
95
|
+
type: "string",
|
|
96
|
+
})
|
|
92
97
|
.option("golem-command", {
|
|
93
98
|
description: "Use a specific golem binary for Go Evinse analysis.",
|
|
94
99
|
default: readEnvironmentVariable("GOLEM_CMD"),
|