@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.
- package/README.md +15 -5
- package/bin/audit.js +7 -0
- package/bin/cdxgen.js +241 -81
- package/bin/repl.js +138 -0
- package/data/rules/ai-agent-governance.yaml +249 -0
- package/data/rules/dependency-sources.yaml +41 -0
- package/data/rules/mcp-servers.yaml +304 -0
- package/data/rules/package-integrity.yaml +123 -0
- package/lib/audit/index.js +353 -29
- package/lib/audit/index.poku.js +247 -7
- package/lib/audit/reporters.js +26 -0
- package/lib/audit/scoring.js +262 -13
- package/lib/audit/scoring.poku.js +179 -0
- package/lib/audit/targets.js +391 -2
- package/lib/audit/targets.poku.js +416 -3
- package/lib/cli/index.js +588 -45
- package/lib/cli/index.poku.js +735 -1
- package/lib/evinser/evinser.js +8 -5
- package/lib/helpers/agentFormulationParser.js +318 -0
- package/lib/helpers/aiInventory.js +262 -0
- package/lib/helpers/aiInventory.poku.js +111 -0
- package/lib/helpers/analyzer.js +1769 -0
- package/lib/helpers/analyzer.poku.js +284 -3
- package/lib/helpers/auditCategories.js +76 -0
- package/lib/helpers/ciParsers/githubActions.js +140 -16
- package/lib/helpers/ciParsers/githubActions.poku.js +110 -0
- package/lib/helpers/communityAiConfigParser.js +672 -0
- package/lib/helpers/communityAiConfigParser.poku.js +63 -0
- package/lib/helpers/depsUtils.js +108 -0
- package/lib/helpers/depsUtils.poku.js +72 -1
- package/lib/helpers/display.js +325 -3
- package/lib/helpers/display.poku.js +301 -0
- package/lib/helpers/formulationParsers.js +28 -0
- package/lib/helpers/formulationParsers.poku.js +504 -1
- package/lib/helpers/jsonLike.js +102 -0
- package/lib/helpers/jsonLike.poku.js +34 -0
- package/lib/helpers/mcp.js +248 -0
- package/lib/helpers/mcp.poku.js +101 -0
- package/lib/helpers/mcpConfigParser.js +656 -0
- package/lib/helpers/mcpConfigParser.poku.js +126 -0
- package/lib/helpers/mcpDiscovery.js +84 -0
- package/lib/helpers/mcpDiscovery.poku.js +21 -0
- package/lib/helpers/protobom.js +3 -3
- package/lib/helpers/provenanceUtils.js +29 -4
- package/lib/helpers/provenanceUtils.poku.js +29 -3
- package/lib/helpers/registryProvenance.js +210 -0
- package/lib/helpers/registryProvenance.poku.js +144 -0
- package/lib/helpers/rustFormulationParser.js +330 -0
- package/lib/helpers/source.js +21 -2
- package/lib/helpers/source.poku.js +38 -0
- package/lib/helpers/utils.js +1331 -83
- package/lib/helpers/utils.poku.js +599 -188
- package/lib/helpers/vsixutils.js +12 -4
- package/lib/helpers/vsixutils.poku.js +34 -0
- package/lib/managers/binary.js +36 -12
- package/lib/managers/binary.poku.js +68 -0
- package/lib/managers/docker.js +59 -9
- package/lib/managers/docker.poku.js +61 -0
- package/lib/managers/piptree.js +12 -7
- package/lib/managers/piptree.poku.js +44 -0
- package/lib/stages/postgen/annotator.js +2 -1
- package/lib/stages/postgen/annotator.poku.js +15 -0
- package/lib/stages/postgen/auditBom.js +20 -6
- package/lib/stages/postgen/auditBom.poku.js +694 -1
- package/lib/stages/postgen/postgen.js +262 -11
- package/lib/stages/postgen/postgen.poku.js +306 -2
- package/lib/stages/postgen/ruleEngine.js +49 -1
- package/lib/stages/postgen/spdxConverter.poku.js +70 -0
- package/lib/stages/pregen/pregen.js +6 -4
- package/package.json +1 -1
- package/types/bin/repl.d.ts.map +1 -1
- package/types/lib/audit/index.d.ts.map +1 -1
- package/types/lib/audit/reporters.d.ts.map +1 -1
- package/types/lib/audit/scoring.d.ts.map +1 -1
- package/types/lib/audit/targets.d.ts +12 -0
- package/types/lib/audit/targets.d.ts.map +1 -1
- package/types/lib/cli/index.d.ts +2 -8
- package/types/lib/cli/index.d.ts.map +1 -1
- package/types/lib/evinser/evinser.d.ts.map +1 -1
- package/types/lib/helpers/agentFormulationParser.d.ts +19 -0
- package/types/lib/helpers/agentFormulationParser.d.ts.map +1 -0
- package/types/lib/helpers/aiInventory.d.ts +23 -0
- package/types/lib/helpers/aiInventory.d.ts.map +1 -0
- package/types/lib/helpers/analyzer.d.ts +10 -0
- package/types/lib/helpers/analyzer.d.ts.map +1 -1
- package/types/lib/helpers/auditCategories.d.ts +12 -0
- package/types/lib/helpers/auditCategories.d.ts.map +1 -0
- package/types/lib/helpers/ciParsers/githubActions.d.ts.map +1 -1
- package/types/lib/helpers/communityAiConfigParser.d.ts +29 -0
- package/types/lib/helpers/communityAiConfigParser.d.ts.map +1 -0
- package/types/lib/helpers/depsUtils.d.ts +8 -0
- package/types/lib/helpers/depsUtils.d.ts.map +1 -1
- package/types/lib/helpers/display.d.ts +17 -1
- package/types/lib/helpers/display.d.ts.map +1 -1
- package/types/lib/helpers/formulationParsers.d.ts.map +1 -1
- package/types/lib/helpers/jsonLike.d.ts +4 -0
- package/types/lib/helpers/jsonLike.d.ts.map +1 -0
- package/types/lib/helpers/mcp.d.ts +29 -0
- package/types/lib/helpers/mcp.d.ts.map +1 -0
- package/types/lib/helpers/mcpConfigParser.d.ts +30 -0
- package/types/lib/helpers/mcpConfigParser.d.ts.map +1 -0
- package/types/lib/helpers/mcpDiscovery.d.ts +5 -0
- package/types/lib/helpers/mcpDiscovery.d.ts.map +1 -0
- package/types/lib/helpers/provenanceUtils.d.ts +5 -3
- package/types/lib/helpers/provenanceUtils.d.ts.map +1 -1
- package/types/lib/helpers/registryProvenance.d.ts +9 -0
- package/types/lib/helpers/registryProvenance.d.ts.map +1 -1
- package/types/lib/helpers/rustFormulationParser.d.ts +17 -0
- package/types/lib/helpers/rustFormulationParser.d.ts.map +1 -0
- package/types/lib/helpers/source.d.ts.map +1 -1
- package/types/lib/helpers/utils.d.ts +31 -1
- package/types/lib/helpers/utils.d.ts.map +1 -1
- package/types/lib/helpers/vsixutils.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/piptree.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/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
|
+
}
|