@cyclonedx/cdxgen 9.8.10 → 9.9.1

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 CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  ![cdxgen logo](cdxgen.png)
4
4
 
5
- cdxgen is a cli tool, library, [REPL](./ADVANCED.md), and server to create a valid and compliant [CycloneDX][cyclonedx-homepage] Software Bill of Materials (SBOM) 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 1.5 is a lightweight SBOM specification that is easily created, human and machine-readable, and simple to parse.
5
+ cdxgen is a CLI tool, library, [REPL](./ADVANCED.md), and server to create a valid and compliant [CycloneDX][cyclonedx-homepage] Software Bill of Materials (SBOM) 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 1.5 is a lightweight SBOM specification that is easily created, human and machine-readable, and simple to parse.
6
6
 
7
7
  When used with plugins, cdxgen could generate an OBOM for Linux docker images and even VMs running Linux or Windows operating systems. cdxgen also includes an evinse tool to generate component evidence and SaaSBOM for some languages.
8
8
 
@@ -12,45 +12,45 @@ CycloneDX 1.5 specification is new and unsupported by many downstream tools. Use
12
12
 
13
13
  ## Why cdxgen?
14
14
 
15
- A typical application might have several repos, components, and libraries. Traditional techniques to generate a single SBOM per language or package manifest do not work in enterprise environments. So we built cdxgen - the universal polyglot SBOM generator!
15
+ Most SBOM tools are like barcode scanners. They can scan a few package manifest 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. Traditional techniques to generate a SBOM per language or package manifest either do not work in enterprise environments or doesn't provide the confidence required for both compliance and automated analysis. So we built cdxgen - the universal polyglot SBOM generator that is both precise and comprehensive!
16
16
 
17
17
  <img src="./docs/why-cdxgen.jpg" alt="why cdxgen" width="256">
18
18
 
19
19
  ## Supported languages and package format
20
20
 
