@cyclonedx/cdxgen 9.8.10 → 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 +40 -35
- package/analyzer.js +6 -2
- package/bin/cdxgen.js +8 -5
- package/bin/evinse.js +43 -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 +101 -86
- package/package.json +5 -5
- package/server.js +0 -5
- package/utils.js +378 -163
- package/utils.test.js +80 -6
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
|
|
|
@@ -181,6 +181,9 @@ Options:
|
|
|
181
181
|
--only Include components only containining this word in
|
|
182
182
|
purl. Useful to generate BOM with first party co
|
|
183
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"]
|
|
184
187
|
--auto-compositions Automatically set compositions when the BOM was f
|
|
185
188
|
iltered. Defaults to true
|
|
186
189
|
[boolean] [default: true]
|
|
@@ -338,7 +341,7 @@ cdxgen can retain the dependency tree under the `dependencies` attribute for a s
|
|
|
338
341
|
- Gradle
|
|
339
342
|
- Scala SBT
|
|
340
343
|
- Python (requirements.txt, setup.py, pyproject.toml, poetry.lock)
|
|
341
|
-
-
|
|
344
|
+
- .NET (project.assets.json, paket.lock)
|
|
342
345
|
- Go (go.mod)
|
|
343
346
|
|
|
344
347
|
## Environment variables
|
|
@@ -367,6 +370,7 @@ cdxgen can retain the dependency tree under the `dependencies` attribute for a s
|
|
|
367
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 |
|
|
368
371
|
| CDXGEN_TIMEOUT_MS | Default timeout for known execution involving maven, gradle or sbt |
|
|
369
372
|
| CDXGEN_SERVER_TIMEOUT_MS | Default timeout in server mode |
|
|
373
|
+
| CDXGEN_MAX_BUFFER | Max buffer for stdout and stderr. Defaults to 100MB |
|
|
370
374
|
| CLJ_CMD | Set to override the clojure cli command |
|
|
371
375
|
| LEIN_CMD | Set to override the leiningen command |
|
|
372
376
|
| SBOM_SIGN_ALGORITHM | Signature algorithm. Some valid values are RS256, RS384, RS512, PS256, PS384, PS512, ES256 etc |
|
|
@@ -377,6 +381,7 @@ cdxgen can retain the dependency tree under the `dependencies` attribute for a s
|
|
|
377
381
|
| CDX_MAVEN_INCLUDE_TEST_SCOPE | Whether test scoped dependencies should be included from Maven projects, Default: true |
|
|
378
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. |
|
|
379
383
|
| ASTGEN_IGNORE_FILE_PATTERN | Ignore regex to use |
|
|
384
|
+
| PYPI_URL | Override pypi url. Default: https://pypi.org/pypi/ |
|
|
380
385
|
|
|
381
386
|
## Plugins
|
|
382
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
|
@@ -143,6 +143,7 @@ const args = yargs(hideBin(process.argv))
|
|
|
143
143
|
"Validate the generated SBOM using json schema. Defaults to true. Pass --no-validate to disable."
|
|
144
144
|
})
|
|
145
145
|
.option("evidence", {
|
|
146
|
+
hidden: true,
|
|
146
147
|
type: "boolean",
|
|
147
148
|
default: false,
|
|
148
149
|
description: "Generate SBOM with evidence for supported languages. WIP"
|
|
@@ -165,8 +166,15 @@ const args = yargs(hideBin(process.argv))
|
|
|
165
166
|
description:
|
|
166
167
|
"Include components only containining this word in purl. Useful to generate BOM with first party components alone. Multiple values allowed."
|
|
167
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")
|
|
168
175
|
.array("filter")
|
|
169
176
|
.array("only")
|
|
177
|
+
.array("author")
|
|
170
178
|
.option("auto-compositions", {
|
|
171
179
|
type: "boolean",
|
|
172
180
|
default: true,
|
|
@@ -213,11 +221,6 @@ if (!args.projectName) {
|
|
|
213
221
|
}
|
|
214
222
|
}
|
|
215
223
|
|
|
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
224
|
// Support for obom aliases
|
|
222
225
|
if (process.argv[1].includes("obom") && !args.type) {
|
|
223
226
|
args.type = "os";
|
package/bin/evinse.js
CHANGED
|
@@ -9,7 +9,12 @@ 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";
|
|
13
18
|
import { findUpSync } from "find-up";
|
|
14
19
|
import { load as _load } from "js-yaml";
|
|
15
20
|
|
|
@@ -65,7 +70,18 @@ const args = yargs(hideBin(process.argv))
|
|
|
65
70
|
alias: "l",
|
|
66
71
|
description: "Application language",
|
|
67
72
|
default: "java",
|
|
68
|
-
choices: [
|
|
73
|
+
choices: [
|
|
74
|
+
"java",
|
|
75
|
+
"jar",
|
|
76
|
+
"js",
|
|
77
|
+
"ts",
|
|
78
|
+
"javascript",
|
|
79
|
+
"py",
|
|
80
|
+
"python",
|
|
81
|
+
"android",
|
|
82
|
+
"c",
|
|
83
|
+
"cpp"
|
|
84
|
+
]
|
|
69
85
|
})
|
|
70
86
|
.option("db-path", {
|
|
71
87
|
description: `Atom slices DB path. Default ${ATOM_DB}`,
|
|
@@ -98,6 +114,12 @@ const args = yargs(hideBin(process.argv))
|
|
|
98
114
|
default: false,
|
|
99
115
|
type: "boolean"
|
|
100
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
|
+
})
|
|
101
123
|
.option("usages-slices-file", {
|
|
102
124
|
description: "Use an existing usages slices file.",
|
|
103
125
|
default: "usages.slices.json"
|
|
@@ -106,11 +128,27 @@ const args = yargs(hideBin(process.argv))
|
|
|
106
128
|
description: "Use an existing data-flow slices file.",
|
|
107
129
|
default: "data-flow.slices.json"
|
|
108
130
|
})
|
|
131
|
+
.option("reachables-slices-file", {
|
|
132
|
+
description: "Use an existing reachables slices file.",
|
|
133
|
+
default: "reachables.slices.json"
|
|
134
|
+
})
|
|
109
135
|
.option("print", {
|
|
110
136
|
alias: "p",
|
|
111
137
|
type: "boolean",
|
|
112
138
|
description: "Print the evidences as table"
|
|
113
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")
|
|
114
152
|
.config(config)
|
|
115
153
|
.scriptName("evinse")
|
|
116
154
|
.version()
|
|
@@ -119,8 +157,8 @@ const args = yargs(hideBin(process.argv))
|
|
|
119
157
|
const evinseArt = `
|
|
120
158
|
███████╗██╗ ██╗██╗███╗ ██╗███████╗███████╗
|
|
121
159
|
██╔════╝██║ ██║██║████╗ ██║██╔════╝██╔════╝
|
|
122
|
-
█████╗ ██║ ██║██║██╔██╗ ██║███████╗█████╗
|
|
123
|
-
██╔══╝ ╚██╗ ██╔╝██║██║╚██╗██║╚════██║██╔══╝
|
|
160
|
+
█████╗ ██║ ██║██║██╔██╗ ██║███████╗█████╗
|
|
161
|
+
██╔══╝ ╚██╗ ██╔╝██║██║╚██╗██║╚════██║██╔══╝
|
|
124
162
|
███████╗ ╚████╔╝ ██║██║ ╚████║███████║███████╗
|
|
125
163
|
╚══════╝ ╚═══╝ ╚═╝╚═╝ ╚═══╝╚══════╝╚══════╝
|
|
126
164
|
`;
|
|
@@ -141,6 +179,7 @@ console.log(evinseArt);
|
|
|
141
179
|
if (args.print) {
|
|
142
180
|
printOccurrences(bomJson);
|
|
143
181
|
printCallStack(bomJson);
|
|
182
|
+
printReachables(sliceArtefacts);
|
|
144
183
|
printServices(bomJson);
|
|
145
184
|
}
|
|
146
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
|
+
}
|
package/display.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "fs";
|
|
1
2
|
import { createStream, table } from "table";
|
|
2
3
|
|
|
3
4
|
// https://github.com/yangshun/tree-node-cli/blob/master/src/index.js
|
|
@@ -277,3 +278,36 @@ const recursePrint = (depMap, subtree, level, shownList, treeGraphics) => {
|
|
|
277
278
|
}
|
|
278
279
|
}
|
|
279
280
|
};
|
|
281
|
+
|
|
282
|
+
export const printReachables = (sliceArtefacts) => {
|
|
283
|
+
const reachablesSlicesFile = sliceArtefacts.reachablesSlicesFile;
|
|
284
|
+
if (!existsSync(reachablesSlicesFile)) {
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
const purlCounts = {};
|
|
288
|
+
const reachablesSlices = JSON.parse(
|
|
289
|
+
readFileSync(reachablesSlicesFile, "utf-8")
|
|
290
|
+
);
|
|
291
|
+
for (const areachable of reachablesSlices.reachables || []) {
|
|
292
|
+
const purls = areachable.purls || [];
|
|
293
|
+
for (const apurl of purls) {
|
|
294
|
+
purlCounts[apurl] = (purlCounts[apurl] || 0) + 1;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
const sortedPurls = Object.fromEntries(
|
|
298
|
+
Object.entries(purlCounts).sort(([, a], [, b]) => b - a)
|
|
299
|
+
);
|
|
300
|
+
const data = [["Package URL", "Reachable Flows"]];
|
|
301
|
+
for (const apurl of Object.keys(sortedPurls)) {
|
|
302
|
+
data.push([apurl, "" + sortedPurls[apurl]]);
|
|
303
|
+
}
|
|
304
|
+
const config = {
|
|
305
|
+
header: {
|
|
306
|
+
alignment: "center",
|
|
307
|
+
content: "Reachable Components\nGenerated with \u2665 by cdxgen"
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
if (data.length > 1) {
|
|
311
|
+
console.log(table(data, config));
|
|
312
|
+
}
|
|
313
|
+
};
|
package/docker.js
CHANGED
|
@@ -323,6 +323,9 @@ export const parseImageName = (fullImageName) => {
|
|
|
323
323
|
fullImageName = fullImageName.replace(":" + nameObj.tag, "");
|
|
324
324
|
}
|
|
325
325
|
}
|
|
326
|
+
if (fullImageName && fullImageName.startsWith("library/")) {
|
|
327
|
+
fullImageName = fullImageName.replace("library/", "");
|
|
328
|
+
}
|
|
326
329
|
// The left over string is the repo name
|
|
327
330
|
nameObj.repo = fullImageName;
|
|
328
331
|
return nameObj;
|
|
@@ -333,7 +336,9 @@ export const parseImageName = (fullImageName) => {
|
|
|
333
336
|
*/
|
|
334
337
|
export const getImage = async (fullImageName) => {
|
|
335
338
|
let localData = undefined;
|
|
339
|
+
let pullData = undefined;
|
|
336
340
|
const { repo, tag, digest } = parseImageName(fullImageName);
|
|
341
|
+
let repoWithTag = `${repo}:${tag !== "" ? tag : ":latest"}`;
|
|
337
342
|
// Fetch only the latest tag if none is specified
|
|
338
343
|
if (tag === "" && digest === "") {
|
|
339
344
|
fullImageName = fullImageName + ":latest";
|
|
@@ -379,6 +384,14 @@ export const getImage = async (fullImageName) => {
|
|
|
379
384
|
}
|
|
380
385
|
}
|
|
381
386
|
}
|
|
387
|
+
try {
|
|
388
|
+
localData = await makeRequest(`images/${repoWithTag}/json`);
|
|
389
|
+
if (localData) {
|
|
390
|
+
return localData;
|
|
391
|
+
}
|
|
392
|
+
} catch (err) {
|
|
393
|
+
// ignore
|
|
394
|
+
}
|
|
382
395
|
try {
|
|
383
396
|
localData = await makeRequest(`images/${repo}/json`);
|
|
384
397
|
} catch (err) {
|
|
@@ -397,7 +410,7 @@ export const getImage = async (fullImageName) => {
|
|
|
397
410
|
}
|
|
398
411
|
// If the data is not available locally
|
|
399
412
|
try {
|
|
400
|
-
|
|
413
|
+
pullData = await makeRequest(
|
|
401
414
|
`images/create?fromImage=${fullImageName}`,
|
|
402
415
|
"POST"
|
|
403
416
|
);
|
|
@@ -415,15 +428,42 @@ export const getImage = async (fullImageName) => {
|
|
|
415
428
|
return undefined;
|
|
416
429
|
}
|
|
417
430
|
} catch (err) {
|
|
418
|
-
|
|
431
|
+
try {
|
|
432
|
+
if (DEBUG_MODE) {
|
|
433
|
+
console.log(`Re-trying the pull with the name ${repoWithTag}.`);
|
|
434
|
+
}
|
|
435
|
+
pullData = await makeRequest(
|
|
436
|
+
`images/create?fromImage=${repoWithTag}`,
|
|
437
|
+
"POST"
|
|
438
|
+
);
|
|
439
|
+
} catch (err) {
|
|
440
|
+
// continue regardless of error
|
|
441
|
+
}
|
|
419
442
|
}
|
|
420
443
|
try {
|
|
421
444
|
if (DEBUG_MODE) {
|
|
422
|
-
console.log(`Trying with ${
|
|
445
|
+
console.log(`Trying with ${repoWithTag}`);
|
|
446
|
+
}
|
|
447
|
+
localData = await makeRequest(`images/${repoWithTag}/json`);
|
|
448
|
+
if (localData) {
|
|
449
|
+
return localData;
|
|
423
450
|
}
|
|
424
|
-
localData = await makeRequest(`images/${repo}/json`);
|
|
425
451
|
} catch (err) {
|
|
426
452
|
try {
|
|
453
|
+
if (DEBUG_MODE) {
|
|
454
|
+
console.log(`Trying with ${repo}`);
|
|
455
|
+
}
|
|
456
|
+
localData = await makeRequest(`images/${repo}/json`);
|
|
457
|
+
if (localData) {
|
|
458
|
+
return localData;
|
|
459
|
+
}
|
|
460
|
+
} catch (err) {
|
|
461
|
+
// continue regardless of error
|
|
462
|
+
}
|
|
463
|
+
try {
|
|
464
|
+
if (DEBUG_MODE) {
|
|
465
|
+
console.log(`Trying with ${fullImageName}`);
|
|
466
|
+
}
|
|
427
467
|
localData = await makeRequest(`images/${fullImageName}/json`);
|
|
428
468
|
} catch (err) {
|
|
429
469
|
// continue regardless of error
|
|
@@ -701,7 +741,26 @@ export const exportImage = async (fullImageName) => {
|
|
|
701
741
|
})
|
|
702
742
|
);
|
|
703
743
|
} catch (err) {
|
|
704
|
-
|
|
744
|
+
if (localData && localData.Id) {
|
|
745
|
+
console.log(`Retrying with ${localData.Id}`);
|
|
746
|
+
try {
|
|
747
|
+
await stream.pipeline(
|
|
748
|
+
client.stream(`images/${localData.Id}/get`),
|
|
749
|
+
x({
|
|
750
|
+
sync: true,
|
|
751
|
+
preserveOwner: false,
|
|
752
|
+
noMtime: true,
|
|
753
|
+
noChmod: true,
|
|
754
|
+
strict: true,
|
|
755
|
+
C: tempDir,
|
|
756
|
+
portable: true,
|
|
757
|
+
onwarn: () => {}
|
|
758
|
+
})
|
|
759
|
+
);
|
|
760
|
+
} catch (err) {
|
|
761
|
+
console.log(err);
|
|
762
|
+
}
|
|
763
|
+
}
|
|
705
764
|
}
|
|
706
765
|
}
|
|
707
766
|
// Continue with extracting the layers
|