@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.
Files changed (181) hide show
  1. package/README.md +242 -90
  2. package/bin/audit.js +191 -0
  3. package/bin/cdxgen.js +532 -168
  4. package/bin/convert.js +99 -0
  5. package/bin/evinse.js +23 -0
  6. package/bin/repl.js +339 -8
  7. package/bin/sign.js +8 -0
  8. package/bin/validate.js +8 -0
  9. package/bin/verify.js +8 -0
  10. package/data/container-knowledge-index.json +125 -0
  11. package/data/gtfobins-index.json +6296 -0
  12. package/data/lolbas-index.json +150 -0
  13. package/data/queries-darwin.json +63 -3
  14. package/data/queries-win.json +45 -3
  15. package/data/queries.json +74 -2
  16. package/data/rules/chrome-extensions.yaml +240 -0
  17. package/data/rules/ci-permissions.yaml +478 -18
  18. package/data/rules/container-risk.yaml +270 -0
  19. package/data/rules/obom-runtime.yaml +891 -0
  20. package/data/rules/package-integrity.yaml +49 -0
  21. package/data/spdx-export.schema.json +6794 -0
  22. package/data/spdx-model-v3.0.1.jsonld +15999 -0
  23. package/lib/audit/index.js +1924 -0
  24. package/lib/audit/index.poku.js +1488 -0
  25. package/lib/audit/progress.js +137 -0
  26. package/lib/audit/progress.poku.js +188 -0
  27. package/lib/audit/reporters.js +618 -0
  28. package/lib/audit/scoring.js +310 -0
  29. package/lib/audit/scoring.poku.js +341 -0
  30. package/lib/audit/targets.js +260 -0
  31. package/lib/audit/targets.poku.js +331 -0
  32. package/lib/cli/index.js +276 -68
  33. package/lib/cli/index.poku.js +368 -0
  34. package/lib/helpers/analyzer.js +1052 -5
  35. package/lib/helpers/analyzer.poku.js +301 -0
  36. package/lib/helpers/annotationFormatter.js +49 -0
  37. package/lib/helpers/annotationFormatter.poku.js +44 -0
  38. package/lib/helpers/bomUtils.js +36 -0
  39. package/lib/helpers/bomUtils.poku.js +51 -0
  40. package/lib/helpers/caxa.js +2 -2
  41. package/lib/helpers/chromextutils.js +1153 -0
  42. package/lib/helpers/chromextutils.poku.js +493 -0
  43. package/lib/helpers/ciParsers/githubActions.js +1632 -45
  44. package/lib/helpers/ciParsers/githubActions.poku.js +853 -1
  45. package/lib/helpers/containerRisk.js +186 -0
  46. package/lib/helpers/containerRisk.poku.js +52 -0
  47. package/lib/helpers/depsUtils.js +16 -0
  48. package/lib/helpers/depsUtils.poku.js +58 -1
  49. package/lib/helpers/display.js +245 -61
  50. package/lib/helpers/display.poku.js +162 -2
  51. package/lib/helpers/exportUtils.js +123 -0
  52. package/lib/helpers/exportUtils.poku.js +60 -0
  53. package/lib/helpers/formulationParsers.js +69 -0
  54. package/lib/helpers/formulationParsers.poku.js +44 -0
  55. package/lib/helpers/gtfobins.js +189 -0
  56. package/lib/helpers/gtfobins.poku.js +49 -0
  57. package/lib/helpers/lolbas.js +267 -0
  58. package/lib/helpers/lolbas.poku.js +39 -0
  59. package/lib/helpers/osqueryTransform.js +84 -0
  60. package/lib/helpers/osqueryTransform.poku.js +49 -0
  61. package/lib/helpers/provenanceUtils.js +193 -0
  62. package/lib/helpers/provenanceUtils.poku.js +145 -0
  63. package/lib/helpers/pylockutils.js +281 -0
  64. package/lib/helpers/pylockutils.poku.js +48 -0
  65. package/lib/helpers/registryProvenance.js +793 -0
  66. package/lib/helpers/registryProvenance.poku.js +452 -0
  67. package/lib/helpers/remote/dependency-track.js +84 -0
  68. package/lib/helpers/remote/dependency-track.poku.js +119 -0
  69. package/lib/helpers/source.js +1267 -0
  70. package/lib/helpers/source.poku.js +771 -0
  71. package/lib/helpers/spdxUtils.js +97 -0
  72. package/lib/helpers/spdxUtils.poku.js +70 -0
  73. package/lib/helpers/table.js +384 -0
  74. package/lib/helpers/table.poku.js +186 -0
  75. package/lib/helpers/unicodeScan.js +147 -0
  76. package/lib/helpers/unicodeScan.poku.js +45 -0
  77. package/lib/helpers/utils.js +882 -136
  78. package/lib/helpers/utils.poku.js +995 -91
  79. package/lib/managers/binary.js +29 -5
  80. package/lib/managers/docker.js +179 -52
  81. package/lib/managers/docker.poku.js +327 -28
  82. package/lib/managers/oci.js +107 -23
  83. package/lib/managers/oci.poku.js +132 -0
  84. package/lib/server/openapi.yaml +50 -0
  85. package/lib/server/server.js +228 -331
  86. package/lib/server/server.poku.js +220 -5
  87. package/lib/stages/postgen/annotator.js +7 -0
  88. package/lib/stages/postgen/annotator.poku.js +40 -0
  89. package/lib/stages/postgen/auditBom.js +20 -5
  90. package/lib/stages/postgen/auditBom.poku.js +1729 -67
  91. package/lib/stages/postgen/postgen.js +40 -0
  92. package/lib/stages/postgen/postgen.poku.js +47 -0
  93. package/lib/stages/postgen/ruleEngine.js +80 -2
  94. package/lib/stages/postgen/spdxConverter.js +796 -0
  95. package/lib/stages/postgen/spdxConverter.poku.js +341 -0
  96. package/lib/validator/bomValidator.js +232 -0
  97. package/lib/validator/bomValidator.poku.js +70 -0
  98. package/lib/validator/complianceRules.js +70 -7
  99. package/lib/validator/complianceRules.poku.js +30 -0
  100. package/lib/validator/reporters/annotations.js +2 -2
  101. package/lib/validator/reporters/console.js +13 -2
  102. package/lib/validator/reporters.poku.js +13 -0
  103. package/package.json +10 -8
  104. package/types/bin/audit.d.ts +3 -0
  105. package/types/bin/audit.d.ts.map +1 -0
  106. package/types/bin/convert.d.ts +3 -0
  107. package/types/bin/convert.d.ts.map +1 -0
  108. package/types/bin/repl.d.ts.map +1 -1
  109. package/types/lib/audit/index.d.ts +115 -0
  110. package/types/lib/audit/index.d.ts.map +1 -0
  111. package/types/lib/audit/progress.d.ts +27 -0
  112. package/types/lib/audit/progress.d.ts.map +1 -0
  113. package/types/lib/audit/reporters.d.ts +35 -0
  114. package/types/lib/audit/reporters.d.ts.map +1 -0
  115. package/types/lib/audit/scoring.d.ts +35 -0
  116. package/types/lib/audit/scoring.d.ts.map +1 -0
  117. package/types/lib/audit/targets.d.ts +63 -0
  118. package/types/lib/audit/targets.d.ts.map +1 -0
  119. package/types/lib/cli/index.d.ts +8 -0
  120. package/types/lib/cli/index.d.ts.map +1 -1
  121. package/types/lib/helpers/analyzer.d.ts +13 -0
  122. package/types/lib/helpers/analyzer.d.ts.map +1 -1
  123. package/types/lib/helpers/annotationFormatter.d.ts +23 -0
  124. package/types/lib/helpers/annotationFormatter.d.ts.map +1 -0
  125. package/types/lib/helpers/bomUtils.d.ts +5 -0
  126. package/types/lib/helpers/bomUtils.d.ts.map +1 -0
  127. package/types/lib/helpers/chromextutils.d.ts +97 -0
  128. package/types/lib/helpers/chromextutils.d.ts.map +1 -0
  129. package/types/lib/helpers/ciParsers/githubActions.d.ts +3 -8
  130. package/types/lib/helpers/ciParsers/githubActions.d.ts.map +1 -1
  131. package/types/lib/helpers/containerRisk.d.ts +17 -0
  132. package/types/lib/helpers/containerRisk.d.ts.map +1 -0
  133. package/types/lib/helpers/depsUtils.d.ts.map +1 -1
  134. package/types/lib/helpers/display.d.ts +4 -1
  135. package/types/lib/helpers/display.d.ts.map +1 -1
  136. package/types/lib/helpers/exportUtils.d.ts +40 -0
  137. package/types/lib/helpers/exportUtils.d.ts.map +1 -0
  138. package/types/lib/helpers/formulationParsers.d.ts.map +1 -1
  139. package/types/lib/helpers/gtfobins.d.ts +17 -0
  140. package/types/lib/helpers/gtfobins.d.ts.map +1 -0
  141. package/types/lib/helpers/lolbas.d.ts +16 -0
  142. package/types/lib/helpers/lolbas.d.ts.map +1 -0
  143. package/types/lib/helpers/osqueryTransform.d.ts +7 -0
  144. package/types/lib/helpers/osqueryTransform.d.ts.map +1 -0
  145. package/types/lib/helpers/provenanceUtils.d.ts +90 -0
  146. package/types/lib/helpers/provenanceUtils.d.ts.map +1 -0
  147. package/types/lib/helpers/pylockutils.d.ts +51 -0
  148. package/types/lib/helpers/pylockutils.d.ts.map +1 -0
  149. package/types/lib/helpers/registryProvenance.d.ts +17 -0
  150. package/types/lib/helpers/registryProvenance.d.ts.map +1 -0
  151. package/types/lib/helpers/remote/dependency-track.d.ts +16 -0
  152. package/types/lib/helpers/remote/dependency-track.d.ts.map +1 -0
  153. package/types/lib/helpers/source.d.ts +141 -0
  154. package/types/lib/helpers/source.d.ts.map +1 -0
  155. package/types/lib/helpers/spdxUtils.d.ts +2 -0
  156. package/types/lib/helpers/spdxUtils.d.ts.map +1 -0
  157. package/types/lib/helpers/table.d.ts +6 -0
  158. package/types/lib/helpers/table.d.ts.map +1 -0
  159. package/types/lib/helpers/unicodeScan.d.ts +46 -0
  160. package/types/lib/helpers/unicodeScan.d.ts.map +1 -0
  161. package/types/lib/helpers/utils.d.ts +30 -11
  162. package/types/lib/helpers/utils.d.ts.map +1 -1
  163. package/types/lib/managers/binary.d.ts.map +1 -1
  164. package/types/lib/managers/docker.d.ts.map +1 -1
  165. package/types/lib/managers/oci.d.ts.map +1 -1
  166. package/types/lib/server/server.d.ts +0 -35
  167. package/types/lib/server/server.d.ts.map +1 -1
  168. package/types/lib/stages/postgen/annotator.d.ts.map +1 -1
  169. package/types/lib/stages/postgen/auditBom.d.ts.map +1 -1
  170. package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
  171. package/types/lib/stages/postgen/ruleEngine.d.ts.map +1 -1
  172. package/types/lib/stages/postgen/spdxConverter.d.ts +11 -0
  173. package/types/lib/stages/postgen/spdxConverter.d.ts.map +1 -0
  174. package/types/lib/validator/bomValidator.d.ts +1 -0
  175. package/types/lib/validator/bomValidator.d.ts.map +1 -1
  176. package/types/lib/validator/complianceRules.d.ts.map +1 -1
  177. package/types/lib/validator/reporters/console.d.ts.map +1 -1
  178. package/types/bin/dependencies.d.ts +0 -3
  179. package/types/bin/dependencies.d.ts.map +0 -1
  180. package/types/bin/licenses.d.ts +0 -3
  181. package/types/bin/licenses.d.ts.map +0 -1
