@cyclonedx/cdxgen 12.3.1 → 12.3.2

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 (56) hide show
  1. package/bin/cdxgen.js +1 -2
  2. package/data/rules/ai-agent-governance.yaml +43 -0
  3. package/data/rules/mcp-servers.yaml +36 -2
  4. package/lib/cli/index.js +295 -17
  5. package/lib/cli/index.poku.js +296 -1
  6. package/lib/helpers/agentFormulationParser.js +4 -1
  7. package/lib/helpers/aiInventory.js +262 -0
  8. package/lib/helpers/aiInventory.poku.js +111 -0
  9. package/lib/helpers/analyzer.js +375 -45
  10. package/lib/helpers/analyzer.poku.js +50 -0
  11. package/lib/helpers/auditCategories.js +76 -0
  12. package/lib/helpers/display.js +5 -2
  13. package/lib/helpers/display.poku.js +25 -0
  14. package/lib/helpers/formulationParsers.js +26 -6
  15. package/lib/helpers/jsonLike.js +21 -20
  16. package/lib/helpers/jsonLike.poku.js +34 -0
  17. package/lib/helpers/mcpConfigParser.js +11 -11
  18. package/lib/helpers/mcpConfigParser.poku.js +67 -0
  19. package/lib/helpers/mcpDiscovery.js +13 -23
  20. package/lib/helpers/mcpDiscovery.poku.js +21 -0
  21. package/lib/helpers/utils.js +2 -1
  22. package/lib/helpers/utils.poku.js +19 -1
  23. package/lib/stages/postgen/annotator.js +2 -1
  24. package/lib/stages/postgen/annotator.poku.js +15 -0
  25. package/lib/stages/postgen/auditBom.js +12 -6
  26. package/lib/stages/postgen/auditBom.poku.js +111 -4
  27. package/lib/stages/postgen/postgen.js +229 -6
  28. package/lib/stages/postgen/postgen.poku.js +180 -0
  29. package/package.json +1 -1
  30. package/types/lib/cli/index.d.ts +1 -0
  31. package/types/lib/cli/index.d.ts.map +1 -1
  32. package/types/lib/helpers/agentFormulationParser.d.ts +19 -0
  33. package/types/lib/helpers/agentFormulationParser.d.ts.map +1 -0
  34. package/types/lib/helpers/aiInventory.d.ts +23 -0
  35. package/types/lib/helpers/aiInventory.d.ts.map +1 -0
  36. package/types/lib/helpers/analyzer.d.ts +5 -0
  37. package/types/lib/helpers/analyzer.d.ts.map +1 -1
  38. package/types/lib/helpers/auditCategories.d.ts +12 -0
  39. package/types/lib/helpers/auditCategories.d.ts.map +1 -0
  40. package/types/lib/helpers/communityAiConfigParser.d.ts +29 -0
  41. package/types/lib/helpers/communityAiConfigParser.d.ts.map +1 -0
  42. package/types/lib/helpers/display.d.ts.map +1 -1
  43. package/types/lib/helpers/formulationParsers.d.ts.map +1 -1
  44. package/types/lib/helpers/jsonLike.d.ts +4 -0
  45. package/types/lib/helpers/jsonLike.d.ts.map +1 -0
  46. package/types/lib/helpers/mcp.d.ts +29 -0
  47. package/types/lib/helpers/mcp.d.ts.map +1 -0
  48. package/types/lib/helpers/mcpConfigParser.d.ts +30 -0
  49. package/types/lib/helpers/mcpConfigParser.d.ts.map +1 -0
  50. package/types/lib/helpers/mcpDiscovery.d.ts +5 -0
  51. package/types/lib/helpers/mcpDiscovery.d.ts.map +1 -0
  52. package/types/lib/helpers/utils.d.ts +2 -0
  53. package/types/lib/helpers/utils.d.ts.map +1 -1
  54. package/types/lib/stages/postgen/annotator.d.ts.map +1 -1
  55. package/types/lib/stages/postgen/auditBom.d.ts.map +1 -1
  56. package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
@@ -4,6 +4,11 @@ import process from "node:process";
4
4
 
5
5
  import { PackageURL } from "packageurl-js";
6
6
 