21
- | Language/Platform | Package format | Transitive dependencies |
22
- | ------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
23
- | node.js | npm-shrinkwrap.json, package-lock.json, pnpm-lock.yaml, yarn.lock, rush.js, bower.json, .min.js | Yes except .min.js |
24
- | java | maven (pom.xml [1]), gradle (build.gradle, .kts), scala (sbt), bazel | Yes unless pom.xml is manually parsed due to unavailability of maven or errors |
25
- | php | composer.lock | Yes |
26
- | python | pyproject.toml, setup.py, requirements.txt [2], Pipfile.lock, poetry.lock, pdm.lock, bdist_wheel, .whl, .egg-info | Yes using the automatic pip install/freeze. When disabled, only with Pipfile.lock and poetry.lock |
27
- | go | binary, go.mod, go.sum, Gopkg.lock | Yes except binary |
28
- | ruby | Gemfile.lock, gemspec | Only for Gemfile.lock |
29
- | rust | binary, Cargo.toml, Cargo.lock | Only for Cargo.lock |
30
- | .Net | .csproj, packages.config, project.assets.json [3], packages.lock.json, .nupkg, paket.lock | Only for project.assets.json, packages.lock.json, paket.lock |
31
- | dart | pubspec.lock, pubspec.yaml | Only for pubspec.lock |
32
- | haskell | cabal.project.freeze | Yes |
33
- | elixir | mix.lock | Yes |
34
- | 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. |
35
- | clojure | Clojure CLI (deps.edn), Leiningen (project.clj) | Yes unless the files are parsed manually due to lack of clojure cli or leiningen command |
36
- | swift | Package.resolved, Package.swift (swiftpm) | Yes |
37
- | docker / oci image | All supported languages. Linux OS packages with plugins [4] | Best effort based on lock files |
38
- | GitHub Actions | .github/workflows/\*.yml | N/A |
39
- | Linux | All supported languages. Linux OS packages with plugins [5] | Best effort based on lock files |
40
- | Windows | All supported languages. OS packages with best effort [5] | Best effort based on lock files |
41
- | Jenkins Plugins | .hpi files | |
42
- | Helm Charts | .yaml | N/A |
43
- | Skaffold | .yaml | N/A |
44
- | kustomization | .yaml | N/A |
45
- | Tekton tasks | .yaml | N/A |
46
- | Kubernetes | .yaml | N/A |
47
- | Maven Cache | $HOME/.m2/repository/\*\*/\*.jar | N/A |
48
- | SBT Cache | $HOME/.ivy2/cache/\*\*/\*.jar | N/A |
49
- | Gradle Cache | $HOME/caches/modules-2/files-2.1/\*\*/\*.jar | N/A |
50
- | Helm Index | $HOME/.cache/helm/repository/\*\*/\*.yaml | N/A |
51
- | Docker compose | docker-compose\*.yml. Images would also be scanned. | N/A |
52
- | Google CloudBuild configuration | cloudbuild.yaml | N/A |
53
- | OpenAPI | openapi\*.json, openapi\*.yaml | N/A |
21
+ | Language/Platform | Package format | Transitive dependencies | Evidence |
22
+ | ------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | -------- |
23
+ | Node.js | npm-shrinkwrap.json, package-lock.json, pnpm-lock.yaml, yarn.lock, rush.js, bower.json, .min.js | Yes except .min.js | Yes |
24
+ | Java | maven (pom.xml [1]), gradle (build.gradle, .kts), scala (sbt), bazel | Yes unless pom.xml is manually parsed due to unavailability of maven or errors | Yes |
25
+ | PHP | composer.lock | Yes | |
26
+ | Python | pyproject.toml, setup.py, requirements.txt [2], Pipfile.lock, poetry.lock, pdm.lock, bdist_wheel, .whl, .egg-info | Yes using the automatic pip install/freeze. When disabled, only with Pipfile.lock and poetry.lock | Yes |
27
+ | Go | binary, go.mod, go.sum, Gopkg.lock | Yes except binary | Yes |
28
+ | Ruby | Gemfile.lock, gemspec | Only for Gemfile.lock | |
29
+ | Rust | binary, Cargo.toml, Cargo.lock | Only for Cargo.lock | |
30
+ | .Net | .csproj, packages.config, project.assets.json [3], packages.lock.json, .nupkg, paket.lock | Only for project.assets.json, packages.lock.json, paket.lock | |
31
+ | Dart | pubspec.lock, pubspec.yaml | Only for pubspec.lock | |
32
+ | Haskell | cabal.project.freeze | Yes | |
33
+ | Elixir | mix.lock | Yes | |
34
+ | 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 |
35
+ | Clojure | Clojure CLI (deps.edn), Leiningen (project.clj) | Yes unless the files are parsed manually due to lack of clojure cli or leiningen command | |
36
+ | Swift | Package.resolved, Package.swift (swiftpm) | Yes | |
37
+ | Docker / oci image | All supported languages. Linux OS packages with plugins [4] | Best effort based on lock files | Yes |
38
+ | GitHub Actions | .github/workflows/\*.yml | N/A | Yes |
39
+ | Linux | All supported languages. Linux OS packages with plugins [5] | Best effort based on lock files | Yes |
40
+ | Windows | All supported languages. OS packages with best effort [5] | Best effort based on lock files | Yes |
41
+ | Jenkins Plugins | .hpi files | | Yes |
42
+ | Helm Charts | .yaml | N/A | |
43
+ | Skaffold | .yaml | N/A | |
44
+ | kustomization | .yaml | N/A | |
45
+ | Tekton tasks | .yaml | N/A | |
46
+ | Kubernetes | .yaml | N/A | |
47
+ | Maven Cache | $HOME/.m2/repository/\*\*/\*.jar | N/A | |
48
+ | SBT Cache | $HOME/.ivy2/cache/\*\*/\*.jar | N/A | |
49
+ | Gradle Cache | $HOME/caches/modules-2/files-2.1/\*\*/\*.jar | N/A | |
50
+ | Helm Index | $HOME/.cache/helm/repository/\*\*/\*.yaml | N/A | |
51
+ | Docker compose | docker-compose\*.yml. Images would also be scanned. | N/A | |
52
+ | Google CloudBuild configuration | cloudbuild.yaml | N/A | |
53
+ | OpenAPI | openapi\*.json, openapi\*.yaml | N/A | |
54
54
 
