agentshield-sdk 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +191 -0
- package/LICENSE +21 -0
- package/README.md +975 -0
- package/bin/agent-shield.js +680 -0
- package/package.json +118 -0
- package/src/adaptive.js +330 -0
- package/src/agent-protocol.js +998 -0
- package/src/alert-tuning.js +480 -0
- package/src/allowlist.js +603 -0
- package/src/audit-immutable.js +914 -0
- package/src/audit-streaming.js +469 -0
- package/src/badges.js +196 -0
- package/src/behavior-profiling.js +289 -0
- package/src/benchmark-harness.js +804 -0
- package/src/canary.js +271 -0
- package/src/certification.js +563 -0
- package/src/circuit-breaker.js +321 -0
- package/src/compliance.js +617 -0
- package/src/confidence-tuning.js +324 -0
- package/src/confused-deputy.js +624 -0
- package/src/context-scoring.js +360 -0
- package/src/conversation.js +494 -0
- package/src/cost-optimizer.js +1024 -0
- package/src/ctf.js +462 -0
- package/src/detector-core.js +1999 -0
- package/src/distributed.js +359 -0
- package/src/document-scanner.js +795 -0
- package/src/embedding.js +307 -0
- package/src/encoding.js +429 -0
- package/src/enterprise.js +405 -0
- package/src/errors.js +100 -0
- package/src/eu-ai-act.js +523 -0
- package/src/fuzzer.js +764 -0
- package/src/honeypot.js +328 -0
- package/src/i18n-patterns.js +523 -0
- package/src/index.js +430 -0
- package/src/integrations.js +528 -0
- package/src/llm-redteam.js +670 -0
- package/src/main.js +741 -0
- package/src/main.mjs +38 -0
- package/src/mcp-bridge.js +542 -0
- package/src/mcp-certification.js +846 -0
- package/src/mcp-sdk-integration.js +355 -0
- package/src/mcp-security-runtime.js +741 -0
- package/src/mcp-server.js +740 -0
- package/src/middleware.js +208 -0
- package/src/model-finetuning.js +884 -0
- package/src/model-fingerprint.js +1042 -0
- package/src/multi-agent-trust.js +453 -0
- package/src/multi-agent.js +404 -0
- package/src/multimodal.js +296 -0
- package/src/nist-mapping.js +505 -0
- package/src/observability.js +330 -0
- package/src/openclaw.js +450 -0
- package/src/otel.js +544 -0
- package/src/owasp-2025.js +483 -0
- package/src/pii.js +390 -0
- package/src/plugin-marketplace.js +628 -0
- package/src/plugin-system.js +349 -0
- package/src/policy-dsl.js +775 -0
- package/src/policy-extended.js +635 -0
- package/src/policy.js +443 -0
- package/src/presets.js +409 -0
- package/src/production.js +557 -0
- package/src/prompt-leakage.js +321 -0
- package/src/rag-vulnerability.js +579 -0
- package/src/redteam.js +475 -0
- package/src/response-handler.js +429 -0
- package/src/scanners.js +357 -0
- package/src/self-healing.js +363 -0
- package/src/semantic.js +339 -0
- package/src/shield-score.js +250 -0
- package/src/sso-saml.js +897 -0
- package/src/stream-scanner.js +806 -0
- package/src/testing.js +505 -0
- package/src/threat-encyclopedia.js +629 -0
- package/src/threat-intel-network.js +1017 -0
- package/src/token-analysis.js +467 -0
- package/src/tool-guard.js +412 -0
- package/src/tool-output-validator.js +354 -0
- package/src/utils.js +83 -0
- package/src/watermark.js +235 -0
- package/src/worker-scanner.js +601 -0
- package/types/index.d.ts +2088 -0
|
@@ -0,0 +1,505 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Agent Shield — NIST AI RMF Mapping & AI-BOM Generator
|
|
5
|
+
*
|
|
6
|
+
* Maps Agent Shield capabilities to the NIST AI Risk Management Framework
|
|
7
|
+
* (2025 updates). Generates AI Bill of Materials (AI-BOM) for compliance.
|
|
8
|
+
*
|
|
9
|
+
* All processing runs locally — no data ever leaves your environment.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
// =========================================================================
|
|
13
|
+
// NIST AI RMF 2025 Framework
|
|
14
|
+
// =========================================================================
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* NIST AI RMF functions, categories, and subcategories with Agent Shield mapping.
|
|
18
|
+
* @type {object}
|
|
19
|
+
*/
|
|
20
|
+
const NIST_AI_RMF_2025 = {
|
|
21
|
+
version: '1.0-2025',
|
|
22
|
+
functions: {
|
|
23
|
+
GOVERN: {
|
|
24
|
+
name: 'Govern',
|
|
25
|
+
description: 'Establish and maintain AI risk management culture, accountability, and policies.',
|
|
26
|
+
categories: [
|
|
27
|
+
{ id: 'GOVERN-1', name: 'AI Risk Culture', description: 'Foster organizational culture for AI risk management', agentShieldMapping: ['compliance.js:ComplianceReporter'], automatable: false },
|
|
28
|
+
{ id: 'GOVERN-2', name: 'Accountability', description: 'Establish accountability structures for AI systems', agentShieldMapping: ['enterprise.js:RoleBasedPolicy', 'multi-agent-trust.js:CapabilityToken'], automatable: true },
|
|
29
|
+
{ id: 'GOVERN-3', name: 'Workforce', description: 'AI risk management workforce competencies', agentShieldMapping: [], automatable: false },
|
|
30
|
+
{ id: 'GOVERN-4', name: 'Stakeholder Engagement', description: 'Engage stakeholders in AI risk decisions', agentShieldMapping: [], automatable: false },
|
|
31
|
+
{ id: 'GOVERN-5', name: 'Risk Assessment', description: 'Continuous AI risk assessment processes', agentShieldMapping: ['shield-score.js:ShieldScoreCalculator', 'owasp-2025.js:OWASPCoverageMatrix'], automatable: true },
|
|
32
|
+
{ id: 'GOVERN-6', name: 'Policies & Procedures', description: 'AI governance policies and procedures', agentShieldMapping: ['policy.js:loadPolicy', 'policy-dsl.js:PolicyDSL'], automatable: true }
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
MAP: {
|
|
36
|
+
name: 'Map',
|
|
37
|
+
description: 'Identify and document AI system context, requirements, and risks.',
|
|
38
|
+
categories: [
|
|
39
|
+
{ id: 'MAP-1', name: 'Context', description: 'Map AI system intended purpose and context of use', agentShieldMapping: ['compliance.js:ComplianceReporter'], automatable: false },
|
|
40
|
+
{ id: 'MAP-2', name: 'Requirements', description: 'Document AI system requirements and constraints', agentShieldMapping: ['owasp-2025.js:OWASPCoverageMatrix'], automatable: true },
|
|
41
|
+
{ id: 'MAP-3', name: 'Risks', description: 'Identify and characterize AI-specific risks', agentShieldMapping: ['threat-encyclopedia.js:ThreatEncyclopedia', 'redteam.js:AttackSimulator'], automatable: true },
|
|
42
|
+
{ id: 'MAP-4', name: 'Benefits', description: 'Document intended benefits relative to risks', agentShieldMapping: [], automatable: false },
|
|
43
|
+
{ id: 'MAP-5', name: 'Documentation', description: 'Maintain AI system documentation', agentShieldMapping: ['compliance.js:AuditTrail', 'audit-immutable.js:ImmutableAuditLog'], automatable: true }
|
|
44
|
+
]
|
|
45
|
+
},
|
|
46
|
+
MEASURE: {
|
|
47
|
+
name: 'Measure',
|
|
48
|
+
description: 'Assess, analyze, and monitor AI risks using quantitative and qualitative methods.',
|
|
49
|
+
categories: [
|
|
50
|
+
{ id: 'MEASURE-1', name: 'Metrics', description: 'Define and track AI risk metrics', agentShieldMapping: ['shield-score.js:ShieldScoreCalculator', 'benchmark-harness.js:BenchmarkMetrics'], automatable: true },
|
|
51
|
+
{ id: 'MEASURE-2', name: 'Testing', description: 'Test AI systems for safety, security, and fairness', agentShieldMapping: ['redteam.js:AttackSimulator', 'fuzzer.js:FuzzingHarness', 'testing.js:TestSuiteGenerator'], automatable: true },
|
|
52
|
+
{ id: 'MEASURE-3', name: 'Monitoring', description: 'Continuously monitor AI system behavior', agentShieldMapping: ['behavior-profiling.js:BehaviorProfile', 'observability.js:MetricsCollector', 'circuit-breaker.js:CircuitBreaker'], automatable: true },
|
|
53
|
+
{ id: 'MEASURE-4', name: 'Feedback', description: 'Collect and integrate feedback on AI risk', agentShieldMapping: ['allowlist.js:FeedbackLoop', 'self-healing.js:SelfHealingEngine'], automatable: true }
|
|
54
|
+
]
|
|
55
|
+
},
|
|
56
|
+
MANAGE: {
|
|
57
|
+
name: 'Manage',
|
|
58
|
+
description: 'Allocate resources and implement plans to respond to AI risks.',
|
|
59
|
+
categories: [
|
|
60
|
+
{ id: 'MANAGE-1', name: 'Risk Treatment', description: 'Treat identified AI risks with appropriate controls', agentShieldMapping: ['detector-core.js:scanText', 'middleware.js:wrapAgent', 'mcp-bridge.js:MCPBridge'], automatable: true },
|
|
61
|
+
{ id: 'MANAGE-2', name: 'Incident Response', description: 'Respond to AI-related security incidents', agentShieldMapping: ['compliance.js:IncidentPlaybook', 'circuit-breaker.js:CircuitBreaker'], automatable: true },
|
|
62
|
+
{ id: 'MANAGE-3', name: 'Communication', description: 'Communicate AI risks to stakeholders', agentShieldMapping: ['policy.js:WebhookAlert', 'audit-streaming.js:AuditStreamManager'], automatable: true },
|
|
63
|
+
{ id: 'MANAGE-4', name: 'Improvement', description: 'Continuously improve AI risk management', agentShieldMapping: ['self-healing.js:SelfHealingEngine', 'confidence-tuning.js:ConfidenceTuner'], automatable: true }
|
|
64
|
+
]
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* NIST SP 800-53 controls relevant to AI systems.
|
|
71
|
+
* @type {Array<object>}
|
|
72
|
+
*/
|
|
73
|
+
const SP800_53_AI_CONTROLS = [
|
|
74
|
+
{ id: 'AC-3', family: 'Access Control', name: 'Access Enforcement', description: 'Enforce approved authorizations for AI system access', agentShieldCoverage: 'enterprise.js:RoleBasedPolicy' },
|
|
75
|
+
{ id: 'AU-2', family: 'Audit', name: 'Event Logging', description: 'Log AI system security-relevant events', agentShieldCoverage: 'audit-immutable.js:ImmutableAuditLog' },
|
|
76
|
+
{ id: 'AU-6', family: 'Audit', name: 'Audit Review', description: 'Review and analyze AI system audit records', agentShieldCoverage: 'audit-streaming.js:AuditStreamManager' },
|
|
77
|
+
{ id: 'CA-7', family: 'Assessment', name: 'Continuous Monitoring', description: 'Continuously monitor AI system security', agentShieldCoverage: 'observability.js:MetricsCollector' },
|
|
78
|
+
{ id: 'CM-3', family: 'Configuration', name: 'Configuration Change Control', description: 'Control changes to AI system configuration', agentShieldCoverage: 'policy-dsl.js:PolicyDSL' },
|
|
79
|
+
{ id: 'IA-9', family: 'Identification', name: 'Service Identification', description: 'Identify and authenticate AI services', agentShieldCoverage: 'agent-protocol.js:AgentIdentity' },
|
|
80
|
+
{ id: 'IR-4', family: 'Incident Response', name: 'Incident Handling', description: 'Handle AI-related security incidents', agentShieldCoverage: 'compliance.js:IncidentPlaybook' },
|
|
81
|
+
{ id: 'RA-5', family: 'Risk Assessment', name: 'Vulnerability Monitoring', description: 'Monitor AI system vulnerabilities', agentShieldCoverage: 'shield-score.js:ShieldScoreCalculator' },
|
|
82
|
+
{ id: 'SA-11', family: 'Acquisition', name: 'Developer Testing', description: 'Test AI system security controls', agentShieldCoverage: 'testing.js:TestSuiteGenerator' },
|
|
83
|
+
{ id: 'SC-7', family: 'System Protection', name: 'Boundary Protection', description: 'Protect AI system communication boundaries', agentShieldCoverage: 'agent-protocol.js:SecureChannel' },
|
|
84
|
+
{ id: 'SI-3', family: 'System Integrity', name: 'Malicious Code Protection', description: 'Protect AI systems from malicious inputs', agentShieldCoverage: 'detector-core.js:scanText' },
|
|
85
|
+
{ id: 'SI-4', family: 'System Integrity', name: 'System Monitoring', description: 'Monitor AI system for anomalous behavior', agentShieldCoverage: 'behavior-profiling.js:BehaviorProfile' }
|
|
86
|
+
];
|
|
87
|
+
|
|
88
|
+
// =========================================================================
|
|
89
|
+
// NISTMapper
|
|
90
|
+
// =========================================================================
|
|
91
|
+
|
|
92
|
+
class NISTMapper {
|
|
93
|
+
/**
|
|
94
|
+
* @param {object} [options]
|
|
95
|
+
* @param {string} [options.organizationName='Organization'] - Org name for reports
|
|
96
|
+
* @param {string} [options.systemName='AI System'] - AI system name
|
|
97
|
+
* @param {'low'|'medium'|'high'|'critical'} [options.riskLevel='medium'] - Risk level
|
|
98
|
+
*/
|
|
99
|
+
constructor(options = {}) {
|
|
100
|
+
this.organizationName = options.organizationName || 'Organization';
|
|
101
|
+
this.systemName = options.systemName || 'AI System';
|
|
102
|
+
this.riskLevel = options.riskLevel || 'medium';
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Returns which NIST categories Agent Shield covers and how.
|
|
107
|
+
* @returns {object}
|
|
108
|
+
*/
|
|
109
|
+
getCoverageMap() {
|
|
110
|
+
const map = {};
|
|
111
|
+
for (const [funcName, func] of Object.entries(NIST_AI_RMF_2025.functions)) {
|
|
112
|
+
map[funcName] = func.categories.map(cat => ({
|
|
113
|
+
id: cat.id,
|
|
114
|
+
name: cat.name,
|
|
115
|
+
covered: cat.agentShieldMapping.length > 0,
|
|
116
|
+
automatable: cat.automatable,
|
|
117
|
+
modules: cat.agentShieldMapping,
|
|
118
|
+
coverageLevel: cat.agentShieldMapping.length > 1 ? 'strong' : cat.agentShieldMapping.length === 1 ? 'basic' : 'none'
|
|
119
|
+
}));
|
|
120
|
+
}
|
|
121
|
+
return map;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Returns percentage of NIST controls addressed.
|
|
126
|
+
* @returns {{ percentage: number, covered: number, total: number, byFunction: object }}
|
|
127
|
+
*/
|
|
128
|
+
getCoverageScore() {
|
|
129
|
+
const byFunction = {};
|
|
130
|
+
let covered = 0;
|
|
131
|
+
let total = 0;
|
|
132
|
+
|
|
133
|
+
for (const [funcName, func] of Object.entries(NIST_AI_RMF_2025.functions)) {
|
|
134
|
+
const funcCovered = func.categories.filter(c => c.agentShieldMapping.length > 0).length;
|
|
135
|
+
const funcTotal = func.categories.length;
|
|
136
|
+
byFunction[funcName] = { covered: funcCovered, total: funcTotal, percentage: Math.round((funcCovered / funcTotal) * 100) };
|
|
137
|
+
covered += funcCovered;
|
|
138
|
+
total += funcTotal;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return { percentage: Math.round((covered / total) * 100), covered, total, byFunction };
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Returns uncovered or partially covered areas.
|
|
146
|
+
* @returns {Array<object>}
|
|
147
|
+
*/
|
|
148
|
+
getGaps() {
|
|
149
|
+
const gaps = [];
|
|
150
|
+
for (const [funcName, func] of Object.entries(NIST_AI_RMF_2025.functions)) {
|
|
151
|
+
for (const cat of func.categories) {
|
|
152
|
+
if (cat.agentShieldMapping.length === 0) {
|
|
153
|
+
gaps.push({ function: funcName, id: cat.id, name: cat.name, description: cat.description, automatable: cat.automatable });
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return gaps;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Generates a NIST AI RMF profile document.
|
|
162
|
+
* @param {string} [systemDescription=''] - Description of the AI system
|
|
163
|
+
* @returns {object}
|
|
164
|
+
*/
|
|
165
|
+
generateProfile(systemDescription = '') {
|
|
166
|
+
return {
|
|
167
|
+
framework: 'NIST AI RMF',
|
|
168
|
+
version: NIST_AI_RMF_2025.version,
|
|
169
|
+
generatedAt: new Date().toISOString(),
|
|
170
|
+
organization: this.organizationName,
|
|
171
|
+
system: { name: this.systemName, description: systemDescription, riskLevel: this.riskLevel },
|
|
172
|
+
coverage: this.getCoverageScore(),
|
|
173
|
+
coverageMap: this.getCoverageMap(),
|
|
174
|
+
gaps: this.getGaps(),
|
|
175
|
+
sp800_53_mapping: SP800_53_AI_CONTROLS.map(c => ({ ...c, covered: !!c.agentShieldCoverage }))
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Generates a formatted report.
|
|
181
|
+
* @param {'text'|'json'|'markdown'} [format='text']
|
|
182
|
+
* @returns {string}
|
|
183
|
+
*/
|
|
184
|
+
generateReport(format = 'text') {
|
|
185
|
+
const profile = this.generateProfile();
|
|
186
|
+
|
|
187
|
+
if (format === 'json') return JSON.stringify(profile, null, 2);
|
|
188
|
+
|
|
189
|
+
if (format === 'markdown') {
|
|
190
|
+
const lines = [
|
|
191
|
+
'# NIST AI RMF Coverage Report',
|
|
192
|
+
'',
|
|
193
|
+
`**Organization:** ${this.organizationName}`,
|
|
194
|
+
`**System:** ${this.systemName}`,
|
|
195
|
+
`**Risk Level:** ${this.riskLevel}`,
|
|
196
|
+
`**Coverage:** ${profile.coverage.percentage}%`,
|
|
197
|
+
''
|
|
198
|
+
];
|
|
199
|
+
|
|
200
|
+
for (const [funcName, func] of Object.entries(NIST_AI_RMF_2025.functions)) {
|
|
201
|
+
const funcScore = profile.coverage.byFunction[funcName];
|
|
202
|
+
lines.push(`## ${func.name} (${funcScore.covered}/${funcScore.total})`);
|
|
203
|
+
lines.push('');
|
|
204
|
+
for (const cat of func.categories) {
|
|
205
|
+
const icon = cat.agentShieldMapping.length > 0 ? 'x' : ' ';
|
|
206
|
+
lines.push(`- [${icon}] **${cat.id}** ${cat.name}: ${cat.description}`);
|
|
207
|
+
}
|
|
208
|
+
lines.push('');
|
|
209
|
+
}
|
|
210
|
+
return lines.join('\n');
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// text format
|
|
214
|
+
const score = profile.coverage;
|
|
215
|
+
const lines = [
|
|
216
|
+
`=== NIST AI RMF Coverage Report ===`,
|
|
217
|
+
`Organization: ${this.organizationName}`,
|
|
218
|
+
`System: ${this.systemName} | Risk: ${this.riskLevel}`,
|
|
219
|
+
`Coverage: ${score.percentage}% (${score.covered}/${score.total})`,
|
|
220
|
+
''
|
|
221
|
+
];
|
|
222
|
+
for (const [funcName, func] of Object.entries(NIST_AI_RMF_2025.functions)) {
|
|
223
|
+
const fs = score.byFunction[funcName];
|
|
224
|
+
lines.push(`${func.name}: ${fs.percentage}% (${fs.covered}/${fs.total})`);
|
|
225
|
+
for (const cat of func.categories) {
|
|
226
|
+
const icon = cat.agentShieldMapping.length > 0 ? '●' : '○';
|
|
227
|
+
lines.push(` ${icon} ${cat.id} ${cat.name}`);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return lines.join('\n');
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// =========================================================================
|
|
235
|
+
// AIBOMGenerator — AI Bill of Materials
|
|
236
|
+
// =========================================================================
|
|
237
|
+
|
|
238
|
+
class AIBOMGenerator {
|
|
239
|
+
/**
|
|
240
|
+
* @param {object} [options]
|
|
241
|
+
* @param {'spdx'|'cyclonedx'|'custom'} [options.format='custom'] - Output format
|
|
242
|
+
* @param {string} [options.organizationName] - Organization name
|
|
243
|
+
* @param {string} [options.systemName] - System name
|
|
244
|
+
*/
|
|
245
|
+
constructor(options = {}) {
|
|
246
|
+
this.format = options.format || 'custom';
|
|
247
|
+
this.organizationName = options.organizationName || 'Organization';
|
|
248
|
+
this.systemName = options.systemName || 'AI System';
|
|
249
|
+
this.components = [];
|
|
250
|
+
this.models = [];
|
|
251
|
+
this.datasets = [];
|
|
252
|
+
this.services = [];
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Adds a generic component.
|
|
257
|
+
* @param {object} component - { name, version, type, supplier, license, hash }
|
|
258
|
+
*/
|
|
259
|
+
addComponent(component) {
|
|
260
|
+
this.components.push({ ...component, addedAt: new Date().toISOString() });
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Adds an AI model.
|
|
265
|
+
* @param {object} model - { name, provider, version, type, parameters, trainingData, license }
|
|
266
|
+
*/
|
|
267
|
+
addModel(model) {
|
|
268
|
+
this.models.push({ ...model, addedAt: new Date().toISOString() });
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Adds a dataset.
|
|
273
|
+
* @param {object} dataset - { name, source, version, format, size, privacyLevel }
|
|
274
|
+
*/
|
|
275
|
+
addDataset(dataset) {
|
|
276
|
+
this.datasets.push({ ...dataset, addedAt: new Date().toISOString() });
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Adds an external service.
|
|
281
|
+
* @param {object} service - { name, endpoint, provider, version, sla }
|
|
282
|
+
*/
|
|
283
|
+
addService(service) {
|
|
284
|
+
this.services.push({ ...service, addedAt: new Date().toISOString() });
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Generates the AI-BOM.
|
|
289
|
+
* @returns {object}
|
|
290
|
+
*/
|
|
291
|
+
generate() {
|
|
292
|
+
if (this.format === 'spdx') return this.toSPDX();
|
|
293
|
+
if (this.format === 'cyclonedx') return this.toCycloneDX();
|
|
294
|
+
return this.toJSON();
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Validates completeness of the BOM.
|
|
299
|
+
* @returns {{ valid: boolean, warnings: Array }}
|
|
300
|
+
*/
|
|
301
|
+
validate() {
|
|
302
|
+
const warnings = [];
|
|
303
|
+
if (this.models.length === 0) warnings.push('No AI models documented');
|
|
304
|
+
if (this.components.length === 0 && this.services.length === 0) warnings.push('No components or services documented');
|
|
305
|
+
for (const m of this.models) {
|
|
306
|
+
if (!m.version) warnings.push(`Model "${m.name}" missing version`);
|
|
307
|
+
if (!m.license) warnings.push(`Model "${m.name}" missing license`);
|
|
308
|
+
}
|
|
309
|
+
for (const d of this.datasets) {
|
|
310
|
+
if (!d.privacyLevel) warnings.push(`Dataset "${d.name}" missing privacy level`);
|
|
311
|
+
}
|
|
312
|
+
return { valid: warnings.length === 0, warnings };
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Custom JSON format.
|
|
317
|
+
* @returns {object}
|
|
318
|
+
*/
|
|
319
|
+
toJSON() {
|
|
320
|
+
return {
|
|
321
|
+
bomFormat: 'AgentShield-AI-BOM',
|
|
322
|
+
specVersion: '1.0',
|
|
323
|
+
generatedAt: new Date().toISOString(),
|
|
324
|
+
system: { name: this.systemName, organization: this.organizationName },
|
|
325
|
+
models: this.models,
|
|
326
|
+
datasets: this.datasets,
|
|
327
|
+
components: this.components,
|
|
328
|
+
services: this.services,
|
|
329
|
+
summary: { totalModels: this.models.length, totalDatasets: this.datasets.length, totalComponents: this.components.length, totalServices: this.services.length }
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* SPDX-compatible format.
|
|
335
|
+
* @returns {object}
|
|
336
|
+
*/
|
|
337
|
+
toSPDX() {
|
|
338
|
+
return {
|
|
339
|
+
spdxVersion: 'SPDX-2.3',
|
|
340
|
+
dataLicense: 'CC0-1.0',
|
|
341
|
+
SPDXID: 'SPDXRef-DOCUMENT',
|
|
342
|
+
name: `AI-BOM-${this.systemName}`,
|
|
343
|
+
documentNamespace: `https://spdx.org/spdxdocs/ai-bom-${Date.now()}`,
|
|
344
|
+
creationInfo: { created: new Date().toISOString(), creators: [`Organization: ${this.organizationName}`, 'Tool: AgentShield'] },
|
|
345
|
+
packages: [
|
|
346
|
+
...this.models.map((m, i) => ({
|
|
347
|
+
SPDXID: `SPDXRef-Model-${i}`,
|
|
348
|
+
name: m.name,
|
|
349
|
+
versionInfo: m.version || 'unknown',
|
|
350
|
+
supplier: m.provider || 'unknown',
|
|
351
|
+
downloadLocation: 'NOASSERTION',
|
|
352
|
+
licenseConcluded: m.license || 'NOASSERTION',
|
|
353
|
+
primaryPackagePurpose: 'AI_MODEL'
|
|
354
|
+
})),
|
|
355
|
+
...this.components.map((c, i) => ({
|
|
356
|
+
SPDXID: `SPDXRef-Component-${i}`,
|
|
357
|
+
name: c.name,
|
|
358
|
+
versionInfo: c.version || 'unknown',
|
|
359
|
+
supplier: c.supplier || 'unknown',
|
|
360
|
+
downloadLocation: 'NOASSERTION',
|
|
361
|
+
licenseConcluded: c.license || 'NOASSERTION',
|
|
362
|
+
primaryPackagePurpose: 'LIBRARY'
|
|
363
|
+
}))
|
|
364
|
+
]
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* CycloneDX-compatible format.
|
|
370
|
+
* @returns {object}
|
|
371
|
+
*/
|
|
372
|
+
toCycloneDX() {
|
|
373
|
+
return {
|
|
374
|
+
bomFormat: 'CycloneDX',
|
|
375
|
+
specVersion: '1.5',
|
|
376
|
+
version: 1,
|
|
377
|
+
metadata: {
|
|
378
|
+
timestamp: new Date().toISOString(),
|
|
379
|
+
tools: [{ vendor: 'AgentShield', name: 'AI-BOM Generator', version: '1.0' }],
|
|
380
|
+
component: { type: 'application', name: this.systemName, version: '1.0' }
|
|
381
|
+
},
|
|
382
|
+
components: [
|
|
383
|
+
...this.models.map(m => ({
|
|
384
|
+
type: 'machine-learning-model',
|
|
385
|
+
name: m.name,
|
|
386
|
+
version: m.version || 'unknown',
|
|
387
|
+
supplier: { name: m.provider || 'unknown' },
|
|
388
|
+
licenses: m.license ? [{ license: { id: m.license } }] : [],
|
|
389
|
+
properties: [
|
|
390
|
+
{ name: 'ai:type', value: m.type || 'unknown' },
|
|
391
|
+
{ name: 'ai:parameters', value: String(m.parameters || 'unknown') }
|
|
392
|
+
]
|
|
393
|
+
})),
|
|
394
|
+
...this.components.map(c => ({
|
|
395
|
+
type: 'library',
|
|
396
|
+
name: c.name,
|
|
397
|
+
version: c.version || 'unknown',
|
|
398
|
+
supplier: { name: c.supplier || 'unknown' },
|
|
399
|
+
hashes: c.hash ? [{ alg: 'SHA-256', content: c.hash }] : []
|
|
400
|
+
}))
|
|
401
|
+
]
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// =========================================================================
|
|
407
|
+
// ComplianceChecker
|
|
408
|
+
// =========================================================================
|
|
409
|
+
|
|
410
|
+
class ComplianceChecker {
|
|
411
|
+
/**
|
|
412
|
+
* @param {NISTMapper} nistMapper
|
|
413
|
+
*/
|
|
414
|
+
constructor(nistMapper) {
|
|
415
|
+
this.mapper = nistMapper;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Checks current state against a NIST profile.
|
|
420
|
+
* @param {object} profile - Generated profile
|
|
421
|
+
* @param {object} currentState - Current system state
|
|
422
|
+
* @returns {{ compliant: boolean, gaps: Array, score: number }}
|
|
423
|
+
*/
|
|
424
|
+
checkAgainstProfile(profile, currentState = {}) {
|
|
425
|
+
const gaps = [];
|
|
426
|
+
const activeModules = currentState.activeModules || [];
|
|
427
|
+
|
|
428
|
+
for (const [funcName, categories] of Object.entries(profile.coverageMap)) {
|
|
429
|
+
for (const cat of categories) {
|
|
430
|
+
if (cat.covered && cat.modules.length > 0) {
|
|
431
|
+
const moduleName = cat.modules[0].split(':')[0].replace('.js', '');
|
|
432
|
+
if (!activeModules.includes(moduleName)) {
|
|
433
|
+
gaps.push({ function: funcName, category: cat.id, name: cat.name, reason: 'Module available but not active' });
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
const score = profile.coverage.percentage;
|
|
440
|
+
return { compliant: gaps.length === 0 && score >= 80, gaps, score };
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Generates a prioritized action plan.
|
|
445
|
+
* @returns {Array<object>}
|
|
446
|
+
*/
|
|
447
|
+
generateActionPlan() {
|
|
448
|
+
const gaps = this.mapper.getGaps();
|
|
449
|
+
return gaps.map((gap, i) => ({
|
|
450
|
+
priority: i + 1,
|
|
451
|
+
action: `Address ${gap.id} — ${gap.name}`,
|
|
452
|
+
description: gap.description,
|
|
453
|
+
automatable: gap.automatable,
|
|
454
|
+
effort: gap.automatable ? 'low' : 'high'
|
|
455
|
+
}));
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* Generates an audit artifact.
|
|
460
|
+
* @param {'text'|'json'|'markdown'} [format='json']
|
|
461
|
+
* @returns {string}
|
|
462
|
+
*/
|
|
463
|
+
generateAuditArtifact(format = 'json') {
|
|
464
|
+
const profile = this.mapper.generateProfile();
|
|
465
|
+
const actionPlan = this.generateActionPlan();
|
|
466
|
+
|
|
467
|
+
const artifact = {
|
|
468
|
+
type: 'NIST AI RMF Audit Artifact',
|
|
469
|
+
generatedAt: new Date().toISOString(),
|
|
470
|
+
organization: this.mapper.organizationName,
|
|
471
|
+
system: this.mapper.systemName,
|
|
472
|
+
framework: 'NIST AI RMF 1.0 (2025)',
|
|
473
|
+
riskLevel: this.mapper.riskLevel,
|
|
474
|
+
coverageScore: profile.coverage,
|
|
475
|
+
gaps: profile.gaps,
|
|
476
|
+
actionPlan,
|
|
477
|
+
sp800_53: profile.sp800_53_mapping
|
|
478
|
+
};
|
|
479
|
+
|
|
480
|
+
if (format === 'json') return JSON.stringify(artifact, null, 2);
|
|
481
|
+
if (format === 'markdown') {
|
|
482
|
+
return [
|
|
483
|
+
'# NIST AI RMF Audit Artifact',
|
|
484
|
+
`**Date:** ${artifact.generatedAt}`,
|
|
485
|
+
`**Coverage:** ${artifact.coverageScore.percentage}%`,
|
|
486
|
+
'',
|
|
487
|
+
'## Action Plan',
|
|
488
|
+
...actionPlan.map(a => `${a.priority}. **${a.action}** — ${a.description} (effort: ${a.effort})`)
|
|
489
|
+
].join('\n');
|
|
490
|
+
}
|
|
491
|
+
return JSON.stringify(artifact, null, 2);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// =========================================================================
|
|
496
|
+
// Exports
|
|
497
|
+
// =========================================================================
|
|
498
|
+
|
|
499
|
+
module.exports = {
|
|
500
|
+
NIST_AI_RMF_2025,
|
|
501
|
+
SP800_53_AI_CONTROLS,
|
|
502
|
+
NISTMapper,
|
|
503
|
+
AIBOMGenerator,
|
|
504
|
+
ComplianceChecker
|
|
505
|
+
};
|