@cyclonedx/cdxgen 12.3.0 → 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 (121) hide show
  1. package/README.md +15 -5
  2. package/bin/audit.js +7 -0
  3. package/bin/cdxgen.js +241 -81
  4. package/bin/repl.js +138 -0
  5. package/data/rules/ai-agent-governance.yaml +249 -0
  6. package/data/rules/dependency-sources.yaml +41 -0
  7. package/data/rules/mcp-servers.yaml +304 -0
  8. package/data/rules/package-integrity.yaml +123 -0
  9. package/lib/audit/index.js +353 -29
  10. package/lib/audit/index.poku.js +247 -7
  11. package/lib/audit/reporters.js +26 -0
  12. package/lib/audit/scoring.js +262 -13
  13. package/lib/audit/scoring.poku.js +179 -0
  14. package/lib/audit/targets.js +391 -2
  15. package/lib/audit/targets.poku.js +416 -3
  16. package/lib/cli/index.js +588 -45
  17. package/lib/cli/index.poku.js +735 -1
  18. package/lib/evinser/evinser.js +8 -5
  19. package/lib/helpers/agentFormulationParser.js +318 -0
  20. package/lib/helpers/aiInventory.js +262 -0
  21. package/lib/helpers/aiInventory.poku.js +111 -0
  22. package/lib/helpers/analyzer.js +1769 -0
  23. package/lib/helpers/analyzer.poku.js +284 -3
  24. package/lib/helpers/auditCategories.js +76 -0
  25. package/lib/helpers/ciParsers/githubActions.js +140 -16
  26. package/lib/helpers/ciParsers/githubActions.poku.js +110 -0
  27. package/lib/helpers/communityAiConfigParser.js +672 -0
  28. package/lib/helpers/communityAiConfigParser.poku.js +63 -0
  29. package/lib/helpers/depsUtils.js +108 -0
  30. package/lib/helpers/depsUtils.poku.js +72 -1
  31. package/lib/helpers/display.js +325 -3
  32. package/lib/helpers/display.poku.js +301 -0
  33. package/lib/helpers/formulationParsers.js +28 -0
  34. package/lib/helpers/formulationParsers.poku.js +504 -1
  35. package/lib/helpers/jsonLike.js +102 -0
  36. package/lib/helpers/jsonLike.poku.js +34 -0
  37. package/lib/helpers/mcp.js +248 -0
  38. package/lib/helpers/mcp.poku.js +101 -0
  39. package/lib/helpers/mcpConfigParser.js +656 -0
  40. package/lib/helpers/mcpConfigParser.poku.js +126 -0
  41. package/lib/helpers/mcpDiscovery.js +84 -0
  42. package/lib/helpers/mcpDiscovery.poku.js +21 -0
  43. package/lib/helpers/protobom.js +3 -3
  44. package/lib/helpers/provenanceUtils.js +29 -4
  45. package/lib/helpers/provenanceUtils.poku.js +29 -3
  46. package/lib/helpers/registryProvenance.js +210 -0
  47. package/lib/helpers/registryProvenance.poku.js +144 -0
  48. package/lib/helpers/rustFormulationParser.js +330 -0
  49. package/lib/helpers/source.js +21 -2
  50. package/lib/helpers/source.poku.js +38 -0
  51. package/lib/helpers/utils.js +1331 -83
  52. package/lib/helpers/utils.poku.js +599 -188
  53. package/lib/helpers/vsixutils.js +12 -4
  54. package/lib/helpers/vsixutils.poku.js +34 -0
  55. package/lib/managers/binary.js +36 -12
  56. package/lib/managers/binary.poku.js +68 -0
  57. package/lib/managers/docker.js +59 -9
  58. package/lib/managers/docker.poku.js +61 -0
  59. package/lib/managers/piptree.js +12 -7
  60. package/lib/managers/piptree.poku.js +44 -0
  61. package/lib/stages/postgen/annotator.js +2 -1
  62. package/lib/stages/postgen/annotator.poku.js +15 -0
  63. package/lib/stages/postgen/auditBom.js +20 -6
  64. package/lib/stages/postgen/auditBom.poku.js +694 -1
  65. package/lib/stages/postgen/postgen.js +262 -11
  66. package/lib/stages/postgen/postgen.poku.js +306 -2
  67. package/lib/stages/postgen/ruleEngine.js +49 -1
  68. package/lib/stages/postgen/spdxConverter.poku.js +70 -0
  69. package/lib/stages/pregen/pregen.js +6 -4
  70. package/package.json +1 -1
  71. package/types/bin/repl.d.ts.map +1 -1
  72. package/types/lib/audit/index.d.ts.map +1 -1
  73. package/types/lib/audit/reporters.d.ts.map +1 -1
  74. package/types/lib/audit/scoring.d.ts.map +1 -1
  75. package/types/lib/audit/targets.d.ts +12 -0
  76. package/types/lib/audit/targets.d.ts.map +1 -1
  77. package/types/lib/cli/index.d.ts +2 -8
  78. package/types/lib/cli/index.d.ts.map +1 -1
  79. package/types/lib/evinser/evinser.d.ts.map +1 -1
  80. package/types/lib/helpers/agentFormulationParser.d.ts +19 -0
  81. package/types/lib/helpers/agentFormulationParser.d.ts.map +1 -0
  82. package/types/lib/helpers/aiInventory.d.ts +23 -0
  83. package/types/lib/helpers/aiInventory.d.ts.map +1 -0
  84. package/types/lib/helpers/analyzer.d.ts +10 -0
  85. package/types/lib/helpers/analyzer.d.ts.map +1 -1
  86. package/types/lib/helpers/auditCategories.d.ts +12 -0
  87. package/types/lib/helpers/auditCategories.d.ts.map +1 -0
  88. package/types/lib/helpers/ciParsers/githubActions.d.ts.map +1 -1
  89. package/types/lib/helpers/communityAiConfigParser.d.ts +29 -0
  90. package/types/lib/helpers/communityAiConfigParser.d.ts.map +1 -0
  91. package/types/lib/helpers/depsUtils.d.ts +8 -0
  92. package/types/lib/helpers/depsUtils.d.ts.map +1 -1
  93. package/types/lib/helpers/display.d.ts +17 -1
  94. package/types/lib/helpers/display.d.ts.map +1 -1
  95. package/types/lib/helpers/formulationParsers.d.ts.map +1 -1
  96. package/types/lib/helpers/jsonLike.d.ts +4 -0
  97. package/types/lib/helpers/jsonLike.d.ts.map +1 -0
  98. package/types/lib/helpers/mcp.d.ts +29 -0
  99. package/types/lib/helpers/mcp.d.ts.map +1 -0
  100. package/types/lib/helpers/mcpConfigParser.d.ts +30 -0
  101. package/types/lib/helpers/mcpConfigParser.d.ts.map +1 -0
  102. package/types/lib/helpers/mcpDiscovery.d.ts +5 -0
  103. package/types/lib/helpers/mcpDiscovery.d.ts.map +1 -0
  104. package/types/lib/helpers/provenanceUtils.d.ts +5 -3
  105. package/types/lib/helpers/provenanceUtils.d.ts.map +1 -1
  106. package/types/lib/helpers/registryProvenance.d.ts +9 -0
  107. package/types/lib/helpers/registryProvenance.d.ts.map +1 -1
  108. package/types/lib/helpers/rustFormulationParser.d.ts +17 -0
  109. package/types/lib/helpers/rustFormulationParser.d.ts.map +1 -0
  110. package/types/lib/helpers/source.d.ts.map +1 -1
  111. package/types/lib/helpers/utils.d.ts +31 -1
  112. package/types/lib/helpers/utils.d.ts.map +1 -1
  113. package/types/lib/helpers/vsixutils.d.ts.map +1 -1
  114. package/types/lib/managers/binary.d.ts.map +1 -1
  115. package/types/lib/managers/docker.d.ts.map +1 -1
  116. package/types/lib/managers/piptree.d.ts.map +1 -1
  117. package/types/lib/stages/postgen/annotator.d.ts.map +1 -1
  118. package/types/lib/stages/postgen/auditBom.d.ts.map +1 -1
  119. package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
  120. package/types/lib/stages/postgen/ruleEngine.d.ts.map +1 -1
  121. package/types/lib/stages/pregen/pregen.d.ts.map +1 -1
