@cyclonedx/cdxgen 12.2.0 → 12.3.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 +242 -90
- package/bin/audit.js +191 -0
- package/bin/cdxgen.js +532 -168
- package/bin/convert.js +99 -0
- package/bin/evinse.js +23 -0
- package/bin/repl.js +339 -8
- package/bin/sign.js +8 -0
- package/bin/validate.js +8 -0
- package/bin/verify.js +8 -0
- package/data/container-knowledge-index.json +125 -0
- package/data/gtfobins-index.json +6296 -0
- package/data/lolbas-index.json +150 -0
- package/data/queries-darwin.json +63 -3
- package/data/queries-win.json +45 -3
- package/data/queries.json +74 -2
- package/data/rules/chrome-extensions.yaml +240 -0
- package/data/rules/ci-permissions.yaml +478 -18
- package/data/rules/container-risk.yaml +270 -0
- package/data/rules/obom-runtime.yaml +891 -0
- package/data/rules/package-integrity.yaml +49 -0
- package/data/spdx-export.schema.json +6794 -0
- package/data/spdx-model-v3.0.1.jsonld +15999 -0
- package/lib/audit/index.js +1924 -0
- package/lib/audit/index.poku.js +1488 -0
- package/lib/audit/progress.js +137 -0
- package/lib/audit/progress.poku.js +188 -0
- package/lib/audit/reporters.js +618 -0
- package/lib/audit/scoring.js +310 -0
- package/lib/audit/scoring.poku.js +341 -0
- package/lib/audit/targets.js +260 -0
- package/lib/audit/targets.poku.js +331 -0
- package/lib/cli/index.js +276 -68
- package/lib/cli/index.poku.js +368 -0
- package/lib/helpers/analyzer.js +1052 -5
- package/lib/helpers/analyzer.poku.js +301 -0
- package/lib/helpers/annotationFormatter.js +49 -0
- package/lib/helpers/annotationFormatter.poku.js +44 -0
- package/lib/helpers/bomUtils.js +36 -0
- package/lib/helpers/bomUtils.poku.js +51 -0
- package/lib/helpers/caxa.js +2 -2
- package/lib/helpers/chromextutils.js +1153 -0
- package/lib/helpers/chromextutils.poku.js +493 -0
- package/lib/helpers/ciParsers/githubActions.js +1632 -45
- package/lib/helpers/ciParsers/githubActions.poku.js +853 -1
- package/lib/helpers/containerRisk.js +186 -0
- package/lib/helpers/containerRisk.poku.js +52 -0
- package/lib/helpers/depsUtils.js +16 -0
- package/lib/helpers/depsUtils.poku.js +58 -1
- package/lib/helpers/display.js +245 -61
- package/lib/helpers/display.poku.js +162 -2
- package/lib/helpers/exportUtils.js +123 -0
- package/lib/helpers/exportUtils.poku.js +60 -0
- package/lib/helpers/formulationParsers.js +69 -0
- package/lib/helpers/formulationParsers.poku.js +44 -0
- package/lib/helpers/gtfobins.js +189 -0
- package/lib/helpers/gtfobins.poku.js +49 -0
- package/lib/helpers/lolbas.js +267 -0
- package/lib/helpers/lolbas.poku.js +39 -0
- package/lib/helpers/osqueryTransform.js +84 -0
- package/lib/helpers/osqueryTransform.poku.js +49 -0
- package/lib/helpers/provenanceUtils.js +193 -0
- package/lib/helpers/provenanceUtils.poku.js +145 -0
- package/lib/helpers/pylockutils.js +281 -0
- package/lib/helpers/pylockutils.poku.js +48 -0
- package/lib/helpers/registryProvenance.js +793 -0
- package/lib/helpers/registryProvenance.poku.js +452 -0
- package/lib/helpers/remote/dependency-track.js +84 -0
- package/lib/helpers/remote/dependency-track.poku.js +119 -0
- package/lib/helpers/source.js +1267 -0
- package/lib/helpers/source.poku.js +771 -0
- package/lib/helpers/spdxUtils.js +97 -0
- package/lib/helpers/spdxUtils.poku.js +70 -0
- package/lib/helpers/table.js +384 -0
- package/lib/helpers/table.poku.js +186 -0
- package/lib/helpers/unicodeScan.js +147 -0
- package/lib/helpers/unicodeScan.poku.js +45 -0
- package/lib/helpers/utils.js +882 -136
- package/lib/helpers/utils.poku.js +995 -91
- package/lib/managers/binary.js +29 -5
- package/lib/managers/docker.js +179 -52
- package/lib/managers/docker.poku.js +327 -28
- package/lib/managers/oci.js +107 -23
- package/lib/managers/oci.poku.js +132 -0
- package/lib/server/openapi.yaml +50 -0
- package/lib/server/server.js +228 -331
- package/lib/server/server.poku.js +220 -5
- package/lib/stages/postgen/annotator.js +7 -0
- package/lib/stages/postgen/annotator.poku.js +40 -0
- package/lib/stages/postgen/auditBom.js +20 -5
- package/lib/stages/postgen/auditBom.poku.js +1729 -67
- package/lib/stages/postgen/postgen.js +40 -0
- package/lib/stages/postgen/postgen.poku.js +47 -0
- package/lib/stages/postgen/ruleEngine.js +80 -2
- package/lib/stages/postgen/spdxConverter.js +796 -0
- package/lib/stages/postgen/spdxConverter.poku.js +341 -0
- package/lib/validator/bomValidator.js +232 -0
- package/lib/validator/bomValidator.poku.js +70 -0
- package/lib/validator/complianceRules.js +70 -7
- package/lib/validator/complianceRules.poku.js +30 -0
- package/lib/validator/reporters/annotations.js +2 -2
- package/lib/validator/reporters/console.js +13 -2
- package/lib/validator/reporters.poku.js +13 -0
- package/package.json +10 -8
- package/types/bin/audit.d.ts +3 -0
- package/types/bin/audit.d.ts.map +1 -0
- package/types/bin/convert.d.ts +3 -0
- package/types/bin/convert.d.ts.map +1 -0
- package/types/bin/repl.d.ts.map +1 -1
- package/types/lib/audit/index.d.ts +115 -0
- package/types/lib/audit/index.d.ts.map +1 -0
- package/types/lib/audit/progress.d.ts +27 -0
- package/types/lib/audit/progress.d.ts.map +1 -0
- package/types/lib/audit/reporters.d.ts +35 -0
- package/types/lib/audit/reporters.d.ts.map +1 -0
- package/types/lib/audit/scoring.d.ts +35 -0
- package/types/lib/audit/scoring.d.ts.map +1 -0
- package/types/lib/audit/targets.d.ts +63 -0
- package/types/lib/audit/targets.d.ts.map +1 -0
- package/types/lib/cli/index.d.ts +8 -0
- package/types/lib/cli/index.d.ts.map +1 -1
- package/types/lib/helpers/analyzer.d.ts +13 -0
- package/types/lib/helpers/analyzer.d.ts.map +1 -1
- package/types/lib/helpers/annotationFormatter.d.ts +23 -0
- package/types/lib/helpers/annotationFormatter.d.ts.map +1 -0
- package/types/lib/helpers/bomUtils.d.ts +5 -0
- package/types/lib/helpers/bomUtils.d.ts.map +1 -0
- package/types/lib/helpers/chromextutils.d.ts +97 -0
- package/types/lib/helpers/chromextutils.d.ts.map +1 -0
- package/types/lib/helpers/ciParsers/githubActions.d.ts +3 -8
- package/types/lib/helpers/ciParsers/githubActions.d.ts.map +1 -1
- package/types/lib/helpers/containerRisk.d.ts +17 -0
- package/types/lib/helpers/containerRisk.d.ts.map +1 -0
- package/types/lib/helpers/depsUtils.d.ts.map +1 -1
- package/types/lib/helpers/display.d.ts +4 -1
- package/types/lib/helpers/display.d.ts.map +1 -1
- package/types/lib/helpers/exportUtils.d.ts +40 -0
- package/types/lib/helpers/exportUtils.d.ts.map +1 -0
- package/types/lib/helpers/formulationParsers.d.ts.map +1 -1
- package/types/lib/helpers/gtfobins.d.ts +17 -0
- package/types/lib/helpers/gtfobins.d.ts.map +1 -0
- package/types/lib/helpers/lolbas.d.ts +16 -0
- package/types/lib/helpers/lolbas.d.ts.map +1 -0
- package/types/lib/helpers/osqueryTransform.d.ts +7 -0
- package/types/lib/helpers/osqueryTransform.d.ts.map +1 -0
- package/types/lib/helpers/provenanceUtils.d.ts +90 -0
- package/types/lib/helpers/provenanceUtils.d.ts.map +1 -0
- package/types/lib/helpers/pylockutils.d.ts +51 -0
- package/types/lib/helpers/pylockutils.d.ts.map +1 -0
- package/types/lib/helpers/registryProvenance.d.ts +17 -0
- package/types/lib/helpers/registryProvenance.d.ts.map +1 -0
- package/types/lib/helpers/remote/dependency-track.d.ts +16 -0
- package/types/lib/helpers/remote/dependency-track.d.ts.map +1 -0
- package/types/lib/helpers/source.d.ts +141 -0
- package/types/lib/helpers/source.d.ts.map +1 -0
- package/types/lib/helpers/spdxUtils.d.ts +2 -0
- package/types/lib/helpers/spdxUtils.d.ts.map +1 -0
- package/types/lib/helpers/table.d.ts +6 -0
- package/types/lib/helpers/table.d.ts.map +1 -0
- package/types/lib/helpers/unicodeScan.d.ts +46 -0
- package/types/lib/helpers/unicodeScan.d.ts.map +1 -0
- package/types/lib/helpers/utils.d.ts +30 -11
- package/types/lib/helpers/utils.d.ts.map +1 -1
- package/types/lib/managers/binary.d.ts.map +1 -1
- package/types/lib/managers/docker.d.ts.map +1 -1
- package/types/lib/managers/oci.d.ts.map +1 -1
- package/types/lib/server/server.d.ts +0 -35
- package/types/lib/server/server.d.ts.map +1 -1
- package/types/lib/stages/postgen/annotator.d.ts.map +1 -1
- package/types/lib/stages/postgen/auditBom.d.ts.map +1 -1
- package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
- package/types/lib/stages/postgen/ruleEngine.d.ts.map +1 -1
- package/types/lib/stages/postgen/spdxConverter.d.ts +11 -0
- package/types/lib/stages/postgen/spdxConverter.d.ts.map +1 -0
- package/types/lib/validator/bomValidator.d.ts +1 -0
- package/types/lib/validator/bomValidator.d.ts.map +1 -1
- package/types/lib/validator/complianceRules.d.ts.map +1 -1
- package/types/lib/validator/reporters/console.d.ts.map +1 -1
- package/types/bin/dependencies.d.ts +0 -3
- package/types/bin/dependencies.d.ts.map +0 -1
- package/types/bin/licenses.d.ts +0 -3
- package/types/bin/licenses.d.ts.map +0 -1
|
@@ -7,6 +7,7 @@ import { PackageURL } from "packageurl-js";
|
|
|
7
7
|
import { mergeDependencies } from "../../helpers/depsUtils.js";
|
|
8
8
|
import { addFormulationSection } from "../../helpers/formulationParsers.js";
|
|
9
9
|
import { thoughtLog } from "../../helpers/logger.js";
|
|
10
|
+
import { buildReleaseNotesFromGit } from "../../helpers/source.js";
|
|
10
11
|
import {
|
|
11
12
|
DEBUG_MODE,
|
|
12
13
|
dirNameStr,
|
|
@@ -107,6 +108,7 @@ export function postProcess(bomNSData, options, filePath) {
|
|
|
107
108
|
filePath,
|
|
108
109
|
bomNSData.formulationList,
|
|
109
110
|
);
|
|
111
|
+
bomNSData.bomJson = applyReleaseNotes(bomNSData.bomJson, options, filePath);
|
|
110
112
|
// Support for automatic annotations
|
|
111
113
|
if (options.specVersion >= 1.6) {
|
|
112
114
|
bomNSData.bomJson = annotate(bomNSData.bomJson, options);
|
|
@@ -116,6 +118,44 @@ export function postProcess(bomNSData, options, filePath) {
|
|
|
116
118
|
return bomNSData;
|
|
117
119
|
}
|
|
118
120
|
|
|
121
|
+
function applyReleaseNotes(bomJson, options, filePath) {
|
|
122
|
+
if (!options?.includeReleaseNotes) {
|
|
123
|
+
return bomJson;
|
|
124
|
+
}
|
|
125
|
+
const specVersion = Number(options.specVersion || 1.7);
|
|
126
|
+
if (specVersion < 1.6) {
|
|
127
|
+
const errorMessage =
|
|
128
|
+
"releaseNotes in metadata.tools.components requires CycloneDX spec version 1.6 or above.";
|
|
129
|
+
if (options.failOnError) {
|
|
130
|
+
throw new Error(errorMessage);
|
|
131
|
+
}
|
|
132
|
+
console.warn(errorMessage);
|
|
133
|
+
return bomJson;
|
|
134
|
+
}
|
|
135
|
+
const toolComponents = bomJson?.metadata?.tools?.components;
|
|
136
|
+
if (!Array.isArray(toolComponents) || !toolComponents.length) {
|
|
137
|
+
return bomJson;
|
|
138
|
+
}
|
|
139
|
+
const cdxgenToolComponent = toolComponents.find(
|
|
140
|
+
(comp) => comp?.group === "@cyclonedx" && comp?.name === "cdxgen",
|
|
141
|
+
);
|
|
142
|
+
if (!cdxgenToolComponent) {
|
|
143
|
+
return bomJson;
|
|
144
|
+
}
|
|
145
|
+
const releaseNotes = buildReleaseNotesFromGit(filePath, options);
|
|
146
|
+
if (!releaseNotes) {
|
|
147
|
+
const errorMessage =
|
|
148
|
+
"Unable to compute release notes. Provide --release-notes-current-tag and optionally --release-notes-previous-tag.";
|
|
149
|
+
if (options.failOnError) {
|
|
150
|
+
throw new Error(errorMessage);
|
|
151
|
+
}
|
|
152
|
+
console.warn(errorMessage);
|
|
153
|
+
return bomJson;
|
|
154
|
+
}
|
|
155
|
+
cdxgenToolComponent.releaseNotes = releaseNotes;
|
|
156
|
+
return bomJson;
|
|
157
|
+
}
|
|
158
|
+
|
|
119
159
|
/**
|
|
120
160
|
* Apply additional metadata based on components
|
|
121
161
|
*
|
|
@@ -158,3 +158,50 @@ it("postProcess passes formulationList from bomNSData into the formulation secti
|
|
|
158
158
|
"pixi-pkg from formulationList should appear in formulation components",
|
|
159
159
|
);
|
|
160
160
|
});
|
|
161
|
+
|
|
162
|
+
it("postProcess attaches releaseNotes to cdxgen metadata tool component", () => {
|
|
163
|
+
const bomNSData = {
|
|
164
|
+
bomJson: {
|
|
165
|
+
bomFormat: "CycloneDX",
|
|
166
|
+
specVersion: "1.7",
|
|
167
|
+
components: [],
|
|
168
|
+
dependencies: [],
|
|
169
|
+
metadata: {
|
|
170
|
+
tools: {
|
|
171
|
+
components: [
|
|
172
|
+
{
|
|
173
|
+
group: "@cyclonedx",
|
|
174
|
+
name: "cdxgen",
|
|
175
|
+
version: "12.3.0",
|
|
176
|
+
type: "application",
|
|
177
|
+
},
|
|
178
|
+
],
|
|
179
|
+
},
|
|
180
|
+
properties: [],
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
const options = {
|
|
185
|
+
includeReleaseNotes: true,
|
|
186
|
+
releaseNotesCurrentTag: "v1.0.0",
|
|
187
|
+
releaseNotesPreviousTag: "v0.9.0",
|
|
188
|
+
specVersion: 1.7,
|
|
189
|
+
failOnError: true,
|
|
190
|
+
};
|
|
191
|
+
const result = postProcess(bomNSData, options);
|
|
192
|
+
const cdxTool = result.bomJson.metadata.tools.components[0];
|
|
193
|
+
assert.strictEqual(cdxTool.releaseNotes.title, "Release notes for v1.0.0");
|
|
194
|
+
assert.strictEqual(
|
|
195
|
+
cdxTool.releaseNotes.description,
|
|
196
|
+
"Changes between v0.9.0 and v1.0.0.",
|
|
197
|
+
);
|
|
198
|
+
assert.ok(cdxTool.releaseNotes.timestamp);
|
|
199
|
+
assert.deepStrictEqual(cdxTool.releaseNotes.tags, ["v1.0.0", "v0.9.0"]);
|
|
200
|
+
assert.ok(Array.isArray(cdxTool.releaseNotes.resolves));
|
|
201
|
+
for (const aresolve of cdxTool.releaseNotes.resolves) {
|
|
202
|
+
assert.ok(aresolve.type);
|
|
203
|
+
assert.ok(aresolve.id);
|
|
204
|
+
assert.ok(aresolve.name);
|
|
205
|
+
assert.ok(aresolve.description);
|
|
206
|
+
}
|
|
207
|
+
});
|
|
@@ -34,6 +34,66 @@ function extractProperty(obj, propName) {
|
|
|
34
34
|
return prop?.value ?? null;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
function dedupeObjectsByIdentity(items) {
|
|
38
|
+
const seen = new Set();
|
|
39
|
+
const deduped = [];
|
|
40
|
+
(items || []).forEach((item) => {
|
|
41
|
+
if (!item) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const key =
|
|
45
|
+
item["bom-ref"] ||
|
|
46
|
+
item.purl ||
|
|
47
|
+
`${item.type || "unknown"}:${item.name || "unnamed"}:${item.version || ""}`;
|
|
48
|
+
if (seen.has(key)) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
seen.add(key);
|
|
52
|
+
deduped.push(item);
|
|
53
|
+
});
|
|
54
|
+
return deduped;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function getFormulationEntries(bomJson) {
|
|
58
|
+
return Array.isArray(bomJson?.formulation) ? bomJson.formulation : [];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function getFormulationComponents(bomJson) {
|
|
62
|
+
return getFormulationEntries(bomJson).flatMap(
|
|
63
|
+
(entry) => entry?.components || [],
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function getAuditComponents(bomJson) {
|
|
68
|
+
return dedupeObjectsByIdentity([
|
|
69
|
+
...(Array.isArray(bomJson?.components) ? bomJson.components : []),
|
|
70
|
+
...getFormulationComponents(bomJson),
|
|
71
|
+
]);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function getAuditWorkflows(bomJson) {
|
|
75
|
+
return dedupeObjectsByIdentity(
|
|
76
|
+
getFormulationEntries(bomJson).flatMap((entry) => entry?.workflows || []),
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function normalizeAttackMetadata(rule) {
|
|
81
|
+
const tactics = Array.isArray(rule?.attack?.tactics)
|
|
82
|
+
? rule.attack.tactics
|
|
83
|
+
: [];
|
|
84
|
+
const techniques = Array.isArray(rule?.attack?.techniques)
|
|
85
|
+
? rule.attack.techniques
|
|
86
|
+
: [];
|
|
87
|
+
return {
|
|
88
|
+
tactics: tactics
|
|
89
|
+
.filter((value) => typeof value === "string" && value.trim().length > 0)
|
|
90
|
+
.map((value) => value.trim()),
|
|
91
|
+
techniques: techniques
|
|
92
|
+
.filter((value) => typeof value === "string" && value.trim().length > 0)
|
|
93
|
+
.map((value) => value.trim()),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
37
97
|
/**
|
|
38
98
|
* Helper: Check if property exists and equals expected value
|
|
39
99
|
* Usage: $hasProp(component, 'cdx:foo', 'bar')
|
|
@@ -145,6 +205,15 @@ function registerCdxHelpers(expression) {
|
|
|
145
205
|
expression.registerFunction("safeStr", (val) => {
|
|
146
206
|
return val === null || val === undefined ? "" : String(val).trim();
|
|
147
207
|
});
|
|
208
|
+
expression.registerFunction("auditComponents", (bomJson) =>
|
|
209
|
+
getAuditComponents(bomJson),
|
|
210
|
+
);
|
|
211
|
+
expression.registerFunction("auditWorkflows", (bomJson) =>
|
|
212
|
+
getAuditWorkflows(bomJson),
|
|
213
|
+
);
|
|
214
|
+
expression.registerFunction("formulationComponents", (bomJson) =>
|
|
215
|
+
getFormulationComponents(bomJson),
|
|
216
|
+
);
|
|
148
217
|
return expression;
|
|
149
218
|
}
|
|
150
219
|
|
|
@@ -217,6 +286,10 @@ export async function loadRules(rulesDir) {
|
|
|
217
286
|
}
|
|
218
287
|
rule.severity = rule.severity || "medium";
|
|
219
288
|
rule.category = rule.category || "unknown";
|
|
289
|
+
const attack = normalizeAttackMetadata(rule);
|
|
290
|
+
if (attack.tactics.length || attack.techniques.length) {
|
|
291
|
+
rule.attack = attack;
|
|
292
|
+
}
|
|
220
293
|
if (!["critical", "high", "medium", "low"].includes(rule.severity)) {
|
|
221
294
|
console.warn(
|
|
222
295
|
`Rule ${rule.id} has invalid severity '${rule.severity}'; defaulting to 'medium'`,
|
|
@@ -287,11 +360,13 @@ export async function evaluateRule(rule, bomJson) {
|
|
|
287
360
|
return findings;
|
|
288
361
|
}
|
|
289
362
|
for (const item of matches) {
|
|
363
|
+
const attack = normalizeAttackMetadata(rule);
|
|
290
364
|
const context = {
|
|
291
365
|
...item,
|
|
292
366
|
bom: bomJson,
|
|
293
|
-
components: bomJson
|
|
294
|
-
workflows: bomJson
|
|
367
|
+
components: getAuditComponents(bomJson),
|
|
368
|
+
workflows: getAuditWorkflows(bomJson),
|
|
369
|
+
formulationComponents: getFormulationComponents(bomJson),
|
|
295
370
|
services: bomJson.services || [],
|
|
296
371
|
metadata: bomJson.metadata || {},
|
|
297
372
|
};
|
|
@@ -327,6 +402,9 @@ export async function evaluateRule(rule, bomJson) {
|
|
|
327
402
|
}
|
|
328
403
|
}
|
|
329
404
|
findings.push({
|
|
405
|
+
attack,
|
|
406
|
+
attackTactics: attack.tactics,
|
|
407
|
+
attackTechniques: attack.techniques,
|
|
330
408
|
ruleId: rule.id,
|
|
331
409
|
name: rule.name || rule.id,
|
|
332
410
|
description: rule.description,
|