55
55
  NOTE:
56
56
 
@@ -170,10 +170,7 @@ Options:
170
170
  faults to true. Pass --no-validate to disable.
171
171
  [boolean] [default: true]
172
172
  --evidence Generate SBOM with evidence for supported languag
173
- es. WIP [boolean] [default: false]
174
- --usages-slices-file Path for the usages slice file created by atom.
175
- --data-flow-slices-file Path for the data-flow slice file created by atom
176
- .
173
+ es. [boolean] [default: false]
177
174
  --spec-version CycloneDX Specification version to use. Defaults
178
175
  to 1.5 [default: 1.5]
179
176
  --filter Filter components containining this word in purl.
@@ -181,6 +178,9 @@ Options:
181
178
  --only Include components only containining this word in
182
179
  purl. Useful to generate BOM with first party co
183
180
  mponents alone. Multiple values allowed. [array]
181
+ --author The person(s) who created the BOM. Set this value
182
+ if you're intending the modify the BOM and claim
183
+ authorship.[array] [default: "OWASP Foundation"]
184
184
  --auto-compositions Automatically set compositions when the BOM was f
185
185
  iltered. Defaults to true
186
186
  [boolean] [default: true]
@@ -338,7 +338,7 @@ cdxgen can retain the dependency tree under the `dependencies` attribute for a s
338
338
  - Gradle
339
339
  - Scala SBT
340
340
  - Python (requirements.txt, setup.py, pyproject.toml, poetry.lock)
341
- - csharp (projects.assets.json)
341
+ - .NET (project.assets.json, paket.lock)
342
342
  - Go (go.mod)
343
343
 
344
344
  ## Environment variables
@@ -367,6 +367,7 @@ cdxgen can retain the dependency tree under the `dependencies` attribute for a s
367
367
  | 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 |
368
368
  | CDXGEN_TIMEOUT_MS | Default timeout for known execution involving maven, gradle or sbt |
369
369
  | CDXGEN_SERVER_TIMEOUT_MS | Default timeout in server mode |
370
+ | CDXGEN_MAX_BUFFER | Max buffer for stdout and stderr. Defaults to 100MB |
370
371
  | CLJ_CMD | Set to override the clojure cli command |
371
372
  | LEIN_CMD | Set to override the leiningen command |
372
373
  | SBOM_SIGN_ALGORITHM | Signature algorithm. Some valid values are RS256, RS384, RS512, PS256, PS384, PS512, ES256 etc |
@@ -377,6 +378,7 @@ cdxgen can retain the dependency tree under the `dependencies` attribute for a s
377
378
  | CDX_MAVEN_INCLUDE_TEST_SCOPE | Whether test scoped dependencies should be included from Maven projects, Default: true |
378
379
  | ASTGEN_IGNORE_DIRS | Comma separated list of directories to ignore while analyzing using babel. The environment variable is also used by atom and astgen. |
379
380
  | ASTGEN_IGNORE_FILE_PATTERN | Ignore regex to use |
381
+ | PYPI_URL | Override pypi url. Default: https://pypi.org/pypi/ |
380
382
 
381
383
  ## Plugins
382
384
 
@@ -394,7 +396,7 @@ sudo npm install -g @cyclonedx/cdxgen-plugins-bin
394
396
  cdxgen odoo@sha256:4e1e147f0e6714e8f8c5806d2b484075b4076ca50490577cdf9162566086d15e -o /tmp/bom.json
395
397
  ```
396
398
 
397
- You can also pass `-t docker` for simple labels. Only the `latest` tag would be pulled if none was specified.
399
+ You can also pass `-t docker` with repository names. Only the `latest` tag would be pulled if none was specified.
398
400
 
399
401
  ```shell
400
402
  cdxgen shiftleft/scan-slim -o /tmp/bom.json -t docker
package/analyzer.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { parse } from "@babel/parser";
2
2
  import traverse from "@babel/traverse";