package/bin/repl.js CHANGED
@@ -143,6 +143,13 @@ function printAuditTable(title, rows) {
143
143
  );
144
144
  }
145
145
 
146
+ function getPropertyValue(propertiesOrObject, propertyName) {
147
+ const properties = Array.isArray(propertiesOrObject)
148
+ ? propertiesOrObject
149
+ : propertiesOrObject?.properties;
150
+ return properties?.find((property) => property.name === propertyName)?.value;
151
+ }
152
+
146
153
  function isLikelyObom(bom) {
147
154
  return Boolean(
148
155
  bom?.components?.some((comp) =>
@@ -151,6 +158,69 @@ function isLikelyObom(bom) {
151
158
  );
152
159
  }
153
160
 
161
+ function isLikelyCargoBom(bom) {
162
+ const formulation = Array.isArray(bom?.formulation)
163
+ ? bom.formulation
164
+ : bom?.formulation
165
+ ? [bom.formulation]
166
+ : [];
167
+ return Boolean(
168
+ bom?.components?.some((component) =>
169
+ component?.purl?.startsWith("pkg:cargo/"),
170
+ ) ||
171
+ formulation.some((entry) =>
172
+ entry?.components?.some(
173
+ (component) =>
174
+ getPropertyValue(component, "cdx:rust:buildTool") === "cargo",
175
+ ),
176
+ ),
177
+ );
178
+ }
179
+
180
+ function getCargoHotspotComponents(bom) {
181
+ return (bom?.components || []).filter(
182
+ (component) =>
183
+ component?.purl?.startsWith("pkg:cargo/") &&
184
+ (getPropertyValue(component, "cdx:cargo:yanked") === "true" ||
185
+ Boolean(getPropertyValue(component, "cdx:cargo:git")) ||
186
+ Boolean(getPropertyValue(component, "cdx:cargo:path")) ||
187
+ getPropertyValue(component, "cdx:cargo:dependencyKind") === "build" ||
188
+ getPropertyValue(component, "cdx:cargo:workspaceDependencyResolved") ===
189
+ "true" ||
190
+ Boolean(getPropertyValue(component, "cdx:cargo:target"))),
191
+ );
192
+ }
193
+
194
+ function getCargoWorkflowComponents(bom) {
195
+ return (bom?.components || []).filter(
196
+ (component) =>
197
+ getPropertyValue(component, "cdx:github:action:ecosystem") === "cargo" ||
198
+ getPropertyValue(component, "cdx:github:step:usesCargo") === "true",
199
+ );
200
+ }
201
+
202
+ function getCargoFormulationEntries(bom) {
203
+ const formulation = Array.isArray(bom?.formulation)
204
+ ? bom.formulation
205
+ : bom?.formulation
206
+ ? [bom.formulation]
207
+ : [];
208
+ const matchingEntries = [];
209
+ for (const formulationEntry of formulation) {
210
+ const cargoComponents = (formulationEntry?.components || []).filter(
211
+ (component) =>
212
+ getPropertyValue(component, "cdx:rust:buildTool") === "cargo",
213
+ );
214
+ if (cargoComponents.length) {
215
+ matchingEntries.push({
216
+ ...formulationEntry,
217
+ components: cargoComponents,
218
+ });
219
+ }
220
+ }
221
+ return matchingEntries;
222
+ }
223
+
154
224
  let historyFile;
155
225
  const historyConfigDir = join(homedir(), ".config", ".cdxgen");
156
226
  if (!process.env.CDXGEN_REPL_HISTORY && !fs.existsSync(historyConfigDir)) {
@@ -182,6 +252,11 @@ export const importSbom = (sbomOrPath) => {
182
252
  "💭 OBOM detected. Try .osinfocategories, .obomtips, .processes, or .services_snapshot",
183
253
  );
184
254
  }
255
+ if (isLikelyCargoBom(sbom)) {
256
+ console.log(
257
+ "💭 Cargo signals detected. Try .cargohotspots or .cargoworkflows.",
258
+ );
259
+ }
185
260
  if (getAuditAnnotations().length) {
186
261
  console.log(
187
262
  "💭 Audit annotations detected. Try .auditfindings, .auditactions, or .dispatchedges.",
@@ -280,6 +355,11 @@ cdxgenRepl.defineCommand("create", {
280
355
  "💭 Type .auditfindings to review cdx-audit and bom-audit annotations.",
281
356
  );
282
357
  }
358
+ if (isLikelyCargoBom(sbom)) {
359
+ console.log(
360
+ "💭 Type .cargohotspots or .cargoworkflows for Cargo-specific pivots.",
361
+ );
362
+ }
283
363
  } else {
284
364
  console.log("BOM was not generated successfully");
285
365
  }
@@ -758,6 +838,64 @@ cdxgenRepl.defineCommand("formulation", {
758
838
  this.displayPrompt();
759
839
  },
760
840
  });
841
+ cdxgenRepl.defineCommand("cargohotspots", {
842
+ help: "show Cargo package components with high-signal source, workspace, or build metadata",
843
+ action() {
844
+ const interactiveBom = getInteractiveBom();
845
+ if (!interactiveBom?.components) {
846
+ console.log("⚠ No BOM is loaded. Use .import command to import an SBOM");
847
+ this.displayPrompt();
848
+ return;
849
+ }
850
+ const cargoComponents = getCargoHotspotComponents(interactiveBom);
851
+ if (!cargoComponents.length) {
852
+ console.log(
853
+ "No Cargo hotspot components found. Look for Cargo BOMs enriched with manifest, registry, or workspace metadata.",
854
+ );
855
+ this.displayPrompt();
856
+ return;
857
+ }
858
+ printTable(
859
+ { components: cargoComponents, dependencies: [] },
860
+ undefined,
861
+ undefined,
862
+ `Found ${cargoComponents.length} Cargo component(s) with high-signal source, workspace, or build metadata.`,
863
+ );
864
+ this.displayPrompt();
865
+ },
866
+ });
867
+ cdxgenRepl.defineCommand("cargoworkflows", {
868
+ help: "show Cargo-native build formulation plus Cargo-related workflow actions and run steps",
869
+ action() {
870
+ const interactiveBom = getInteractiveBom();
871
+ if (!interactiveBom) {
872
+ console.log("⚠ No BOM is loaded. Use .import command to import an SBOM");
873
+ this.displayPrompt();
874
+ return;
875
+ }
876
+ const cargoWorkflowComponents = getCargoWorkflowComponents(interactiveBom);
877
+ const cargoFormulation = getCargoFormulationEntries(interactiveBom);
878
+ if (!cargoWorkflowComponents.length && !cargoFormulation.length) {
879
+ console.log(
880
+ "No Cargo workflow or formulation pivots found. Import an SBOM generated with --include-formulation for Cargo projects.",
881
+ );
882
+ this.displayPrompt();
883
+ return;
884
+ }
885
+ if (cargoWorkflowComponents.length) {
886
+ printTable(
887
+ { components: cargoWorkflowComponents, dependencies: [] },
888
+ undefined,
889
+ undefined,
890
+ `Found ${cargoWorkflowComponents.length} Cargo-related workflow component(s).`,
891
+ );
892
+ }
893
+ if (cargoFormulation.length) {
894
+ printFormulation({ formulation: cargoFormulation });
895
+ }
896
+ this.displayPrompt();
897
+ },
898
+ });
761
899
  cdxgenRepl.defineCommand("auditfindings", {
762
900
  help: "summarize cdx-audit and bom-audit annotations from the loaded BOM",
763
901
  action() {
@@ -0,0 +1,249 @@
1
+ - id: AGT-001
2
+ name: "AI agent instruction file contains hidden Unicode characters"
3
+ description: "Hidden Unicode in AI agent instructions or skill files can conceal misleading prompts, hidden tool behavior, or review-evasion content."
4
+ severity: medium
5
+ category: ai-agent
6
+ standards:
7
+ owasp-ai-top-10:
8
+ - "LLM05: Supply Chain Vulnerabilities"
9
+ nist-ai-rmf:
10
+ - "Govern"
11
+ - "Manage"
12
+ nist-ssdf:
13
+ - "Review and protect build and automation instructions"
14
+ condition: |
15
+ formulation.components[
16
+ $prop($, 'cdx:agent:inventorySource') = 'agent-file'
17
+ and $prop($, 'cdx:file:hasHiddenUnicode') = 'true'
18
+ ]
19
+ location: |
20
+ {
21
+ "bomRef": $."bom-ref",
22
+ "file": $prop($, 'SrcFile')
23
+ }
24
+ message: "AI agent file '{{ name }}' contains hidden Unicode characters"
25
+ mitigation: "Review the file with hidden-character rendering enabled, remove suspicious bidirectional or zero-width characters, and verify instruction blocks before merge."
26
+ evidence: |
27
+ {
28
+ "codePoints": $prop($, 'cdx:file:hiddenUnicodeCodePoints'),
29
+ "lineNumbers": $prop($, 'cdx:file:hiddenUnicodeLineNumbers'),
30
+ "inComments": $prop($, 'cdx:file:hiddenUnicodeInComments')
31
+ }
32
+
33
+ - id: AGT-002
34
+ name: "AI agent instructions reference a public MCP endpoint without auth hints"
35
+ description: "Public MCP endpoints referenced from agent or skill files deserve review when the instruction surface does not indicate any bearer, token, or OAuth controls."
36
+ severity: high
37
+ category: ai-agent
38
+ attack:
39
+ tactics: [TA0001]
40
+ techniques: [T1190]
41
+ standards:
42
+ owasp-ai-top-10:
43
+ - "LLM07: Insecure Plugin Design"
44
+ - "LLM08: Excessive Agency"
45
+ nist-ai-rmf:
46
+ - "Map"
47
+ - "Manage"
48
+ nist-ssdf:
49
+ - "Review externally reachable AI and automation interfaces"
50
+ condition: |
51
+ formulation.components[
52
+ $prop($, 'cdx:agent:inventorySource') = 'agent-file'
53
+ and $prop($, 'cdx:agent:hasPublicMcpEndpoint') = 'true'
54
+ and $nullSafeProp($, 'cdx:agent:authHints') = ''
55
+ ]
56
+ location: |
57
+ {
58
+ "bomRef": $."bom-ref",
59
+ "file": $prop($, 'SrcFile')
60
+ }
61
+ message: "AI agent file '{{ name }}' references a public MCP endpoint without any auth hints"
62
+ mitigation: "Treat public MCP endpoints as untrusted until authentication, authorization, and endpoint provenance are documented explicitly."
63
+ evidence: |
64
+ {
65
+ "hiddenMcpUrls": $prop($, 'cdx:agent:hiddenMcpUrls'),
66
+ "hiddenMcpHosts": $prop($, 'cdx:agent:hiddenMcpHosts'),
67
+ "providerNames": $prop($, 'cdx:agent:providerNames')
68
+ }
69
+
70
+ - id: AGT-003
71
+ name: "AI agent instructions reference MCP surfaces not declared elsewhere in the BOM"
72
+ description: "Agent files that mention MCP servers, packages, or endpoints without corresponding MCP package inventory or source-derived MCP services can hide runtime trust dependencies from reviewers."
73
+ severity: medium
74
+ category: ai-agent
75
+ standards:
76
+ owasp-ai-top-10:
77
+ - "LLM05: Supply Chain Vulnerabilities"
78
+ - "LLM08: Excessive Agency"
79
+ nist-ai-rmf:
80
+ - "Map"
81
+ - "Govern"
82
+ nist-ssdf:
83
+ - "Maintain complete third-party and runtime dependency inventory"
84
+ condition: |
85
+ formulation.components[
86
+ $prop($, 'cdx:agent:inventorySource') = 'agent-file'
87
+ and $prop($, 'cdx:agent:hasMcpReferences') = 'true'
88
+ and $count($$.components[$prop($, 'cdx:mcp:package') = 'true']) = 0
89
+ and $count($auditServices($$)[$nullSafeProp($, 'cdx:mcp:inventorySource') = 'source-code-analysis']) = 0
90
+ ]
91
+ location: |
92
+ {
93
+ "bomRef": $."bom-ref",
94
+ "file": $prop($, 'SrcFile')
95
+ }
96
+ message: "AI agent file '{{ name }}' references MCP surfaces that are not otherwise declared in the BOM"
97
+ mitigation: "Inventory the referenced MCP packages, endpoints, and trust boundaries explicitly so reviewers can validate provenance and access controls."
98
+ evidence: |
99
+ {
100
+ "mcpPackageRefs": $prop($, 'cdx:agent:mcpPackageRefs'),
101
+ "hiddenMcpUrls": $prop($, 'cdx:agent:hiddenMcpUrls'),
102
+ "hiddenComponentKinds": $prop($, 'cdx:agent:hiddenComponentKinds')
103
+ }
104
+
105
+ - id: AGT-004
106
+ name: "AI agent instructions reference tunneled or reverse-proxied MCP exposure"
107
+ description: "Localhost tunneling and reverse-proxy references in agent files can turn development-only MCP servers into remotely reachable control surfaces."
108
+ severity: high
109
+ category: ai-agent
110
+ attack:
111
+ tactics: [TA0001, TA0011]
112
+ techniques: [T1190, T1071]
113
+ standards:
114
+ owasp-ai-top-10:
115
+ - "LLM07: Insecure Plugin Design"
116
+ - "LLM08: Excessive Agency"
117
+ nist-ai-rmf:
118
+ - "Map"
119
+ - "Manage"
120
+ nist-ssdf:
121
+ - "Review externally reachable development interfaces"
122
+ condition: |
123
+ formulation.components[
124
+ $prop($, 'cdx:agent:inventorySource') = 'agent-file'
125
+ and $prop($, 'cdx:agent:hasTunnelReference') = 'true'
126
+ ]
127
+ location: |
128
+ {
129
+ "bomRef": $."bom-ref",
130
+ "file": $prop($, 'SrcFile')
131
+ }
132
+ message: "AI agent file '{{ name }}' references a tunneled or reverse-proxied MCP endpoint"
133
+ mitigation: "Avoid exposing localhost MCP servers through ad-hoc tunnels; require reviewed ingress, authentication, and environment-specific controls."
134
+ evidence: |
135
+ {
136
+ "hiddenMcpUrls": $prop($, 'cdx:agent:hiddenMcpUrls'),
137
+ "hiddenMcpHosts": $prop($, 'cdx:agent:hiddenMcpHosts')
138
+ }
139
+
140
+ - id: AGT-005
141
+ name: "AI agent instructions reference non-official MCP packages or wrappers"
142
+ description: "Non-official MCP wrappers referenced directly from agent instructions deserve extra review before they are trusted in developer tooling or automation flows."
143
+ severity: medium
144
+ category: ai-agent
145
+ standards:
146
+ owasp-ai-top-10:
147
+ - "LLM05: Supply Chain Vulnerabilities"
148
+ - "LLM07: Insecure Plugin Design"
149
+ nist-ai-rmf:
150
+ - "Govern"
151
+ - "Map"
152
+ nist-ssdf:
153
+ - "Verify provenance of third-party AI integrations"
154
+ condition: |
155
+ formulation.components[
156
+ $prop($, 'cdx:agent:inventorySource') = 'agent-file'
157
+ and $prop($, 'cdx:agent:hasNonOfficialMcpReference') = 'true'
158
+ ]
159
+ location: |
160
+ {
161
+ "bomRef": $."bom-ref",
162
+ "file": $prop($, 'SrcFile')
163
+ }
164
+ message: "AI agent file '{{ name }}' references non-official MCP packages or wrappers"
165
+ mitigation: "Prefer official MCP SDKs where possible and document provenance, version pinning, and trust assumptions for any wrapper packages."
166
+ evidence: |
167
+ {
168
+ "mcpPackageRefs": $prop($, 'cdx:agent:mcpPackageRefs'),
169
+ "hiddenComponentKinds": $prop($, 'cdx:agent:hiddenComponentKinds')
170
+ }
171
+
172
+ - id: AGT-006
173
+ name: "AI agent instructions contain inline credential patterns"
174
+ description: "Agent or skill files that embed bearer tokens, API keys, or similar secrets create immediate review and credential-rotation risk."
175
+ severity: critical
176
+ category: ai-agent
177
+ attack:
178
+ tactics: [TA0006]
179
+ techniques: [T1552]
180
+ standards:
181
+ owasp-ai-top-10:
182
+ - "LLM05: Supply Chain Vulnerabilities"
183
+ - "LLM07: Insecure Plugin Design"
184
+ nist-ai-rmf:
185
+ - "Govern"
186
+ - "Manage"
187
+ nist-ssdf:
188
+ - "Protect secrets used by AI automation and developer tooling"
189
+ condition: |
190
+ formulation.components[
191
+ $prop($, 'cdx:agent:inventorySource') = 'agent-file'
192
+ and $prop($, 'cdx:agent:credentialExposure') = 'true'
193
+ ]
194
+ location: |
195
+ {
196
+ "bomRef": $."bom-ref",
197
+ "file": $prop($, 'SrcFile')
198
+ }
199
+ message: "AI agent file '{{ name }}' contains inline credential patterns"
200
+ mitigation: "Remove embedded credentials from agent instructions and move them into reviewed secret-management flows before the file is shared or executed."
201
+ evidence: |
202
+ {
203
+ "credentialRiskIndicators": $prop($, 'cdx:agent:credentialRiskIndicators'),
204
+ "hiddenMcpUrls": $prop($, 'cdx:agent:hiddenMcpUrls'),
205
+ "providerNames": $prop($, 'cdx:agent:providerNames')
206
+ }
207
+
208
+ - id: AGT-007
209
+ name: "AI agent or skill file is included in a build or post-build SBOM"
210
+ description: "Shipped AI instruction and skill files deserve explicit review because they can alter developer tooling, release-time automation, and downstream runtime behavior."
211
+ severity: medium
212
+ category: ai-agent
213
+ standards:
214
+ owasp-ai-top-10:
215
+ - "LLM05: Supply Chain Vulnerabilities"
216
+ - "LLM08: Excessive Agency"
217
+ nist-ai-rmf:
218
+ - "Govern"
219
+ - "Map"
220
+ nist-ssdf:
221
+ - "Review build and release instructions before distribution"
222
+ condition: |
223
+ components[
224
+ (
225
+ $prop($, 'cdx:agent:inventorySource') = 'agent-file'
226
+ or $prop($, 'cdx:agent:inventorySource') = 'community-config'
227
+ )
228
+ and (
229
+ $prop($, 'cdx:file:kind') = 'skill-file'
230
+ or $prop($, 'cdx:file:kind') = 'agent-instructions'
231
+ or $prop($, 'cdx:file:kind') = 'copilot-instructions'
232
+ or $prop($, 'cdx:file:kind') = 'copilot-setup-workflow'
233
+ or $prop($, 'cdx:file:kind') = 'ai-agent-file'
234
+ )
235
+ and $count($$.metadata.lifecycles[phase = 'build' or phase = 'post-build']) > 0
236
+ ]
237
+ location: |
238
+ {
239
+ "bomRef": $."bom-ref",
240
+ "file": $prop($, 'SrcFile')
241
+ }
242
+ message: "AI instruction or skill file '{{ name }}' is included in a build/post-build SBOM"
243
+ mitigation: "If the file must ship, keep the BOM review-friendly with '--bom-audit --bom-audit-categories ai-agent' and consider '--tlp-classification AMBER'. If you want a package-only BOM, rerun with '--exclude-type ai-skill'."
244
+ evidence: |
245
+ {
246
+ "inventorySource": $prop($, 'cdx:agent:inventorySource'),
247
+ "fileKind": $prop($, 'cdx:file:kind'),
248
+ "providerNames": $prop($, 'cdx:agent:providerNames')
249
+ }
@@ -121,3 +121,44 @@
121
121
  "registry": $prop($, 'cdx:pypi:registry'),
122
122
  "resolvedFrom": $prop($, 'cdx:pypi:resolved_from')
123
123
  }
124
+ - id: PKG-007
125
+ name: "Cargo dependency from mutable git source"
126
+ description: "Cargo git dependencies without revision or tag pinning can change unexpectedly and reduce build reproducibility"
127
+ severity: high
128
+ category: dependency-source
129
+ condition: |
130
+ components[
131
+ $hasProp($, 'cdx:cargo:git')
132
+ and $prop($, 'cdx:cargo:gitRev') = null
133
+ and $prop($, 'cdx:cargo:gitTag') = null
134
+ ]
135
+ location: |
136
+ { "bomRef": $."bom-ref", "purl": purl }
137
+ message: "Cargo dependency '{{ name }}@{{ version }}' tracks git source '{{ $prop($, 'cdx:cargo:git') }}' without an immutable revision pin"
138
+ mitigation: "Prefer crates.io releases or pin git dependencies with `rev = \"<commit-sha>\"` or a signed, reviewed tag"
139
+ evidence: |
140
+ {
141
+ "git": $prop($, 'cdx:cargo:git'),
142
+ "branch": $prop($, 'cdx:cargo:gitBranch'),
143
+ "tag": $prop($, 'cdx:cargo:gitTag'),
144
+ "dependencyKind": $prop($, 'cdx:cargo:dependencyKind')
145
+ }
146
+ - id: PKG-008
147
+ name: "Cargo dependency from local path"
148
+ description: "Cargo path dependencies are local source references that reduce release reproducibility and may bypass registry review controls"
149
+ severity: high
150
+ category: dependency-source
151
+ condition: |
152
+ components[
153
+ $hasProp($, 'cdx:cargo:path')
154
+ ]
155
+ location: |
156
+ { "bomRef": $."bom-ref", "purl": purl }
157
+ message: "Cargo dependency '{{ name }}@{{ version }}' uses local path source '{{ $prop($, 'cdx:cargo:path') }}'"
158
+ mitigation: "Use published crate versions for release builds or vendor the dependency explicitly with clear provenance review"
159
+ evidence: |
160
+ {
161
+ "path": $prop($, 'cdx:cargo:path'),
162
+ "dependencyKind": $prop($, 'cdx:cargo:dependencyKind'),
163
+ "target": $prop($, 'cdx:cargo:target')
164
+ }