coverme-security-scanner 3.6.0 → 3.7.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/bin/merge-reports.js +231 -0
- package/commands/coverme.md +76 -203
- package/package.json +2 -1
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Merge multiple partial security reports into a single comprehensive report
|
|
5
|
+
* Usage: coverme-merge .coverme/partial-*.json -o scan.json
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { readFileSync, writeFileSync, readdirSync } from 'fs';
|
|
9
|
+
import { join, dirname } from 'path';
|
|
10
|
+
|
|
11
|
+
function mergeReports(inputDir, outputFile) {
|
|
12
|
+
const files = readdirSync(inputDir).filter(f => f.startsWith('partial-') && f.endsWith('.json'));
|
|
13
|
+
|
|
14
|
+
if (files.length === 0) {
|
|
15
|
+
console.error('No partial-*.json files found in', inputDir);
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
console.log(`Merging ${files.length} partial reports...`);
|
|
20
|
+
|
|
21
|
+
// Initialize merged report
|
|
22
|
+
const merged = {
|
|
23
|
+
project: '',
|
|
24
|
+
date: new Date().toISOString().split('T')[0],
|
|
25
|
+
branch: '',
|
|
26
|
+
scope: '',
|
|
27
|
+
methodology: '7 parallel security agents with attack chain analysis',
|
|
28
|
+
summary: { critical: 0, high: 0, medium: 0, low: 0, total: 0 },
|
|
29
|
+
overallRiskLevel: 'low',
|
|
30
|
+
executiveSummary: '',
|
|
31
|
+
topPriorities: [],
|
|
32
|
+
attackChains: [],
|
|
33
|
+
riskMatrix: [],
|
|
34
|
+
architecture: { overview: '', components: [], trustBoundaries: [] },
|
|
35
|
+
network: { diagram: '', ports: [], externalDeps: [] },
|
|
36
|
+
findings: [],
|
|
37
|
+
threatModel: [],
|
|
38
|
+
positiveObservations: [],
|
|
39
|
+
complianceMapping: [],
|
|
40
|
+
remediation: { p0: [], p1: [], p2: [], p3: [] },
|
|
41
|
+
qualityReview: { deadCode: [], dryViolations: [], deprecated: [] },
|
|
42
|
+
resolvedIssues: [],
|
|
43
|
+
privacyAnalysis: []
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// Process each partial file
|
|
47
|
+
for (const file of files) {
|
|
48
|
+
const filePath = join(inputDir, file);
|
|
49
|
+
console.log(` Processing: ${file}`);
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
const partial = JSON.parse(readFileSync(filePath, 'utf-8'));
|
|
53
|
+
|
|
54
|
+
// Merge simple fields (take first non-empty value)
|
|
55
|
+
if (partial.project && !merged.project) merged.project = partial.project;
|
|
56
|
+
if (partial.date) merged.date = partial.date;
|
|
57
|
+
if (partial.branch && !merged.branch) merged.branch = partial.branch;
|
|
58
|
+
if (partial.scope && !merged.scope) merged.scope = partial.scope;
|
|
59
|
+
if (partial.executiveSummary && !merged.executiveSummary) {
|
|
60
|
+
merged.executiveSummary = partial.executiveSummary;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Merge arrays (deduplicate by id where applicable)
|
|
64
|
+
if (partial.findings) {
|
|
65
|
+
for (const f of partial.findings) {
|
|
66
|
+
if (!merged.findings.find(x => x.id === f.id)) {
|
|
67
|
+
merged.findings.push(f);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (partial.attackChains) {
|
|
73
|
+
for (const ac of partial.attackChains) {
|
|
74
|
+
if (!merged.attackChains.find(x => x.id === ac.id)) {
|
|
75
|
+
merged.attackChains.push(ac);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (partial.topPriorities) {
|
|
81
|
+
merged.topPriorities.push(...partial.topPriorities);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (partial.riskMatrix) {
|
|
85
|
+
for (const rm of partial.riskMatrix) {
|
|
86
|
+
if (!merged.riskMatrix.find(x => x.category === rm.category)) {
|
|
87
|
+
merged.riskMatrix.push(rm);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (partial.architecture) {
|
|
93
|
+
if (partial.architecture.overview && !merged.architecture.overview) {
|
|
94
|
+
merged.architecture.overview = partial.architecture.overview;
|
|
95
|
+
}
|
|
96
|
+
if (partial.architecture.components) {
|
|
97
|
+
merged.architecture.components.push(...partial.architecture.components);
|
|
98
|
+
}
|
|
99
|
+
if (partial.architecture.trustBoundaries) {
|
|
100
|
+
merged.architecture.trustBoundaries.push(...partial.architecture.trustBoundaries);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (partial.network) {
|
|
105
|
+
if (partial.network.diagram && !merged.network.diagram) {
|
|
106
|
+
merged.network.diagram = partial.network.diagram;
|
|
107
|
+
}
|
|
108
|
+
if (partial.network.ports) {
|
|
109
|
+
for (const p of partial.network.ports) {
|
|
110
|
+
if (!merged.network.ports.find(x => x.port === p.port)) {
|
|
111
|
+
merged.network.ports.push(p);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (partial.network.externalDeps) {
|
|
116
|
+
merged.network.externalDeps.push(...partial.network.externalDeps);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (partial.threatModel) {
|
|
121
|
+
for (const tm of partial.threatModel) {
|
|
122
|
+
if (!merged.threatModel.find(x => x.id === tm.id)) {
|
|
123
|
+
merged.threatModel.push(tm);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (partial.positiveObservations) {
|
|
129
|
+
merged.positiveObservations.push(...partial.positiveObservations);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (partial.complianceMapping) {
|
|
133
|
+
for (const cm of partial.complianceMapping) {
|
|
134
|
+
const existing = merged.complianceMapping.find(x => x.framework === cm.framework);
|
|
135
|
+
if (existing) {
|
|
136
|
+
existing.controls.push(...cm.controls);
|
|
137
|
+
} else {
|
|
138
|
+
merged.complianceMapping.push(cm);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (partial.remediation) {
|
|
144
|
+
if (partial.remediation.p0) merged.remediation.p0.push(...partial.remediation.p0);
|
|
145
|
+
if (partial.remediation.p1) merged.remediation.p1.push(...partial.remediation.p1);
|
|
146
|
+
if (partial.remediation.p2) merged.remediation.p2.push(...partial.remediation.p2);
|
|
147
|
+
if (partial.remediation.p3) merged.remediation.p3.push(...partial.remediation.p3);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (partial.qualityReview) {
|
|
151
|
+
if (partial.qualityReview.deadCode) {
|
|
152
|
+
merged.qualityReview.deadCode.push(...partial.qualityReview.deadCode);
|
|
153
|
+
}
|
|
154
|
+
if (partial.qualityReview.dryViolations) {
|
|
155
|
+
merged.qualityReview.dryViolations.push(...partial.qualityReview.dryViolations);
|
|
156
|
+
}
|
|
157
|
+
if (partial.qualityReview.deprecated) {
|
|
158
|
+
merged.qualityReview.deprecated.push(...partial.qualityReview.deprecated);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (partial.resolvedIssues) {
|
|
163
|
+
merged.resolvedIssues.push(...partial.resolvedIssues);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (partial.privacyAnalysis) {
|
|
167
|
+
merged.privacyAnalysis.push(...partial.privacyAnalysis);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
} catch (e) {
|
|
171
|
+
console.error(` Error parsing ${file}:`, e.message);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Calculate summary counts
|
|
176
|
+
merged.summary.critical = merged.findings.filter(f => f.severity === 'critical').length;
|
|
177
|
+
merged.summary.high = merged.findings.filter(f => f.severity === 'high').length;
|
|
178
|
+
merged.summary.medium = merged.findings.filter(f => f.severity === 'medium').length;
|
|
179
|
+
merged.summary.low = merged.findings.filter(f => f.severity === 'low').length;
|
|
180
|
+
merged.summary.total = merged.findings.length;
|
|
181
|
+
|
|
182
|
+
// Determine overall risk level
|
|
183
|
+
if (merged.summary.critical > 0) {
|
|
184
|
+
merged.overallRiskLevel = 'critical';
|
|
185
|
+
} else if (merged.summary.high > 2) {
|
|
186
|
+
merged.overallRiskLevel = 'high';
|
|
187
|
+
} else if (merged.summary.high > 0 || merged.summary.medium > 3) {
|
|
188
|
+
merged.overallRiskLevel = 'medium';
|
|
189
|
+
} else {
|
|
190
|
+
merged.overallRiskLevel = 'low';
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Deduplicate top priorities (keep first 5)
|
|
194
|
+
const seenPriorities = new Set();
|
|
195
|
+
merged.topPriorities = merged.topPriorities.filter(p => {
|
|
196
|
+
if (seenPriorities.has(p.finding)) return false;
|
|
197
|
+
seenPriorities.add(p.finding);
|
|
198
|
+
return true;
|
|
199
|
+
}).slice(0, 5);
|
|
200
|
+
|
|
201
|
+
// Remove empty arrays
|
|
202
|
+
if (merged.qualityReview.deadCode.length === 0 &&
|
|
203
|
+
merged.qualityReview.dryViolations.length === 0 &&
|
|
204
|
+
merged.qualityReview.deprecated.length === 0) {
|
|
205
|
+
delete merged.qualityReview;
|
|
206
|
+
}
|
|
207
|
+
if (merged.resolvedIssues.length === 0) delete merged.resolvedIssues;
|
|
208
|
+
if (merged.privacyAnalysis.length === 0) delete merged.privacyAnalysis;
|
|
209
|
+
|
|
210
|
+
// Write merged report
|
|
211
|
+
writeFileSync(outputFile, JSON.stringify(merged, null, 2));
|
|
212
|
+
console.log(`\nMerged report written to: ${outputFile}`);
|
|
213
|
+
console.log(` Total findings: ${merged.summary.total}`);
|
|
214
|
+
console.log(` Critical: ${merged.summary.critical}, High: ${merged.summary.high}, Medium: ${merged.summary.medium}, Low: ${merged.summary.low}`);
|
|
215
|
+
console.log(` Attack chains: ${merged.attackChains.length}`);
|
|
216
|
+
console.log(` Overall risk: ${merged.overallRiskLevel.toUpperCase()}`);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// CLI
|
|
220
|
+
const args = process.argv.slice(2);
|
|
221
|
+
if (args.length < 1) {
|
|
222
|
+
console.log('Usage: coverme-merge <input-dir> [output-file]');
|
|
223
|
+
console.log(' input-dir: Directory containing partial-*.json files');
|
|
224
|
+
console.log(' output-file: Output file (default: scan.json)');
|
|
225
|
+
process.exit(1);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const inputDir = args[0];
|
|
229
|
+
const outputFile = args[1] || 'scan.json';
|
|
230
|
+
|
|
231
|
+
mergeReports(inputDir, outputFile);
|
package/commands/coverme.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Security Assessment Generator
|
|
1
|
+
# Security Assessment Generator v3
|
|
2
2
|
|
|
3
3
|
Run a comprehensive security assessment on this codebase and generate a professional PDF report with deep analysis.
|
|
4
4
|
|
|
@@ -14,25 +14,23 @@ Before starting the scan, create the output directory:
|
|
|
14
14
|
mkdir -p .coverme
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
This prevents errors when saving the scan results.
|
|
18
|
-
|
|
19
17
|
### Step 1: Launch Parallel Agents
|
|
20
18
|
|
|
21
|
-
Launch these 7 agents simultaneously using the Task tool:
|
|
19
|
+
Launch these 7 agents simultaneously using the Task tool. **IMPORTANT: Each agent must write its own partial JSON file immediately when done.**
|
|
22
20
|
|
|
23
21
|
1. **Executive Summary Agent** (subagent_type: Explore)
|
|
24
22
|
- Understand what the system does
|
|
25
23
|
- Identify the tech stack and architecture
|
|
26
24
|
- Map trust boundaries and critical assets
|
|
27
25
|
- Determine overall risk level
|
|
28
|
-
-
|
|
26
|
+
- **When done: Write findings to `.coverme/partial-01-executive.json`**
|
|
29
27
|
|
|
30
28
|
2. **Attack Surface Agent** (subagent_type: Explore)
|
|
31
29
|
- Map all entry points (APIs, webhooks, file uploads, CLI args)
|
|
32
30
|
- Identify unauthenticated endpoints
|
|
33
31
|
- Find admin/debug interfaces
|
|
34
|
-
- Check for exposed internal services
|
|
35
32
|
- Document external dependencies and their trust level
|
|
33
|
+
- **When done: Write findings to `.coverme/partial-02-attack-surface.json`**
|
|
36
34
|
|
|
37
35
|
3. **Vulnerability Hunter Agent** (subagent_type: Explore)
|
|
38
36
|
- OWASP Top 10 deep dive with CODE EVIDENCE
|
|
@@ -40,121 +38,37 @@ Launch these 7 agents simultaneously using the Task tool:
|
|
|
40
38
|
- Authentication/authorization bypass paths
|
|
41
39
|
- Injection vulnerabilities (SQL, command, XSS, SSTI)
|
|
42
40
|
- Secrets in code, hardcoded credentials (show exact lines)
|
|
43
|
-
-
|
|
44
|
-
- Rate limiting gaps, brute force opportunities
|
|
41
|
+
- **When done: Write findings to `.coverme/partial-03-vulnerabilities.json`**
|
|
45
42
|
|
|
46
43
|
4. **Attack Chain Analyst Agent** (subagent_type: Explore)
|
|
47
44
|
- Identify how vulnerabilities COMBINE for greater impact
|
|
48
45
|
- Map realistic attack scenarios (entry -> pivot -> objective)
|
|
49
46
|
- Calculate blast radius for each chain
|
|
50
|
-
-
|
|
51
|
-
- Prioritize chains by likelihood and impact
|
|
47
|
+
- **When done: Write findings to `.coverme/partial-04-attack-chains.json`**
|
|
52
48
|
|
|
53
49
|
5. **Business Logic Agent** (subagent_type: Explore)
|
|
54
50
|
- Race conditions in critical flows (payments, credits, locks)
|
|
55
51
|
- Workflow bypass opportunities (skip steps, replay)
|
|
56
52
|
- Credit/billing manipulation vectors
|
|
57
|
-
- Data validation gaps at business boundaries
|
|
58
|
-
- PII handling and data residency violations
|
|
59
53
|
- Privilege escalation paths
|
|
54
|
+
- **When done: Write findings to `.coverme/partial-05-business-logic.json`**
|
|
60
55
|
|
|
61
56
|
6. **Infrastructure Agent** (subagent_type: Explore)
|
|
62
57
|
- Docker/Kubernetes security (securityContext, network policies)
|
|
63
58
|
- CI/CD pipeline security gates (or lack thereof)
|
|
64
59
|
- Secrets management (env vars, mounted secrets, hardcoded)
|
|
65
|
-
- Cloud configuration (IAM, S3 buckets, security groups)
|
|
66
|
-
- Database security (encryption, access controls)
|
|
67
60
|
- Dependency vulnerabilities (npm audit, CVEs)
|
|
61
|
+
- **When done: Write findings to `.coverme/partial-06-infrastructure.json`**
|
|
68
62
|
|
|
69
63
|
7. **Compliance & Impact Agent** (subagent_type: Explore)
|
|
70
|
-
- Map findings to compliance frameworks (SOC2, PCI-DSS, GDPR
|
|
64
|
+
- Map findings to compliance frameworks (SOC2, PCI-DSS, GDPR)
|
|
71
65
|
- Calculate business impact for each critical finding
|
|
72
66
|
- Estimate financial exposure ranges
|
|
73
|
-
-
|
|
74
|
-
- Determine data breach notification requirements
|
|
75
|
-
|
|
76
|
-
### Step 2: Deep Dive on Findings
|
|
77
|
-
|
|
78
|
-
For EVERY critical and high finding, ensure you have:
|
|
79
|
-
|
|
80
|
-
1. **Code Evidence** - The EXACT vulnerable code snippet:
|
|
81
|
-
```
|
|
82
|
-
"codeEvidence": [{
|
|
83
|
-
"file": "src/auth/login.js",
|
|
84
|
-
"startLine": 45,
|
|
85
|
-
"endLine": 52,
|
|
86
|
-
"code": "const user = await db.query(`SELECT * FROM users WHERE id = ${req.params.id}`);",
|
|
87
|
-
"annotation": "User input directly interpolated into SQL query"
|
|
88
|
-
}]
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
2. **Exploitability Assessment**:
|
|
92
|
-
```
|
|
93
|
-
"exploitability": {
|
|
94
|
-
"skillLevel": "novice", // novice/intermediate/expert
|
|
95
|
-
"accessRequired": "network", // network/adjacent/local/physical
|
|
96
|
-
"authRequired": "none", // none/low/high
|
|
97
|
-
"userInteraction": "none", // none/required
|
|
98
|
-
"hasPublicExploit": true, // Known PoC exists?
|
|
99
|
-
"exploitMaturity": "weaponized", // theoretical/poc/weaponized
|
|
100
|
-
"automatable": true // Can be mass-exploited?
|
|
101
|
-
}
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
3. **Blast Radius**:
|
|
105
|
-
```
|
|
106
|
-
"blastRadius": {
|
|
107
|
-
"affectedUsers": "all", // none/single/subset/all
|
|
108
|
-
"affectedData": ["PII", "credentials", "financial"],
|
|
109
|
-
"affectedServices": ["auth", "payments"],
|
|
110
|
-
"cascadeRisk": true, // Leads to further compromise?
|
|
111
|
-
"containment": "system" // isolated/component/system/infrastructure
|
|
112
|
-
}
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
4. **Business Impact**:
|
|
116
|
-
```
|
|
117
|
-
"businessImpact": {
|
|
118
|
-
"confidentiality": "high",
|
|
119
|
-
"integrity": "high",
|
|
120
|
-
"availability": "low",
|
|
121
|
-
"financialExposure": "$100k-$1M potential fraud",
|
|
122
|
-
"complianceViolations": ["PCI-DSS 6.5.1", "SOC2 CC6.1"],
|
|
123
|
-
"reputationalRisk": "high",
|
|
124
|
-
"slaImpact": "99.9% SLA at risk"
|
|
125
|
-
}
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
5. **Proof of Concept** (safe, non-destructive):
|
|
129
|
-
```
|
|
130
|
-
"proofOfConcept": "curl -X POST /api/admin/users -H 'X-Admin: true' -d '{\"role\":\"admin\"}'"
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
### Step 3: Build Attack Chains
|
|
134
|
-
|
|
135
|
-
Identify 2-5 realistic attack chains that combine multiple vulnerabilities:
|
|
67
|
+
- **When done: Write findings to `.coverme/partial-07-compliance.json`**
|
|
136
68
|
|
|
137
|
-
|
|
138
|
-
"attackChains": [
|
|
139
|
-
{
|
|
140
|
-
"id": "AC-01",
|
|
141
|
-
"name": "Credential Theft to Full Infrastructure Compromise",
|
|
142
|
-
"description": "Attacker chains unauthenticated endpoint access with hardcoded secrets to gain full system control",
|
|
143
|
-
"likelihood": "high",
|
|
144
|
-
"impact": "critical",
|
|
145
|
-
"steps": [
|
|
146
|
-
{ "order": 1, "findingId": "HIGH-02", "action": "Access unauthenticated /enclave/register endpoint", "outcome": "Register malicious enclave with attacker-controlled keys" },
|
|
147
|
-
{ "order": 2, "findingId": "HIGH-01", "action": "Use leaked tracker API key from Helm values", "outcome": "Gain access to usage analytics and user activity" },
|
|
148
|
-
{ "order": 3, "findingId": "CRIT-01", "action": "Pivot using AWS credentials from .env", "outcome": "Full AWS account access, S3 data exfiltration" }
|
|
149
|
-
],
|
|
150
|
-
"mitigationStrategy": "Breaking any link stops the chain. Priority: rotate AWS credentials immediately."
|
|
151
|
-
}
|
|
152
|
-
]
|
|
153
|
-
```
|
|
69
|
+
### Agent Output Format
|
|
154
70
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
After all agents complete, compile their findings into a JSON file with this enhanced schema:
|
|
71
|
+
Each agent should write a partial JSON with this structure (include only relevant fields):
|
|
158
72
|
|
|
159
73
|
```json
|
|
160
74
|
{
|
|
@@ -162,40 +76,10 @@ After all agents complete, compile their findings into a JSON file with this enh
|
|
|
162
76
|
"date": "YYYY-MM-DD",
|
|
163
77
|
"branch": "branch-name",
|
|
164
78
|
"scope": "X files, ~Y lines",
|
|
165
|
-
"
|
|
166
|
-
|
|
167
|
-
"summary": {
|
|
168
|
-
"critical": 0,
|
|
169
|
-
"high": 0,
|
|
170
|
-
"medium": 0,
|
|
171
|
-
"low": 0,
|
|
172
|
-
"total": 0
|
|
173
|
-
},
|
|
174
|
-
|
|
175
|
-
"overallRiskLevel": "critical|high|medium|low",
|
|
176
|
-
"executiveSummary": "2-3 paragraphs: what the system does, key findings, recommended actions...",
|
|
79
|
+
"executiveSummary": "Summary paragraph...",
|
|
177
80
|
|
|
178
81
|
"topPriorities": [
|
|
179
|
-
{ "finding": "Description", "severity": "critical", "action": "
|
|
180
|
-
],
|
|
181
|
-
|
|
182
|
-
"attackChains": [
|
|
183
|
-
{
|
|
184
|
-
"id": "AC-01",
|
|
185
|
-
"name": "Chain name",
|
|
186
|
-
"description": "How vulnerabilities combine",
|
|
187
|
-
"likelihood": "high",
|
|
188
|
-
"impact": "critical",
|
|
189
|
-
"steps": [
|
|
190
|
-
{ "order": 1, "findingId": "CRIT-01", "action": "What attacker does", "outcome": "What they achieve" }
|
|
191
|
-
],
|
|
192
|
-
"mitigationStrategy": "How to break the chain"
|
|
193
|
-
}
|
|
194
|
-
],
|
|
195
|
-
|
|
196
|
-
"riskMatrix": [
|
|
197
|
-
{ "category": "Authentication", "currentRisk": "high", "residualRisk": "low", "trend": "stable" },
|
|
198
|
-
{ "category": "Data Protection", "currentRisk": "medium", "residualRisk": "low", "trend": "improving" }
|
|
82
|
+
{ "finding": "Description", "severity": "critical", "action": "Action needed" }
|
|
199
83
|
],
|
|
200
84
|
|
|
201
85
|
"architecture": {
|
|
@@ -204,7 +88,7 @@ After all agents complete, compile their findings into a JSON file with this enh
|
|
|
204
88
|
{ "name": "Component", "technology": "Tech", "description": "Purpose" }
|
|
205
89
|
],
|
|
206
90
|
"trustBoundaries": [
|
|
207
|
-
{ "id": "TB-01", "boundary": "
|
|
91
|
+
{ "id": "TB-01", "boundary": "Name", "trustLevel": "untrusted", "description": "..." }
|
|
208
92
|
]
|
|
209
93
|
},
|
|
210
94
|
|
|
@@ -212,9 +96,6 @@ After all agents complete, compile their findings into a JSON file with this enh
|
|
|
212
96
|
"diagram": "ASCII diagram...",
|
|
213
97
|
"ports": [
|
|
214
98
|
{ "port": 443, "protocol": "HTTPS", "component": "API", "binding": "0.0.0.0", "purpose": "Public API" }
|
|
215
|
-
],
|
|
216
|
-
"externalDeps": [
|
|
217
|
-
{ "service": "Stripe", "endpoint": "api.stripe.com", "auth": "API key", "risk": "PCI scope" }
|
|
218
99
|
]
|
|
219
100
|
},
|
|
220
101
|
|
|
@@ -231,58 +112,40 @@ After all agents complete, compile their findings into a JSON file with this enh
|
|
|
231
112
|
"status": "open",
|
|
232
113
|
"dreadScore": 8.5,
|
|
233
114
|
"cwe": "CWE-89",
|
|
234
|
-
"
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
}
|
|
244
|
-
],
|
|
245
|
-
"exploitability": {
|
|
246
|
-
"skillLevel": "novice",
|
|
247
|
-
"accessRequired": "network",
|
|
248
|
-
"authRequired": "none",
|
|
249
|
-
"userInteraction": "none",
|
|
250
|
-
"hasPublicExploit": true,
|
|
251
|
-
"exploitMaturity": "weaponized",
|
|
252
|
-
"automatable": true
|
|
253
|
-
},
|
|
254
|
-
"blastRadius": {
|
|
255
|
-
"affectedUsers": "all",
|
|
256
|
-
"affectedData": ["PII", "credentials"],
|
|
257
|
-
"affectedServices": ["database", "auth"],
|
|
258
|
-
"cascadeRisk": true,
|
|
259
|
-
"containment": "system"
|
|
260
|
-
},
|
|
261
|
-
"businessImpact": {
|
|
262
|
-
"confidentiality": "high",
|
|
263
|
-
"integrity": "high",
|
|
264
|
-
"availability": "none",
|
|
265
|
-
"financialExposure": "$500k-$5M breach costs",
|
|
266
|
-
"complianceViolations": ["GDPR Art 32", "SOC2 CC6.1"],
|
|
267
|
-
"reputationalRisk": "high"
|
|
268
|
-
},
|
|
269
|
-
"proofOfConcept": "curl '/api/users/1 OR 1=1--'",
|
|
270
|
-
"relatedFindings": ["HIGH-02", "HIGH-03"],
|
|
271
|
-
"attackChainPosition": "entry",
|
|
272
|
-
"references": ["https://owasp.org/Top10/A03_2021-Injection/"]
|
|
115
|
+
"codeEvidence": [{
|
|
116
|
+
"file": "src/file.js",
|
|
117
|
+
"startLine": 45,
|
|
118
|
+
"endLine": 50,
|
|
119
|
+
"code": "vulnerable code here",
|
|
120
|
+
"annotation": "Explanation"
|
|
121
|
+
}],
|
|
122
|
+
"proofOfConcept": "curl command or steps",
|
|
123
|
+
"relatedFindings": ["HIGH-02"]
|
|
273
124
|
}
|
|
274
125
|
],
|
|
275
126
|
|
|
276
|
-
"
|
|
127
|
+
"attackChains": [
|
|
277
128
|
{
|
|
278
|
-
"id": "
|
|
279
|
-
"
|
|
280
|
-
"
|
|
281
|
-
"
|
|
282
|
-
"
|
|
129
|
+
"id": "AC-01",
|
|
130
|
+
"name": "Chain name",
|
|
131
|
+
"description": "How vulnerabilities combine",
|
|
132
|
+
"likelihood": "high",
|
|
133
|
+
"impact": "critical",
|
|
134
|
+
"steps": [
|
|
135
|
+
{ "order": 1, "findingId": "CRIT-01", "action": "What attacker does", "outcome": "Result" }
|
|
136
|
+
],
|
|
137
|
+
"mitigationStrategy": "How to break the chain"
|
|
283
138
|
}
|
|
284
139
|
],
|
|
285
140
|
|
|
141
|
+
"riskMatrix": [
|
|
142
|
+
{ "category": "Authentication", "currentRisk": "high", "residualRisk": "low", "trend": "stable" }
|
|
143
|
+
],
|
|
144
|
+
|
|
145
|
+
"threatModel": [
|
|
146
|
+
{ "id": "T-01", "severity": "high", "dread": 6.5, "status": "open", "finding": "Description" }
|
|
147
|
+
],
|
|
148
|
+
|
|
286
149
|
"positiveObservations": [
|
|
287
150
|
{ "title": "Good Practice", "description": "What they did right..." }
|
|
288
151
|
],
|
|
@@ -298,53 +161,63 @@ After all agents complete, compile their findings into a JSON file with this enh
|
|
|
298
161
|
|
|
299
162
|
"remediation": {
|
|
300
163
|
"p0": [{ "action": "Do this NOW", "finding": "CRIT-01", "owner": "Security" }],
|
|
301
|
-
"p1": [{ "action": "Do this week", "finding": "HIGH-01", "owner": "Backend" }]
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
164
|
+
"p1": [{ "action": "Do this week", "finding": "HIGH-01", "owner": "Backend" }]
|
|
165
|
+
},
|
|
166
|
+
|
|
167
|
+
"qualityReview": {
|
|
168
|
+
"deadCode": [{ "type": "dead-code", "action": "DELETE", "file": "path", "description": "..." }],
|
|
169
|
+
"dryViolations": [{ "type": "dry-violation", "action": "MERGE", "file": "path", "description": "..." }]
|
|
170
|
+
},
|
|
171
|
+
|
|
172
|
+
"privacyAnalysis": [
|
|
173
|
+
{ "category": "Linkability", "risk": "medium", "description": "...", "mitigation": "..." }
|
|
174
|
+
]
|
|
305
175
|
}
|
|
306
176
|
```
|
|
307
177
|
|
|
308
|
-
### Step
|
|
178
|
+
### Step 2: Wait for All Agents and Verify
|
|
309
179
|
|
|
310
|
-
|
|
180
|
+
After launching all agents, wait for them to complete. Then verify all partial files exist:
|
|
311
181
|
|
|
312
|
-
1. **Create the output directory first:**
|
|
313
182
|
```bash
|
|
314
|
-
|
|
183
|
+
ls -la .coverme/partial-*.json
|
|
315
184
|
```
|
|
316
185
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
186
|
+
You should see 7 files (partial-01 through partial-07).
|
|
187
|
+
|
|
188
|
+
### Step 3: Merge and Generate PDF
|
|
189
|
+
|
|
190
|
+
Once all 7 partial files are written, merge them and generate the PDF:
|
|
320
191
|
|
|
321
|
-
3. **Generate the PDF:**
|
|
322
192
|
```bash
|
|
323
|
-
coverme .coverme/scan.json security-assessment-$(date +%Y-%m-%d).pdf && open security-assessment-$(date +%Y-%m-%d).pdf
|
|
193
|
+
coverme-merge .coverme && coverme .coverme/scan.json security-assessment-$(date +%Y-%m-%d).pdf && open security-assessment-$(date +%Y-%m-%d).pdf
|
|
324
194
|
```
|
|
325
195
|
|
|
326
|
-
|
|
196
|
+
This command:
|
|
197
|
+
1. Merges all partial-*.json files into scan.json
|
|
198
|
+
2. Generates the PDF report
|
|
199
|
+
3. Opens it automatically
|
|
327
200
|
|
|
328
201
|
### Quality Checklist
|
|
329
202
|
|
|
330
203
|
Before generating the PDF, verify:
|
|
204
|
+
- [ ] All 7 partial JSON files exist in .coverme/
|
|
331
205
|
- [ ] Every CRITICAL/HIGH finding has codeEvidence with actual code
|
|
332
|
-
- [ ] Every CRITICAL/HIGH finding has exploitability assessment
|
|
333
|
-
- [ ] Every CRITICAL/HIGH finding has blastRadius defined
|
|
334
206
|
- [ ] At least 2 attack chains are documented
|
|
335
|
-
- [ ] Top priorities match the most impactful attack chains
|
|
336
|
-
- [ ] Proof of concepts are safe and non-destructive
|
|
337
207
|
- [ ] CWE IDs are accurate for vulnerability types
|
|
338
|
-
- [ ] Compliance violations are specific (e.g., "PCI-DSS 6.5.1" not just "PCI-DSS")
|
|
339
208
|
|
|
340
209
|
### Output
|
|
341
210
|
|
|
342
|
-
The final
|
|
343
|
-
1. `.coverme/
|
|
344
|
-
2.
|
|
211
|
+
The final deliverables are:
|
|
212
|
+
1. `.coverme/partial-*.json` - Individual agent reports
|
|
213
|
+
2. `.coverme/scan.json` - Merged comprehensive report
|
|
214
|
+
3. `security-assessment-YYYY-MM-DD.pdf` - Professional PDF report
|
|
345
215
|
|
|
346
216
|
---
|
|
347
217
|
|
|
348
|
-
Now begin the security assessment
|
|
218
|
+
Now begin the security assessment:
|
|
349
219
|
|
|
350
|
-
|
|
220
|
+
1. Run `mkdir -p .coverme`
|
|
221
|
+
2. Launch all 7 agents in parallel
|
|
222
|
+
3. Each agent writes its own partial JSON when done
|
|
223
|
+
4. After all complete, run the merge and PDF generation command
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "coverme-security-scanner",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.7.0",
|
|
4
4
|
"description": "AI-powered security assessment reports with beautiful PDF output",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"coverme": "./bin/coverme.js",
|
|
8
|
+
"coverme-merge": "./bin/merge-reports.js",
|
|
8
9
|
"coverme-install": "./bin/install-command.js"
|
|
9
10
|
},
|
|
10
11
|
"main": "./dist/index.js",
|