agent-security-scanner-mcp 3.19.0 → 3.20.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/compliance/aiuc-1-controls.json +330 -0
- package/index.js +21 -1
- package/package.json +4 -2
- package/src/cli/report.js +71 -0
- package/src/lib/aivss.js +284 -0
- package/src/lib/compliance-controls.js +164 -0
- package/src/lib/compliance-evaluator.js +149 -0
- package/src/lib/normalize-finding.js +146 -0
- package/src/tools/compliance-controls.js +67 -0
- package/src/tools/score-aivss.js +98 -0
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": "1.0",
|
|
3
|
+
"framework": "AIUC-1",
|
|
4
|
+
"source": "https://www.aiuc-1.com/crosswalks",
|
|
5
|
+
"source_snapshot": "2026-03-14",
|
|
6
|
+
"source_note": "Controls extracted from AIUC-1 crosswalks page, pinned to this date. Update source_snapshot if re-extracted.",
|
|
7
|
+
"domains": ["security", "safety"],
|
|
8
|
+
"controls": [
|
|
9
|
+
{
|
|
10
|
+
"id": "B001",
|
|
11
|
+
"title": "Third-party testing of adversarial robustness",
|
|
12
|
+
"domain": "security",
|
|
13
|
+
"aivss_threats": ["Agent Cascading Failures", "Agent Goal Manipulation"],
|
|
14
|
+
"owasp_llm": ["LLM01", "LLM04", "LLM08"],
|
|
15
|
+
"scanner_tools": ["scan_agent_prompt", "scan_security", "scan_skill"],
|
|
16
|
+
"evidence_requirements": [
|
|
17
|
+
"Scan results showing prompt injection detection coverage",
|
|
18
|
+
"AIVSS scores for adversarial robustness findings"
|
|
19
|
+
],
|
|
20
|
+
"evaluation": {
|
|
21
|
+
"max_aivss_posture": 7.0,
|
|
22
|
+
"fail_on_actions": ["BLOCK"],
|
|
23
|
+
"fail_on_severities": ["CRITICAL"],
|
|
24
|
+
"required_tools": ["scan_agent_prompt"],
|
|
25
|
+
"min_grade": "D",
|
|
26
|
+
"max_critical_findings": 0
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"id": "B002",
|
|
31
|
+
"title": "Detection of adversarial inputs",
|
|
32
|
+
"domain": "security",
|
|
33
|
+
"aivss_threats": ["Prompt Injection", "Evasion Attacks"],
|
|
34
|
+
"owasp_llm": ["LLM01"],
|
|
35
|
+
"scanner_tools": ["scan_agent_prompt"],
|
|
36
|
+
"evidence_requirements": [
|
|
37
|
+
"Prompt injection detection results",
|
|
38
|
+
"Coverage of OWASP prompt injection categories"
|
|
39
|
+
],
|
|
40
|
+
"evaluation": {
|
|
41
|
+
"max_aivss_posture": 7.0,
|
|
42
|
+
"fail_on_actions": ["BLOCK"],
|
|
43
|
+
"fail_on_severities": ["CRITICAL"],
|
|
44
|
+
"required_tools": ["scan_agent_prompt"],
|
|
45
|
+
"min_grade": "D",
|
|
46
|
+
"max_critical_findings": 0
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"id": "B003",
|
|
51
|
+
"title": "Protection of technical details from unauthorized access",
|
|
52
|
+
"domain": "security",
|
|
53
|
+
"aivss_threats": ["Model Theft", "Information Disclosure"],
|
|
54
|
+
"owasp_llm": ["LLM06", "LLM10"],
|
|
55
|
+
"scanner_tools": ["scan_security", "scan_project"],
|
|
56
|
+
"evidence_requirements": [
|
|
57
|
+
"Code scan results showing no information disclosure vulnerabilities",
|
|
58
|
+
"No hardcoded credentials or API keys"
|
|
59
|
+
],
|
|
60
|
+
"evaluation": {
|
|
61
|
+
"max_aivss_posture": 6.0,
|
|
62
|
+
"fail_on_actions": [],
|
|
63
|
+
"fail_on_severities": ["CRITICAL"],
|
|
64
|
+
"required_tools": ["scan_security"],
|
|
65
|
+
"min_grade": "C",
|
|
66
|
+
"max_critical_findings": 0
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"id": "B004",
|
|
71
|
+
"title": "Prevention of endpoint scraping and data extraction",
|
|
72
|
+
"domain": "security",
|
|
73
|
+
"aivss_threats": ["Data Exfiltration", "API Abuse"],
|
|
74
|
+
"owasp_llm": ["LLM02", "LLM06"],
|
|
75
|
+
"scanner_tools": ["scan_security", "scan_agent_action"],
|
|
76
|
+
"evidence_requirements": [
|
|
77
|
+
"Scan results for data exfiltration patterns",
|
|
78
|
+
"Action monitoring for unauthorized HTTP requests"
|
|
79
|
+
],
|
|
80
|
+
"evaluation": {
|
|
81
|
+
"max_aivss_posture": 7.0,
|
|
82
|
+
"fail_on_actions": ["BLOCK"],
|
|
83
|
+
"fail_on_severities": ["CRITICAL"],
|
|
84
|
+
"required_tools": ["scan_security"],
|
|
85
|
+
"min_grade": "C",
|
|
86
|
+
"max_critical_findings": 0
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"id": "B005",
|
|
91
|
+
"title": "Filtering and validation of AI system inputs",
|
|
92
|
+
"domain": "security",
|
|
93
|
+
"aivss_threats": ["Prompt Injection", "Input Manipulation"],
|
|
94
|
+
"owasp_llm": ["LLM01", "LLM03"],
|
|
95
|
+
"scanner_tools": ["scan_agent_prompt", "scan_security"],
|
|
96
|
+
"evidence_requirements": [
|
|
97
|
+
"Input validation scan results",
|
|
98
|
+
"Prompt injection detection coverage"
|
|
99
|
+
],
|
|
100
|
+
"evaluation": {
|
|
101
|
+
"max_aivss_posture": 7.0,
|
|
102
|
+
"fail_on_actions": ["BLOCK"],
|
|
103
|
+
"fail_on_severities": ["CRITICAL"],
|
|
104
|
+
"required_tools": ["scan_agent_prompt"],
|
|
105
|
+
"min_grade": "D",
|
|
106
|
+
"max_critical_findings": 0
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"id": "B006",
|
|
111
|
+
"title": "Prevention of unauthorized actions by AI system",
|
|
112
|
+
"domain": "security",
|
|
113
|
+
"aivss_threats": ["Agent Goal Manipulation", "Unauthorized Actions"],
|
|
114
|
+
"owasp_llm": ["LLM01", "LLM08"],
|
|
115
|
+
"scanner_tools": ["scan_agent_action", "scan_security"],
|
|
116
|
+
"evidence_requirements": [
|
|
117
|
+
"Action monitoring results",
|
|
118
|
+
"Security scan for privilege escalation"
|
|
119
|
+
],
|
|
120
|
+
"evaluation": {
|
|
121
|
+
"max_aivss_posture": 7.0,
|
|
122
|
+
"fail_on_actions": ["BLOCK"],
|
|
123
|
+
"fail_on_severities": ["CRITICAL"],
|
|
124
|
+
"required_tools": ["scan_agent_action"],
|
|
125
|
+
"min_grade": "C",
|
|
126
|
+
"max_critical_findings": 0
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
"id": "B007",
|
|
131
|
+
"title": "Restriction of access privileges for AI components",
|
|
132
|
+
"domain": "security",
|
|
133
|
+
"aivss_threats": ["Privilege Escalation", "Lateral Movement"],
|
|
134
|
+
"owasp_llm": ["LLM06", "LLM08"],
|
|
135
|
+
"scanner_tools": ["scan_security", "scan_mcp_server"],
|
|
136
|
+
"evidence_requirements": [
|
|
137
|
+
"MCP server permission audit results",
|
|
138
|
+
"Least-privilege analysis"
|
|
139
|
+
],
|
|
140
|
+
"evaluation": {
|
|
141
|
+
"max_aivss_posture": 6.0,
|
|
142
|
+
"fail_on_actions": [],
|
|
143
|
+
"fail_on_severities": ["CRITICAL"],
|
|
144
|
+
"required_tools": ["scan_security"],
|
|
145
|
+
"min_grade": "C",
|
|
146
|
+
"max_critical_findings": 0
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
"id": "B008",
|
|
151
|
+
"title": "Protection of deployment infrastructure",
|
|
152
|
+
"domain": "security",
|
|
153
|
+
"aivss_threats": ["Supply Chain Compromise", "Infrastructure Attacks"],
|
|
154
|
+
"owasp_llm": ["LLM05", "LLM09"],
|
|
155
|
+
"scanner_tools": ["scan_security", "scan_project"],
|
|
156
|
+
"evidence_requirements": [
|
|
157
|
+
"Project-level security scan results",
|
|
158
|
+
"Dependency and supply chain analysis"
|
|
159
|
+
],
|
|
160
|
+
"evaluation": {
|
|
161
|
+
"max_aivss_posture": 7.0,
|
|
162
|
+
"fail_on_actions": [],
|
|
163
|
+
"fail_on_severities": ["CRITICAL"],
|
|
164
|
+
"required_tools": ["scan_project"],
|
|
165
|
+
"min_grade": "C",
|
|
166
|
+
"max_critical_findings": 0
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
"id": "B009",
|
|
171
|
+
"title": "Prevention of sensitive output exposure",
|
|
172
|
+
"domain": "security",
|
|
173
|
+
"aivss_threats": ["Data Leakage", "Output Manipulation"],
|
|
174
|
+
"owasp_llm": ["LLM02", "LLM06"],
|
|
175
|
+
"scanner_tools": ["scan_security", "scan_agent_prompt"],
|
|
176
|
+
"evidence_requirements": [
|
|
177
|
+
"Output exposure vulnerability scan results",
|
|
178
|
+
"Sensitive data handling analysis"
|
|
179
|
+
],
|
|
180
|
+
"evaluation": {
|
|
181
|
+
"max_aivss_posture": 6.0,
|
|
182
|
+
"fail_on_actions": [],
|
|
183
|
+
"fail_on_severities": ["CRITICAL"],
|
|
184
|
+
"required_tools": ["scan_security"],
|
|
185
|
+
"min_grade": "C",
|
|
186
|
+
"max_critical_findings": 0
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
"id": "C003",
|
|
191
|
+
"title": "Prevention of harmful AI outputs",
|
|
192
|
+
"domain": "safety",
|
|
193
|
+
"aivss_threats": ["Harmful Content Generation", "Agent Goal Manipulation"],
|
|
194
|
+
"owasp_llm": ["LLM02", "LLM07"],
|
|
195
|
+
"scanner_tools": ["scan_agent_prompt", "scan_skill"],
|
|
196
|
+
"evidence_requirements": [
|
|
197
|
+
"Prompt safety scan results",
|
|
198
|
+
"Skill content safety analysis"
|
|
199
|
+
],
|
|
200
|
+
"evaluation": {
|
|
201
|
+
"max_aivss_posture": 6.0,
|
|
202
|
+
"fail_on_actions": ["BLOCK"],
|
|
203
|
+
"fail_on_severities": ["CRITICAL"],
|
|
204
|
+
"required_tools": ["scan_agent_prompt"],
|
|
205
|
+
"min_grade": "D",
|
|
206
|
+
"max_critical_findings": 0
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
"id": "C004",
|
|
211
|
+
"title": "Prevention of out-of-scope AI outputs",
|
|
212
|
+
"domain": "safety",
|
|
213
|
+
"aivss_threats": ["Scope Creep", "Unauthorized Actions"],
|
|
214
|
+
"owasp_llm": ["LLM07", "LLM08"],
|
|
215
|
+
"scanner_tools": ["scan_agent_prompt", "scan_agent_action"],
|
|
216
|
+
"evidence_requirements": [
|
|
217
|
+
"Scope boundary enforcement results",
|
|
218
|
+
"Action monitoring for out-of-scope operations"
|
|
219
|
+
],
|
|
220
|
+
"evaluation": {
|
|
221
|
+
"max_aivss_posture": 6.0,
|
|
222
|
+
"fail_on_actions": ["BLOCK"],
|
|
223
|
+
"fail_on_severities": ["CRITICAL"],
|
|
224
|
+
"required_tools": ["scan_agent_prompt"],
|
|
225
|
+
"min_grade": "D",
|
|
226
|
+
"max_critical_findings": 0
|
|
227
|
+
}
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
"id": "C005",
|
|
231
|
+
"title": "Detection and mitigation of high-risk AI outputs",
|
|
232
|
+
"domain": "safety",
|
|
233
|
+
"aivss_threats": ["High-Risk Actions", "Safety Violations"],
|
|
234
|
+
"owasp_llm": ["LLM02", "LLM07"],
|
|
235
|
+
"scanner_tools": ["scan_agent_action", "scan_security"],
|
|
236
|
+
"evidence_requirements": [
|
|
237
|
+
"High-risk action detection results",
|
|
238
|
+
"Safety check coverage analysis"
|
|
239
|
+
],
|
|
240
|
+
"evaluation": {
|
|
241
|
+
"max_aivss_posture": 7.0,
|
|
242
|
+
"fail_on_actions": ["BLOCK"],
|
|
243
|
+
"fail_on_severities": ["CRITICAL"],
|
|
244
|
+
"required_tools": ["scan_agent_action"],
|
|
245
|
+
"min_grade": "D",
|
|
246
|
+
"max_critical_findings": 0
|
|
247
|
+
}
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
"id": "C006",
|
|
251
|
+
"title": "Detection and remediation of output vulnerabilities",
|
|
252
|
+
"domain": "safety",
|
|
253
|
+
"aivss_threats": ["Output Injection", "Cross-Site Scripting"],
|
|
254
|
+
"owasp_llm": ["LLM02"],
|
|
255
|
+
"scanner_tools": ["scan_security", "scan_project"],
|
|
256
|
+
"evidence_requirements": [
|
|
257
|
+
"Output vulnerability scan results",
|
|
258
|
+
"XSS and injection detection coverage"
|
|
259
|
+
],
|
|
260
|
+
"evaluation": {
|
|
261
|
+
"max_aivss_posture": 7.0,
|
|
262
|
+
"fail_on_actions": [],
|
|
263
|
+
"fail_on_severities": ["CRITICAL"],
|
|
264
|
+
"required_tools": ["scan_security"],
|
|
265
|
+
"min_grade": "C",
|
|
266
|
+
"max_critical_findings": 0
|
|
267
|
+
}
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
"id": "C007",
|
|
271
|
+
"title": "Flagging of potentially unsafe AI-generated content",
|
|
272
|
+
"domain": "safety",
|
|
273
|
+
"aivss_threats": ["Unsafe Content", "Content Quality"],
|
|
274
|
+
"owasp_llm": ["LLM02", "LLM09"],
|
|
275
|
+
"scanner_tools": ["scan_agent_prompt", "scan_skill"],
|
|
276
|
+
"evidence_requirements": [
|
|
277
|
+
"Content safety scanning results",
|
|
278
|
+
"Unsafe content detection coverage"
|
|
279
|
+
],
|
|
280
|
+
"evaluation": {
|
|
281
|
+
"max_aivss_posture": 6.0,
|
|
282
|
+
"fail_on_actions": ["BLOCK"],
|
|
283
|
+
"fail_on_severities": ["CRITICAL"],
|
|
284
|
+
"required_tools": ["scan_agent_prompt"],
|
|
285
|
+
"min_grade": "D",
|
|
286
|
+
"max_critical_findings": 0
|
|
287
|
+
}
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
"id": "C008",
|
|
291
|
+
"title": "Continuous monitoring and logging of AI system behavior",
|
|
292
|
+
"domain": "safety",
|
|
293
|
+
"aivss_threats": ["Unmonitored Drift", "Behavioral Anomalies"],
|
|
294
|
+
"owasp_llm": ["LLM09", "LLM10"],
|
|
295
|
+
"scanner_tools": ["scan_project", "scan_security"],
|
|
296
|
+
"evidence_requirements": [
|
|
297
|
+
"Monitoring infrastructure scan results",
|
|
298
|
+
"Logging coverage analysis"
|
|
299
|
+
],
|
|
300
|
+
"evaluation": {
|
|
301
|
+
"max_aivss_posture": 6.0,
|
|
302
|
+
"fail_on_actions": [],
|
|
303
|
+
"fail_on_severities": ["CRITICAL"],
|
|
304
|
+
"required_tools": ["scan_project"],
|
|
305
|
+
"min_grade": "C",
|
|
306
|
+
"max_critical_findings": 0
|
|
307
|
+
}
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
"id": "C012",
|
|
311
|
+
"title": "Third-party safety testing of AI systems",
|
|
312
|
+
"domain": "safety",
|
|
313
|
+
"aivss_threats": ["Untested Scenarios", "Safety Gaps"],
|
|
314
|
+
"owasp_llm": ["LLM01", "LLM07"],
|
|
315
|
+
"scanner_tools": ["scan_skill", "scan_agent_prompt", "scan_security"],
|
|
316
|
+
"evidence_requirements": [
|
|
317
|
+
"Third-party scan results (skill, prompt, security)",
|
|
318
|
+
"AIVSS posture scores across all domains"
|
|
319
|
+
],
|
|
320
|
+
"evaluation": {
|
|
321
|
+
"max_aivss_posture": 7.0,
|
|
322
|
+
"fail_on_actions": ["BLOCK"],
|
|
323
|
+
"fail_on_severities": ["CRITICAL"],
|
|
324
|
+
"required_tools": ["scan_skill"],
|
|
325
|
+
"min_grade": "D",
|
|
326
|
+
"max_critical_findings": 0
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
]
|
|
330
|
+
}
|
package/index.js
CHANGED
|
@@ -26,6 +26,8 @@ import { runDoctor } from './src/cli/doctor.js';
|
|
|
26
26
|
import { runDemo } from './src/cli/demo.js';
|
|
27
27
|
import { runInitHooks } from './src/cli/init-hooks.js';
|
|
28
28
|
import { runReport } from './src/cli/report.js';
|
|
29
|
+
import { scoreAivssSchema, scoreAivssTool } from './src/tools/score-aivss.js';
|
|
30
|
+
import { complianceControlsSchema, getComplianceControls } from './src/tools/compliance-controls.js';
|
|
29
31
|
|
|
30
32
|
// Handle both ESM and CJS bundling (Smithery bundles to CJS)
|
|
31
33
|
let __dirname;
|
|
@@ -232,6 +234,24 @@ server.tool(
|
|
|
232
234
|
_healthHandler
|
|
233
235
|
);
|
|
234
236
|
|
|
237
|
+
// ===========================================
|
|
238
|
+
// AIVSS SCORING + COMPLIANCE
|
|
239
|
+
// ===========================================
|
|
240
|
+
|
|
241
|
+
server.tool(
|
|
242
|
+
"score_aivss",
|
|
243
|
+
"Score findings using OWASP AIVSS v2. Accepts any scanner output or raw findings JSON. Returns per-finding AIVSS scores (0-10) and aggregate posture. Use verbosity='minimal' for posture only, 'compact' (default) for scores, 'full' for all metrics.",
|
|
244
|
+
scoreAivssSchema,
|
|
245
|
+
scoreAivssTool
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
server.tool(
|
|
249
|
+
"get_compliance_controls",
|
|
250
|
+
"Look up AIUC-1 compliance controls with evaluation criteria. Filter by domain (security/safety), control IDs, or OWASP LLM tags. Returns structured evaluation rules for pass/partial/fail assessment.",
|
|
251
|
+
complianceControlsSchema,
|
|
252
|
+
getComplianceControls
|
|
253
|
+
);
|
|
254
|
+
|
|
235
255
|
// ===========================================
|
|
236
256
|
// CLI COMMANDS - Extracted to src/cli/
|
|
237
257
|
// ===========================================
|
|
@@ -515,7 +535,7 @@ const cliArgs = process.argv.slice(2);
|
|
|
515
535
|
console.log(' init-hooks Install Claude Code hooks for auto-scanning');
|
|
516
536
|
console.log(' doctor [--fix] Check environment & client configs');
|
|
517
537
|
console.log(' demo [--lang js] Generate vulnerable file + scan it');
|
|
518
|
-
console.log(' report <dir> Generate HTML security report with history');
|
|
538
|
+
console.log(' report <dir> Generate HTML security report with history [--threat-model]');
|
|
519
539
|
console.log(' benchmark [flags] Run accuracy benchmarks\n');
|
|
520
540
|
console.log(' CLI Tools (for scripts & OpenClaw):');
|
|
521
541
|
console.log(' scan-prompt <text> Scan prompt for injection attacks');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-security-scanner-mcp",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.20.0",
|
|
4
4
|
"mcpName": "io.github.sinewaveai/agent-security-scanner-mcp",
|
|
5
5
|
"description": "Security scanner MCP server for AI coding agents. Prompt injection firewall, package hallucination detection (4.3M+ packages), 1000+ vulnerability rules with AST & taint analysis, auto-fix. For Claude Code, Cursor, Windsurf, Cline, OpenClaw.",
|
|
6
6
|
"main": "index.js",
|
|
@@ -110,7 +110,9 @@
|
|
|
110
110
|
"scripts/postinstall.js",
|
|
111
111
|
"cross_file_analyzer.py",
|
|
112
112
|
"daemon.py",
|
|
113
|
-
"python_taint_fallback.py"
|
|
113
|
+
"python_taint_fallback.py",
|
|
114
|
+
"src/lib/*.js",
|
|
115
|
+
"compliance/**"
|
|
114
116
|
],
|
|
115
117
|
"devDependencies": {
|
|
116
118
|
"all-the-package-names": "^2.0.2349",
|
package/src/cli/report.js
CHANGED
|
@@ -4,6 +4,10 @@ import { existsSync, writeFileSync, mkdirSync } from 'fs';
|
|
|
4
4
|
import { resolve, join } from 'path';
|
|
5
5
|
import { scanProject } from '../tools/scan-project.js';
|
|
6
6
|
import { saveResult, loadHistory, getTrends, diffResults } from '../history.js';
|
|
7
|
+
import { normalizeFindings } from '../lib/normalize-finding.js';
|
|
8
|
+
import { scoreBatch } from '../lib/aivss.js';
|
|
9
|
+
import { loadControls } from '../lib/compliance-controls.js';
|
|
10
|
+
import { evaluateAll } from '../lib/compliance-evaluator.js';
|
|
7
11
|
|
|
8
12
|
// Grade color mapping
|
|
9
13
|
const GRADE_COLORS = {
|
|
@@ -359,6 +363,62 @@ function generateHtml(scanResult, history, diff) {
|
|
|
359
363
|
</html>`;
|
|
360
364
|
}
|
|
361
365
|
|
|
366
|
+
/**
|
|
367
|
+
* Build the threat_model section from scan results.
|
|
368
|
+
* Exported for testing.
|
|
369
|
+
*/
|
|
370
|
+
export function buildThreatModel(scanResult) {
|
|
371
|
+
// scan_project wraps scan_security — tag findings as scan_security so
|
|
372
|
+
// controls scoped to either tool can see them. Duplicate each finding
|
|
373
|
+
// under both source_tools for correct evaluator scoping.
|
|
374
|
+
const base = normalizeFindings(scanResult.issues || [], 'scan_security');
|
|
375
|
+
const duped = base.map(f => ({ ...f, source_tool: 'scan_project' }));
|
|
376
|
+
const normalized = [...base, ...duped];
|
|
377
|
+
const aivssResult = scoreBatch(base); // score deduplicated set
|
|
378
|
+
|
|
379
|
+
const grade = scanResult.grade || null;
|
|
380
|
+
const controls = loadControls().controls;
|
|
381
|
+
const evidence = {
|
|
382
|
+
aivssPosture: aivssResult.posture,
|
|
383
|
+
findings: normalized,
|
|
384
|
+
grades: { scan_project: grade, scan_security: grade, project: grade },
|
|
385
|
+
toolsRun: ['scan_project', 'scan_security'],
|
|
386
|
+
};
|
|
387
|
+
const complianceResult = evaluateAll(controls, evidence);
|
|
388
|
+
|
|
389
|
+
return {
|
|
390
|
+
aivss: {
|
|
391
|
+
model: aivssResult.posture.model,
|
|
392
|
+
posture: {
|
|
393
|
+
max_score: aivssResult.posture.max_score,
|
|
394
|
+
p95_score: aivssResult.posture.p95_score,
|
|
395
|
+
mean_score: aivssResult.posture.mean_score,
|
|
396
|
+
posture_score: aivssResult.posture.posture_score,
|
|
397
|
+
posture_rating: aivssResult.posture.posture_rating,
|
|
398
|
+
score_distribution: aivssResult.posture.score_distribution,
|
|
399
|
+
},
|
|
400
|
+
findings: aivssResult.findings.map(f => ({
|
|
401
|
+
rule_id: f.rule_id,
|
|
402
|
+
aivss_score: f.aivss_score,
|
|
403
|
+
rating: f.rating,
|
|
404
|
+
vector_string: f.vector_string,
|
|
405
|
+
metrics: f.metrics,
|
|
406
|
+
})),
|
|
407
|
+
},
|
|
408
|
+
compliance: {
|
|
409
|
+
framework: 'AIUC-1',
|
|
410
|
+
controls_evaluated: complianceResult.controls_evaluated,
|
|
411
|
+
summary: {
|
|
412
|
+
pass: complianceResult.pass,
|
|
413
|
+
partial: complianceResult.partial,
|
|
414
|
+
fail: complianceResult.fail,
|
|
415
|
+
not_evaluated: complianceResult.not_evaluated,
|
|
416
|
+
},
|
|
417
|
+
results: complianceResult.results,
|
|
418
|
+
},
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
|
|
362
422
|
/**
|
|
363
423
|
* Run the report CLI command.
|
|
364
424
|
*
|
|
@@ -378,6 +438,7 @@ export async function runReport(args) {
|
|
|
378
438
|
}
|
|
379
439
|
|
|
380
440
|
const jsonOutput = args.includes('--json');
|
|
441
|
+
const threatModel = args.includes('--threat-model');
|
|
381
442
|
const daysIdx = args.indexOf('--days');
|
|
382
443
|
const days = daysIdx !== -1 && args[daysIdx + 1] ? parseInt(args[daysIdx + 1], 10) : 90;
|
|
383
444
|
|
|
@@ -390,6 +451,11 @@ export async function runReport(args) {
|
|
|
390
451
|
});
|
|
391
452
|
const scanResult = JSON.parse(result.content[0].text);
|
|
392
453
|
|
|
454
|
+
// Attach threat model before saving to history so future trends include AIVSS posture
|
|
455
|
+
if (threatModel) {
|
|
456
|
+
scanResult.threat_model = buildThreatModel(scanResult);
|
|
457
|
+
}
|
|
458
|
+
|
|
393
459
|
// Save result to history
|
|
394
460
|
const savedPath = saveResult(dirPath, scanResult);
|
|
395
461
|
console.log(` Results saved to ${savedPath}`);
|
|
@@ -413,10 +479,15 @@ export async function runReport(args) {
|
|
|
413
479
|
diff,
|
|
414
480
|
generated_at: new Date().toISOString(),
|
|
415
481
|
};
|
|
482
|
+
|
|
416
483
|
console.log(JSON.stringify(jsonReport, null, 2));
|
|
417
484
|
return;
|
|
418
485
|
}
|
|
419
486
|
|
|
487
|
+
if (threatModel) {
|
|
488
|
+
console.log(' Note: --threat-model currently only produces output with --json. HTML rendering is planned.');
|
|
489
|
+
}
|
|
490
|
+
|
|
420
491
|
// Generate HTML report
|
|
421
492
|
const html = generateHtml(scanResult, trends, diff);
|
|
422
493
|
const scannerDir = join(dirPath, '.scanner');
|