@cyclonedx/cdxgen 9.8.6 → 9.8.8
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 +17 -8
- package/analyzer.js +3 -3
- package/bin/cdxgen.js +3 -3
- package/bin/repl.js +20 -20
- package/binary.js +1 -1
- package/docker.js +1 -1
- package/index.js +186 -76
- package/package.json +9 -9
- package/server.js +7 -3
- package/utils.js +342 -71
- package/utils.test.js +90 -18
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
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
|
-
When used with plugins, cdxgen could generate an
|
|
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
|
|
|
9
9
|
NOTE:
|
|
10
10
|
|
|
@@ -27,7 +27,7 @@ A typical application might have several repos, components, and libraries. Tradi
|
|
|
27
27
|
| go | binary, go.mod, go.sum, Gopkg.lock | Yes except binary |
|
|
28
28
|
| ruby | Gemfile.lock, gemspec | Only for Gemfile.lock |
|
|
29
29
|
| rust | binary, Cargo.toml, Cargo.lock | Only for Cargo.lock |
|
|
30
|
-
| .Net | .csproj, packages.config, project.assets.json [3], packages.lock.json, .nupkg
|
|
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
31
|
| dart | pubspec.lock, pubspec.yaml | Only for pubspec.lock |
|
|
32
32
|
| haskell | cabal.project.freeze | Yes |
|
|
33
33
|
| elixir | mix.lock | Yes |
|
|
@@ -61,7 +61,7 @@ NOTE:
|
|
|
61
61
|
|
|
62
62
|
Footnotes:
|
|
63
63
|
|
|
64
|
-
- [1] - For multi-module applications, the
|
|
64
|
+
- [1] - For multi-module applications, the BOM file could include components not included in the packaged war or ear file.
|
|
65
65
|
- [2] - Pip freeze is automatically performed to improve precision. Requires virtual environment.
|
|
66
66
|
- [3] - Perform dotnet or nuget restore to generate project.assets.json. Without this file, cdxgen would not include indirect dependencies.
|
|
67
67
|
- [4] - See the section on plugins
|
|
@@ -197,7 +197,7 @@ To print the SBOM as a table pass `-p` argument.
|
|
|
197
197
|
cdxgen -t java -o bom.json -p
|
|
198
198
|
```
|
|
199
199
|
|
|
200
|
-
To recursively generate a single
|
|
200
|
+
To recursively generate a single BOM for all languages pass `-r` argument.
|
|
201
201
|
|
|
202
202
|
```shell
|
|
203
203
|
cdxgen -r -o bom.json
|
|
@@ -254,6 +254,14 @@ Arguments can be passed either via the query string or as a JSON body. The follo
|
|
|
254
254
|
| projectGroup | Dependency track project group |
|
|
255
255
|
| projectVersion | Dependency track project version [default: ""] |
|
|
256
256
|
|
|
257
|
+
### Health endpoint
|
|
258
|
+
|
|
259
|
+
Use the /health endpoint to check if the SBOM server is up and running.
|
|
260
|
+
|
|
261
|
+
```shell
|
|
262
|
+
curl "http://127.0.0.1:9090/health"
|
|
263
|
+
```
|
|
264
|
+
|
|
257
265
|
### Scanning a local path
|
|
258
266
|
|
|
259
267
|
```shell
|
|
@@ -281,7 +289,7 @@ docker compose up
|
|
|
281
289
|
|
|
282
290
|
## War file support
|
|
283
291
|
|
|
284
|
-
cdxgen can generate a
|
|
292
|
+
cdxgen can generate a BOM file from a given war file.
|
|
285
293
|
|
|
286
294
|
```shell
|
|
287
295
|
# cdxgen -t java app.war
|
|
@@ -318,6 +326,7 @@ cdxgen can retain the dependency tree under the `dependencies` attribute for a s
|
|
|
318
326
|
- Scala SBT
|
|
319
327
|
- Python (requirements.txt, setup.py, pyproject.toml, poetry.lock)
|
|
320
328
|
- csharp (projects.assets.json)
|
|
329
|
+
- Go (go.mod)
|
|
321
330
|
|
|
322
331
|
## Environment variables
|
|
323
332
|
|
|
@@ -399,9 +408,9 @@ systemctl --user start podman.socket
|
|
|
399
408
|
podman system service -t 0 &
|
|
400
409
|
```
|
|
401
410
|
|
|
402
|
-
### Generate
|
|
411
|
+
### Generate OBOM for a live system
|
|
403
412
|
|
|
404
|
-
You can use the `obom` command to generate an
|
|
413
|
+
You can use the `obom` command to generate an OBOM for a live system or a VM for compliance and vulnerability management purposes. Windows and Linux operating systems are supported in this mode.
|
|
405
414
|
|
|
406
415
|
```shell
|
|
407
416
|
# obom is an alias for cdxgen -t os
|
|
@@ -417,7 +426,7 @@ See [evinse mode](./ADVANCED.md) in the advanced documentation.
|
|
|
417
426
|
|
|
418
427
|
## BoM signing
|
|
419
428
|
|
|
420
|
-
cdxgen can sign the generated
|
|
429
|
+
cdxgen can sign the generated BOM json file to increase authenticity and non-repudiation capabilities. To enable this, set the following environment variables.
|
|
421
430
|
|
|
422
431
|
- SBOM_SIGN_ALGORITHM: Algorithm. Example: RS512
|
|
423
432
|
- SBOM_SIGN_PRIVATE_KEY: Location to the RSA private key
|
package/analyzer.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { parse } from "@babel/parser";
|
|
2
2
|
import traverse from "@babel/traverse";
|
|
3
|
-
import { join } from "path";
|
|
4
|
-
import { readdirSync, statSync, readFileSync } from "fs";
|
|
5
|
-
import { basename, resolve, isAbsolute, relative } from "path";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { readdirSync, statSync, readFileSync } from "node:fs";
|
|
5
|
+
import { basename, resolve, isAbsolute, relative } from "node:path";
|
|
6
6
|
|
|
7
7
|
const IGNORE_DIRS = process.env.ASTGEN_IGNORE_DIRS
|
|
8
8
|
? process.env.ASTGEN_IGNORE_DIRS.split(",")
|
package/bin/cdxgen.js
CHANGED
|
@@ -6,8 +6,7 @@ import fs from "node:fs";
|
|
|
6
6
|
import { tmpdir } from "node:os";
|
|
7
7
|
import { basename, dirname, join, resolve } from "node:path";
|
|
8
8
|
import jws from "jws";
|
|
9
|
-
import crypto from "crypto";
|
|
10
|
-
import { start as _serverStart } from "../server.js";
|
|
9
|
+
import crypto from "node:crypto";
|
|
11
10
|
import { fileURLToPath } from "node:url";
|
|
12
11
|
import globalAgent from "global-agent";
|
|
13
12
|
import process from "node:process";
|
|
@@ -243,7 +242,8 @@ const checkPermissions = (filePath) => {
|
|
|
243
242
|
(async () => {
|
|
244
243
|
// Start SBOM server
|
|
245
244
|
if (args.server) {
|
|
246
|
-
|
|
245
|
+
const serverModule = await import("../server.js");
|
|
246
|
+
return await serverModule.start(options);
|
|
247
247
|
}
|
|
248
248
|
// Check if cdxgen has the required permissions
|
|
249
249
|
if (!checkPermissions(filePath)) {
|
package/bin/repl.js
CHANGED
|
@@ -110,16 +110,16 @@ cdxgenRepl.defineCommand("create", {
|
|
|
110
110
|
});
|
|
111
111
|
if (bomNSData) {
|
|
112
112
|
sbom = bomNSData.bomJson;
|
|
113
|
-
console.log("✅
|
|
114
|
-
console.log("💭 Type .print to view the
|
|
113
|
+
console.log("✅ BOM imported successfully.");
|
|
114
|
+
console.log("💭 Type .print to view the BOM as a table");
|
|
115
115
|
} else {
|
|
116
|
-
console.log("
|
|
116
|
+
console.log("BOM was not generated successfully");
|
|
117
117
|
}
|
|
118
118
|
this.displayPrompt();
|
|
119
119
|
}
|
|
120
120
|
});
|
|
121
121
|
cdxgenRepl.defineCommand("import", {
|
|
122
|
-
help: "import an existing
|
|
122
|
+
help: "import an existing BOM",
|
|
123
123
|
action(sbomOrPath) {
|
|
124
124
|
this.clearBufferedCommand();
|
|
125
125
|
importSbom(sbomOrPath);
|
|
@@ -139,7 +139,7 @@ cdxgenRepl.defineCommand("sbom", {
|
|
|
139
139
|
console.log(sbom);
|
|
140
140
|
} else {
|
|
141
141
|
console.log(
|
|
142
|
-
"⚠ No
|
|
142
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM"
|
|
143
143
|
);
|
|
144
144
|
}
|
|
145
145
|
this.displayPrompt();
|
|
@@ -171,7 +171,7 @@ cdxgenRepl.defineCommand("search", {
|
|
|
171
171
|
}
|
|
172
172
|
} else {
|
|
173
173
|
console.log(
|
|
174
|
-
"⚠ No
|
|
174
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM"
|
|
175
175
|
);
|
|
176
176
|
}
|
|
177
177
|
this.displayPrompt();
|
|
@@ -205,7 +205,7 @@ cdxgenRepl.defineCommand("sort", {
|
|
|
205
205
|
}
|
|
206
206
|
} else {
|
|
207
207
|
console.log(
|
|
208
|
-
"⚠ No
|
|
208
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM"
|
|
209
209
|
);
|
|
210
210
|
}
|
|
211
211
|
this.displayPrompt();
|
|
@@ -229,7 +229,7 @@ cdxgenRepl.defineCommand("query", {
|
|
|
229
229
|
}
|
|
230
230
|
} else {
|
|
231
231
|
console.log(
|
|
232
|
-
"⚠ No
|
|
232
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM"
|
|
233
233
|
);
|
|
234
234
|
}
|
|
235
235
|
this.displayPrompt();
|
|
@@ -242,7 +242,7 @@ cdxgenRepl.defineCommand("print", {
|
|
|
242
242
|
printTable(sbom);
|
|
243
243
|
} else {
|
|
244
244
|
console.log(
|
|
245
|
-
"⚠ No
|
|
245
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM"
|
|
246
246
|
);
|
|
247
247
|
}
|
|
248
248
|
this.displayPrompt();
|
|
@@ -255,7 +255,7 @@ cdxgenRepl.defineCommand("tree", {
|
|
|
255
255
|
printDependencyTree(sbom);
|
|
256
256
|
} else {
|
|
257
257
|
console.log(
|
|
258
|
-
"⚠ No
|
|
258
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM"
|
|
259
259
|
);
|
|
260
260
|
}
|
|
261
261
|
this.displayPrompt();
|
|
@@ -271,7 +271,7 @@ cdxgenRepl.defineCommand("validate", {
|
|
|
271
271
|
}
|
|
272
272
|
} else {
|
|
273
273
|
console.log(
|
|
274
|
-
"⚠ No
|
|
274
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM"
|
|
275
275
|
);
|
|
276
276
|
}
|
|
277
277
|
this.displayPrompt();
|
|
@@ -285,10 +285,10 @@ cdxgenRepl.defineCommand("save", {
|
|
|
285
285
|
saveToFile = "bom.json";
|
|
286
286
|
}
|
|
287
287
|
fs.writeFileSync(saveToFile, JSON.stringify(sbom, null, 2));
|
|
288
|
-
console.log(`
|
|
288
|
+
console.log(`BOM saved successfully to ${saveToFile}`);
|
|
289
289
|
} else {
|
|
290
290
|
console.log(
|
|
291
|
-
"⚠ No
|
|
291
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM"
|
|
292
292
|
);
|
|
293
293
|
}
|
|
294
294
|
this.displayPrompt();
|
|
@@ -313,10 +313,10 @@ cdxgenRepl.defineCommand("update", {
|
|
|
313
313
|
if (newSbom && newSbom.components.length <= sbom.components.length) {
|
|
314
314
|
sbom = newSbom;
|
|
315
315
|
}
|
|
316
|
-
console.log("
|
|
316
|
+
console.log("BOM updated successfully.");
|
|
317
317
|
} else {
|
|
318
318
|
console.log(
|
|
319
|
-
"⚠ No
|
|
319
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM"
|
|
320
320
|
);
|
|
321
321
|
}
|
|
322
322
|
this.displayPrompt();
|
|
@@ -333,7 +333,7 @@ cdxgenRepl.defineCommand("occurrences", {
|
|
|
333
333
|
let components = await expression.evaluate(sbom);
|
|
334
334
|
if (!components) {
|
|
335
335
|
console.log(
|
|
336
|
-
"No results found. Use evinse command to generate an
|
|
336
|
+
"No results found. Use evinse command to generate an BOM with evidence."
|
|
337
337
|
);
|
|
338
338
|
} else {
|
|
339
339
|
if (!Array.isArray(components)) {
|
|
@@ -346,7 +346,7 @@ cdxgenRepl.defineCommand("occurrences", {
|
|
|
346
346
|
}
|
|
347
347
|
} else {
|
|
348
348
|
console.log(
|
|
349
|
-
"⚠ No
|
|
349
|
+
"⚠ No BOM is loaded. Use .import command to import an evinse BOM"
|
|
350
350
|
);
|
|
351
351
|
}
|
|
352
352
|
this.displayPrompt();
|
|
@@ -437,7 +437,7 @@ cdxgenRepl.defineCommand("osinfocategories", {
|
|
|
437
437
|
let catgories = await expression.evaluate(sbom);
|
|
438
438
|
if (!catgories) {
|
|
439
439
|
console.log(
|
|
440
|
-
"Unable to retrieve the os info categories. Only
|
|
440
|
+
"Unable to retrieve the os info categories. Only OBOMs generated by cdxgen are supported by this tool."
|
|
441
441
|
);
|
|
442
442
|
} else {
|
|
443
443
|
console.log(catgories.join("\n"));
|
|
@@ -447,7 +447,7 @@ cdxgenRepl.defineCommand("osinfocategories", {
|
|
|
447
447
|
}
|
|
448
448
|
} else {
|
|
449
449
|
console.log(
|
|
450
|
-
"⚠ No
|
|
450
|
+
"⚠ No OBOM is loaded. Use .import command to import an OBOM"
|
|
451
451
|
);
|
|
452
452
|
}
|
|
453
453
|
this.displayPrompt();
|
|
@@ -546,7 +546,7 @@ cdxgenRepl.defineCommand("osinfocategories", {
|
|
|
546
546
|
}
|
|
547
547
|
} else {
|
|
548
548
|
console.log(
|
|
549
|
-
"⚠ No
|
|
549
|
+
"⚠ No OBOM is loaded. Use .import command to import an OBOM"
|
|
550
550
|
);
|
|
551
551
|
}
|
|
552
552
|
this.displayPrompt();
|
package/binary.js
CHANGED
|
@@ -230,7 +230,7 @@ export const getGoBuildInfo = (src) => {
|
|
|
230
230
|
let result = spawnSync(GOVERSION_BIN, [src], {
|
|
231
231
|
encoding: "utf-8"
|
|
232
232
|
});
|
|
233
|
-
if (result.status !== 0 || result.error) {
|
|
233
|
+
if (result.status !== 0 || result.error || !result.stdout) {
|
|
234
234
|
if (result.stdout || result.stderr) {
|
|
235
235
|
console.error(result.stdout, result.stderr);
|
|
236
236
|
}
|