7
+ import {
8
+ AI_INVENTORY_PROJECT_TYPES,
9
+ matchesAiInventoryExcludeType,
10
+ optionIncludesAiInventoryProjectType,
11
+ } from "../../helpers/aiInventory.js";
7
12
  import { mergeDependencies, mergeServices } from "../../helpers/depsUtils.js";
8
13
  import { addFormulationSection } from "../../helpers/formulationParsers.js";
9
14
  import { thoughtLog } from "../../helpers/logger.js";
@@ -104,6 +109,189 @@ function applyFormulation(bomJson, options, filePath, formulationList) {
104
109
  return bomJson;
105
110
  }
106
111
 
112
+ const WEAK_TLP_CLASSIFICATIONS = new Set(["CLEAR", "GREEN", "AMBER"]);
113
+ const SENSITIVE_PROPERTY_NAMES = new Set([
114
+ "cdx:agent:description",
115
+ "cdx:agent:hiddenMcpUrls",
116
+ "cdx:agent:permission",
117
+ "cdx:mcp:command",
118
+ "cdx:mcp:configuredEndpoints",
119
+ "cdx:mcp:description",
120
+ "cdx:mcp:resourceUri",
121
+ "cdx:skill:metadata",
122
+ ]);
123
+ const SENSITIVE_PROPERTY_PREFIXES = ["cdx:crewai:", "cdx:mcp:auth:"];
124
+ const SECRET_ASSIGNMENT_PATTERN =
125
+ /(?:^|[\s,{\[])(?:authorization|password|passwd|pwd|token|access[_-]?token|id[_-]?token|refresh[_-]?token|api[_-]?key|client[_-]?secret|secret|session(?:id)?|cookie)\s*(?:[:=]|=>)\s*["'`]?[^"'`\s,}\]]{4,}/iu;
126
+ const ENV_SECRET_PATTERN =
127
+ /\b[A-Z0-9_]*(?:TOKEN|PASSWORD|SECRET|API_KEY|CLIENT_SECRET|SESSION|COOKIE)[A-Z0-9_]*=\S+/u;
128
+ const AUTH_HEADER_PATTERN =
129
+ /\bAuthorization\s*:\s*(?:Bearer|Basic)\s+[A-Za-z0-9._~+/=-]{8,}/iu;
130
+ const BEARER_TOKEN_PATTERN = /\b(?:Bearer|Basic)\s+[A-Za-z0-9._~+/=-]{12,}/u;
131
+ const PRIVATE_KEY_PATTERN =
132
+ /-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/u;
133
+ const SIGNED_URL_PARAM_NAMES = new Set([
134
+ "access_token",
135
+ "api_key",
136
+ "client_secret",
137
+ "id_token",
138
+ "signature",
139
+ "sig",
140
+ "token",
141
+ "x-amz-signature",
142
+ "x-goog-signature",
143
+ ]);
144
+
145
+ function normalizeSpecVersion(specVersion) {
146
+ return Number.parseFloat(String(specVersion || 0));
147
+ }
148
+
149
+ function normalizeTlpClassification(tlpClassification) {
150
+ return String(tlpClassification || "")
151
+ .trim()
152
+ .toUpperCase();
153
+ }
154
+
155
+ function hasSensitivePropertyName(propertyName) {
156
+ if (SENSITIVE_PROPERTY_NAMES.has(propertyName)) {
157
+ return true;
158
+ }
159
+ return SENSITIVE_PROPERTY_PREFIXES.some((prefix) =>
160
+ propertyName.startsWith(prefix),
161
+ );
162
+ }
163
+
164
+ function extractUrlCandidates(value) {
165
+ return Array.from(value.matchAll(/https?:\/\/[^\s]+/gu), (match) =>
166
+ match[0].replace(/[),.;]+$/u, ""),
167
+ );
168
+ }
169
+
170
+ function hasSensitiveUrlValue(value) {
171
+ for (const candidate of extractUrlCandidates(value)) {
172
+ if (!URL.canParse(candidate)) {
173
+ continue;
174
+ }
175
+ const parsedUrl = new URL(candidate);
176
+ if (parsedUrl.username || parsedUrl.password || parsedUrl.hash) {
177
+ return true;
178
+ }
179
+ for (const [paramName] of parsedUrl.searchParams) {
180
+ if (SIGNED_URL_PARAM_NAMES.has(paramName.toLowerCase())) {
181
+ return true;
182
+ }
183
+ }
184
+ }
185
+ return false;
186
+ }
187
+
188
+ function hasKnownSensitiveText(value) {
189
+ return (
190
+ SECRET_ASSIGNMENT_PATTERN.test(value) ||
191
+ ENV_SECRET_PATTERN.test(value) ||
192
+ AUTH_HEADER_PATTERN.test(value) ||
193
+ BEARER_TOKEN_PATTERN.test(value) ||
194
+ PRIVATE_KEY_PATTERN.test(value)
195
+ );
196
+ }
197
+
198
+ function propertyContainsSensitiveValue(propertyName, propertyValue) {
199
+ if (!hasSensitivePropertyName(propertyName) || !propertyValue?.trim()) {
200
+ return false;
201
+ }
202
+ return (
203
+ hasSensitiveUrlValue(propertyValue) || hasKnownSensitiveText(propertyValue)
204
+ );
205
+ }
206
+
207
+ function collectSensitivePropertyViolations(
208
+ subject,
209
+ violations = [],
210
+ location = "bom",
211
+ seen = new Set(),
212
+ ) {
213
+ if (!subject || typeof subject !== "object" || seen.has(subject)) {
214
+ return violations;
215
+ }
216
+ seen.add(subject);
217
+ if (Array.isArray(subject.properties)) {
218
+ const subjectLabel = subject["bom-ref"] || subject.name || location;
219
+ for (const property of subject.properties) {
220
+ if (
221
+ typeof property?.name === "string" &&
222
+ typeof property?.value === "string" &&
223
+ propertyContainsSensitiveValue(property.name, property.value)
224
+ ) {
225
+ violations.push({
226
+ propertyName: property.name,
227
+ subjectLabel,
228
+ });
229
+ }
230
+ }
231
+ }
232
+ if (Array.isArray(subject)) {
233
+ subject.forEach((entry, index) => {
234
+ collectSensitivePropertyViolations(
235
+ entry,
236
+ violations,
237
+ `${location}[${index}]`,
238
+ seen,
239
+ );
240
+ });
241
+ return violations;
242
+ }
243
+ for (const [key, value] of Object.entries(subject)) {
244
+ if (key === "properties") {
245
+ continue;
246
+ }
247
+ collectSensitivePropertyViolations(
248
+ value,
249
+ violations,
250
+ `${location}.${key}`,
251
+ seen,
252
+ );
253
+ }
254
+ return violations;
255
+ }
256
+
257
+ function validateTlpClassification(bomJson, options) {
258
+ const specVersion = normalizeSpecVersion(
259
+ bomJson?.specVersion || options?.specVersion,
260
+ );
261
+ if (specVersion < 1.7) {
262
+ return bomJson;
263
+ }
264
+ const tlpClassification = normalizeTlpClassification(
265
+ bomJson?.metadata?.distributionConstraints?.tlp ||
266
+ bomJson?.metadata?.distribution ||
267
+ options?.tlpClassification,
268
+ );
269
+ if (!WEAK_TLP_CLASSIFICATIONS.has(tlpClassification)) {
270
+ return bomJson;
271
+ }
272
+ const violations = collectSensitivePropertyViolations(bomJson);
273
+ if (!violations.length) {
274
+ return bomJson;
275
+ }
276
+ const uniqueViolations = [
277
+ ...new Set(
278
+ violations.map(
279
+ ({ propertyName, subjectLabel }) =>
280
+ `${propertyName} on ${subjectLabel}`,
281
+ ),
282
+ ),
283
+ ];
284
+ const errorMessage =
285
+ `CycloneDX 1.7+ BOMs with TLP classification '${tlpClassification}' must not include known sensitive property values. ` +
286
+ "Redact the values or raise the TLP classification to AMBER_AND_STRICT or RED. " +
287
+ `Found: ${uniqueViolations.slice(0, 5).join("; ")}${uniqueViolations.length > 5 ? `; and ${uniqueViolations.length - 5} more` : ""}`;
288
+ if (options?.failOnError) {
289
+ throw new Error(errorMessage);
290
+ }
291
+ console.warn(errorMessage);
292
+ return bomJson;
293
+ }
294
+
107
295
  /**
108
296
  * Filter and enhance BOM post generation.
109
297
  *
@@ -131,6 +319,7 @@ export function postProcess(bomNSData, options, filePath) {
131
319
  bomNSData.formulationList,
132
320
  );
133
321
  bomNSData.bomJson = applyReleaseNotes(bomNSData.bomJson, options, filePath);
322
+ bomNSData.bomJson = validateTlpClassification(bomNSData.bomJson, options);
134
323
  // Support for automatic annotations
135
324
  if (options.specVersion >= 1.6) {
136
325
  bomNSData.bomJson = annotate(bomNSData.bomJson, options);
@@ -431,12 +620,17 @@ function getIdentityTechniques(comp) {
431
620
  */
432
621
  export function filterBom(bomJson, options) {
433
622
  const newPkgMap = {};
623
+ const newServices = [];
434
624
  let filtered = false;
435
625
  let anyFiltered = false;
436
626
  if (!bomJson?.components) {
437
627
  return bomJson;
438
628
  }
439
629
  for (const comp of bomJson.components) {
630
+ if (shouldExcludeInventoryType(comp, options)) {
631
+ filtered = true;
632
+ continue;
633
+ }
440
634
  // minimum confidence filter
441
635
  if (options?.minConfidence > 0) {
442
636
  const confidence = Math.min(options.minConfidence, 1);
@@ -470,6 +664,7 @@ export function filterBom(bomJson, options) {
470
664
  ) {
471
665
  filtered = true;
472
666
  } else if (options.only?.length) {
667
+ const componentPurl = comp.purl?.toLowerCase?.() || "";
473
668
  if (!Array.isArray(options.only)) {
474
669
  options.only = [options.only];
475
670
  }
@@ -478,7 +673,7 @@ export function filterBom(bomJson, options) {
478
673
  for (const filterstr of options.only) {
479
674
  if (
480
675
  filterstr.length &&
481
- comp.purl.toLowerCase().includes(filterstr.toLowerCase())
676
+ componentPurl.includes(filterstr.toLowerCase())
482
677
  ) {
483
678
  filtered = true;
484
679
  purlfiltered = false;
@@ -493,11 +688,12 @@ export function filterBom(bomJson, options) {
493
688
  options.filter = [options.filter];
494
689
  }
495
690
  let purlfiltered = false;
691
+ const componentPurl = comp.purl?.toLowerCase?.() || "";
496
692
  for (const filterstr of options.filter) {
497
693
  // Check the purl
498
694
  if (
499
695
  filterstr.length &&
500
- comp.purl.toLowerCase().includes(filterstr.toLowerCase())
696
+ componentPurl.includes(filterstr.toLowerCase())
501
697
  ) {
502
698
  filtered = true;
503
699
  purlfiltered = true;
@@ -522,40 +718,59 @@ export function filterBom(bomJson, options) {
522
718
  newPkgMap[comp["bom-ref"]] = comp;
523
719
  }
524
720
  }
721
+ for (const service of bomJson.services || []) {
722
+ if (shouldExcludeInventoryType(service, options)) {
723
+ filtered = true;
724
+ continue;
725
+ }
726
+ newServices.push(service);
727
+ }
525
728
  if (filtered) {
526
729
  if (!anyFiltered) {
527
730
  anyFiltered = true;
528
731
  }
529
732
  const newcomponents = [];
530
733
  const newdependencies = [];
734
+ const retainedRefs = new Set();
531
735
  for (const aref of Object.keys(newPkgMap).sort()) {
532
736
  newcomponents.push(newPkgMap[aref]);
737
+ retainedRefs.add(aref);
738
+ }
739
+ for (const service of newServices) {
740
+ if (service?.["bom-ref"]) {
741
+ retainedRefs.add(service["bom-ref"]);
742
+ }
533
743
  }
534
744
  if (bomJson.metadata?.component?.["bom-ref"]) {
535
745
  newPkgMap[bomJson.metadata.component["bom-ref"]] =
536
746
  bomJson.metadata.component;
747
+ retainedRefs.add(bomJson.metadata.component["bom-ref"]);
537
748
  }
538
749
  if (bomJson.metadata?.component?.components) {
539
750
  for (const comp of bomJson.metadata.component.components) {
540
751
  newPkgMap[comp["bom-ref"]] = comp;
752
+ retainedRefs.add(comp["bom-ref"]);
541
753
  }
542
754
  }
543
- for (const adep of bomJson.dependencies) {
544
- if (newPkgMap[adep.ref]) {
545
- const newdepson = (adep.dependsOn || []).filter((d) => newPkgMap[d]);
755
+ for (const adep of bomJson.dependencies || []) {
756
+ if (retainedRefs.has(adep.ref)) {
757
+ const newdepson = (adep.dependsOn || []).filter((d) =>
758
+ retainedRefs.has(d),
759
+ );
546
760
  const obj = {
547
761
  ref: adep.ref,
548
762
  dependsOn: newdepson,
549
763
  };
550
764
  // Filter provides array if needed
551
765
  if (adep.provides?.length) {
552
- obj.provides = adep.provides.filter((d) => newPkgMap[d]);
766
+ obj.provides = adep.provides.filter((d) => retainedRefs.has(d));
553
767
  }
554
768
  newdependencies.push(obj);
555
769
  }
556
770
  }
557
771
  bomJson.components = newcomponents;
558
772
  bomJson.dependencies = newdependencies;
773
+ bomJson.services = newServices;
559
774
  // We set the compositions.aggregate to incomplete by default
560
775
  if (
561
776
  options.specVersion >= 1.5 &&
@@ -593,6 +808,14 @@ export function filterBom(bomJson, options) {
593
808
  return bomJson;
594
809
  }
595
810
 
811
+ function shouldExcludeInventoryType(subject, options) {
812
+ return AI_INVENTORY_PROJECT_TYPES.some(
813
+ (type) =>
814
+ optionIncludesAiInventoryProjectType(options?.excludeType, type) &&
815
+ matchesAiInventoryExcludeType(subject, type),
816
+ );
817
+ }
818
+
596
819
  /**
597
820
  * Clean up
598
821
  */
@@ -88,6 +88,70 @@ it("filter bom tests2", () => {
88
88
  ]);
89
89
  });
90
90
 
91
+ it("exclude-type mcp removes inventory artifacts but retains MCP SDK packages", () => {
92
+ const bomJson = {
93
+ components: [
94
+ {
95
+ "bom-ref": "pkg:npm/%40modelcontextprotocol/server-filesystem@1.0.0",
96
+ name: "@modelcontextprotocol/server-filesystem",
97
+ purl: "pkg:npm/%40modelcontextprotocol/server-filesystem@1.0.0",
98
+ },
99
+ {
100
+ "bom-ref": "file:/repo/.vscode/mcp.json",
101
+ name: "mcp.json",
102
+ properties: [{ name: "cdx:file:kind", value: "mcp-config" }],
103
+ type: "file",
104
+ },
105
+ {
106
+ "bom-ref": "urn:mcp:tool:docs:search",
107
+ name: "search",
108
+ properties: [
109
+ { name: "cdx:mcp:role", value: "tool" },
110
+ {
111
+ name: "cdx:mcp:serviceRef",
112
+ value: "urn:service:mcp:docs:latest",
113
+ },
114
+ ],
115
+ type: "application",
116
+ },
117
+ ],
118
+ dependencies: [
119
+ {
120
+ dependsOn: ["urn:mcp:tool:docs:search"],
121
+ ref: "urn:service:mcp:docs:latest",
122
+ },
123
+ {
124
+ provides: ["urn:mcp:tool:docs:search"],
125
+ ref: "pkg:npm/%40modelcontextprotocol/server-filesystem@1.0.0",
126
+ },
127
+ ],
128
+ metadata: { properties: [] },
129
+ services: [
130
+ {
131
+ "bom-ref": "urn:service:mcp:docs:latest",
132
+ group: "mcp",
133
+ name: "docs",
134
+ properties: [{ name: "cdx:mcp:inventorySource", value: "config-file" }],
135
+ },
136
+ ],
137
+ };
138
+
139
+ const filteredBom = filterBom(bomJson, { excludeType: ["mcp"] });
140
+
141
+ assert.deepStrictEqual(
142
+ filteredBom.components.map((component) => component["bom-ref"]),
143
+ ["pkg:npm/%40modelcontextprotocol/server-filesystem@1.0.0"],
144
+ );
145
+ assert.deepStrictEqual(filteredBom.services, []);
146
+ assert.deepStrictEqual(filteredBom.dependencies, [
147
+ {
148
+ dependsOn: [],
149
+ provides: [],
150
+ ref: "pkg:npm/%40modelcontextprotocol/server-filesystem@1.0.0",
151
+ },
152
+ ]);
153
+ });
154
+
91
155
  it("postProcess adds formulation exactly once when includeFormulation is true", () => {
92
156
  const bomNSData = {
93
157
  bomJson: {
@@ -308,6 +372,122 @@ it("postProcess attaches releaseNotes to cdxgen metadata tool component", () =>
308
372
  }
309
373
  });
310
374
 
375
+ it("postProcess fails for weak TLP when sensitive property values are present", () => {
376
+ const bomNSData = {
377
+ bomJson: {
378
+ bomFormat: "CycloneDX",
379
+ specVersion: "1.7",
380
+ components: [
381
+ {
382
+ "bom-ref": "urn:service:mcp:gateway:latest",
383
+ name: "gateway",
384
+ properties: [
385
+ {
386
+ name: "cdx:mcp:configuredEndpoints",
387
+ value:
388
+ "https://user:pass@example.com/mcp?access_token=abc123456789",
389
+ },
390
+ ],
391
+ type: "application",
392
+ },
393
+ ],
394
+ dependencies: [],
395
+ metadata: {
396
+ distributionConstraints: { tlp: "CLEAR" },
397
+ properties: [],
398
+ tools: {
399
+ components: [
400
+ { group: "@cyclonedx", name: "cdxgen", version: "test" },
401
+ ],
402
+ },
403
+ },
404
+ },
405
+ };
406
+ assert.throws(
407
+ () => postProcess(bomNSData, { failOnError: true, specVersion: 1.7 }),
408
+ /TLP classification 'CLEAR'/,
409
+ );
410
+ });
411
+
412
+ it("postProcess allows sensitive property values when TLP is strong", () => {
413
+ const bomNSData = {
414
+ bomJson: {
415
+ bomFormat: "CycloneDX",
416
+ specVersion: "1.7",
417
+ components: [
418
+ {
419
+ "bom-ref": "urn:service:mcp:gateway:latest",
420
+ name: "gateway",
421
+ properties: [
422
+ {
423
+ name: "cdx:mcp:command",
424
+ value: "Authorization: Bearer super-secret-token-value",
425
+ },
426
+ ],
427
+ type: "application",
428
+ },
429
+ ],
430
+ dependencies: [],
431
+ metadata: {
432
+ distributionConstraints: { tlp: "RED" },
433
+ properties: [],
434
+ tools: {
435
+ components: [
436
+ { group: "@cyclonedx", name: "cdxgen", version: "test" },
437
+ ],
438
+ },
439
+ },
440
+ },
441
+ };
442
+ const result = postProcess(bomNSData, {
443
+ failOnError: true,
444
+ specVersion: 1.7,
445
+ });
446
+ assert.strictEqual(
447
+ result.bomJson.metadata.distributionConstraints.tlp,
448
+ "RED",
449
+ );
450
+ });
451
+
452
+ it("postProcess does not enforce TLP validation when no TLP is set", () => {
453
+ const bomNSData = {
454
+ bomJson: {
455
+ bomFormat: "CycloneDX",
456
+ specVersion: "1.7",
457
+ components: [
458
+ {
459
+ "bom-ref": "urn:service:mcp:gateway:latest",
460
+ name: "gateway",
461
+ properties: [
462
+ {
463
+ name: "cdx:mcp:resourceUri",
464
+ value: "https://user:pass@example.com/private#fragment",
465
+ },
466
+ ],
467
+ type: "application",
468
+ },
469
+ ],
470
+ dependencies: [],
471
+ metadata: {
472
+ properties: [],
473
+ tools: {
474
+ components: [
475
+ { group: "@cyclonedx", name: "cdxgen", version: "test" },
476
+ ],
477
+ },
478
+ },
479
+ },
480
+ };
481
+ const result = postProcess(bomNSData, {
482
+ failOnError: true,
483
+ specVersion: 1.7,
484
+ });
485
+ assert.strictEqual(
486
+ result.bomJson.metadata.distributionConstraints,
487
+ undefined,
488
+ );
489
+ });
490
+
311
491
  it("cleanup helpers do not delete directories in dry-run mode", () => {
312
492
  const pipTarget = join(tmpdir(), `cdxgen-pip-${Date.now()}`);
313
493
  const tmpDir = join(tmpdir(), `cdxgen-tmp-${Date.now()}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyclonedx/cdxgen",
3
- "version": "12.3.1",
3
+ "version": "12.3.2",
4
4
  "description": "Creates CycloneDX Software Bill of Materials (SBOM) from source or container image",
5
5
  "keywords": [
6
6
  "sbom",
@@ -297,4 +297,5 @@ export function createBom(path: string, options: Object): Promise<Object>;
297
297
  export function submitBom(args: Object, bomContents: Object): Promise<{
298
298
  token: string;
299
299
  } | undefined>;
300
+ export { summarizeAiInventory } from "../helpers/aiInventory.js";
300
301
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../lib/cli/index.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../lib/cli/index.js"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export namespace agentFormulationParser {
2
+ export let id: string;
3
+ export { AGENT_FILE_PATTERNS as patterns };
4
+ export function parse(files: any, _options?: {}): {
5
+ components: {
6
+ "bom-ref": string;
7
+ name: any;
8
+ properties: {
9
+ name: string;
10
+ value: any;
11
+ }[];
12
+ type: string;
13
+ }[];
14
+ services: any[];
15
+ };
16
+ }
17
+ declare const AGENT_FILE_PATTERNS: string[];
18
+ export {};
19
+ //# sourceMappingURL=agentFormulationParser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agentFormulationParser.d.ts","sourceRoot":"","sources":["../../../lib/helpers/agentFormulationParser.js"],"names":[],"mappings":";;;IA6IE;;;;;;;;;;;MA+KC;;AAjTH,4CASE"}
@@ -0,0 +1,23 @@
1
+ export function inventoryPropertyValue(subject: any, name: any): any;
2
+ export function optionIncludesAiInventoryProjectType(optionValue: any, type: any): boolean;
3
+ export function inventoryTypesForSubject(subject: any): any[];
4
+ export function matchesAiInventoryType(subject: any, type: any): boolean;
5
+ export function matchesAiInventoryExcludeType(subject: any, type: any): boolean;
6
+ export function filterInventorySubjectsByTypes(subjects: any, types: any): any;
7
+ export function filterInventoryDependencies(dependencies: any, components: any, services: any): any;
8
+ export function collectAiInventory(discoveryPath: any, options: any, types: any): {
9
+ components: any[];
10
+ dependencies: any;
11
+ services: Object[];
12
+ };
13
+ export function summarizeAiInventory(inventory: any): {
14
+ instructionCount: any;
15
+ mcpConfigCount: any;
16
+ mcpServiceCount: any;
17
+ skillCount: any;
18
+ };
19
+ export const AI_INVENTORY_PROJECT_TYPES: string[];
20
+ export const AI_INSTRUCTION_FILE_KINDS: Set<string>;
21
+ export const AI_SKILL_FILE_KIND: "skill-file";
22
+ export const MCP_CONFIG_FILE_KIND: "mcp-config";
23
+ //# sourceMappingURL=aiInventory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aiInventory.d.ts","sourceRoot":"","sources":["../../../lib/helpers/aiInventory.js"],"names":[],"mappings":"AA2DA,qEAEC;AAYD,2FAaC;AAED,8DA2BC;AAED,yEAEC;AAED,gFAYC;AAED,+EAUC;AAED,oGA8BC;AAED;;;;EA2DC;AAED;;;;;EAqBC;AA9PD,kDAA8D;AAC9D,oDAaG;AACH,iCAAkC,YAAY,CAAC;AAC/C,mCAAoC,YAAY,CAAC"}
@@ -15,6 +15,11 @@ export function detectExtensionCapabilities(src: string, deep?: boolean): {
15
15
  [x: string]: string[];
16
16
  };
17
17
  };
18
+ export function detectPythonMcpInventory(src: string, deep?: boolean): {
19
+ components: Object[];
20
+ dependencies: Object[];
21
+ services: Object[];
22
+ };
18
23
  export function detectMcpInventory(src: string, deep?: boolean): {
19
24
  components: Object[];
20
25
  dependencies: Object[];
@@ -1 +1 @@
1
- {"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../../../lib/helpers/analyzer.js"],"names":[],"mappings":"AA+3BA,gEAQE;AAmUK;;;GAiBN;AASM,kDAHI,MAAM,GACJ;IAAC,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAC;IAAC,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAAC,qBAAqB,EAAE,MAAM,EAAE,CAAA;CAAC,CAe/H;AAWM,iDANI,MAAM,SACN,OAAO,GACL;IAAC,YAAY,EAAE,MAAM,EAAE,CAAC;IAAC,UAAU,EAAE;YAAO,MAAM,GAAE,MAAM,EAAE;KAAC,CAAA;CAAC,CAwF1E;AA2sBM,wCAJI,MAAM,SACN,OAAO,GACL;IAAC,UAAU,EAAE,MAAM,EAAE,CAAC;IAAC,YAAY,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAC,CAktB9E"}
1
+ {"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../../../lib/helpers/analyzer.js"],"names":[],"mappings":"AA+3BA,gEAQE;AAmUK;;;GAiBN;AASM,kDAHI,MAAM,GACJ;IAAC,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAC;IAAC,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAAC,qBAAqB,EAAE,MAAM,EAAE,CAAA;CAAC,CAe/H;AAWM,iDANI,MAAM,SACN,OAAO,GACL;IAAC,YAAY,EAAE,MAAM,EAAE,CAAC;IAAC,UAAU,EAAE;YAAO,MAAM,GAAE,MAAM,EAAE;KAAC,CAAA;CAAC,CAwF1E;AAo7BM,8CAJI,MAAM,SACN,OAAO,GACL;IAAC,UAAU,EAAE,MAAM,EAAE,CAAC;IAAC,YAAY,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAC,CAsI9E;AASM,wCAJI,MAAM,SACN,OAAO,GACL;IAAC,UAAU,EAAE,MAAM,EAAE,CAAC;IAAC,YAAY,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAC,CAsqB9E"}
@@ -0,0 +1,12 @@
1
+ export function normalizeBomAuditCategories(categories: any): any[];
2
+ export function expandBomAuditCategories(categories: any): any[];
3
+ export function availableBomAuditCategories(rules: any): any[];
4
+ export function validateBomAuditCategories(categories: any, rules: any): {
5
+ categories: any[];
6
+ expandedCategories: any[];
7
+ validCategories: any[];
8
+ };
9
+ export const BOM_AUDIT_CATEGORY_ALIASES: Readonly<{
10
+ "ai-inventory": string[];
11
+ }>;
12
+ //# sourceMappingURL=auditCategories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auditCategories.d.ts","sourceRoot":"","sources":["../../../lib/helpers/auditCategories.js"],"names":[],"mappings":"AAQA,oEAeC;AAED,iEAWC;AAED,+DAIC;AAUD;;;;EAuBC;AA3ED;;GAEG"}
@@ -0,0 +1,29 @@
1
+ export namespace communityAiConfigParser {
2
+ export let id: string;
3
+ export { COMMUNITY_AI_PATTERNS as patterns };
4
+ export function parse(files: any, _options?: {}): {
5
+ components: {
6
+ "bom-ref": string;
7
+ name: any;
8
+ properties: {
9
+ name: string;
10
+ value: any;
11
+ }[];
12
+ type: string;
13
+ version: string | undefined;
14
+ }[];
15
+ services: {
16
+ "bom-ref": string;
17
+ group: any;
18
+ name: any;
19
+ properties: {
20
+ name: string;
21
+ value: any;
22
+ }[];
23
+ version: string;
24
+ }[];
25
+ };
26
+ }
27
+ declare const COMMUNITY_AI_PATTERNS: string[];
28
+ export {};
29
+ //# sourceMappingURL=communityAiConfigParser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"communityAiConfigParser.d.ts","sourceRoot":"","sources":["../../../lib/helpers/communityAiConfigParser.js"],"names":[],"mappings":";;;IA8lBE;;;;;;;;;;;;;;;;;;;;;MAgEC;;AAlpBH,8CAiCE"}