@cyclonedx/cdxgen 9.8.9 → 9.9.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 +54 -36
- package/analyzer.js +6 -2
- package/bin/cdxgen.js +65 -30
- package/bin/evinse.js +67 -4
- package/bin/verify.js +2 -0
- package/binary.js +20 -2
- package/data/README.md +1 -0
- package/data/frameworks-list.json +128 -0
- package/display.js +34 -0
- package/docker.js +64 -5
- package/evinser.js +109 -10
- package/index.js +103 -91
- package/package.json +7 -6
- package/postgen.js +92 -0
- package/postgen.test.js +70 -0
- package/server.js +18 -11
- package/utils.js +407 -177
- package/utils.test.js +81 -7
package/README.md
CHANGED
|
@@ -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
|
-
|
|
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
|
|
|
@@ -126,6 +126,7 @@ import { createBom, submitBom } from "npm:@cyclonedx/cdxgen@^9.0.1";
|
|
|
126
126
|
|
|
127
127
|
```text
|
|
128
128
|
$ cdxgen -h
|
|
129
|
+
Options:
|
|
129
130
|
-o, --output Output file for bom.xml or bom.json. Default bom.
|
|
130
131
|
json
|
|
131
132
|
-t, --type Project type
|
|
@@ -149,7 +150,9 @@ $ cdxgen -h
|
|
|
149
150
|
d or the project name and version together
|
|
150
151
|
--parent-project-id Dependency track parent project id
|
|
151
152
|
--required-only Include only the packages with required scope on
|
|
152
|
-
the SBOM.
|
|
153
|
+
the SBOM. Would set compositions.aggregate to inc
|
|
154
|
+
omplete unless --no-auto-compositions is passed.
|
|
155
|
+
[boolean]
|
|
153
156
|
--fail-on-error Fail if any dependency extractor fails. [boolean]
|
|
154
157
|
--no-babel Do not use babel to perform usage analysis for Ja
|
|
155
158
|
vaScript/TypeScript projects. [boolean]
|
|
@@ -166,11 +169,24 @@ $ cdxgen -h
|
|
|
166
169
|
--validate Validate the generated SBOM using json schema. De
|
|
167
170
|
faults to true. Pass --no-validate to disable.
|
|
168
171
|
[boolean] [default: true]
|
|
172
|
+
--evidence Generate SBOM with evidence for supported languag
|
|
173
|
+
es. WIP [boolean] [default: false]
|
|
169
174
|
--usages-slices-file Path for the usages slice file created by atom.
|
|
170
175
|
--data-flow-slices-file Path for the data-flow slice file created by atom
|
|
171
176
|
.
|
|
172
177
|
--spec-version CycloneDX Specification version to use. Defaults
|
|
173
178
|
to 1.5 [default: 1.5]
|
|
179
|
+
--filter Filter components containining this word in purl.
|
|
180
|
+
Multiple values allowed. [array]
|
|
181
|
+
--only Include components only containining this word in
|
|
182
|
+
purl. Useful to generate BOM with first party co
|
|
183
|
+
mponents alone. Multiple values allowed. [array]
|
|
184
|
+
--author The person(s) who created the BOM. Set this value
|
|
185
|
+
if you're intending the modify the BOM and claim
|
|
186
|
+
authorship.[array] [default: "OWASP Foundation"]
|
|
187
|
+
--auto-compositions Automatically set compositions when the BOM was f
|
|
188
|
+
iltered. Defaults to true
|
|
189
|
+
[boolean] [default: true]
|
|
174
190
|
-h, --help Show help [boolean]
|
|
175
191
|
-v, --version Show version number [boolean]
|
|
176
192
|
```
|
|
@@ -325,7 +341,7 @@ cdxgen can retain the dependency tree under the `dependencies` attribute for a s
|
|
|
325
341
|
- Gradle
|
|
326
342
|
- Scala SBT
|
|
327
343
|
- Python (requirements.txt, setup.py, pyproject.toml, poetry.lock)
|
|
328
|
-
-
|
|
344
|
+
- .NET (project.assets.json, paket.lock)
|
|
329
345
|
- Go (go.mod)
|
|
330
346
|
|
|
331
347
|
## Environment variables
|
|
@@ -354,6 +370,7 @@ cdxgen can retain the dependency tree under the `dependencies` attribute for a s
|
|
|
354
370
|
| 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 |
|
|
355
371
|
| CDXGEN_TIMEOUT_MS | Default timeout for known execution involving maven, gradle or sbt |
|
|
356
372
|
| CDXGEN_SERVER_TIMEOUT_MS | Default timeout in server mode |
|
|
373
|
+
| CDXGEN_MAX_BUFFER | Max buffer for stdout and stderr. Defaults to 100MB |
|
|
357
374
|
| CLJ_CMD | Set to override the clojure cli command |
|
|
358
375
|
| LEIN_CMD | Set to override the leiningen command |
|
|
359
376
|
| SBOM_SIGN_ALGORITHM | Signature algorithm. Some valid values are RS256, RS384, RS512, PS256, PS384, PS512, ES256 etc |
|
|
@@ -364,6 +381,7 @@ cdxgen can retain the dependency tree under the `dependencies` attribute for a s
|
|
|
364
381
|
| CDX_MAVEN_INCLUDE_TEST_SCOPE | Whether test scoped dependencies should be included from Maven projects, Default: true |
|
|
365
382
|
| ASTGEN_IGNORE_DIRS | Comma separated list of directories to ignore while analyzing using babel. The environment variable is also used by atom and astgen. |
|
|
366
383
|
| ASTGEN_IGNORE_FILE_PATTERN | Ignore regex to use |
|
|
384
|
+
| PYPI_URL | Override pypi url. Default: https://pypi.org/pypi/ |
|
|
367
385
|
|
|
368
386
|
## Plugins
|
|
369
387
|
|
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,
|
|
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
|
-
|
|
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
|
@@ -11,6 +11,29 @@ import { fileURLToPath } from "node:url";
|
|
|
11
11
|
import globalAgent from "global-agent";
|
|
12
12
|
import process from "node:process";
|
|
13
13
|
import { printTable, printDependencyTree } from "../display.js";
|
|
14
|
+
import { findUpSync } from "find-up";
|
|
15
|
+
import { load as _load } from "js-yaml";
|
|
16
|
+
import { postProcess } from "../postgen.js";
|
|
17
|
+
|
|
18
|
+
// Support for config files
|
|
19
|
+
const configPath = findUpSync([
|
|
20
|
+
".cdxgenrc",
|
|
21
|
+
".cdxgen.json",
|
|
22
|
+
".cdxgen.yml",
|
|
23
|
+
".cdxgen.yaml"
|
|
24
|
+
]);
|
|
25
|
+
let config = {};
|
|
26
|
+
if (configPath) {
|
|
27
|
+
try {
|
|
28
|
+
if (configPath.endsWith(".yml") || configPath.endsWith(".yaml")) {
|
|
29
|
+
config = _load(fs.readFileSync(configPath, "utf-8"));
|
|
30
|
+
} else {
|
|
31
|
+
config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
|
32
|
+
}
|
|
33
|
+
} catch (e) {
|
|
34
|
+
console.log("Invalid config file", configPath);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
14
37
|
|
|
15
38
|
let url = import.meta.url;
|
|
16
39
|
if (!url.startsWith("file://")) {
|
|
@@ -22,6 +45,7 @@ import yargs from "yargs";
|
|
|
22
45
|
import { hideBin } from "yargs/helpers";
|
|
23
46
|
|
|
24
47
|
const args = yargs(hideBin(process.argv))
|
|
48
|
+
.env("CDXGEN")
|
|
25
49
|
.option("output", {
|
|
26
50
|
alias: "o",
|
|
27
51
|
description: "Output file for bom.xml or bom.json. Default bom.json"
|
|
@@ -77,7 +101,8 @@ const args = yargs(hideBin(process.argv))
|
|
|
77
101
|
})
|
|
78
102
|
.option("required-only", {
|
|
79
103
|
type: "boolean",
|
|
80
|
-
description:
|
|
104
|
+
description:
|
|
105
|
+
"Include only the packages with required scope on the SBOM. Would set compositions.aggregate to incomplete unless --no-auto-compositions is passed."
|
|
81
106
|
})
|
|
82
107
|
.option("fail-on-error", {
|
|
83
108
|
type: "boolean",
|
|
@@ -118,6 +143,7 @@ const args = yargs(hideBin(process.argv))
|
|
|
118
143
|
"Validate the generated SBOM using json schema. Defaults to true. Pass --no-validate to disable."
|
|
119
144
|
})
|
|
120
145
|
.option("evidence", {
|
|
146
|
+
hidden: true,
|
|
121
147
|
type: "boolean",
|
|
122
148
|
default: false,
|
|
123
149
|
description: "Generate SBOM with evidence for supported languages. WIP"
|
|
@@ -132,6 +158,35 @@ const args = yargs(hideBin(process.argv))
|
|
|
132
158
|
description: "CycloneDX Specification version to use. Defaults to 1.5",
|
|
133
159
|
default: 1.5
|
|
134
160
|
})
|
|
161
|
+
.option("filter", {
|
|
162
|
+
description:
|
|
163
|
+
"Filter components containining this word in purl. Multiple values allowed."
|
|
164
|
+
})
|
|
165
|
+
.option("only", {
|
|
166
|
+
description:
|
|
167
|
+
"Include components only containining this word in purl. Useful to generate BOM with first party components alone. Multiple values allowed."
|
|
168
|
+
})
|
|
169
|
+
.option("author", {
|
|
170
|
+
description:
|
|
171
|
+
"The person(s) who created the BOM. Set this value if you're intending the modify the BOM and claim authorship.",
|
|
172
|
+
default: "OWASP Foundation"
|
|
173
|
+
})
|
|
174
|
+
.completion("completion", "Generate bash/zsh completion")
|
|
175
|
+
.array("filter")
|
|
176
|
+
.array("only")
|
|
177
|
+
.array("author")
|
|
178
|
+
.option("auto-compositions", {
|
|
179
|
+
type: "boolean",
|
|
180
|
+
default: true,
|
|
181
|
+
description:
|
|
182
|
+
"Automatically set compositions when the BOM was filtered. Defaults to true"
|
|
183
|
+
})
|
|
184
|
+
.example([
|
|
185
|
+
["$0 -t java .", "Generate a Java SBOM for the current directory"],
|
|
186
|
+
["$0 --server", "Run cdxgen as a server"]
|
|
187
|
+
])
|
|
188
|
+
.epilogue("for documentation, visit https://cyclonedx.github.io/cdxgen")
|
|
189
|
+
.config(config)
|
|
135
190
|
.scriptName("cdxgen")
|
|
136
191
|
.version()
|
|
137
192
|
.alias("v", "version")
|
|
@@ -166,43 +221,20 @@ if (!args.projectName) {
|
|
|
166
221
|
}
|
|
167
222
|
}
|
|
168
223
|
|
|
169
|
-
// To help dependency track users, we downgrade the spec version to 1.4 automatically
|
|
170
|
-
if (args.serverUrl || args.apiKey) {
|
|
171
|
-
args.specVersion = 1.4;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
224
|
// Support for obom aliases
|
|
175
225
|
if (process.argv[1].includes("obom") && !args.type) {
|
|
176
226
|
args.type = "os";
|
|
177
227
|
}
|
|
178
228
|
|
|
179
229
|
/**
|
|
180
|
-
*
|
|
181
|
-
* multiProject: Boolean to indicate monorepo or multi-module projects
|
|
230
|
+
* Command line options
|
|
182
231
|
*/
|
|
183
|
-
const options = {
|
|
232
|
+
const options = Object.assign({}, args, {
|
|
184
233
|
projectType: args.type,
|
|
185
234
|
multiProject: args.recurse,
|
|
186
|
-
output: args.output,
|
|
187
|
-
resolveClass: args.resolveClass,
|
|
188
|
-
installDeps: args.installDeps,
|
|
189
|
-
requiredOnly: args.requiredOnly,
|
|
190
|
-
failOnError: args.failOnError,
|
|
191
235
|
noBabel: args.noBabel || args.babel === false,
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
project: args.projectId,
|
|
195
|
-
projectName: args.projectName,
|
|
196
|
-
projectGroup: args.projectGroup,
|
|
197
|
-
projectVersion: args.projectVersion,
|
|
198
|
-
server: args.server,
|
|
199
|
-
serverHost: args.serverHost,
|
|
200
|
-
serverPort: args.serverPort,
|
|
201
|
-
specVersion: args.specVersion,
|
|
202
|
-
evidence: args.evidence,
|
|
203
|
-
usagesSlicesFile: args.usagesSlicesFile,
|
|
204
|
-
dataFlowSlicesFile: args.dataFlowSlicesFile
|
|
205
|
-
};
|
|
236
|
+
project: args.projectId
|
|
237
|
+
});
|
|
206
238
|
|
|
207
239
|
/**
|
|
208
240
|
* Check for node >= 20 permissions
|
|
@@ -243,7 +275,7 @@ const checkPermissions = (filePath) => {
|
|
|
243
275
|
// Start SBOM server
|
|
244
276
|
if (args.server) {
|
|
245
277
|
const serverModule = await import("../server.js");
|
|
246
|
-
return
|
|
278
|
+
return serverModule.start(options);
|
|
247
279
|
}
|
|
248
280
|
// Check if cdxgen has the required permissions
|
|
249
281
|
if (!checkPermissions(filePath)) {
|
|
@@ -253,7 +285,10 @@ const checkPermissions = (filePath) => {
|
|
|
253
285
|
if (!options.usagesSlicesFile) {
|
|
254
286
|
options.usagesSlicesFile = `${options.projectName}-usages.json`;
|
|
255
287
|
}
|
|
256
|
-
|
|
288
|
+
let bomNSData = (await createBom(filePath, options)) || {};
|
|
289
|
+
if (options.requiredOnly || options["filter"] || options["only"]) {
|
|
290
|
+
bomNSData = postProcess(bomNSData, options);
|
|
291
|
+
}
|
|
257
292
|
if (!args.output) {
|
|
258
293
|
args.output = "bom.json";
|
|
259
294
|
}
|
package/bin/evinse.js
CHANGED
|
@@ -9,7 +9,34 @@ import { homedir, platform as _platform } from "node:os";
|
|
|
9
9
|
import process from "node:process";
|
|
10
10
|
import { analyzeProject, createEvinseFile, prepareDB } from "../evinser.js";
|
|
11
11
|
import { validateBom } from "../validator.js";
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
printCallStack,
|
|
14
|
+
printOccurrences,
|
|
15
|
+
printServices,
|
|
16
|
+
printReachables
|
|
17
|
+
} from "../display.js";
|
|
18
|
+
import { findUpSync } from "find-up";
|
|
19
|
+
import { load as _load } from "js-yaml";
|
|
20
|
+
|
|
21
|
+
// Support for config files
|
|
22
|
+
const configPath = findUpSync([
|
|
23
|
+
".cdxgenrc",
|
|
24
|
+
".cdxgen.json",
|
|
25
|
+
".cdxgen.yml",
|
|
26
|
+
".cdxgen.yaml"
|
|
27
|
+
]);
|
|
28
|
+
let config = {};
|
|
29
|
+
if (configPath) {
|
|
30
|
+
try {
|
|
31
|
+
if (configPath.endsWith(".yml") || configPath.endsWith(".yaml")) {
|
|
32
|
+
config = _load(fs.readFileSync(configPath, "utf-8"));
|
|
33
|
+
} else {
|
|
34
|
+
config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
|
35
|
+
}
|
|
36
|
+
} catch (e) {
|
|
37
|
+
console.log("Invalid config file", configPath);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
13
40
|
|
|
14
41
|
const isWin = _platform() === "win32";
|
|
15
42
|
const isMac = _platform() === "darwin";
|
|
@@ -28,6 +55,7 @@ if (!process.env.ATOM_DB && !fs.existsSync(ATOM_DB)) {
|
|
|
28
55
|
}
|
|
29
56
|
}
|
|
30
57
|
const args = yargs(hideBin(process.argv))
|
|
58
|
+
.env("EVINSE")
|
|
31
59
|
.option("input", {
|
|
32
60
|
alias: "i",
|
|
33
61
|
description: "Input SBOM file. Default bom.json",
|
|
@@ -42,7 +70,18 @@ const args = yargs(hideBin(process.argv))
|
|
|
42
70
|
alias: "l",
|
|
43
71
|
description: "Application language",
|
|
44
72
|
default: "java",
|
|
45
|
-
choices: [
|
|
73
|
+
choices: [
|
|
74
|
+
"java",
|
|
75
|
+
"jar",
|
|
76
|
+
"js",
|
|
77
|
+
"ts",
|
|
78
|
+
"javascript",
|
|
79
|
+
"py",
|
|
80
|
+
"python",
|
|
81
|
+
"android",
|
|
82
|
+
"c",
|
|
83
|
+
"cpp"
|
|
84
|
+
]
|
|
46
85
|
})
|
|
47
86
|
.option("db-path", {
|
|
48
87
|
description: `Atom slices DB path. Default ${ATOM_DB}`,
|
|
@@ -75,6 +114,12 @@ const args = yargs(hideBin(process.argv))
|
|
|
75
114
|
default: false,
|
|
76
115
|
type: "boolean"
|
|
77
116
|
})
|
|
117
|
+
.option("with-reachables", {
|
|
118
|
+
description:
|
|
119
|
+
"Enable auto-tagged reachable slicing. Requires SBOM generated with --deep mode.",
|
|
120
|
+
default: false,
|
|
121
|
+
type: "boolean"
|
|
122
|
+
})
|
|
78
123
|
.option("usages-slices-file", {
|
|
79
124
|
description: "Use an existing usages slices file.",
|
|
80
125
|
default: "usages.slices.json"
|
|
@@ -83,11 +128,28 @@ const args = yargs(hideBin(process.argv))
|
|
|
83
128
|
description: "Use an existing data-flow slices file.",
|
|
84
129
|
default: "data-flow.slices.json"
|
|
85
130
|
})
|
|
131
|
+
.option("reachables-slices-file", {
|
|
132
|
+
description: "Use an existing reachables slices file.",
|
|
133
|
+
default: "reachables.slices.json"
|
|
134
|
+
})
|
|
86
135
|
.option("print", {
|
|
87
136
|
alias: "p",
|
|
88
137
|
type: "boolean",
|
|
89
138
|
description: "Print the evidences as table"
|
|
90
139
|
})
|
|
140
|
+
.example([
|
|
141
|
+
[
|
|
142
|
+
"$0 -i bom.json -o bom.evinse.json -l java .",
|
|
143
|
+
"Generate a Java SBOM with evidence for the current directory"
|
|
144
|
+
],
|
|
145
|
+
[
|
|
146
|
+
"$0 -i bom.json -o bom.evinse.json -l java --with-reachables .",
|
|
147
|
+
"Generate a Java SBOM with occurrence and reachable evidence for the current directory"
|
|
148
|
+
]
|
|
149
|
+
])
|
|
150
|
+
.completion("completion", "Generate bash/zsh completion")
|
|
151
|
+
.epilogue("for documentation, visit https://cyclonedx.github.io/cdxgen")
|
|
152
|
+
.config(config)
|
|
91
153
|
.scriptName("evinse")
|
|
92
154
|
.version()
|
|
93
155
|
.help("h").argv;
|
|
@@ -95,8 +157,8 @@ const args = yargs(hideBin(process.argv))
|
|
|
95
157
|
const evinseArt = `
|
|
96
158
|
███████╗██╗ ██╗██╗███╗ ██╗███████╗███████╗
|
|
97
159
|
██╔════╝██║ ██║██║████╗ ██║██╔════╝██╔════╝
|
|
98
|
-
█████╗ ██║ ██║██║██╔██╗ ██║███████╗█████╗
|
|
99
|
-
██╔══╝ ╚██╗ ██╔╝██║██║╚██╗██║╚════██║██╔══╝
|
|
160
|
+
█████╗ ██║ ██║██║██╔██╗ ██║███████╗█████╗
|
|
161
|
+
██╔══╝ ╚██╗ ██╔╝██║██║╚██╗██║╚════██║██╔══╝
|
|
100
162
|
███████╗ ╚████╔╝ ██║██║ ╚████║███████║███████╗
|
|
101
163
|
╚══════╝ ╚═══╝ ╚═╝╚═╝ ╚═══╝╚══════╝╚══════╝
|
|
102
164
|
`;
|
|
@@ -117,6 +179,7 @@ console.log(evinseArt);
|
|
|
117
179
|
if (args.print) {
|
|
118
180
|
printOccurrences(bomJson);
|
|
119
181
|
printCallStack(bomJson);
|
|
182
|
+
printReachables(sliceArtefacts);
|
|
120
183
|
printServices(bomJson);
|
|
121
184
|
}
|
|
122
185
|
}
|
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 {
|
|
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 |
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
{
|
|
2
|
+
"all": [
|
|
3
|
+
"System.Web",
|
|
4
|
+
"System.ServiceModel",
|
|
5
|
+
"System.Data",
|
|
6
|
+
"spring",
|
|
7
|
+
"flask",
|
|
8
|
+
"django",
|
|
9
|
+
"beego",
|
|
10
|
+
"chi",
|
|
11
|
+
"echo",
|
|
12
|
+
"github.com/gin-gonic/gin",
|
|
13
|
+
"gorilla",
|
|
14
|
+
"rye",
|
|
15
|
+
"httprouter",
|
|
16
|
+
"akka",
|
|
17
|
+
"dropwizard",
|
|
18
|
+
"vertx",
|
|
19
|
+
"gwt",
|
|
20
|
+
"jax-rs",
|
|
21
|
+
"jax-ws",
|
|
22
|
+
"jsf",
|
|
23
|
+
"play",
|
|
24
|
+
"spark",
|
|
25
|
+
"struts",
|
|
26
|
+
"angular",
|
|
27
|
+
"react",
|
|
28
|
+
"next",
|
|
29
|
+
"ember",
|
|
30
|
+
"express",
|
|
31
|
+
"knex",
|
|
32
|
+
"vue",
|
|
33
|
+
"aiohttp",
|
|
34
|
+
"bottle",
|
|
35
|
+
"cherrypy",
|
|
36
|
+
"drt",
|
|
37
|
+
"falcon",
|
|
38
|
+
"hug",
|
|
39
|
+
"pyramid",
|
|
40
|
+
"sanic",
|
|
41
|
+
"tornado",
|
|
42
|
+
"vibora",
|
|
43
|
+
"koa",
|
|
44
|
+
"-sdk",
|
|
45
|
+
"org.apache",
|
|
46
|
+
"appfuse",
|
|
47
|
+
"drools",
|
|
48
|
+
"jbpm",
|
|
49
|
+
"activiti",
|
|
50
|
+
"barracuda",
|
|
51
|
+
"birt",
|
|
52
|
+
"biojava",
|
|
53
|
+
"bluecove",
|
|
54
|
+
"bouncycastle",
|
|
55
|
+
"cascading",
|
|
56
|
+
"deeplearning4j",
|
|
57
|
+
"eclipselink",
|
|
58
|
+
"geoapi",
|
|
59
|
+
"geotools",
|
|
60
|
+
"hibernate",
|
|
61
|
+
"hsqldb",
|
|
62
|
+
"ibatis",
|
|
63
|
+
"javassist",
|
|
64
|
+
"jersey",
|
|
65
|
+
"jetty",
|
|
66
|
+
"jfreechart",
|
|
67
|
+
"jhipster",
|
|
68
|
+
"jmonkeyengine",
|
|
69
|
+
"jsf",
|
|
70
|
+
"keycloak",
|
|
71
|
+
"liquibase",
|
|
72
|
+
"lwjgl",
|
|
73
|
+
"micronaut",
|
|
74
|
+
"mybatis",
|
|
75
|
+
"netty",
|
|
76
|
+
"neuroph",
|
|
77
|
+
"opencv",
|
|
78
|
+
"orientdb",
|
|
79
|
+
"ormlite",
|
|
80
|
+
"payara",
|
|
81
|
+
"primefaces",
|
|
82
|
+
"quarkus",
|
|
83
|
+
"quartz",
|
|
84
|
+
"sax",
|
|
85
|
+
"slf4j",
|
|
86
|
+
"jasper",
|
|
87
|
+
"spock",
|
|
88
|
+
"thymeleaf",
|
|
89
|
+
"vaadin",
|
|
90
|
+
"vertx",
|
|
91
|
+
"wildfly",
|
|
92
|
+
"zkoss",
|
|
93
|
+
"org.ow2.asm",
|
|
94
|
+
"backbone",
|
|
95
|
+
"dojo",
|
|
96
|
+
"ember",
|
|
97
|
+
"enyo",
|
|
98
|
+
"extjs",
|
|
99
|
+
"jquery",
|
|
100
|
+
"jqwidgets",
|
|
101
|
+
"knockout",
|
|
102
|
+
"mootools",
|
|
103
|
+
"prototypejs",
|
|
104
|
+
"qooxdoo",
|
|
105
|
+
"openui5",
|
|
106
|
+
"solidjs",
|
|
107
|
+
"sproutcore",
|
|
108
|
+
"svelte",
|
|
109
|
+
"wakanda",
|
|
110
|
+
"webix",
|
|
111
|
+
"github.com/aerogo/aero",
|
|
112
|
+
"github.com/aofei/air",
|
|
113
|
+
"github.com/go-the-way/anoweb",
|
|
114
|
+
"github.com/appist/appy",
|
|
115
|
+
"github.com/ungerik/go-rest",
|
|
116
|
+
"goa.design/goa",
|
|
117
|
+
"github.com/aceld/zinx",
|
|
118
|
+
"github.com/dolab/gogo",
|
|
119
|
+
"github.com/yarf-framework/yarf",
|
|
120
|
+
"github.com/norunners/vert",
|
|
121
|
+
"pkg:cargo/rocket",
|
|
122
|
+
"pkg:cargo/actix",
|
|
123
|
+
"pkg:cargo/nickel",
|
|
124
|
+
"pkg:cargo/yew",
|
|
125
|
+
"pkg:cargo/azul",
|
|
126
|
+
"pkg:cargo/conrod"
|
|
127
|
+
]
|
|
128
|
+
}
|