3
3
  import { join } from "node:path";
4
- import { readdirSync, statSync, readFileSync } from "node:fs";
4
+ import { readdirSync, lstatSync, readFileSync } from "node:fs";
5
5
  import { basename, resolve, isAbsolute, relative } from "node:path";
6
6
 
7
7
  const IGNORE_DIRS = process.env.ASTGEN_IGNORE_DIRS
@@ -46,7 +46,11 @@ const getAllFiles = (dir, extn, files, result, regex) => {
46
46
  continue;
47
47
  }
48
48
  const file = join(dir, files[i]);
49
- if (statSync(file).isDirectory()) {
49
+ const fileStat = lstatSync(file);
50
+ if (fileStat.isSymbolicLink()) {
51
+ continue;
52
+ }
53
+ if (fileStat.isDirectory()) {
50
54
  // Ignore directories
51
55
  const dirName = basename(file);
52
56
  if (
package/bin/cdxgen.js CHANGED
@@ -10,10 +10,19 @@ import crypto from "node:crypto";
10
10
  import { fileURLToPath } from "node:url";
11
11
  import globalAgent from "global-agent";
12
12
  import process from "node:process";
13
- import { printTable, printDependencyTree } from "../display.js";
13
+ import {
14
+ printCallStack,
15
+ printOccurrences,
16
+ printServices,
17
+ printReachables,
18
+ printTable,
19
+ printDependencyTree
20
+ } from "../display.js";
14
21
  import { findUpSync } from "find-up";
15
22
  import { load as _load } from "js-yaml";
16
23
  import { postProcess } from "../postgen.js";
24
+ import { analyzeProject, createEvinseFile, prepareDB } from "../evinser.js";
25
+ import { ATOM_DB } from "../utils.js";
17
26
 
18
27
  // Support for config files
19
28
  const configPath = findUpSync([
@@ -48,7 +57,14 @@ const args = yargs(hideBin(process.argv))
48
57
  .env("CDXGEN")
49
58
  .option("output", {
50
59
  alias: "o",
51
- description: "Output file for bom.xml or bom.json. Default bom.json"
60
+ description: "Output file for bom.xml or bom.json. Default bom.json",
61
+ default: "bom.json"
62
+ })
63
+ .option("evinse-output", {
64
+ description:
65
+ "Create bom with evidence as a separate file. Default bom.json",
66
+ default: "bom.json",
67
+ hidden: true
52
68
  })
53
69
  .option("type", {
54
70
  alias: "t",
@@ -90,14 +106,17 @@ const args = yargs(hideBin(process.argv))
90
106
  })
91
107
  .option("project-version", {
92
108
  description: "Dependency track project version",
93
- default: ""
109
+ default: "",
110
+ type: "string"
94
111
  })
95
112
  .option("project-id", {
96
113
  description:
97
- "Dependency track project id. Either provide the id or the project name and version together"
114
+ "Dependency track project id. Either provide the id or the project name and version together",
115
+ type: "string"
98
116
  })
99
117
  .option("parent-project-id", {
100
- description: "Dependency track parent project id"
118
+ description: "Dependency track parent project id",
119
+ type: "string"
101
120
  })
102
121
  .option("required-only", {
103
122
  type: "boolean",
@@ -145,17 +164,32 @@ const args = yargs(hideBin(process.argv))
145
164
  .option("evidence", {
146
165
  type: "boolean",
147
166
  default: false,
148
- description: "Generate SBOM with evidence for supported languages. WIP"
167
+ description: "Generate SBOM with evidence for supported languages."
168
+ })
169
+ .option("deps-slices-file", {
170
+ description: "Path for the parsedeps slice file created by atom.",
171
+ default: "deps.slices.json",
172
+ hidden: true
149
173
  })
150
174
  .option("usages-slices-file", {
151
- description: "Path for the usages slice file created by atom."
175
+ description: "Path for the usages slices file created by atom.",
176
+ default: "usages.slices.json",
177
+ hidden: true
152
178
  })
153
179
  .option("data-flow-slices-file", {
154
- description: "Path for the data-flow slice file created by atom."
180
+ description: "Path for the data-flow slices file created by atom.",
181
+ default: "data-flow.slices.json",
182
+ hidden: true
183
+ })
184
+ .option("reachables-slices-file", {
185
+ description: "Path for the reachables slices file created by atom.",
186
+ default: "reachables.slices.json",
187
+ hidden: true
155
188
  })
156
189
  .option("spec-version", {
157
190
  description: "CycloneDX Specification version to use. Defaults to 1.5",
158
- default: 1.5
191
+ default: 1.5,
192
+ type: "number"
159
193
  })
160
194
  .option("filter", {
161
195
  description:
@@ -165,8 +199,15 @@ const args = yargs(hideBin(process.argv))
165
199
  description:
166
200
  "Include components only containining this word in purl. Useful to generate BOM with first party components alone. Multiple values allowed."
167
201
  })
202
+ .option("author", {
203
+ description:
204
+ "The person(s) who created the BOM. Set this value if you're intending the modify the BOM and claim authorship.",
205
+ default: "OWASP Foundation"
206
+ })
207
+ .completion("completion", "Generate bash/zsh completion")
168
208
  .array("filter")
169
209
  .array("only")
210
+ .array("author")
170
211
  .option("auto-compositions", {
171
212
  type: "boolean",
172
213
  default: true,
@@ -213,11 +254,6 @@ if (!args.projectName) {
213
254
  }
214
255
  }
215
256
 
216
- // To help dependency track users, we downgrade the spec version to 1.4 automatically
217
- if (args.serverUrl || args.apiKey) {
218
- args.specVersion = 1.4;
219
- }
220
-
221
257
  // Support for obom aliases
222
258
  if (process.argv[1].includes("obom") && !args.type) {
223
259
  args.type = "os";
@@ -286,9 +322,6 @@ const checkPermissions = (filePath) => {
286
322
  if (options.requiredOnly || options["filter"] || options["only"]) {
287
323
  bomNSData = postProcess(bomNSData, options);
288
324
  }
289
- if (!args.output) {
290
- args.output = "bom.json";
291
- }
292
325
  if (
293
326
  args.output &&
294
327
  (typeof args.output === "string" || args.output instanceof String)
@@ -455,6 +488,34 @@ const checkPermissions = (filePath) => {
455
488
  console.log("Try running the command with -t <type> or -r argument");
456
489
  }
457
490
  }
491
+ // Evidence generation
492
+ if (args.evidence) {
493
+ const evinseOptions = {
494
+ _: args._,
495
+ input: options.output,
496
+ output: options.evinseOutput,
497
+ language: options.projectType || "java",
498
+ dbPath: process.env.ATOM_DB || ATOM_DB,
499
+ skipMavenCollector: false,
500
+ force: false,
501
+ withReachables: options.deep,
502
+ usagesSlicesFile: options.usagesSlicesFile,
503
+ dataFlowSlicesFile: options.dataFlowSlicesFile,
504
+ reachablesSlicesFile: options.reachablesSlicesFile
505
+ };
506
+ const dbObjMap = await prepareDB(evinseOptions);
507
+ if (dbObjMap) {
508
+ const sliceArtefacts = await analyzeProject(dbObjMap, evinseOptions);
509
+ const evinseJson = createEvinseFile(sliceArtefacts, evinseOptions);
510
+ bomNSData.bomJson = evinseJson;
511
+ if (args.print && evinseJson) {
512
+ printOccurrences(evinseJson);
513
+ printCallStack(evinseJson);
514
+ printReachables(sliceArtefacts);
515
+ printServices(evinseJson);
516
+ }
517
+ }
518
+ }
458
519
  // Perform automatic validation
459
520
  if (args.validate) {
460
521
  if (!validateBom(bomNSData.bomJson)) {
package/bin/evinse.js CHANGED
@@ -3,13 +3,17 @@
3
3
  // Evinse (Evinse Verification Is Nearly SBOM Evidence)
4
4
  import yargs from "yargs";
5
5
  import { hideBin } from "yargs/helpers";
6
- import { join } from "node:path";
7
6
  import fs from "node:fs";
8
- import { homedir, platform as _platform } from "node:os";
9
7
  import process from "node:process";
10
8
  import { analyzeProject, createEvinseFile, prepareDB } from "../evinser.js";
11
9
  import { validateBom } from "../validator.js";
12
- import { printCallStack, printOccurrences, printServices } from "../display.js";
10
+ import {
11
+ printCallStack,
12
+ printOccurrences,
13
+ printServices,
14
+ printReachables
15
+ } from "../display.js";
16
+ import { ATOM_DB } from "../utils.js";
13
17
  import { findUpSync } from "find-up";
14
18
  import { load as _load } from "js-yaml";
15
19
 
@@ -33,22 +37,6 @@ if (configPath) {
33
37
  }
34
38
  }
35
39
 
36
- const isWin = _platform() === "win32";
37
- const isMac = _platform() === "darwin";
38
- let ATOM_DB = join(homedir(), ".local", "share", ".atomdb");
39
- if (isWin) {
40
- ATOM_DB = join(homedir(), "AppData", "Local", ".atomdb");
41
- } else if (isMac) {
42
- ATOM_DB = join(homedir(), "Library", "Application Support", ".atomdb");
43
- }
44
-
45
- if (!process.env.ATOM_DB && !fs.existsSync(ATOM_DB)) {
46
- try {
47
- fs.mkdirSync(ATOM_DB, { recursive: true });
48
- } catch (e) {
49
- // ignore
50
- }
51
- }
52
40
  const args = yargs(hideBin(process.argv))
53
41
  .env("EVINSE")
54
42
  .option("input", {
@@ -65,7 +53,18 @@ const args = yargs(hideBin(process.argv))
65
53
  alias: "l",
66
54
  description: "Application language",
67
55
  default: "java",
68
- choices: ["java", "jar", "javascript", "python", "android", "cpp"]
56
+ choices: [
57
+ "java",
58
+ "jar",
59
+ "js",
60
+ "ts",
61
+ "javascript",
62
+ "py",
63
+ "python",
64
+ "android",
65
+ "c",
66
+ "cpp"
67
+ ]
69
68
  })
70
69
  .option("db-path", {
71
70
  description: `Atom slices DB path. Default ${ATOM_DB}`,
@@ -98,6 +97,12 @@ const args = yargs(hideBin(process.argv))
98
97
  default: false,
99
98
  type: "boolean"
100
99
  })
100
+ .option("with-reachables", {
101
+ description:
102
+ "Enable auto-tagged reachable slicing. Requires SBOM generated with --deep mode.",
103
+ default: false,
104
+ type: "boolean"
105
+ })
101
106
  .option("usages-slices-file", {
102
107
  description: "Use an existing usages slices file.",
103
108
  default: "usages.slices.json"
@@ -106,11 +111,27 @@ const args = yargs(hideBin(process.argv))
106
111
  description: "Use an existing data-flow slices file.",
107
112
  default: "data-flow.slices.json"
108
113
  })
114
+ .option("reachables-slices-file", {
115
+ description: "Use an existing reachables slices file.",
116
+ default: "reachables.slices.json"
117
+ })
109
118
  .option("print", {
110
119
  alias: "p",
111
120
  type: "boolean",
112
121
  description: "Print the evidences as table"
113
122
  })
123
+ .example([
124
+ [
125
+ "$0 -i bom.json -o bom.evinse.json -l java .",
126
+ "Generate a Java SBOM with evidence for the current directory"
127
+ ],
128
+ [
129
+ "$0 -i bom.json -o bom.evinse.json -l java --with-reachables .",
130
+ "Generate a Java SBOM with occurrence and reachable evidence for the current directory"
131
+ ]
132
+ ])
133
+ .completion("completion", "Generate bash/zsh completion")
134
+ .epilogue("for documentation, visit https://cyclonedx.github.io/cdxgen")
114
135
  .config(config)
115
136
  .scriptName("evinse")
116
137
  .version()
@@ -119,8 +140,8 @@ const args = yargs(hideBin(process.argv))
119
140
  const evinseArt = `
120
141
  ███████╗██╗ ██╗██╗███╗ ██╗███████╗███████╗
121
142
  ██╔════╝██║ ██║██║████╗ ██║██╔════╝██╔════╝
122
- █████╗ ██║ ██║██║██╔██╗ ██║███████╗█████╗
123
- ██╔══╝ ╚██╗ ██╔╝██║██║╚██╗██║╚════██║██╔══╝
143
+ █████╗ ██║ ██║██║██╔██╗ ██║███████╗█████╗
144
+ ██╔══╝ ╚██╗ ██╔╝██║██║╚██╗██║╚════██║██╔══╝
124
145
  ███████╗ ╚████╔╝ ██║██║ ╚████║███████║███████╗
125
146
  ╚══════╝ ╚═══╝ ╚═╝╚═╝ ╚═══╝╚══════╝╚══════╝
126
147
  `;
@@ -141,6 +162,7 @@ console.log(evinseArt);
141
162
  if (args.print) {
142
163
  printOccurrences(bomJson);
143
164
  printCallStack(bomJson);
165
+ printReachables(sliceArtefacts);
144
166
  printServices(bomJson);
145
167
  }
146
168
  }
package/bin/verify.js CHANGED
@@ -24,6 +24,8 @@ const args = yargs(hideBin(process.argv))
24
24
  default: "public.key",
25
25
  description: "Public key in PEM format. Default public.key"
26
26
  })
27
+ .completion("completion", "Generate bash/zsh completion")
28
+ .epilogue("for documentation, visit https://cyclonedx.github.io/cdxgen")
27
29
  .scriptName("cdx-verify")
28
30
  .version()
29
31
  .help("h").argv;
package/binary.js CHANGED
@@ -1,5 +1,11 @@
1
- import { platform as _platform, arch as _arch, tmpdir } from "node:os";
2
- import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
1
+ import { platform as _platform, arch as _arch, tmpdir, homedir } from "node:os";
2
+ import {
3
+ existsSync,
4
+ mkdirSync,
5
+ mkdtempSync,
6
+ readFileSync,
7
+ rmSync
8
+ } from "node:fs";
3
9
  import { join, dirname, basename } from "node:path";
4
10
  import { spawnSync } from "node:child_process";
5
11
  import { PackageURL } from "packageurl-js";
@@ -284,6 +290,13 @@ export const getOSPackages = (src) => {
284
290
  const allTypes = new Set();
285
291
  if (TRIVY_BIN) {
286
292
  let imageType = "image";
293
+ const trivyCacheDir = join(homedir(), ".cache", "trivy");
294
+ try {
295
+ mkdirSync(join(trivyCacheDir, "db"), { recursive: true });
296
+ mkdirSync(join(trivyCacheDir, "java-db"), { recursive: true });
297
+ } catch (err) {
298
+ // ignore errors
299
+ }
287
300
  if (existsSync(src)) {
288
301
  imageType = "rootfs";
289
302
  }
@@ -292,12 +305,17 @@ export const getOSPackages = (src) => {
292
305
  const args = [
293
306
  imageType,
294
307
  "--skip-db-update",
308
+ "--skip-java-db-update",
295
309
  "--offline-scan",
310
+ "--skip-files",
311
+ "**/*.jar",
296
312
  "--no-progress",
297
313
  "--exit-code",
298
314
  "0",
299
315
  "--format",
300
316
  "cyclonedx",
317
+ "--cache-dir",
318
+ trivyCacheDir,
301
319
  "--output",
302
320
  bomJsonFile
303
321
  ];
package/data/README.md CHANGED
@@ -18,3 +18,4 @@ Contents of data directory and their purpose.
18
18
  | spdx.schema.json | jsonschema for validation |
19
19
  | vendor-alias.json | List to correct the group names. Used while parsing .jar files |
20
20
  | wrapdb-releases.json | Database of all available meson wraps. Generated using contrib/wrapdb.py. |
21
+ | frameworks-list.json | List of string fragments to categorize components into frameworks |