coverme-scanner 1.0.23 → 1.0.24
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/.claude/commands/coverme.md +26 -4
- package/dist/cli/index.js +163 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +12 -0
- package/dist/cli/init.js.map +1 -1
- package/dist/templates/agents.example.json +33 -0
- package/dist/templates/agents.schema.json +75 -0
- package/package.json +1 -1
- package/src/cli/index.ts +182 -1
- package/src/cli/init.ts +12 -0
- package/src/templates/agents.example.json +33 -0
- package/src/templates/agents.schema.json +75 -0
|
@@ -18,12 +18,31 @@ Execute ALL phases automatically. Do NOT stop until the HTML report is open.
|
|
|
18
18
|
|
|
19
19
|
---
|
|
20
20
|
|
|
21
|
-
## Phase
|
|
21
|
+
## Phase 0: Load Custom Agents (if exists)
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
**FIRST**, check if `.coverme/agents.json` exists:
|
|
24
|
+
```bash
|
|
25
|
+
cat .coverme/agents.json 2>/dev/null || echo "NO_CUSTOM_AGENTS"
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
If the file exists, parse it and add custom agents to the appropriate phases:
|
|
29
|
+
- Agents with `"phase": "discovery"` → run in Phase 1 alongside built-in agents
|
|
30
|
+
- Agents with `"phase": "validation"` → run in Phase 2 alongside validators
|
|
31
|
+
- Agents with `"phase": "consensus"` → run in Phase 3
|
|
32
|
+
|
|
33
|
+
For each custom agent, use its `prompt` field as the agent instructions and `idPrefix` for finding IDs.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Phase 1: Discovery (10+ parallel agents)
|
|
38
|
+
|
|
39
|
+
Launch ALL built-in agents + custom discovery agents IN PARALLEL using the Task tool with `run_in_background: true`:
|
|
24
40
|
|
|
25
41
|
**IMPORTANT**: Set `run_in_background: true` on ALL Task tool calls to run agents in parallel without blocking.
|
|
26
42
|
|
|
43
|
+
### Custom Agents (from .coverme/agents.json)
|
|
44
|
+
If custom agents with `"phase": "discovery"` were loaded in Phase 0, launch them here in parallel with the built-in agents.
|
|
45
|
+
|
|
27
46
|
### Agent 1: Security Scanner (Core)
|
|
28
47
|
```
|
|
29
48
|
Scan for OWASP Top 10 and common vulnerabilities:
|
|
@@ -427,11 +446,14 @@ Output JSON: [{id: "TEST-XXX", title, severity, category: "testing", file, line,
|
|
|
427
446
|
|
|
428
447
|
---
|
|
429
448
|
|
|
430
|
-
## Phase 2: Cross-Validation (3 parallel validators)
|
|
449
|
+
## Phase 2: Cross-Validation (3+ parallel validators)
|
|
431
450
|
|
|
432
451
|
Wait for all Phase 1 background agents to complete using `AgentOutputTool`.
|
|
433
452
|
|
|
434
|
-
Then launch 3 validators IN PARALLEL with `run_in_background: true`:
|
|
453
|
+
Then launch 3 built-in validators + custom validation agents IN PARALLEL with `run_in_background: true`:
|
|
454
|
+
|
|
455
|
+
### Custom Validators (from .coverme/agents.json)
|
|
456
|
+
If custom agents with `"phase": "validation"` were loaded in Phase 0, launch them here in parallel with the built-in validators.
|
|
435
457
|
|
|
436
458
|
### Validator A: False Positive Hunter
|
|
437
459
|
```
|
package/dist/cli/index.js
CHANGED
|
@@ -38,5 +38,168 @@ program
|
|
|
38
38
|
.action(async (jsonFile, options) => {
|
|
39
39
|
await (0, index_js_1.generateReport)(jsonFile, options.output, options.format || 'pdf');
|
|
40
40
|
});
|
|
41
|
+
// Agent management commands
|
|
42
|
+
const agentCmd = program
|
|
43
|
+
.command('agent')
|
|
44
|
+
.description('Manage custom agents');
|
|
45
|
+
agentCmd
|
|
46
|
+
.command('init')
|
|
47
|
+
.description('Create .coverme/agents.json with example custom agents')
|
|
48
|
+
.action(() => {
|
|
49
|
+
const covermeDir = (0, path_1.join)(process.cwd(), '.coverme');
|
|
50
|
+
if (!(0, fs_1.existsSync)(covermeDir)) {
|
|
51
|
+
(0, fs_1.mkdirSync)(covermeDir, { recursive: true });
|
|
52
|
+
}
|
|
53
|
+
const agentsPath = (0, path_1.join)(covermeDir, 'agents.json');
|
|
54
|
+
if ((0, fs_1.existsSync)(agentsPath)) {
|
|
55
|
+
console.log(`agents.json already exists at ${agentsPath}`);
|
|
56
|
+
console.log('Use "coverme agent add" to add a new agent');
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const exampleAgents = {
|
|
60
|
+
customAgents: [],
|
|
61
|
+
settings: {
|
|
62
|
+
runCustomAgentsInParallel: true,
|
|
63
|
+
customAgentTimeout: 120000
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
(0, fs_1.writeFileSync)(agentsPath, JSON.stringify(exampleAgents, null, 2));
|
|
67
|
+
console.log(`Created ${agentsPath}`);
|
|
68
|
+
console.log('Use "coverme agent add" to add custom agents');
|
|
69
|
+
});
|
|
70
|
+
agentCmd
|
|
71
|
+
.command('add')
|
|
72
|
+
.description('Add a new custom agent interactively')
|
|
73
|
+
.option('--id <id>', 'Agent ID (lowercase, no spaces)')
|
|
74
|
+
.option('--name <name>', 'Agent display name')
|
|
75
|
+
.option('--phase <phase>', 'Phase: discovery, validation, or consensus')
|
|
76
|
+
.option('--prefix <prefix>', 'Finding ID prefix (2-6 uppercase letters)')
|
|
77
|
+
.option('--prompt <prompt>', 'Agent prompt/instructions')
|
|
78
|
+
.action((options) => {
|
|
79
|
+
const covermeDir = (0, path_1.join)(process.cwd(), '.coverme');
|
|
80
|
+
const agentsPath = (0, path_1.join)(covermeDir, 'agents.json');
|
|
81
|
+
if (!(0, fs_1.existsSync)(covermeDir)) {
|
|
82
|
+
(0, fs_1.mkdirSync)(covermeDir, { recursive: true });
|
|
83
|
+
}
|
|
84
|
+
let agents = { customAgents: [], settings: { runCustomAgentsInParallel: true, customAgentTimeout: 120000 } };
|
|
85
|
+
if ((0, fs_1.existsSync)(agentsPath)) {
|
|
86
|
+
agents = JSON.parse((0, fs_1.readFileSync)(agentsPath, 'utf-8'));
|
|
87
|
+
}
|
|
88
|
+
if (!options.id || !options.name || !options.phase || !options.prompt) {
|
|
89
|
+
console.log(`
|
|
90
|
+
Usage: coverme agent add --id <id> --name <name> --phase <phase> --prefix <prefix> --prompt <prompt>
|
|
91
|
+
|
|
92
|
+
Example:
|
|
93
|
+
coverme agent add \\
|
|
94
|
+
--id "dror" \\
|
|
95
|
+
--name "Dror - Security Expert" \\
|
|
96
|
+
--phase "discovery" \\
|
|
97
|
+
--prefix "DROR" \\
|
|
98
|
+
--prompt "You are Dror, a security expert. Find advanced vulnerabilities..."
|
|
99
|
+
|
|
100
|
+
Phases:
|
|
101
|
+
discovery - Runs in Phase 1 with security scanners
|
|
102
|
+
validation - Runs in Phase 2 with validators
|
|
103
|
+
consensus - Runs in Phase 3 during consensus building
|
|
104
|
+
`);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const newAgent = {
|
|
108
|
+
id: options.id,
|
|
109
|
+
name: options.name,
|
|
110
|
+
phase: options.phase,
|
|
111
|
+
priority: 5,
|
|
112
|
+
idPrefix: options.prefix || options.id.toUpperCase().slice(0, 4),
|
|
113
|
+
prompt: options.prompt,
|
|
114
|
+
enabled: true,
|
|
115
|
+
runInBackground: true
|
|
116
|
+
};
|
|
117
|
+
// Check for duplicate ID
|
|
118
|
+
if (agents.customAgents.some((a) => a.id === newAgent.id)) {
|
|
119
|
+
console.error(`Agent with id "${newAgent.id}" already exists`);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
agents.customAgents.push(newAgent);
|
|
123
|
+
(0, fs_1.writeFileSync)(agentsPath, JSON.stringify(agents, null, 2));
|
|
124
|
+
console.log(`Added agent "${newAgent.name}" to ${agentsPath}`);
|
|
125
|
+
console.log(`This agent will run in the ${newAgent.phase} phase with ID prefix ${newAgent.idPrefix}-XXX`);
|
|
126
|
+
});
|
|
127
|
+
agentCmd
|
|
128
|
+
.command('list')
|
|
129
|
+
.description('List all custom agents')
|
|
130
|
+
.action(() => {
|
|
131
|
+
const agentsPath = (0, path_1.join)(process.cwd(), '.coverme', 'agents.json');
|
|
132
|
+
if (!(0, fs_1.existsSync)(agentsPath)) {
|
|
133
|
+
console.log('No custom agents configured. Run "coverme agent init" first.');
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const agents = JSON.parse((0, fs_1.readFileSync)(agentsPath, 'utf-8'));
|
|
137
|
+
if (!agents.customAgents || agents.customAgents.length === 0) {
|
|
138
|
+
console.log('No custom agents configured. Use "coverme agent add" to add one.');
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
console.log('\nCustom Agents:\n');
|
|
142
|
+
for (const agent of agents.customAgents) {
|
|
143
|
+
const status = agent.enabled !== false ? '✓' : '✗';
|
|
144
|
+
console.log(` ${status} ${agent.name}`);
|
|
145
|
+
console.log(` ID: ${agent.id} | Phase: ${agent.phase} | Prefix: ${agent.idPrefix}`);
|
|
146
|
+
console.log(` Prompt: ${agent.prompt.slice(0, 60)}...`);
|
|
147
|
+
console.log('');
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
agentCmd
|
|
151
|
+
.command('remove')
|
|
152
|
+
.description('Remove a custom agent')
|
|
153
|
+
.argument('<id>', 'Agent ID to remove')
|
|
154
|
+
.action((id) => {
|
|
155
|
+
const agentsPath = (0, path_1.join)(process.cwd(), '.coverme', 'agents.json');
|
|
156
|
+
if (!(0, fs_1.existsSync)(agentsPath)) {
|
|
157
|
+
console.error('No agents.json found');
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
const agents = JSON.parse((0, fs_1.readFileSync)(agentsPath, 'utf-8'));
|
|
161
|
+
const idx = agents.customAgents.findIndex((a) => a.id === id);
|
|
162
|
+
if (idx === -1) {
|
|
163
|
+
console.error(`Agent "${id}" not found`);
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
const removed = agents.customAgents.splice(idx, 1)[0];
|
|
167
|
+
(0, fs_1.writeFileSync)(agentsPath, JSON.stringify(agents, null, 2));
|
|
168
|
+
console.log(`Removed agent "${removed.name}"`);
|
|
169
|
+
});
|
|
170
|
+
agentCmd
|
|
171
|
+
.command('example')
|
|
172
|
+
.description('Show example agent configurations')
|
|
173
|
+
.action(() => {
|
|
174
|
+
const examplePath = (0, path_1.join)(__dirname, '..', 'templates', 'agents.example.json');
|
|
175
|
+
if ((0, fs_1.existsSync)(examplePath)) {
|
|
176
|
+
console.log((0, fs_1.readFileSync)(examplePath, 'utf-8'));
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
console.log(`
|
|
180
|
+
Example agents.json:
|
|
181
|
+
|
|
182
|
+
{
|
|
183
|
+
"customAgents": [
|
|
184
|
+
{
|
|
185
|
+
"id": "dror",
|
|
186
|
+
"name": "Dror - Senior Security Expert",
|
|
187
|
+
"phase": "discovery",
|
|
188
|
+
"priority": 1,
|
|
189
|
+
"idPrefix": "DROR",
|
|
190
|
+
"prompt": "You are Dror, a senior security expert with 15 years of experience..."
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
"id": "compliance",
|
|
194
|
+
"name": "Compliance Checker",
|
|
195
|
+
"phase": "discovery",
|
|
196
|
+
"idPrefix": "COMP",
|
|
197
|
+
"prompt": "Check for GDPR, PCI-DSS, HIPAA, SOC2 compliance issues..."
|
|
198
|
+
}
|
|
199
|
+
]
|
|
200
|
+
}
|
|
201
|
+
`);
|
|
202
|
+
}
|
|
203
|
+
});
|
|
41
204
|
program.parse();
|
|
42
205
|
//# sourceMappingURL=index.js.map
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";;;AAEA,yCAAoC;AACpC,uCAAiC;AACjC,uCAAiC;AACjC,iDAAoD;AACpD,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/init.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAIA,UAAU,WAAW;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAihBD,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAIA,UAAU,WAAW;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAihBD,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CA2I9D"}
|
package/dist/cli/init.js
CHANGED
|
@@ -675,6 +675,18 @@ Reports saved to: .coverme/
|
|
|
675
675
|
- report_YYYY-MM-DD_HH-MM-SS.html
|
|
676
676
|
- scan_YYYY-MM-DD_HH-MM-SS.json
|
|
677
677
|
|
|
678
|
+
Custom Agents:
|
|
679
|
+
Add your own security experts to the scan:
|
|
680
|
+
|
|
681
|
+
coverme agent add \\
|
|
682
|
+
--id "john" \\
|
|
683
|
+
--name "John - Security Expert" \\
|
|
684
|
+
--phase "discovery" \\
|
|
685
|
+
--prefix "JOHN" \\
|
|
686
|
+
--prompt "You are John, a senior security expert..."
|
|
687
|
+
|
|
688
|
+
See examples: coverme agent example
|
|
689
|
+
|
|
678
690
|
The .coverme/ folder is automatically added to .gitignore
|
|
679
691
|
|
|
680
692
|
================================================================================
|
package/dist/cli/init.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuhBA,
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "./agents.schema.json",
|
|
3
|
+
"customAgents": [
|
|
4
|
+
{
|
|
5
|
+
"id": "john",
|
|
6
|
+
"name": "John - Senior Security Expert",
|
|
7
|
+
"phase": "discovery",
|
|
8
|
+
"priority": 1,
|
|
9
|
+
"idPrefix": "JOHN",
|
|
10
|
+
"prompt": "You are John, a senior security expert with 15 years of experience in penetration testing and secure code review.\n\nYour specialty areas:\n- Advanced injection attacks (second-order SQLi, blind XXE)\n- Authentication bypass techniques\n- Business logic exploitation\n- Cloud security (AWS, GCP, Azure misconfigurations)\n\nScan the codebase and find issues that junior scanners might miss.\n\nFor EACH finding, output:\n```json\n{\n \"id\": \"JOHN-XXX\",\n \"title\": \"...\",\n \"severity\": \"critical|high|medium|low\",\n \"category\": \"security\",\n \"file\": \"path/to/file\",\n \"line\": 123,\n \"code\": \"vulnerable code snippet\",\n \"description\": \"What is the issue\",\n \"impact\": \"What an attacker could do\",\n \"recommendation\": \"How to fix it\",\n \"confidence\": 85\n}\n```"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"id": "compliance",
|
|
14
|
+
"name": "Compliance Checker",
|
|
15
|
+
"phase": "discovery",
|
|
16
|
+
"priority": 2,
|
|
17
|
+
"idPrefix": "COMP",
|
|
18
|
+
"prompt": "Check for compliance issues:\n- GDPR data handling\n- PCI-DSS requirements for payment data\n- HIPAA for health data\n- SOC2 controls\n\nOutput findings in standard JSON format with id prefix COMP-XXX."
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"id": "custom-validator",
|
|
22
|
+
"name": "Domain Expert Validator",
|
|
23
|
+
"phase": "validation",
|
|
24
|
+
"priority": 1,
|
|
25
|
+
"idPrefix": "VAL",
|
|
26
|
+
"prompt": "You understand our specific business domain.\n\nReview findings and mark as false positive if:\n- The 'vulnerability' is actually our intended behavior\n- There's domain-specific context that makes it safe\n- Our architecture already handles this elsewhere\n\nOutput: { confirmed: [...], falsePositives: [{id, reason}] }"
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
"settings": {
|
|
30
|
+
"runCustomAgentsInParallel": true,
|
|
31
|
+
"customAgentTimeout": 120000
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"title": "CoverMe Custom Agents Configuration",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"properties": {
|
|
6
|
+
"customAgents": {
|
|
7
|
+
"type": "array",
|
|
8
|
+
"description": "List of custom agents to add to the scan",
|
|
9
|
+
"items": {
|
|
10
|
+
"type": "object",
|
|
11
|
+
"required": ["id", "name", "phase", "prompt"],
|
|
12
|
+
"properties": {
|
|
13
|
+
"id": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"description": "Unique identifier for the agent (lowercase, no spaces)",
|
|
16
|
+
"pattern": "^[a-z][a-z0-9-]*$"
|
|
17
|
+
},
|
|
18
|
+
"name": {
|
|
19
|
+
"type": "string",
|
|
20
|
+
"description": "Display name for the agent"
|
|
21
|
+
},
|
|
22
|
+
"phase": {
|
|
23
|
+
"type": "string",
|
|
24
|
+
"enum": ["discovery", "validation", "consensus"],
|
|
25
|
+
"description": "Which phase this agent runs in"
|
|
26
|
+
},
|
|
27
|
+
"priority": {
|
|
28
|
+
"type": "integer",
|
|
29
|
+
"minimum": 1,
|
|
30
|
+
"maximum": 10,
|
|
31
|
+
"default": 5,
|
|
32
|
+
"description": "Priority within phase (1=first, 10=last)"
|
|
33
|
+
},
|
|
34
|
+
"idPrefix": {
|
|
35
|
+
"type": "string",
|
|
36
|
+
"pattern": "^[A-Z]{2,6}$",
|
|
37
|
+
"description": "Prefix for finding IDs (e.g., 'DROR' -> DROR-001)"
|
|
38
|
+
},
|
|
39
|
+
"prompt": {
|
|
40
|
+
"type": "string",
|
|
41
|
+
"description": "The prompt/instructions for this agent"
|
|
42
|
+
},
|
|
43
|
+
"enabled": {
|
|
44
|
+
"type": "boolean",
|
|
45
|
+
"default": true,
|
|
46
|
+
"description": "Whether this agent is active"
|
|
47
|
+
},
|
|
48
|
+
"timeout": {
|
|
49
|
+
"type": "integer",
|
|
50
|
+
"default": 120000,
|
|
51
|
+
"description": "Timeout in milliseconds"
|
|
52
|
+
},
|
|
53
|
+
"runInBackground": {
|
|
54
|
+
"type": "boolean",
|
|
55
|
+
"default": true,
|
|
56
|
+
"description": "Run this agent in background"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"settings": {
|
|
62
|
+
"type": "object",
|
|
63
|
+
"properties": {
|
|
64
|
+
"runCustomAgentsInParallel": {
|
|
65
|
+
"type": "boolean",
|
|
66
|
+
"default": true
|
|
67
|
+
},
|
|
68
|
+
"customAgentTimeout": {
|
|
69
|
+
"type": "integer",
|
|
70
|
+
"default": 120000
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
package/package.json
CHANGED
package/src/cli/index.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { Command } from 'commander';
|
|
|
4
4
|
import { init } from './init.js';
|
|
5
5
|
import { scan } from './scan.js';
|
|
6
6
|
import { generateReport } from '../report/index.js';
|
|
7
|
-
import { readFileSync } from 'fs';
|
|
7
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync, copyFileSync } from 'fs';
|
|
8
8
|
import { join } from 'path';
|
|
9
9
|
|
|
10
10
|
const pkg = JSON.parse(readFileSync(join(__dirname, '..', '..', 'package.json'), 'utf-8'));
|
|
@@ -44,4 +44,185 @@ program
|
|
|
44
44
|
await generateReport(jsonFile, options.output, options.format || 'pdf');
|
|
45
45
|
});
|
|
46
46
|
|
|
47
|
+
// Agent management commands
|
|
48
|
+
const agentCmd = program
|
|
49
|
+
.command('agent')
|
|
50
|
+
.description('Manage custom agents');
|
|
51
|
+
|
|
52
|
+
agentCmd
|
|
53
|
+
.command('init')
|
|
54
|
+
.description('Create .coverme/agents.json with example custom agents')
|
|
55
|
+
.action(() => {
|
|
56
|
+
const covermeDir = join(process.cwd(), '.coverme');
|
|
57
|
+
if (!existsSync(covermeDir)) {
|
|
58
|
+
mkdirSync(covermeDir, { recursive: true });
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const agentsPath = join(covermeDir, 'agents.json');
|
|
62
|
+
if (existsSync(agentsPath)) {
|
|
63
|
+
console.log(`agents.json already exists at ${agentsPath}`);
|
|
64
|
+
console.log('Use "coverme agent add" to add a new agent');
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const exampleAgents = {
|
|
69
|
+
customAgents: [],
|
|
70
|
+
settings: {
|
|
71
|
+
runCustomAgentsInParallel: true,
|
|
72
|
+
customAgentTimeout: 120000
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
writeFileSync(agentsPath, JSON.stringify(exampleAgents, null, 2));
|
|
77
|
+
console.log(`Created ${agentsPath}`);
|
|
78
|
+
console.log('Use "coverme agent add" to add custom agents');
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
agentCmd
|
|
82
|
+
.command('add')
|
|
83
|
+
.description('Add a new custom agent interactively')
|
|
84
|
+
.option('--id <id>', 'Agent ID (lowercase, no spaces)')
|
|
85
|
+
.option('--name <name>', 'Agent display name')
|
|
86
|
+
.option('--phase <phase>', 'Phase: discovery, validation, or consensus')
|
|
87
|
+
.option('--prefix <prefix>', 'Finding ID prefix (2-6 uppercase letters)')
|
|
88
|
+
.option('--prompt <prompt>', 'Agent prompt/instructions')
|
|
89
|
+
.action((options) => {
|
|
90
|
+
const covermeDir = join(process.cwd(), '.coverme');
|
|
91
|
+
const agentsPath = join(covermeDir, 'agents.json');
|
|
92
|
+
|
|
93
|
+
if (!existsSync(covermeDir)) {
|
|
94
|
+
mkdirSync(covermeDir, { recursive: true });
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
let agents: any = { customAgents: [], settings: { runCustomAgentsInParallel: true, customAgentTimeout: 120000 } };
|
|
98
|
+
if (existsSync(agentsPath)) {
|
|
99
|
+
agents = JSON.parse(readFileSync(agentsPath, 'utf-8'));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (!options.id || !options.name || !options.phase || !options.prompt) {
|
|
103
|
+
console.log(`
|
|
104
|
+
Usage: coverme agent add --id <id> --name <name> --phase <phase> --prefix <prefix> --prompt <prompt>
|
|
105
|
+
|
|
106
|
+
Example:
|
|
107
|
+
coverme agent add \\
|
|
108
|
+
--id "dror" \\
|
|
109
|
+
--name "Dror - Security Expert" \\
|
|
110
|
+
--phase "discovery" \\
|
|
111
|
+
--prefix "DROR" \\
|
|
112
|
+
--prompt "You are Dror, a security expert. Find advanced vulnerabilities..."
|
|
113
|
+
|
|
114
|
+
Phases:
|
|
115
|
+
discovery - Runs in Phase 1 with security scanners
|
|
116
|
+
validation - Runs in Phase 2 with validators
|
|
117
|
+
consensus - Runs in Phase 3 during consensus building
|
|
118
|
+
`);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const newAgent = {
|
|
123
|
+
id: options.id,
|
|
124
|
+
name: options.name,
|
|
125
|
+
phase: options.phase,
|
|
126
|
+
priority: 5,
|
|
127
|
+
idPrefix: options.prefix || options.id.toUpperCase().slice(0, 4),
|
|
128
|
+
prompt: options.prompt,
|
|
129
|
+
enabled: true,
|
|
130
|
+
runInBackground: true
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
// Check for duplicate ID
|
|
134
|
+
if (agents.customAgents.some((a: any) => a.id === newAgent.id)) {
|
|
135
|
+
console.error(`Agent with id "${newAgent.id}" already exists`);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
agents.customAgents.push(newAgent);
|
|
140
|
+
writeFileSync(agentsPath, JSON.stringify(agents, null, 2));
|
|
141
|
+
console.log(`Added agent "${newAgent.name}" to ${agentsPath}`);
|
|
142
|
+
console.log(`This agent will run in the ${newAgent.phase} phase with ID prefix ${newAgent.idPrefix}-XXX`);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
agentCmd
|
|
146
|
+
.command('list')
|
|
147
|
+
.description('List all custom agents')
|
|
148
|
+
.action(() => {
|
|
149
|
+
const agentsPath = join(process.cwd(), '.coverme', 'agents.json');
|
|
150
|
+
if (!existsSync(agentsPath)) {
|
|
151
|
+
console.log('No custom agents configured. Run "coverme agent init" first.');
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const agents = JSON.parse(readFileSync(agentsPath, 'utf-8'));
|
|
156
|
+
if (!agents.customAgents || agents.customAgents.length === 0) {
|
|
157
|
+
console.log('No custom agents configured. Use "coverme agent add" to add one.');
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
console.log('\nCustom Agents:\n');
|
|
162
|
+
for (const agent of agents.customAgents) {
|
|
163
|
+
const status = agent.enabled !== false ? '✓' : '✗';
|
|
164
|
+
console.log(` ${status} ${agent.name}`);
|
|
165
|
+
console.log(` ID: ${agent.id} | Phase: ${agent.phase} | Prefix: ${agent.idPrefix}`);
|
|
166
|
+
console.log(` Prompt: ${agent.prompt.slice(0, 60)}...`);
|
|
167
|
+
console.log('');
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
agentCmd
|
|
172
|
+
.command('remove')
|
|
173
|
+
.description('Remove a custom agent')
|
|
174
|
+
.argument('<id>', 'Agent ID to remove')
|
|
175
|
+
.action((id: string) => {
|
|
176
|
+
const agentsPath = join(process.cwd(), '.coverme', 'agents.json');
|
|
177
|
+
if (!existsSync(agentsPath)) {
|
|
178
|
+
console.error('No agents.json found');
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const agents = JSON.parse(readFileSync(agentsPath, 'utf-8'));
|
|
183
|
+
const idx = agents.customAgents.findIndex((a: any) => a.id === id);
|
|
184
|
+
if (idx === -1) {
|
|
185
|
+
console.error(`Agent "${id}" not found`);
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const removed = agents.customAgents.splice(idx, 1)[0];
|
|
190
|
+
writeFileSync(agentsPath, JSON.stringify(agents, null, 2));
|
|
191
|
+
console.log(`Removed agent "${removed.name}"`);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
agentCmd
|
|
195
|
+
.command('example')
|
|
196
|
+
.description('Show example agent configurations')
|
|
197
|
+
.action(() => {
|
|
198
|
+
const examplePath = join(__dirname, '..', 'templates', 'agents.example.json');
|
|
199
|
+
if (existsSync(examplePath)) {
|
|
200
|
+
console.log(readFileSync(examplePath, 'utf-8'));
|
|
201
|
+
} else {
|
|
202
|
+
console.log(`
|
|
203
|
+
Example agents.json:
|
|
204
|
+
|
|
205
|
+
{
|
|
206
|
+
"customAgents": [
|
|
207
|
+
{
|
|
208
|
+
"id": "dror",
|
|
209
|
+
"name": "Dror - Senior Security Expert",
|
|
210
|
+
"phase": "discovery",
|
|
211
|
+
"priority": 1,
|
|
212
|
+
"idPrefix": "DROR",
|
|
213
|
+
"prompt": "You are Dror, a senior security expert with 15 years of experience..."
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
"id": "compliance",
|
|
217
|
+
"name": "Compliance Checker",
|
|
218
|
+
"phase": "discovery",
|
|
219
|
+
"idPrefix": "COMP",
|
|
220
|
+
"prompt": "Check for GDPR, PCI-DSS, HIPAA, SOC2 compliance issues..."
|
|
221
|
+
}
|
|
222
|
+
]
|
|
223
|
+
}
|
|
224
|
+
`);
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
|
|
47
228
|
program.parse();
|
package/src/cli/init.ts
CHANGED
|
@@ -656,6 +656,18 @@ Reports saved to: .coverme/
|
|
|
656
656
|
- report_YYYY-MM-DD_HH-MM-SS.html
|
|
657
657
|
- scan_YYYY-MM-DD_HH-MM-SS.json
|
|
658
658
|
|
|
659
|
+
Custom Agents:
|
|
660
|
+
Add your own security experts to the scan:
|
|
661
|
+
|
|
662
|
+
coverme agent add \\
|
|
663
|
+
--id "john" \\
|
|
664
|
+
--name "John - Security Expert" \\
|
|
665
|
+
--phase "discovery" \\
|
|
666
|
+
--prefix "JOHN" \\
|
|
667
|
+
--prompt "You are John, a senior security expert..."
|
|
668
|
+
|
|
669
|
+
See examples: coverme agent example
|
|
670
|
+
|
|
659
671
|
The .coverme/ folder is automatically added to .gitignore
|
|
660
672
|
|
|
661
673
|
================================================================================
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "./agents.schema.json",
|
|
3
|
+
"customAgents": [
|
|
4
|
+
{
|
|
5
|
+
"id": "john",
|
|
6
|
+
"name": "John - Senior Security Expert",
|
|
7
|
+
"phase": "discovery",
|
|
8
|
+
"priority": 1,
|
|
9
|
+
"idPrefix": "JOHN",
|
|
10
|
+
"prompt": "You are John, a senior security expert with 15 years of experience in penetration testing and secure code review.\n\nYour specialty areas:\n- Advanced injection attacks (second-order SQLi, blind XXE)\n- Authentication bypass techniques\n- Business logic exploitation\n- Cloud security (AWS, GCP, Azure misconfigurations)\n\nScan the codebase and find issues that junior scanners might miss.\n\nFor EACH finding, output:\n```json\n{\n \"id\": \"JOHN-XXX\",\n \"title\": \"...\",\n \"severity\": \"critical|high|medium|low\",\n \"category\": \"security\",\n \"file\": \"path/to/file\",\n \"line\": 123,\n \"code\": \"vulnerable code snippet\",\n \"description\": \"What is the issue\",\n \"impact\": \"What an attacker could do\",\n \"recommendation\": \"How to fix it\",\n \"confidence\": 85\n}\n```"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"id": "compliance",
|
|
14
|
+
"name": "Compliance Checker",
|
|
15
|
+
"phase": "discovery",
|
|
16
|
+
"priority": 2,
|
|
17
|
+
"idPrefix": "COMP",
|
|
18
|
+
"prompt": "Check for compliance issues:\n- GDPR data handling\n- PCI-DSS requirements for payment data\n- HIPAA for health data\n- SOC2 controls\n\nOutput findings in standard JSON format with id prefix COMP-XXX."
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"id": "custom-validator",
|
|
22
|
+
"name": "Domain Expert Validator",
|
|
23
|
+
"phase": "validation",
|
|
24
|
+
"priority": 1,
|
|
25
|
+
"idPrefix": "VAL",
|
|
26
|
+
"prompt": "You understand our specific business domain.\n\nReview findings and mark as false positive if:\n- The 'vulnerability' is actually our intended behavior\n- There's domain-specific context that makes it safe\n- Our architecture already handles this elsewhere\n\nOutput: { confirmed: [...], falsePositives: [{id, reason}] }"
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
"settings": {
|
|
30
|
+
"runCustomAgentsInParallel": true,
|
|
31
|
+
"customAgentTimeout": 120000
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"title": "CoverMe Custom Agents Configuration",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"properties": {
|
|
6
|
+
"customAgents": {
|
|
7
|
+
"type": "array",
|
|
8
|
+
"description": "List of custom agents to add to the scan",
|
|
9
|
+
"items": {
|
|
10
|
+
"type": "object",
|
|
11
|
+
"required": ["id", "name", "phase", "prompt"],
|
|
12
|
+
"properties": {
|
|
13
|
+
"id": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"description": "Unique identifier for the agent (lowercase, no spaces)",
|
|
16
|
+
"pattern": "^[a-z][a-z0-9-]*$"
|
|
17
|
+
},
|
|
18
|
+
"name": {
|
|
19
|
+
"type": "string",
|
|
20
|
+
"description": "Display name for the agent"
|
|
21
|
+
},
|
|
22
|
+
"phase": {
|
|
23
|
+
"type": "string",
|
|
24
|
+
"enum": ["discovery", "validation", "consensus"],
|
|
25
|
+
"description": "Which phase this agent runs in"
|
|
26
|
+
},
|
|
27
|
+
"priority": {
|
|
28
|
+
"type": "integer",
|
|
29
|
+
"minimum": 1,
|
|
30
|
+
"maximum": 10,
|
|
31
|
+
"default": 5,
|
|
32
|
+
"description": "Priority within phase (1=first, 10=last)"
|
|
33
|
+
},
|
|
34
|
+
"idPrefix": {
|
|
35
|
+
"type": "string",
|
|
36
|
+
"pattern": "^[A-Z]{2,6}$",
|
|
37
|
+
"description": "Prefix for finding IDs (e.g., 'DROR' -> DROR-001)"
|
|
38
|
+
},
|
|
39
|
+
"prompt": {
|
|
40
|
+
"type": "string",
|
|
41
|
+
"description": "The prompt/instructions for this agent"
|
|
42
|
+
},
|
|
43
|
+
"enabled": {
|
|
44
|
+
"type": "boolean",
|
|
45
|
+
"default": true,
|
|
46
|
+
"description": "Whether this agent is active"
|
|
47
|
+
},
|
|
48
|
+
"timeout": {
|
|
49
|
+
"type": "integer",
|
|
50
|
+
"default": 120000,
|
|
51
|
+
"description": "Timeout in milliseconds"
|
|
52
|
+
},
|
|
53
|
+
"runInBackground": {
|
|
54
|
+
"type": "boolean",
|
|
55
|
+
"default": true,
|
|
56
|
+
"description": "Run this agent in background"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"settings": {
|
|
62
|
+
"type": "object",
|
|
63
|
+
"properties": {
|
|
64
|
+
"runCustomAgentsInParallel": {
|
|
65
|
+
"type": "boolean",
|
|
66
|
+
"default": true
|
|
67
|
+
},
|
|
68
|
+
"customAgentTimeout": {
|
|
69
|
+
"type": "integer",
|
|
70
|
+
"default": 120000
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|