@@ -0,0 +1,137 @@
1
+ import process from "node:process";
2
+
3
+ const ASCII_FRAMES = ["-", "\\", "|", "/"];
4
+ const CLEAR_LINE = "\r\x1b[2K";
5
+
6
+ /**
7
+ * Build a human-readable label for an audit target.
8
+ *
9
+ * @param {object} target audit target
10
+ * @returns {string} formatted target label
11
+ */
12
+ export function formatTargetLabel(target) {
13
+ const namespacePrefix = target?.namespace ? `${target.namespace}/` : "";
14
+ const versionSuffix = target?.version ? `@${target.version}` : "";
15
+ return `${target?.type || "pkg"}:${namespacePrefix}${target?.name || "unknown"}${versionSuffix}`;
16
+ }
17
+
18
+ /**
19
+ * Decide if interactive progress should be shown.
20
+ *
21
+ * @param {object} [options] progress options
22
+ * @returns {boolean} true when spinner-style progress is appropriate
23
+ */
24
+ export function shouldRenderProgress(options = {}) {
25
+ if (options.enabled === false) {
26
+ return false;
27
+ }
28
+ const stream = options.stream || process.stderr;
29
+ if (!stream?.isTTY) {
30
+ return false;
31
+ }
32
+ return process.env.CI !== "true";
33
+ }
34
+
35
+ /**
36
+ * Create a dependency-free progress renderer for cdx-audit.
37
+ *
38
+ * Progress is always written to stderr so JSON/stdout reports remain clean.
39
+ *
40
+ * @param {object} [options] progress options
41
+ * @returns {{ onProgress: Function, stop: Function }} progress controller
42
+ */
43
+ export function createProgressTracker(options = {}) {
44
+ const stream = options.stream || process.stderr;
45
+ const enabled = shouldRenderProgress({
46
+ enabled: options.enabled,
47
+ stream,
48
+ });
49
+ let frameIndex = 0;
50
+ let hasActiveLine = false;
51
+
52
+ /**
53
+ * Write a line or redraw the active line.
54
+ *
55
+ * @param {string} text output text
56
+ * @param {boolean} persist whether to end the line permanently
57
+ * @returns {void}
58
+ */
59
+ function render(text, persist = false) {
60
+ if (!enabled) {
61
+ if (persist) {
62
+ stream.write(`${text}\n`);
63
+ }
64
+ return;
65
+ }
66
+ stream.write(`${CLEAR_LINE}${text}`);
67
+ hasActiveLine = true;
68
+ if (persist) {
69
+ stream.write("\n");
70
+ hasActiveLine = false;
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Produce the next spinner frame.
76
+ *
77
+ * @returns {string} spinner frame
78
+ */
79
+ function nextFrame() {
80
+ const frame = ASCII_FRAMES[frameIndex % ASCII_FRAMES.length];
81
+ frameIndex += 1;
82
+ return frame;
83
+ }
84
+
85
+ return {
86
+ onProgress(event) {
87
+ const total = event?.total || event?.summary?.totalTargets || 0;
88
+ if (event?.type === "run:info") {
89
+ render(event.message, true);
90
+ return;
91
+ }
92
+ if (event?.type === "run:start") {
93
+ render(
94
+ `Preparing predictive audit for ${total} package(s)...`,
95
+ !enabled,
96
+ );
97
+ return;
98
+ }
99
+ if (event?.type === "target:start") {
100
+ render(
101
+ `[${event.index}/${event.total}] ${nextFrame()} ${event.label} — resolving source`,
102
+ );
103
+ return;
104
+ }
105
+ if (event?.type === "target:stage") {
106
+ render(
107
+ `[${event.index}/${event.total}] ${nextFrame()} ${event.label} — ${event.stage}`,
108
+ );
109
+ return;
110
+ }
111
+ if (event?.type === "target:finish") {
112
+ const finalSeverity = event?.result?.assessment?.severity || "none";
113
+ const finalStatus =
114
+ event?.result?.status === "audited"
115
+ ? finalSeverity.toUpperCase()
116
+ : event?.result?.status?.toUpperCase() || "DONE";
117
+ render(
118
+ `[${event.index}/${event.total}] done ${event.label} — ${finalStatus}`,
119
+ true,
120
+ );
121
+ return;
122
+ }
123
+ if (event?.type === "run:finish") {
124
+ const summary = event.summary || {};
125
+ render(
126
+ `Completed predictive audit: ${summary.scannedTargets || 0}/${summary.totalTargets || 0} scanned, ${summary.erroredTargets || 0} errored, ${summary.skippedTargets || 0} skipped.`,
127
+ true,
128
+ );
129
+ }
130
+ },
131
+ stop() {
132
+ if (enabled && hasActiveLine) {
133
+ stream.write(CLEAR_LINE);
134
+ }
135
+ },
136
+ };
137
+ }
@@ -0,0 +1,188 @@
1
+ import process from "node:process";
2
+
3
+ import { assert, describe, it } from "poku";
4
+
5
+ import {
6
+ createProgressTracker,
7
+ formatTargetLabel,
8
+ shouldRenderProgress,
9
+ } from "./progress.js";
10
+
11
+ function createStream(isTTY = true) {
12
+ return {
13
+ isTTY,
14
+ writes: [],
15
+ write(chunk) {
16
+ this.writes.push(chunk);
17
+ },
18
+ };
19
+ }
20
+
21
+ describe("formatTargetLabel()", () => {
22
+ it("formats namespace and version when present", () => {
23
+ assert.strictEqual(
24
+ formatTargetLabel({
25
+ name: "requests",
26
+ namespace: "pallets",
27
+ type: "pypi",
28
+ version: "2.32.3",
29
+ }),
30
+ "pypi:pallets/requests@2.32.3",
31
+ );
32
+ });
33
+ });
34
+
35
+ describe("shouldRenderProgress()", () => {
36
+ it("disables interactive progress for non-tty streams", () => {
37
+ assert.strictEqual(
38
+ shouldRenderProgress({
39
+ stream: createStream(false),
40
+ }),
41
+ false,
42
+ );
43
+ });
44
+ });
45
+
46
+ describe("createProgressTracker()", () => {
47
+ it("persists preflight info messages before target execution begins", () => {
48
+ const originalCI = process.env.CI;
49
+ delete process.env.CI;
50
+
51
+ try {
52
+ const stream = createStream(true);
53
+ const tracker = createProgressTracker({ stream });
54
+
55
+ tracker.onProgress({
56
+ message:
57
+ "Predictive audit selected 50 of 120 package(s) (12 required + 38 additional) using required-first prioritization. This may take several minutes depending on repository lookups and child SBOM generation.",
58
+ total: 50,
59
+ type: "run:info",
60
+ });
61
+ tracker.onProgress({
62
+ total: 50,
63
+ type: "run:start",
64
+ });
65
+ tracker.stop();
66
+
67
+ const output = stream.writes.join("");
68
+ assert.match(output, /selected 50 of 120 package\(s\)/);
69
+ assert.match(
70
+ output,
71
+ /Preparing predictive audit for 50 package\(s\)\.\.\./,
72
+ );
73
+ } finally {
74
+ if (originalCI === undefined) {
75
+ delete process.env.CI;
76
+ } else {
77
+ process.env.CI = originalCI;
78
+ }
79
+ }
80
+ });
81
+
82
+ it("renders the current package name and stage to stderr-like streams in interactive mode", () => {
83
+ const originalCI = process.env.CI;
84
+ delete process.env.CI;
85
+
86
+ try {
87
+ const stream = createStream(true);
88
+ const tracker = createProgressTracker({ stream });
89
+
90
+ tracker.onProgress({
91
+ total: 2,
92
+ type: "run:start",
93
+ });
94
+ tracker.onProgress({
95
+ index: 1,
96
+ label: "npm:left-pad@1.3.0",
97
+ total: 2,
98
+ type: "target:start",
99
+ });
100
+ tracker.onProgress({
101
+ index: 1,
102
+ label: "npm:left-pad@1.3.0",
103
+ stage: "generating child SBOM",
104
+ total: 2,
105
+ type: "target:stage",
106
+ });
107
+ tracker.onProgress({
108
+ index: 1,
109
+ label: "npm:left-pad@1.3.0",
110
+ result: {
111
+ assessment: {
112
+ severity: "medium",
113
+ },
114
+ status: "audited",
115
+ },
116
+ total: 2,
117
+ type: "target:finish",
118
+ });
119
+ tracker.stop();
120
+
121
+ const output = stream.writes.join("");
122
+ assert.match(output, /npm:left-pad@1.3.0/);
123
+ assert.match(output, /generating child SBOM/);
124
+ assert.match(output, /done npm:left-pad@1.3.0 — MEDIUM/);
125
+ } finally {
126
+ if (originalCI === undefined) {
127
+ delete process.env.CI;
128
+ } else {
129
+ process.env.CI = originalCI;
130
+ }
131
+ }
132
+ });
133
+
134
+ it("persists only start and finish updates when CI disables interactive progress", () => {
135
+ const originalCI = process.env.CI;
136
+ process.env.CI = "true";
137
+
138
+ try {
139
+ const stream = createStream(true);
140
+ const tracker = createProgressTracker({ stream });
141
+
142
+ tracker.onProgress({
143
+ total: 2,
144
+ type: "run:start",
145
+ });
146
+ tracker.onProgress({
147
+ index: 1,
148
+ label: "npm:left-pad@1.3.0",
149
+ total: 2,
150
+ type: "target:start",
151
+ });
152
+ tracker.onProgress({
153
+ index: 1,
154
+ label: "npm:left-pad@1.3.0",
155
+ stage: "generating child SBOM",
156
+ total: 2,
157
+ type: "target:stage",
158
+ });
159
+ tracker.onProgress({
160
+ index: 1,
161
+ label: "npm:left-pad@1.3.0",
162
+ result: {
163
+ assessment: {
164
+ severity: "medium",
165
+ },
166
+ status: "audited",
167
+ },
168
+ total: 2,
169
+ type: "target:finish",
170
+ });
171
+ tracker.stop();
172
+
173
+ const output = stream.writes.join("");
174
+ assert.match(
175
+ output,
176
+ /Preparing predictive audit for 2 package\(s\)\.\.\./,
177
+ );
178
+ assert.doesNotMatch(output, /generating child SBOM/);
179
+ assert.match(output, /done npm:left-pad@1.3.0 — MEDIUM/);
180
+ } finally {
181
+ if (originalCI === undefined) {
182
+ delete process.env.CI;
183
+ } else {
184
+ process.env.CI = originalCI;
185
+ }
186
+ }
187
+ });
188
+ });