@cyclonedx/cdxgen 10.5.0 → 10.5.2
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 +86 -127
- package/bin/cdxgen.js +4 -2
- package/bin/evinse.js +2 -1
- package/bin/repl.js +38 -23
- package/bin/verify.js +2 -1
- package/binary.js +41 -7
- package/data/spdx.schema.json +117 -1
- package/display.js +28 -0
- package/docker.js +35 -7
- package/index.js +330 -103
- package/package.json +21 -12
- package/types/analyzer.d.ts +4 -7
- package/types/binary.d.ts +8 -12
- package/types/binary.d.ts.map +1 -1
- package/types/cbomutils.d.ts +1 -1
- package/types/db.d.ts +9 -22
- package/types/display.d.ts +2 -1
- package/types/display.d.ts.map +1 -1
- package/types/docker.d.ts +33 -52
- package/types/docker.d.ts.map +1 -1
- package/types/envcontext.d.ts +40 -40
- package/types/evinser.d.ts +717 -3436
- package/types/index.d.ts +48 -67
- package/types/index.d.ts.map +1 -1
- package/types/jest.config.d.ts +2 -2
- package/types/piptree.d.ts +2 -6
- package/types/postgen.d.ts +1 -1
- package/types/protobom.d.ts +2 -6
- package/types/server.d.ts +1 -1
- package/types/utils.d.ts +344 -510
- package/types/utils.d.ts.map +1 -1
- package/types/validator.d.ts +1 -1
- package/utils.js +382 -41
- package/utils.test.js +207 -18
package/README.md
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
[![JSR]
|
|
1
|
+
[![JSR][badge-jsr]][jsr-cdxgen]
|
|
2
|
+
[![NPM][badge-npm]][npmjs-cdxgen]
|
|
3
|
+
[![GitHub Releases][badge-github-releases]][github-releases]
|
|
4
|
+
[![NPM Downloads][badge-npm-downloads]][npmjs-cdxgen]
|
|
5
|
+
[![GitHub License][badge-github-license]][github-license]
|
|
6
|
+
[![GitHub Contributors][badge-github-contributors]][github-contributors]
|
|
7
|
+
[![SWH][badge-swh]][swh-cdxgen]
|
|
2
8
|
|
|
3
|
-
|
|
9
|
+
# CycloneDX Generator (cdxgen)
|
|
4
10
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-

|
|
11
|
+

|
|
8
12
|
|
|
9
13
|
cdxgen is a CLI tool, library, [REPL](./ADVANCED.md), and server to create a valid and compliant [CycloneDX][cyclonedx-homepage] Bill of Materials (BOM) containing an aggregate of all project dependencies for C/C++, Node.js, PHP, Python, Ruby, Rust, Java, .Net, Dart, Haskell, Elixir, and Go projects in JSON format. CycloneDX is a full-stack BOM specification that is easily created, human and machine-readable, and simple to parse. The tool supports CycloneDX specification versions from 1.4 - 1.6.
|
|
10
14
|
|
|
@@ -17,70 +21,28 @@ When used with plugins:
|
|
|
17
21
|
|
|
18
22
|
Most SBOM tools are like simple barcode scanners. For easy applications, they can parse a few package manifests and create a list of components only based on these files without any deep inspection. Further, a typical application might have several repos, components, and libraries with complex build requirements. Traditional techniques to generate an SBOM per language or package manifest either do not work in enterprise environments or don't provide the confidence required for both compliance and automated analysis. So we built cdxgen - the universal polyglot SBOM generator that is user-friendly, precise, and comprehensive!
|
|
19
23
|
|
|
20
|
-
<img src="./docs/why-cdxgen.jpg" alt="why cdxgen" width="256">
|
|
21
|
-
|
|
22
|
-
##
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
| Haskell | cabal.project.freeze | Yes | |
|
|
37
|
-
| Elixir | mix.lock | Yes | |
|
|
38
|
-
| C/C++/Objective C/C++11 | conan.lock, conanfile.txt, \*.cmake, CMakeLists.txt, meson.build, codebase without package managers! | Yes only for conan.lock. Best effort basis for cmake without version numbers. | Yes |
|
|
39
|
-
| Clojure | Clojure CLI (deps.edn), Leiningen (project.clj) | Yes unless the files are parsed manually due to lack of clojure cli or leiningen command | |
|
|
40
|
-
| Swift | Package.resolved, Package.swift (swiftpm) | Yes | |
|
|
41
|
-
| Docker / oci image | All supported languages. Linux OS packages with plugins [4] | Best effort based on lock files | Yes |
|
|
42
|
-
| GitHub Actions | .github/workflows/\*.yml | N/A | Yes |
|
|
43
|
-
| Linux | All supported languages. Linux OS packages with plugins [5] | Best effort based on lock files | Yes |
|
|
44
|
-
| Windows | All supported languages. OS packages with best effort [5] | Best effort based on lock files | Yes |
|
|
45
|
-
| Jenkins Plugins | .hpi files | | Yes |
|
|
46
|
-
| Helm Charts | .yaml | N/A | |
|
|
47
|
-
| Skaffold | .yaml | N/A | |
|
|
48
|
-
| kustomization | .yaml | N/A | |
|
|
49
|
-
| Tekton tasks | .yaml | N/A | |
|
|
50
|
-
| Kubernetes | .yaml | N/A | |
|
|
51
|
-
| Maven Cache | $HOME/.m2/repository/\*\*/\*.jar | N/A | |
|
|
52
|
-
| SBT Cache | $HOME/.ivy2/cache/\*\*/\*.jar | N/A | |
|
|
53
|
-
| Gradle Cache | $HOME/caches/modules-2/files-2.1/\*\*/\*.jar | N/A | |
|
|
54
|
-
| Helm Index | $HOME/.cache/helm/repository/\*\*/\*.yaml | N/A | |
|
|
55
|
-
| Docker compose | docker-compose\*.yml. Images would also be scanned. | N/A | |
|
|
56
|
-
| Dockerfile | `*Dockerfile*` Images would also be scanned. | N/A | |
|
|
57
|
-
| Containerfile | `*Containerfile*`. Images would also be scanned. | N/A | |
|
|
58
|
-
| Bitbucket Pipelines | `bitbucket-pipelines.yml` images and pipes would also be scanned. | N/A | |
|
|
59
|
-
| Google CloudBuild configuration | cloudbuild.yaml | N/A | |
|
|
60
|
-
| OpenAPI | openapi\*.json, openapi\*.yaml | N/A | |
|
|
61
|
-
|
|
62
|
-
NOTE:
|
|
63
|
-
|
|
64
|
-
- Apache maven 3.x is required for parsing pom.xml
|
|
65
|
-
- gradle or gradlew is required to parse gradle projects
|
|
66
|
-
- sbt is required for parsing scala sbt projects. Only scala 2.10 + sbt 0.13.6+ and 2.12 + sbt 1.0+ are currently supported.
|
|
67
|
-
- Alternatively, create a lock file using sbt-dependency-lock [plugin](https://github.com/stringbean/sbt-dependency-lock)
|
|
68
|
-
|
|
69
|
-
Footnotes:
|
|
70
|
-
|
|
71
|
-
- [1] - For multi-module applications, the BOM file could include components not included in the packaged war or ear file.
|
|
72
|
-
- [2] - Pip freeze is automatically performed to improve precision. Requires virtual environment.
|
|
73
|
-
- [3] - Perform dotnet or nuget restore to generate project.assets.json. Without this file, cdxgen would not include indirect dependencies.
|
|
74
|
-
- [4] - See the section on plugins
|
|
75
|
-
- [5] - Powered by osquery. See the section on plugins
|
|
76
|
-
|
|
77
|
-
<img src="./docs/cdxgen-tree.jpg" alt="cdxgen tree" width="256">
|
|
24
|
+
<img src="./docs/_media/why-cdxgen.jpg" alt="why cdxgen" width="256">
|
|
25
|
+
|
|
26
|
+
## Documentation
|
|
27
|
+
|
|
28
|
+
Please visit our [documentation site][docs-homepage] for detailed usage, tutorials and support documentation.
|
|
29
|
+
|
|
30
|
+
Sections include:
|
|
31
|
+
- [Getting Started][docs-homepage]
|
|
32
|
+
- [CLI Usage][docs-cli]
|
|
33
|
+
- [Server Usage][docs-server]
|
|
34
|
+
- [Supported Project Types][docs-project-types]
|
|
35
|
+
- [Environment Variables][docs-env-vars]
|
|
36
|
+
- [Advanced Usage][docs-advanced-usage]
|
|
37
|
+
- [Permissions][docs-permissions]
|
|
38
|
+
- [Support (Enterprise & Community)][docs-support]
|
|
39
|
+
|
|
78
40
|
|
|
79
41
|
### Automatic usage detection
|
|
80
42
|
|
|
81
43
|
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.
|
|
82
44
|
|
|
83
|
-
This attribute can be later used for various purposes. For example, [dep-scan]
|
|
45
|
+
This attribute can be later used for various purposes. For example, [dep-scan][depscan-github] uses this attribute to prioritize vulnerabilities. Unfortunately, tools such as dependency track, do not include this feature and might over-report the CVEs.
|
|
84
46
|
|
|
85
47
|
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.
|
|
86
48
|
|
|
@@ -94,7 +56,7 @@ For go, `go mod why` command is used to identify required packages. For php, com
|
|
|
94
56
|
npm install -g @cyclonedx/cdxgen
|
|
95
57
|
```
|
|
96
58
|
|
|
97
|
-
If you are a [Homebrew]
|
|
59
|
+
If you are a [Homebrew][homebrew-homepage] user, you can also install [cdxgen][homebrew-cdxgen] via:
|
|
98
60
|
|
|
99
61
|
```shell
|
|
100
62
|
$ brew install cdxgen
|
|
@@ -103,7 +65,7 @@ $ brew install cdxgen
|
|
|
103
65
|
Deno and bun runtime can be used with limited support.
|
|
104
66
|
|
|
105
67
|
```shell
|
|
106
|
-
deno install --allow-read --allow-env --allow-run --allow-sys=uid,systemMemoryInfo,gid --allow-write --allow-net -n cdxgen "npm:@cyclonedx/cdxgen/cdxgen"
|
|
68
|
+
deno install --allow-read --allow-env --allow-run --allow-sys=uid,systemMemoryInfo,gid,homedir --allow-write --allow-net -n cdxgen "npm:@cyclonedx/cdxgen/cdxgen"
|
|
107
69
|
```
|
|
108
70
|
|
|
109
71
|
You can also use the cdxgen container image with node, deno, or bun runtime versions.
|
|
@@ -139,7 +101,9 @@ $ cdxgen -h
|
|
|
139
101
|
Options:
|
|
140
102
|
-o, --output Output file. Default bom.json
|
|
141
103
|
[default: "bom.json"]
|
|
142
|
-
-t, --type Project type
|
|
104
|
+
-t, --type Project type. Please refer to https://cyclonedx.g
|
|
105
|
+
ithub.io/cdxgen/#/PROJECT_TYPES for supported lan
|
|
106
|
+
guages/platforms.
|
|
143
107
|
-r, --recurse Recurse mode suitable for mono-repos. Defaults to
|
|
144
108
|
true. Pass --no-recurse to disable.
|
|
145
109
|
[boolean] [default: true]
|
|
@@ -290,7 +254,7 @@ Arguments can be passed either via the query string or as a JSON body. The follo
|
|
|
290
254
|
|
|
291
255
|
| Argument | Description |
|
|
292
256
|
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
293
|
-
| type | Project type
|
|
257
|
+
| type | Project type. Please refer to [Supported Project Types][docs-project-types]. |
|
|
294
258
|
| multiProject | [boolean] |
|
|
295
259
|
| requiredOnly | Include only the packages with required scope on the SBOM. [boolean] |
|
|
296
260
|
| noBabel | Do not use babel to perform usage analysis for JavaScript/TypeScript projects. [boolean] |
|
|
@@ -361,7 +325,7 @@ This would create a bom.json.map file with the jar - class name mapping. Refer t
|
|
|
361
325
|
|
|
362
326
|
## Resolving licenses
|
|
363
327
|
|
|
364
|
-
cdxgen can automatically query public registries such as maven, npm, or nuget to resolve the package licenses. This is a time-consuming operation and is disabled by default. To enable, set the environment variable `FETCH_LICENSE` to `true`, as shown. Ensure that `GITHUB_TOKEN` is set or provided by [built-in GITHUB_TOKEN in GitHub Actions]
|
|
328
|
+
cdxgen can automatically query public registries such as maven, npm, or nuget to resolve the package licenses. This is a time-consuming operation and is disabled by default. To enable, set the environment variable `FETCH_LICENSE` to `true`, as shown. Ensure that `GITHUB_TOKEN` is set or provided by [built-in GITHUB_TOKEN in GitHub Actions][github-rate-limit], otherwise rate limiting might prevent license resolving.
|
|
365
329
|
|
|
366
330
|
```bash
|
|
367
331
|
export FETCH_LICENSE=true
|
|
@@ -384,47 +348,6 @@ cdxgen can retain the dependency tree under the `dependencies` attribute for a s
|
|
|
384
348
|
- Ruby (Gemfile.lock)
|
|
385
349
|
- Rust (Cargo.lock)
|
|
386
350
|
|
|
387
|
-
## Environment variables
|
|
388
|
-
|
|
389
|
-
| Variable | Description |
|
|
390
|
-
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
|
391
|
-
| CDXGEN_DEBUG_MODE | Set to `debug` to enable debug messages |
|
|
392
|
-
| GITHUB_TOKEN | Specify GitHub token to prevent traffic shaping while querying license and repo information |
|
|
393
|
-
| MVN_CMD | Set to override maven command |
|
|
394
|
-
| MVN_ARGS | Set to pass additional arguments such as profile or settings to maven |
|
|
395
|
-
| MAVEN_HOME | Specify maven home |
|
|
396
|
-
| MAVEN_CENTRAL_URL | Specify URL of Maven Central for metadata fetching (e.g. when private repo is used) |
|
|
397
|
-
| ANDROID_MAVEN_URL | Specify URL of Android Maven Repository for metadata fetching (e.g. when private repo is used) |
|
|
398
|
-
| BAZEL_TARGET | Bazel target to build. Default :all (Eg: //java-maven) |
|
|
399
|
-
| BAZEL_STRIP_MAVEN_PREFIX | Strip Maven group prefix (e.g. useful when private repo is used, defaults to `/maven2/`) |
|
|
400
|
-
| BAZEL_USE_ACTION_GRAPH | SBOM for specific Bazel target, uses `bazel aquery 'outputs(".*.jar", deps(<BAZEL_TARGET>))'` (defaults to `false`) |
|
|
401
|
-
| GRADLE_CACHE_DIR | Specify gradle cache directory. Useful for class name resolving |
|
|
402
|
-
| GRADLE_MULTI_PROJECT_MODE | Unused. Automatically handled |
|
|
403
|
-
| GRADLE_ARGS | Set to pass additional arguments such as profile or settings to gradle (all tasks). Eg: --configuration runtimeClassPath |
|
|
404
|
-
| GRADLE_ARGS_PROPERTIES | Set to pass additional arguments only to the `gradle properties` task, used for collecting metadata about the project |
|
|
405
|
-
| GRADLE_ARGS_DEPENDENCIES | Set to pass additional arguments only to the `gradle dependencies` task, used for listing actual project dependencies |
|
|
406
|
-
| GRADLE_HOME | Specify gradle home |
|
|
407
|
-
| GRADLE_CMD | Set to override gradle command |
|
|
408
|
-
| GRADLE_DEPENDENCY_TASK | By default cdxgen use the task "dependencies" to collect packages. Set to override the task name. |
|
|
409
|
-
| SBT_CACHE_DIR | Specify sbt cache directory. Useful for class name resolving |
|
|
410
|
-
| FETCH_LICENSE | Set this variable to `true` or `1` to fetch license information from the registry. npm and golang |
|
|
411
|
-
| SEARCH_MAVEN_ORG | If maven metadata is missing in jar file, a search is performed on search.maven.org. Set to `false` or `0` to disable search. |
|
|
412
|
-
| USE_GOSUM | Set to `true` or `1` to generate BOMs for golang projects using go.sum as the dependency source of truth, instead of go.mod |
|
|
413
|
-
| CDXGEN_TIMEOUT_MS | Default timeout for known execution involving maven, gradle or sbt |
|
|
414
|
-
| CDXGEN_SERVER_TIMEOUT_MS | Default timeout in server mode |
|
|
415
|
-
| CDXGEN_MAX_BUFFER | Max buffer for stdout and stderr. Defaults to 100MB |
|
|
416
|
-
| CLJ_CMD | Set to override the clojure cli command |
|
|
417
|
-
| LEIN_CMD | Set to override the leiningen command |
|
|
418
|
-
| SBOM_SIGN_ALGORITHM | Signature algorithm. Some valid values are RS256, RS384, RS512, PS256, PS384, PS512, ES256 etc |
|
|
419
|
-
| SBOM_SIGN_PRIVATE_KEY | Private key to use for signing |
|
|
420
|
-
| SBOM_SIGN_PUBLIC_KEY | Optional. Public key to include in the SBOM signature |
|
|
421
|
-
| CDX_MAVEN_PLUGIN | CycloneDX Maven plugin to use. Default "org.cyclonedx:cyclonedx-maven-plugin:2.7.11" |
|
|
422
|
-
| CDX_MAVEN_GOAL | CycloneDX Maven plugin goal to use. Default makeAggregateBom. Other options: makeBom, makePackageBom |
|
|
423
|
-
| CDX_MAVEN_INCLUDE_TEST_SCOPE | Whether test scoped dependencies should be included from Maven projects, Default: true |
|
|
424
|
-
| ASTGEN_IGNORE_DIRS | Comma separated list of directories to ignore while analyzing using babel. The environment variable is also used by atom and astgen. |
|
|
425
|
-
| ASTGEN_IGNORE_FILE_PATTERN | Ignore regex to use |
|
|
426
|
-
| PYPI_URL | Override pypi url. Default: https://pypi.org/pypi/ |
|
|
427
|
-
|
|
428
351
|
## Plugins
|
|
429
352
|
|
|
430
353
|
cdxgen could be extended with external binary plugins to support more SBOM use cases. These are now installed as an optional dependency.
|
|
@@ -458,7 +381,7 @@ cdxgen /tmp/slim.tar -o /tmp/bom.json -t docker
|
|
|
458
381
|
|
|
459
382
|
### Podman in rootless mode
|
|
460
383
|
|
|
461
|
-
Setup podman in either [rootless]
|
|
384
|
+
Setup podman in either [rootless][podman-github-rootless] or [remote][podman-github-remote] mode
|
|
462
385
|
|
|
463
386
|
Do not forget to start the podman socket required for API access on Linux.
|
|
464
387
|
|
|
@@ -478,7 +401,7 @@ obom
|
|
|
478
401
|
# cdxgen -t os
|
|
479
402
|
```
|
|
480
403
|
|
|
481
|
-
This feature is powered by osquery, which is [installed](https://github.com/cyclonedx/cdxgen-plugins-bin/blob/main/build.sh#L8) along with the binary plugins. cdxgen would opportunistically try to detect as many components, apps, and extensions as possible using the [default queries](queries.json). The process would take several minutes and result in an SBOM file with thousands of components of various types, such as operating-system, device-drivers, files, and data.
|
|
404
|
+
This feature is powered by osquery, which is [installed](https://github.com/cyclonedx/cdxgen-plugins-bin/blob/main/build.sh#L8) along with the binary plugins. cdxgen would opportunistically try to detect as many components, apps, and extensions as possible using the [default queries](data/queries.json). The process would take several minutes and result in an SBOM file with thousands of components of various types, such as operating-system, device-drivers, files, and data.
|
|
482
405
|
|
|
483
406
|
## Generate Cryptography Bill of Materials (CBOM)
|
|
484
407
|
|
|
@@ -501,9 +424,9 @@ cdxgen can sign the generated BOM json file to increase authenticity and non-rep
|
|
|
501
424
|
- SBOM_SIGN_PRIVATE_KEY: Location to the RSA private key
|
|
502
425
|
- SBOM_SIGN_PUBLIC_KEY: Optional. Location to the RSA public key
|
|
503
426
|
|
|
504
|
-
To generate test public/private key pairs, you can run cdxgen by passing the argument `--generate-key-and-sign`. The generated json file would have an attribute called `signature`, which could be used for validation. [jwt.io]
|
|
427
|
+
To generate test public/private key pairs, you can run cdxgen by passing the argument `--generate-key-and-sign`. The generated json file would have an attribute called `signature`, which could be used for validation. [jwt.io][jwt-homepage] is a known site that could be used for such signature validation.
|
|
505
428
|
|
|
506
|
-

|
|
429
|
+

|
|
507
430
|
|
|
508
431
|
### Verifying the signature
|
|
509
432
|
|
|
@@ -516,7 +439,7 @@ cdx-verify -i bom.json --public-key public.key
|
|
|
516
439
|
|
|
517
440
|
### Custom verification tool (Node.js example)
|
|
518
441
|
|
|
519
|
-
There are many [libraries]
|
|
442
|
+
There are many [libraries][jwt-libraries] available to validate JSON Web Tokens. Below is a javascript example.
|
|
520
443
|
|
|
521
444
|
```js
|
|
522
445
|
# npm install jws
|
|
@@ -543,14 +466,13 @@ cdxgen can automatically detect names of services from YAML manifests such as do
|
|
|
543
466
|
|
|
544
467
|
## Conversion to SPDX format
|
|
545
468
|
|
|
546
|
-
Use the [CycloneDX CLI]
|
|
469
|
+
Use the [CycloneDX CLI][cyclonedx-cli-github] tool for advanced use cases such as conversion, diff and merging.
|
|
547
470
|
|
|
548
471
|
## License
|
|
549
472
|
|
|
550
|
-
Permission to modify and redistribute is granted under the terms of the Apache 2.0 license. See the [LICENSE]
|
|
473
|
+
Permission to modify and redistribute is granted under the terms of the Apache 2.0 license. See the [LICENSE][github-license] file for the full license.
|
|
474
|
+
|
|
551
475
|
|
|
552
|
-
[license]: https://github.com/cyclonedx/cdxgen/blob/master/LICENSE
|
|
553
|
-
[cyclonedx-homepage]: https://cyclonedx.org
|
|
554
476
|
|
|
555
477
|
## Integration as library
|
|
556
478
|
|
|
@@ -572,13 +494,12 @@ const bomNSData = await createBom(filePath, options);
|
|
|
572
494
|
const dbody = await submitBom(args, bomNSData.bomJson);
|
|
573
495
|
```
|
|
574
496
|
|
|
575
|
-
##
|
|
497
|
+
## Contributing
|
|
576
498
|
|
|
577
|
-
|
|
499
|
+
Please check out our [contribute to CycloneDX/cdxgen documentation][github-contribute] if you are interested in helping.
|
|
578
500
|
|
|
579
|
-
## Contributing
|
|
580
501
|
|
|
581
|
-
|
|
502
|
+
Before raising a PR, please run the following commands.
|
|
582
503
|
|
|
583
504
|
```bash
|
|
584
505
|
# Generate types using jsdoc syntax
|
|
@@ -589,8 +510,46 @@ npm run lint
|
|
|
589
510
|
npm test
|
|
590
511
|
```
|
|
591
512
|
|
|
592
|
-
If you are completely new to contributing to open-source projects, then look for [issues](https://github.com/CycloneDX/cdxgen/issues) with the labels "good first issue" or "help wanted".
|
|
593
|
-
|
|
594
|
-
## Enterprise support
|
|
595
513
|
|
|
596
|
-
|
|
514
|
+
<!-- LINK LABELS -->
|
|
515
|
+
<!-- Badges -->
|
|
516
|
+
[badge-github-contributors]: https://img.shields.io/github/contributors/cyclonedx/cdxgen
|
|
517
|
+
[badge-github-license]: https://img.shields.io/github/license/cyclonedx/cdxgen
|
|
518
|
+
[badge-github-releases]: https://img.shields.io/github/v/release/cyclonedx/cdxgen
|
|
519
|
+
[badge-jsr]: https://img.shields.io/jsr/v/%40cyclonedx/cdxgen
|
|
520
|
+
[badge-npm]: https://img.shields.io/npm/v/%40cyclonedx%2Fcdxgen
|
|
521
|
+
[badge-npm-downloads]: https://img.shields.io/npm/dy/%40cyclonedx%2Fcdxgen
|
|
522
|
+
[badge-swh]: https://archive.softwareheritage.org/badge/origin/https://github.com/CycloneDX/cdxgen/
|
|
523
|
+
|
|
524
|
+
<!-- cdxgen github project -->
|
|
525
|
+
[github-contribute]: https://github.com/CycloneDX/cdxgen/contribute
|
|
526
|
+
[github-contributors]: https://github.com/CycloneDX/cdxgen/graphs/contributors
|
|
527
|
+
[github-issues]: https://github.com/CycloneDX/cdxgen/issues
|
|
528
|
+
[github-license]: https://github.com/cyclonedx/cdxgen/blob/master/LICENSE
|
|
529
|
+
[github-releases]: https://github.com/CycloneDX/cdxgen/releases
|
|
530
|
+
|
|
531
|
+
<!-- cdxgen documentation site -->
|
|
532
|
+
[docs-homepage]: https://cyclonedx.github.io/cdxgen
|
|
533
|
+
[docs-advanced-usage]: https://cyclonedx.github.io/cdxgen/#/ADVANCED
|
|
534
|
+
[docs-cli]: https://cyclonedx.github.io/cdxgen/#/CLI
|
|
535
|
+
[docs-env-vars]: https://cyclonedx.github.io/cdxgen/#/ENV
|
|
536
|
+
[docs-permissions]: https://cyclonedx.github.io/cdxgen/#/PERMISSIONS
|
|
537
|
+
[docs-project-types]: https://cyclonedx.github.io/cdxgen/#/PROJECT_TYPES
|
|
538
|
+
[docs-server]: https://cyclonedx.github.io/cdxgen/#/SERVER
|
|
539
|
+
[docs-support]: https://cyclonedx.github.io/cdxgen/#/PROJECT_TYPES
|
|
540
|
+
|
|
541
|
+
<!-- web links-->
|
|
542
|
+
[appthreat-homepage]: https://www.appthreat.com
|
|
543
|
+
[cyclonedx-homepage]: https://cyclonedx.org
|
|
544
|
+
[cyclonedx-cli-github]: https://github.com/CycloneDX/cyclonedx-cli
|
|
545
|
+
[depscan-github]: https://github.com/cyclonedx/dep-scan
|
|
546
|
+
[github-rate-limit]: https://docs.github.com/en/rest/overview/rate-limits-for-the-rest-api#primary-rate-limit-for-github_token-in-github-actions
|
|
547
|
+
[homebrew-homepage]: https://brew.sh
|
|
548
|
+
[homebrew-cdxgen]: https://formulae.brew.sh/formula/cdxgen
|
|
549
|
+
[jsr-cdxgen]: https://jsr.io/@cyclonedx/cdxgen
|
|
550
|
+
[jwt-homepage]: https://jwt.io
|
|
551
|
+
[jwt-libraries]: https://jwt.io/libraries
|
|
552
|
+
[npmjs-cdxgen]: https://www.npmjs.com/package/@cyclonedx/cdxgen
|
|
553
|
+
[podman-github-rootless]: https://github.com/containers/podman/blob/master/docs/tutorials/rootless_tutorial.md
|
|
554
|
+
[podman-github-remote]: https://github.com/containers/podman/blob/master/docs/tutorials/mac_win_client.md
|
|
555
|
+
[swh-cdxgen]: https://archive.softwareheritage.org/browse/origin/?origin_url=https://github.com/CycloneDX/cdxgen
|
package/bin/cdxgen.js
CHANGED
|
@@ -67,7 +67,8 @@ const args = yargs(hideBin(process.argv))
|
|
|
67
67
|
})
|
|
68
68
|
.option("type", {
|
|
69
69
|
alias: "t",
|
|
70
|
-
description:
|
|
70
|
+
description:
|
|
71
|
+
"Project type. Please refer to https://cyclonedx.github.io/cdxgen/#/PROJECT_TYPES for supported languages/platforms.",
|
|
71
72
|
})
|
|
72
73
|
.option("recurse", {
|
|
73
74
|
alias: "r",
|
|
@@ -279,7 +280,8 @@ const args = yargs(hideBin(process.argv))
|
|
|
279
280
|
.version()
|
|
280
281
|
.alias("v", "version")
|
|
281
282
|
.help("h")
|
|
282
|
-
.alias("h", "help")
|
|
283
|
+
.alias("h", "help")
|
|
284
|
+
.wrap(Math.min(120, yargs().terminalWidth())).argv;
|
|
283
285
|
|
|
284
286
|
if (args.version) {
|
|
285
287
|
const packageJsonAsString = fs.readFileSync(
|
package/bin/evinse.js
CHANGED
|
@@ -136,7 +136,8 @@ const args = yargs(hideBin(process.argv))
|
|
|
136
136
|
.config(config)
|
|
137
137
|
.scriptName("evinse")
|
|
138
138
|
.version()
|
|
139
|
-
.help("h")
|
|
139
|
+
.help("h")
|
|
140
|
+
.wrap(Math.min(120, yargs().terminalWidth())).argv;
|
|
140
141
|
|
|
141
142
|
const evinseArt = `
|
|
142
143
|
███████╗██╗ ██╗██╗███╗ ██╗███████╗███████╗
|
package/bin/repl.js
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
printOccurrences,
|
|
15
15
|
printServices,
|
|
16
16
|
printTable,
|
|
17
|
+
printVulnerabilities,
|
|
17
18
|
} from "../display.js";
|
|
18
19
|
import { createBom } from "../index.js";
|
|
19
20
|
import { validateBom } from "../validator.js";
|
|
@@ -61,9 +62,13 @@ export const importSbom = (sbomOrPath) => {
|
|
|
61
62
|
if (sbomOrPath?.endsWith(".json") && fs.existsSync(sbomOrPath)) {
|
|
62
63
|
try {
|
|
63
64
|
sbom = JSON.parse(fs.readFileSync(sbomOrPath, "utf-8"));
|
|
64
|
-
|
|
65
|
+
let bomType = "SBOM";
|
|
66
|
+
if (sbom?.vulnerabilities && Array.isArray(sbom.vulnerabilities)) {
|
|
67
|
+
bomType = "VDR";
|
|
68
|
+
}
|
|
69
|
+
console.log(`✅ ${bomType} imported successfully from ${sbomOrPath}`);
|
|
65
70
|
} catch (e) {
|
|
66
|
-
console.log(`⚠ Unable to import the
|
|
71
|
+
console.log(`⚠ Unable to import the BOM from ${sbomOrPath} due to ${e}`);
|
|
67
72
|
}
|
|
68
73
|
} else {
|
|
69
74
|
console.log(`⚠ ${sbomOrPath} is invalid.`);
|
|
@@ -72,13 +77,13 @@ export const importSbom = (sbomOrPath) => {
|
|
|
72
77
|
// Load any sbom passed from the command line
|
|
73
78
|
if (process.argv.length > 2) {
|
|
74
79
|
importSbom(process.argv[process.argv.length - 1]);
|
|
75
|
-
console.log("💭 Type .print to view the
|
|
80
|
+
console.log("💭 Type .print to view the BOM as a table");
|
|
76
81
|
} else if (fs.existsSync("bom.json")) {
|
|
77
82
|
// If the current directory has a bom.json load it
|
|
78
83
|
importSbom("bom.json");
|
|
79
84
|
} else {
|
|
80
85
|
console.log("💭 Use .create <path> to create an SBOM for the given path.");
|
|
81
|
-
console.log("💭 Use .import <json> to import an existing
|
|
86
|
+
console.log("💭 Use .import <json> to import an existing BOM.");
|
|
82
87
|
console.log("💭 Type .exit or press ctrl+d to close.");
|
|
83
88
|
}
|
|
84
89
|
|
|
@@ -302,7 +307,7 @@ cdxgenRepl.defineCommand("validate", {
|
|
|
302
307
|
if (sbom) {
|
|
303
308
|
const result = validateBom(sbom);
|
|
304
309
|
if (result) {
|
|
305
|
-
console.log("
|
|
310
|
+
console.log("BOM is valid!");
|
|
306
311
|
}
|
|
307
312
|
} else {
|
|
308
313
|
console.log(
|
|
@@ -387,22 +392,6 @@ cdxgenRepl.defineCommand("occurrences", {
|
|
|
387
392
|
this.displayPrompt();
|
|
388
393
|
},
|
|
389
394
|
});
|
|
390
|
-
cdxgenRepl.defineCommand("discord", {
|
|
391
|
-
help: "display the discord invite link for support",
|
|
392
|
-
action() {
|
|
393
|
-
console.log("Head to https://discord.gg/pF4BYWEJcS for support");
|
|
394
|
-
this.displayPrompt();
|
|
395
|
-
},
|
|
396
|
-
});
|
|
397
|
-
cdxgenRepl.defineCommand("sponsor", {
|
|
398
|
-
help: "display the sponsorship link to fund this project",
|
|
399
|
-
action() {
|
|
400
|
-
console.log(
|
|
401
|
-
"Hey, thanks a lot for considering! https://github.com/sponsors/prabhu",
|
|
402
|
-
);
|
|
403
|
-
this.displayPrompt();
|
|
404
|
-
},
|
|
405
|
-
});
|
|
406
395
|
cdxgenRepl.defineCommand("callstack", {
|
|
407
396
|
help: "view components with evidence.callstack",
|
|
408
397
|
async action() {
|
|
@@ -442,7 +431,7 @@ cdxgenRepl.defineCommand("services", {
|
|
|
442
431
|
let services = await expression.evaluate(sbom);
|
|
443
432
|
if (!services) {
|
|
444
433
|
console.log(
|
|
445
|
-
"No services found. Use evinse command to generate
|
|
434
|
+
"No services found. Use evinse command to generate a SaaSBOM with evidence.",
|
|
446
435
|
);
|
|
447
436
|
} else {
|
|
448
437
|
if (!Array.isArray(services)) {
|
|
@@ -455,12 +444,38 @@ cdxgenRepl.defineCommand("services", {
|
|
|
455
444
|
}
|
|
456
445
|
} else {
|
|
457
446
|
console.log(
|
|
458
|
-
"⚠ No
|
|
447
|
+
"⚠ No SaaSBOM is loaded. Use .import command to import a SaaSBOM",
|
|
459
448
|
);
|
|
460
449
|
}
|
|
461
450
|
this.displayPrompt();
|
|
462
451
|
},
|
|
463
452
|
});
|
|
453
|
+
cdxgenRepl.defineCommand("vulnerabilities", {
|
|
454
|
+
help: "view vulnerabilities",
|
|
455
|
+
async action() {
|
|
456
|
+
if (sbom) {
|
|
457
|
+
try {
|
|
458
|
+
const expression = jsonata("vulnerabilities");
|
|
459
|
+
let vulnerabilities = await expression.evaluate(sbom);
|
|
460
|
+
if (!vulnerabilities) {
|
|
461
|
+
console.log(
|
|
462
|
+
"No vulnerabilities found. Use depscan to generate a VDR file with vulnerabilities.",
|
|
463
|
+
);
|
|
464
|
+
} else {
|
|
465
|
+
if (!Array.isArray(vulnerabilities)) {
|
|
466
|
+
vulnerabilities = [vulnerabilities];
|
|
467
|
+
}
|
|
468
|
+
printVulnerabilities(vulnerabilities);
|
|
469
|
+
}
|
|
470
|
+
} catch (e) {
|
|
471
|
+
console.log(e);
|
|
472
|
+
}
|
|
473
|
+
} else {
|
|
474
|
+
console.log("⚠ No BOM is loaded. Use .import command to import a VDR");
|
|
475
|
+
}
|
|
476
|
+
this.displayPrompt();
|
|
477
|
+
},
|
|
478
|
+
});
|
|
464
479
|
cdxgenRepl.defineCommand("osinfocategories", {
|
|
465
480
|
help: "view the category names for the OS info from the obom",
|
|
466
481
|
async action() {
|
package/bin/verify.js
CHANGED
|
@@ -28,7 +28,8 @@ const args = yargs(hideBin(process.argv))
|
|
|
28
28
|
.epilogue("for documentation, visit https://cyclonedx.github.io/cdxgen")
|
|
29
29
|
.scriptName("cdx-verify")
|
|
30
30
|
.version()
|
|
31
|
-
.help("h")
|
|
31
|
+
.help("h")
|
|
32
|
+
.wrap(Math.min(120, yargs().terminalWidth())).argv;
|
|
32
33
|
|
|
33
34
|
if (args.version) {
|
|
34
35
|
const packageJsonAsString = fs.readFileSync(
|
package/binary.js
CHANGED
|
@@ -192,14 +192,10 @@ if (existsSync(join(CDXGEN_PLUGINS_DIR, "osquery"))) {
|
|
|
192
192
|
}
|
|
193
193
|
let DOSAI_BIN = null;
|
|
194
194
|
if (existsSync(join(CDXGEN_PLUGINS_DIR, "dosai"))) {
|
|
195
|
-
let platformToUse = platform;
|
|
196
|
-
if (platform === "darwin") {
|
|
197
|
-
platformToUse = "osx";
|
|
198
|
-
}
|
|
199
195
|
DOSAI_BIN = join(
|
|
200
196
|
CDXGEN_PLUGINS_DIR,
|
|
201
197
|
"dosai",
|
|
202
|
-
`dosai-${
|
|
198
|
+
`dosai-${platform}-${arch}${extn}`,
|
|
203
199
|
);
|
|
204
200
|
} else if (process.env.DOSAI_CMD) {
|
|
205
201
|
DOSAI_BIN = process.env.DOSAI_CMD;
|
|
@@ -421,7 +417,12 @@ export function getOSPackages(src) {
|
|
|
421
417
|
if (DEBUG_MODE) {
|
|
422
418
|
console.log(osReleaseData);
|
|
423
419
|
}
|
|
424
|
-
let distro_codename =
|
|
420
|
+
let distro_codename =
|
|
421
|
+
osReleaseData["VERSION_CODENAME"] ||
|
|
422
|
+
osReleaseData["CENTOS_MANTISBT_PROJECT"] ||
|
|
423
|
+
osReleaseData["REDHAT_SUPPORT_PRODUCT"] ||
|
|
424
|
+
"";
|
|
425
|
+
distro_codename = distro_codename.toLowerCase();
|
|
425
426
|
let distro_id = osReleaseData["ID"] || "";
|
|
426
427
|
const distro_id_like = osReleaseData["ID_LIKE"] || "";
|
|
427
428
|
let purl_type = "rpm";
|
|
@@ -505,6 +506,8 @@ export function getOSPackages(src) {
|
|
|
505
506
|
if (distro_codename?.length) {
|
|
506
507
|
purlObj.qualifiers["distro_name"] = distro_codename;
|
|
507
508
|
}
|
|
509
|
+
// Remove any epoch values
|
|
510
|
+
delete purlObj.qualifiers.epoch;
|
|
508
511
|
// Bug fix for mageia and oracle linux
|
|
509
512
|
// Type is being returned as none for ubuntu as well!
|
|
510
513
|
if (purlObj.type === "none") {
|
|
@@ -573,6 +576,32 @@ export function getOSPackages(src) {
|
|
|
573
576
|
// continue regardless of error
|
|
574
577
|
}
|
|
575
578
|
}
|
|
579
|
+
if (comp.purl.includes("epoch=")) {
|
|
580
|
+
try {
|
|
581
|
+
purlObj = PackageURL.fromString(comp.purl);
|
|
582
|
+
purlObj.qualifiers = purlObj.qualifiers || {};
|
|
583
|
+
if (distro_id?.length) {
|
|
584
|
+
purlObj.qualifiers["distro"] = distro_id;
|
|
585
|
+
}
|
|
586
|
+
if (distro_codename?.length) {
|
|
587
|
+
purlObj.qualifiers["distro_name"] = distro_codename;
|
|
588
|
+
}
|
|
589
|
+
delete purlObj.qualifiers.epoch;
|
|
590
|
+
allTypes.add(purlObj.namespace);
|
|
591
|
+
comp.purl = new PackageURL(
|
|
592
|
+
purlObj.type,
|
|
593
|
+
purlObj.namespace,
|
|
594
|
+
name,
|
|
595
|
+
purlObj.version,
|
|
596
|
+
purlObj.qualifiers,
|
|
597
|
+
purlObj.subpath,
|
|
598
|
+
).toString();
|
|
599
|
+
comp["bom-ref"] = decodeURIComponent(comp.purl);
|
|
600
|
+
} catch (err) {
|
|
601
|
+
// continue regardless of error
|
|
602
|
+
console.log(err);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
576
605
|
// Fix licenses
|
|
577
606
|
if (
|
|
578
607
|
comp.licenses &&
|
|
@@ -685,6 +714,7 @@ const retrieveDependencies = (tmpDependencies, origBomRef, comp) => {
|
|
|
685
714
|
if (compPurl.qualifiers.distro) {
|
|
686
715
|
tmpPurl.qualifiers.distro = compPurl.qualifiers.distro;
|
|
687
716
|
}
|
|
717
|
+
delete tmpPurl.qualifiers.epoch;
|
|
688
718
|
}
|
|
689
719
|
dependsOn.add(decodeURIComponent(tmpPurl.toString()));
|
|
690
720
|
} catch (e) {
|
|
@@ -720,7 +750,11 @@ export function executeOsQuery(query) {
|
|
|
720
750
|
timeout: 60 * 1000,
|
|
721
751
|
});
|
|
722
752
|
if (result.status !== 0 || result.error) {
|
|
723
|
-
if (
|
|
753
|
+
if (
|
|
754
|
+
DEBUG_MODE &&
|
|
755
|
+
result.stderr &&
|
|
756
|
+
!result.stderr.includes("no such table")
|
|
757
|
+
) {
|
|
724
758
|
console.error(result.stdout, result.stderr);
|
|
725
759
|
}
|
|
726
760
|
}
|