coverme-scanner 4.0.0 → 4.0.1
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/dist/prompts/coverme-command.md +516 -1205
- package/package.json +1 -1
|
@@ -1,1301 +1,612 @@
|
|
|
1
|
-
# CoverMe Security Scanner
|
|
1
|
+
# CoverMe - Ultimate AI Security Scanner v4.0
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The most comprehensive AI-powered code scanner. **33 specialized agents** including 9 AI-code-specific detectors + adversarial review.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
$ARGUMENTS
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## CRITICAL INSTRUCTIONS
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
"estimatedEffort": {
|
|
15
|
-
"human": "4-6 hours (research, implement, test, deploy)",
|
|
16
|
-
"claudeCode": "15-20 minutes (automated detection, code generation, test creation)",
|
|
17
|
-
"roi": "18x faster with Claude Code"
|
|
18
|
-
}
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
**Why this matters**:
|
|
22
|
-
- Shows tangible value to developers and managers
|
|
23
|
-
- Highlights Claude Code's ability to accelerate fix implementation
|
|
24
|
-
- Quantifies ROI on security investment
|
|
25
|
-
|
|
26
|
-
**Time estimates guide**:
|
|
27
|
-
- **Quick fixes**: Human 30min-2h, Claude Code 5-10min (5-12x faster)
|
|
28
|
-
- **Moderate fixes**: Human 4-6h, Claude Code 15-30min (12-18x faster)
|
|
29
|
-
- **Complex fixes**: Human 1-2 days, Claude Code 1-2h (8-16x faster)
|
|
9
|
+
1. **DO NOT ASK ANY QUESTIONS** - Run autonomously
|
|
10
|
+
2. **DO NOT STOP FOR CONFIRMATION** - Keep going
|
|
11
|
+
3. **COMPLETE EVERYTHING** - All phases without interruption
|
|
12
|
+
4. **AGENTS WRITE TO FILES** - Each agent writes results to `.coverme/agents/{ID}.json`
|
|
13
|
+
5. **AGENTS RETURN ONLY "done" or "skipped"** - Never return findings in response
|
|
30
14
|
|
|
31
15
|
---
|
|
32
16
|
|
|
33
|
-
##
|
|
34
|
-
|
|
35
|
-
### Step 1: Understand the Project
|
|
17
|
+
## Phase 0: Setup
|
|
36
18
|
|
|
37
19
|
```bash
|
|
38
|
-
mkdir -p .coverme
|
|
39
|
-
|
|
40
|
-
# Project structure
|
|
41
|
-
ls -la
|
|
42
|
-
find . -maxdepth 2 -type d -not -path "*/node_modules/*" -not -path "*/.git/*" -not -path "*/dist/*" 2>/dev/null | head -40
|
|
43
|
-
|
|
44
|
-
# Count files
|
|
45
|
-
find . -type f \( -name "*.ts" -o -name "*.js" -o -name "*.tsx" -o -name "*.py" -o -name "*.go" \) -not -path "*/node_modules/*" -not -path "*/.git/*" 2>/dev/null | wc -l
|
|
46
|
-
|
|
47
|
-
# Tech stack
|
|
48
|
-
cat package.json 2>/dev/null | head -50
|
|
49
|
-
cat requirements.txt 2>/dev/null | head -30
|
|
50
|
-
cat go.mod 2>/dev/null | head -30
|
|
20
|
+
mkdir -p .coverme/agents
|
|
21
|
+
rm -f .coverme/agents/*.json 2>/dev/null
|
|
51
22
|
```
|
|
52
23
|
|
|
53
|
-
|
|
54
|
-
|
|
24
|
+
Get project stats:
|
|
55
25
|
```bash
|
|
56
|
-
|
|
57
|
-
find . -type f \( -name "
|
|
26
|
+
FILES=$(find . -type f \( -name "*.ts" -o -name "*.js" -o -name "*.py" -o -name "*.go" \) -not -path "*/node_modules/*" -not -path "*/.git/*" -not -path "*/dist/*" 2>/dev/null | wc -l | tr -d ' ')
|
|
27
|
+
LINES=$(find . -type f \( -name "*.ts" -o -name "*.js" -o -name "*.py" \) -not -path "*/node_modules/*" -not -path "*/dist/*" 2>/dev/null | head -50 | xargs wc -l 2>/dev/null | tail -1 | awk '{print $1}')
|
|
28
|
+
echo "Files: $FILES, Lines: ~$LINES"
|
|
29
|
+
```
|
|
58
30
|
|
|
59
|
-
|
|
60
|
-
find . -type f \( -name "*route*" -o -name "*controller*" -o -name "*api*" -o -name "*endpoint*" -o -name "*handler*" \) -not -path "*/node_modules/*" -not -path "*/.git/*" 2>/dev/null | head -20
|
|
31
|
+
---
|
|
61
32
|
|
|
62
|
-
|
|
63
|
-
find . -type f \( -name "*model*" -o -name "*repository*" -o -name "*db*" -o -name "*database*" -o -name "*query*" \) -not -path "*/node_modules/*" -not -path "*/.git/*" 2>/dev/null | head -20
|
|
33
|
+
## Phase 1: Launch 33 Agents (parallel, background)
|
|
64
34
|
|
|
65
|
-
|
|
66
|
-
|
|
35
|
+
**CRITICAL**: Each agent MUST:
|
|
36
|
+
1. Scan the codebase for its specific issues
|
|
37
|
+
2. Write findings to `.coverme/agents/{PREFIX}.json`
|
|
38
|
+
3. Return ONLY the word "done" or "skipped" - NOTHING ELSE
|
|
67
39
|
|
|
68
|
-
|
|
69
|
-
find . -type f \( -name "*.env*" -o -name "*secret*" -o -name "*config*" -o -name "*credential*" -o -name "*key*" \) -not -path "*/node_modules/*" -not -path "*/.git/*" 2>/dev/null | head -20
|
|
40
|
+
Launch ALL with `run_in_background: true`:
|
|
70
41
|
|
|
71
|
-
|
|
72
|
-
find . -type f \( -name "Dockerfile*" -o -name "docker-compose*" -o -name "*.yaml" -o -name "*.yml" -o -name "*helm*" \) -not -path "*/node_modules/*" -not -path "*/.git/*" 2>/dev/null | head -25
|
|
42
|
+
### Agent 1: SEC - Security Core
|
|
73
43
|
```
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
cat .coverme/scan.json 2>/dev/null | head -100 || echo "NO_PREVIOUS_SCAN"
|
|
44
|
+
Scan for: SQL injection, XSS, command injection, SSTI, hardcoded secrets, weak crypto.
|
|
45
|
+
Write to .coverme/agents/SEC.json:
|
|
46
|
+
[{"id":"SEC-001","title":"...","severity":"critical|high|medium|low","file":"...","line":N,"description":"...","recommendation":"..."}]
|
|
47
|
+
Return ONLY: "done" or "skipped"
|
|
79
48
|
```
|
|
80
49
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
## PHASE 2: DEEP ANALYSIS
|
|
84
|
-
|
|
85
|
-
**Read the critical files you found.** For each category, actively search for issues:
|
|
86
|
-
|
|
87
|
-
### 1. SECURITY ISSUES
|
|
88
|
-
|
|
89
|
-
#### 1.1 Injection Attacks
|
|
90
|
-
- **SQL Injection**: String concatenation in queries, template literals with user input
|
|
91
|
-
```bash
|
|
92
|
-
grep -r "query.*\`.*\$\{" --include="*.ts" --include="*.js" src/
|
|
93
|
-
grep -r "execute.*+.*req\." --include="*.ts" src/
|
|
94
|
-
```
|
|
95
|
-
- **NoSQL Injection**: Unvalidated MongoDB queries, Redis commands with user input
|
|
96
|
-
- **Command Injection**: User input in exec(), spawn(), system calls
|
|
97
|
-
```bash
|
|
98
|
-
grep -r "exec\(.*req\." --include="*.ts" --include="*.js" src/
|
|
99
|
-
grep -r "spawn.*\`.*\$\{" --include="*.ts" src/
|
|
100
|
-
```
|
|
101
|
-
**CRITICAL**: Config files are NOT safe! Check if model names, paths, or commands from config files are validated
|
|
102
|
-
- **Path Traversal**: User input in file paths, missing path normalization
|
|
103
|
-
- **SSRF**: User-controlled URLs, unvalidated webhook endpoints
|
|
104
|
-
- **Template Injection**: Server-side template rendering with user input
|
|
105
|
-
- **XSS**: dangerouslySetInnerHTML, innerHTML, eval() with user data
|
|
106
|
-
|
|
107
|
-
#### 1.2 Authentication & Session Management
|
|
108
|
-
- **Hardcoded Credentials**: Check ENTIRE git history!
|
|
109
|
-
```bash
|
|
110
|
-
# Check if secrets are tracked
|
|
111
|
-
git ls-files | grep -E "secret|credential|\.env$"
|
|
112
|
-
|
|
113
|
-
# Check git HISTORY (even if removed now!)
|
|
114
|
-
git log --all --full-history -- "**/secrets*" "**/credentials*" "**/*.env"
|
|
115
|
-
git log --all -p -S "AWS_SECRET" --source --all | head -100
|
|
116
|
-
```
|
|
117
|
-
- **JWT Vulnerabilities**: 'none' algorithm accepted, weak secrets, missing validation
|
|
118
|
-
```bash
|
|
119
|
-
grep -r "algorithm.*none" --include="*.ts" --include="*.js" src/
|
|
120
|
-
grep -r "jwt.verify.*algorithm" --include="*.ts" src/
|
|
121
|
-
```
|
|
122
|
-
- **Session Fixation**: Session ID not regenerated after login
|
|
123
|
-
- **Weak Password Storage**: MD5, SHA1, plaintext passwords
|
|
124
|
-
- **Missing Rate Limiting**: No protection on auth endpoints
|
|
125
|
-
- **OAuth Misconfiguration**: Insecure redirect_uri, state parameter issues
|
|
126
|
-
|
|
127
|
-
#### 1.3 Authorization Issues
|
|
128
|
-
- **IDOR** (Insecure Direct Object References): User can access others' data
|
|
129
|
-
```bash
|
|
130
|
-
# Look for direct ID usage without auth check
|
|
131
|
-
grep -r "findById.*req\.params" --include="*.ts" --include="*.js" src/
|
|
132
|
-
```
|
|
133
|
-
- **Missing Authorization Checks**: Endpoints accessible without proper roles
|
|
134
|
-
- **Privilege Escalation**: Paths to gain higher privileges
|
|
135
|
-
|
|
136
|
-
#### 1.4 Cryptography
|
|
137
|
-
- **Weak Algorithms**: MD5, SHA1 for passwords, DES, RC4
|
|
138
|
-
```bash
|
|
139
|
-
grep -r "createHash.*md5\|createHash.*sha1" --include="*.ts" --include="*.js" src/
|
|
140
|
-
```
|
|
141
|
-
- **Hardcoded Keys**: Encryption keys in code
|
|
142
|
-
- **Weak Random**: Math.random() for security tokens
|
|
143
|
-
- **ECB Mode**: Insecure block cipher mode
|
|
144
|
-
|
|
145
|
-
#### 1.5 Sensitive Data Exposure
|
|
146
|
-
- **API Keys in Code**: Check git history!
|
|
147
|
-
- **Secrets in Logs**: Password, tokens logged
|
|
148
|
-
```bash
|
|
149
|
-
grep -r "console.log.*password\|logger.*token" --include="*.ts" src/
|
|
150
|
-
```
|
|
151
|
-
- **Error Details Leaked**: Stack traces, internal paths in responses
|
|
152
|
-
- **PII in URLs**: Personal data in query strings
|
|
153
|
-
|
|
154
|
-
#### 1.6 Security Misconfiguration
|
|
155
|
-
- **Debug Mode in Production**: Debug flags, verbose errors
|
|
156
|
-
- **Default Credentials**: Unchanged defaults
|
|
157
|
-
- **Missing Security Headers**: CSP, HSTS, X-Frame-Options
|
|
158
|
-
```bash
|
|
159
|
-
grep -r "helmet\(\)" --include="*.ts" --include="*.js" src/
|
|
160
|
-
# If helmet() has no config, report as MEDIUM
|
|
161
|
-
```
|
|
162
|
-
- **CORS Misconfiguration**: origin: '*' or reflecting any origin
|
|
163
|
-
```bash
|
|
164
|
-
grep -r "Access-Control-Allow-Origin.*\*\|Access-Control-Allow-Origin.*req\.headers\.origin" --include="*.ts" src/
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
#### 1.7 Race Conditions & Business Logic
|
|
168
|
-
- **TOCTOU** (Time-of-check Time-of-use): Non-atomic check-then-act
|
|
169
|
-
- **Double Spend**: Credits/tokens deducted after use instead of before
|
|
170
|
-
- **Quota Bypass**: Race conditions in rate limiting
|
|
171
|
-
- **Workflow Bypass**: Steps can be skipped
|
|
172
|
-
|
|
173
|
-
### 2. QUALITY ISSUES (CRITICAL!)
|
|
174
|
-
|
|
175
|
-
#### 2.1 Silent Failures - **YOUR TOP PRIORITY**
|
|
176
|
-
|
|
177
|
-
Silent failures are **CRITICAL** because they hide production bugs. Search aggressively:
|
|
178
|
-
|
|
179
|
-
**Pattern 1: Empty catch blocks**
|
|
180
|
-
```bash
|
|
181
|
-
grep -r "catch.*{[\s]*}" --include="*.ts" --include="*.js" src/
|
|
182
|
-
grep -r "catch.*{\s*//.*\s*}" --include="*.ts" src/
|
|
50
|
+
### Agent 2: AUTH - Authentication
|
|
183
51
|
```
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
grep -r "catch.*{[\s]*console\." --include="*.ts" --include="*.js" src/
|
|
52
|
+
Scan for: JWT issues, session problems, OAuth flaws, weak passwords, missing MFA.
|
|
53
|
+
Write to .coverme/agents/AUTH.json
|
|
54
|
+
Return ONLY: "done" or "skipped"
|
|
188
55
|
```
|
|
189
56
|
|
|
190
|
-
|
|
191
|
-
```bash
|
|
192
|
-
grep -r "catch.*return \[\]" --include="*.ts" --include="*.js" src/
|
|
193
|
-
grep -r "catch.*return \{\}" --include="*.ts" src/
|
|
194
|
-
grep -r "catch.*return null" --include="*.ts" src/
|
|
195
|
-
grep -r "catch.*return ''" --include="*.ts" src/
|
|
57
|
+
### Agent 3: API - API Security
|
|
196
58
|
```
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
grep -r "\.catch\(\s*\(\)\s*=>" --include="*.ts" --include="*.js" src/
|
|
201
|
-
grep -r "\.catch\(console\." --include="*.ts" src/
|
|
59
|
+
Scan for: CORS issues, rate limiting, input validation, mass assignment, GraphQL issues.
|
|
60
|
+
Write to .coverme/agents/API.json
|
|
61
|
+
Return ONLY: "done" or "skipped"
|
|
202
62
|
```
|
|
203
63
|
|
|
204
|
-
|
|
205
|
-
```javascript
|
|
206
|
-
// CRITICAL - payment error hidden!
|
|
207
|
-
try {
|
|
208
|
-
await chargeCard(amount);
|
|
209
|
-
} catch (e) {
|
|
210
|
-
console.error(e); // Logs but continues to "success" response!
|
|
211
|
-
}
|
|
212
|
-
res.json({ success: true }); // Customer charged $0!
|
|
213
|
-
|
|
214
|
-
// CRITICAL - authentication bypass
|
|
215
|
-
try {
|
|
216
|
-
const user = await authenticate(token);
|
|
217
|
-
} catch {
|
|
218
|
-
// Silent! Attacker can proceed unauthenticated
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// CRITICAL - data corruption
|
|
222
|
-
const data = parseData() || []; // Parse error becomes empty array!
|
|
64
|
+
### Agent 4: INFRA - Infrastructure
|
|
223
65
|
```
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
**Strategy**: Build mental call graph, find orphans
|
|
228
|
-
|
|
229
|
-
```bash
|
|
230
|
-
# Find all exports
|
|
231
|
-
grep -r "export " --include="*.ts" --include="*.js" src/ | cut -d: -f1 | sort -u
|
|
232
|
-
|
|
233
|
-
# For suspicious files, verify they're imported
|
|
234
|
-
grep -r "import.*from.*filename" --include="*.ts" --include="*.js" src/
|
|
66
|
+
Scan for: Docker issues, K8s misconfig, CI/CD secrets, cloud misconfig.
|
|
67
|
+
Write to .coverme/agents/INFRA.json
|
|
68
|
+
Return ONLY: "done" or "skipped"
|
|
235
69
|
```
|
|
236
70
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
- Code behind `if (false)` or `if (0)`
|
|
244
|
-
- Feature flags always false
|
|
71
|
+
### Agent 5: DATA - Data & Privacy
|
|
72
|
+
```
|
|
73
|
+
Scan for: PII exposure, GDPR issues, unencrypted data.
|
|
74
|
+
Write to .coverme/agents/DATA.json
|
|
75
|
+
Return ONLY: "done" or "skipped"
|
|
76
|
+
```
|
|
245
77
|
|
|
246
|
-
|
|
78
|
+
### Agent 5b: SECRETS - Smart Credentials Analysis
|
|
79
|
+
```
|
|
80
|
+
Scan for credentials/secrets WITH CONTEXT ANALYSIS:
|
|
81
|
+
|
|
82
|
+
1. **Find all potential secrets**: API keys, tokens, passwords, connection strings
|
|
83
|
+
|
|
84
|
+
2. **For EACH secret found, analyze context**:
|
|
85
|
+
- Is it in .env file? Check if .env is in .gitignore
|
|
86
|
+
- Is it a sandbox/test/playground key? (look for prefixes: sk_test_, sandbox_, demo_, etc.)
|
|
87
|
+
- Is the domain a test domain? (localhost, *.test, staging.*, sandbox.*)
|
|
88
|
+
- Is there a .env.example suggesting this is dev setup?
|
|
89
|
+
- Is the secret expired? (look for expiry dates, old timestamps)
|
|
90
|
+
- Is it in a test file?
|
|
91
|
+
|
|
92
|
+
3. **Rate severity based on context**:
|
|
93
|
+
- CRITICAL: Production secret in code, not in .env, not gitignored
|
|
94
|
+
- HIGH: Real credentials but only in .env (still bad if committed)
|
|
95
|
+
- MEDIUM: Sandbox/test credentials (may still expire and break things)
|
|
96
|
+
- LOW: Demo/example credentials clearly marked as such
|
|
97
|
+
- INFO: Placeholder values like "your-api-key-here"
|
|
98
|
+
|
|
99
|
+
4. **Smart recommendations**:
|
|
100
|
+
- If sandbox key: "Sandbox key detected. Consider rotating if published to repo. Current risk: LOW"
|
|
101
|
+
- If .env is gitignored: "Secret properly isolated in .env. Verify .env is not committed to git history"
|
|
102
|
+
- If expired: "Key may be expired (created > 1 year ago). Test and rotate"
|
|
103
|
+
|
|
104
|
+
Write to .coverme/agents/SECRETS.json with:
|
|
105
|
+
[{"id":"SECRETS-001","title":"AWS credentials in .env","severity":"medium","file":".env","line":5,"context":{"inGitignore":true,"isPlayground":true,"hasEnvExample":true},"recommendation":"Sandbox credentials properly isolated. Consider rotation schedule."}]
|
|
106
|
+
|
|
107
|
+
Return ONLY: "done" or "skipped"
|
|
108
|
+
```
|
|
247
109
|
|
|
248
|
-
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
110
|
+
### Agent 6: AI - AI/LLM Security
|
|
111
|
+
```
|
|
112
|
+
FIRST: Check if AI code exists (openai, anthropic, langchain, etc.)
|
|
113
|
+
If no AI code: Write {"skipped":true} and return "skipped"
|
|
114
|
+
If AI code: Scan for prompt injection, data leakage, output validation.
|
|
115
|
+
Write to .coverme/agents/AI.json
|
|
116
|
+
Return ONLY: "done" or "skipped"
|
|
117
|
+
```
|
|
254
118
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
119
|
+
### Agent 7: PERF - Performance & DoS
|
|
120
|
+
```
|
|
121
|
+
Scan for: ReDoS, N+1 queries, memory leaks, unbounded operations.
|
|
122
|
+
Write to .coverme/agents/PERF.json
|
|
123
|
+
Return ONLY: "done" or "skipped"
|
|
258
124
|
```
|
|
259
125
|
|
|
260
|
-
|
|
126
|
+
### Agent 8: BIZ - Business Logic
|
|
127
|
+
```
|
|
128
|
+
Scan for: Race conditions, TOCTOU, workflow bypass, financial issues.
|
|
129
|
+
Write to .coverme/agents/BIZ.json
|
|
130
|
+
Return ONLY: "done" or "skipped"
|
|
131
|
+
```
|
|
261
132
|
|
|
262
|
-
###
|
|
133
|
+
### Agent 9: QUAL - Code Quality
|
|
134
|
+
```
|
|
135
|
+
Scan for: High complexity, dead code, anti-patterns.
|
|
136
|
+
Write to .coverme/agents/QUAL.json
|
|
137
|
+
Return ONLY: "done" or "skipped"
|
|
138
|
+
```
|
|
263
139
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
140
|
+
### Agent 9b: SILENT - Silent Failures (CRITICAL)
|
|
141
|
+
```
|
|
142
|
+
Scan SPECIFICALLY for silent error handling patterns:
|
|
143
|
+
|
|
144
|
+
1. **Empty catch blocks**: catch(e) {} or catch { }
|
|
145
|
+
2. **Swallowed errors**: catch(e) { console.log(e) } without rethrow
|
|
146
|
+
3. **Silent fallbacks**: catch(e) { return null } or catch => defaultValue
|
|
147
|
+
4. **Optional chaining abuse**: data?.field?.value without fallback handling
|
|
148
|
+
5. **Nullish coalescing hiding errors**: value ?? {} or value || []
|
|
149
|
+
6. **Promise swallowing**: .catch(() => {}) or .catch(() => null)
|
|
150
|
+
7. **Try without meaningful catch**: try { ... } catch { /* ignore */ }
|
|
151
|
+
8. **Default returns in catch**: catch(e) { return [] } hiding failures
|
|
152
|
+
9. **Logging without action**: catch(e) { logger.error(e); return default }
|
|
153
|
+
10. **Conditional silent fails**: if (!result) return; without error
|
|
154
|
+
|
|
155
|
+
For EACH finding, rate severity:
|
|
156
|
+
- CRITICAL: Payment/auth/security code with silent failure
|
|
157
|
+
- HIGH: Data operations that silently return empty/default
|
|
158
|
+
- MEDIUM: API calls that swallow errors
|
|
159
|
+
- LOW: Non-critical utility functions
|
|
160
|
+
|
|
161
|
+
Write to .coverme/agents/SILENT.json with format:
|
|
162
|
+
[{"id":"SILENT-001","title":"Silent failure in payment processing","severity":"critical","file":"src/payments/charge.ts","line":45,"code":"catch(e) { return { success: false } }","impact":"Payment failures go undetected","recommendation":"Throw PaymentError and alert on-call"}]
|
|
163
|
+
|
|
164
|
+
Return ONLY: "done" or "skipped"
|
|
165
|
+
```
|
|
268
166
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
- Circular dependencies
|
|
276
|
-
```bash
|
|
277
|
-
# Find potential circular deps
|
|
278
|
-
find src/ -name "*.ts" -exec sh -c 'echo "=== {} ===" && grep -o "from ['\''\"]\.[^'\''\"]*" {}' \;
|
|
279
|
-
```
|
|
280
|
-
- Missing dependency injection
|
|
281
|
-
- God modules (doing everything)
|
|
282
|
-
|
|
283
|
-
#### 3.3 Scalability Concerns
|
|
284
|
-
- State stored in memory (not horizontally scalable)
|
|
285
|
-
- Missing queue for long-running tasks
|
|
286
|
-
- No caching strategy
|
|
287
|
-
- Synchronous operations that should be async
|
|
288
|
-
|
|
289
|
-
### 4. PERFORMANCE ISSUES
|
|
290
|
-
|
|
291
|
-
#### 4.1 Database Performance
|
|
292
|
-
- **N+1 Queries** - THE MOST COMMON ISSUE!
|
|
293
|
-
```javascript
|
|
294
|
-
// BAD: N+1
|
|
295
|
-
const users = await User.findAll();
|
|
296
|
-
for (const user of users) {
|
|
297
|
-
user.posts = await Post.find({ userId: user.id }); // N queries!
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
// GOOD: Single query
|
|
301
|
-
const users = await User.findAll({ include: [Post] });
|
|
302
|
-
```
|
|
303
|
-
- Unbounded queries (no LIMIT)
|
|
304
|
-
- Missing pagination
|
|
305
|
-
- SELECT * instead of specific columns
|
|
306
|
-
- Missing indexes
|
|
307
|
-
|
|
308
|
-
#### 4.2 Memory Issues
|
|
309
|
-
- Loading entire files into memory
|
|
310
|
-
- Unbounded array growth
|
|
311
|
-
- Missing streaming for large data
|
|
312
|
-
- Memory leaks (unclosed connections, event listeners)
|
|
313
|
-
|
|
314
|
-
#### 4.3 Blocking Operations
|
|
315
|
-
- fs.readFileSync in production
|
|
316
|
-
- Synchronous crypto operations
|
|
317
|
-
- CPU-intensive work on main thread
|
|
318
|
-
- Large JSON.parse
|
|
319
|
-
|
|
320
|
-
#### 4.4 Network Inefficiencies
|
|
321
|
-
- Sequential API calls that could be parallel
|
|
322
|
-
```javascript
|
|
323
|
-
// BAD: Sequential
|
|
324
|
-
const user = await fetchUser();
|
|
325
|
-
const posts = await fetchPosts(); // Could be parallel!
|
|
326
|
-
|
|
327
|
-
// GOOD: Parallel
|
|
328
|
-
const [user, posts] = await Promise.all([fetchUser(), fetchPosts()]);
|
|
329
|
-
```
|
|
330
|
-
- Missing compression
|
|
331
|
-
- No connection reuse
|
|
167
|
+
### Agent 10: TEST - Testing
|
|
168
|
+
```
|
|
169
|
+
Scan for: Missing tests on critical paths, mocked security, no E2E.
|
|
170
|
+
Write to .coverme/agents/TEST.json
|
|
171
|
+
Return ONLY: "done" or "skipped"
|
|
172
|
+
```
|
|
332
173
|
|
|
333
|
-
|
|
174
|
+
### Agent 11: REDIS - Cache Security
|
|
175
|
+
```
|
|
176
|
+
FIRST: Check if Redis/cache code exists.
|
|
177
|
+
If not: Write {"skipped":true} and return "skipped"
|
|
178
|
+
If yes: Scan for dangerous commands, auth issues, race conditions.
|
|
179
|
+
Write to .coverme/agents/REDIS.json
|
|
180
|
+
Return ONLY: "done" or "skipped"
|
|
181
|
+
```
|
|
334
182
|
|
|
335
|
-
|
|
183
|
+
### Agent 12: RESIL - Resilience
|
|
184
|
+
```
|
|
185
|
+
Scan for: Missing circuit breakers, no timeouts, no retries.
|
|
186
|
+
NOTE: For silent fallbacks, see Agent 9b (SILENT) which handles those specifically.
|
|
187
|
+
Write to .coverme/agents/RESIL.json
|
|
188
|
+
Return ONLY: "done" or "skipped"
|
|
189
|
+
```
|
|
336
190
|
|
|
337
|
-
|
|
191
|
+
### Agent 13: PII - PII Scanner
|
|
192
|
+
```
|
|
193
|
+
Scan for: PII in logs, PII in URLs, unencrypted PII, missing GDPR controls.
|
|
194
|
+
Write to .coverme/agents/PII.json
|
|
195
|
+
Return ONLY: "done" or "skipped"
|
|
196
|
+
```
|
|
338
197
|
|
|
339
|
-
###
|
|
198
|
+
### Agent 14: DEAD - Dead Code
|
|
199
|
+
```
|
|
200
|
+
Scan for: Unused functions, unused deps, commented code, TODO/FIXME.
|
|
201
|
+
Write to .coverme/agents/DEAD.json
|
|
202
|
+
Return ONLY: "done" or "skipped"
|
|
203
|
+
```
|
|
340
204
|
|
|
341
|
-
|
|
205
|
+
### Agent 15: DB - Database Security
|
|
206
|
+
```
|
|
207
|
+
Scan for: SQL injection, NoSQL injection, missing RLS, exposed connections.
|
|
208
|
+
Write to .coverme/agents/DB.json
|
|
209
|
+
Return ONLY: "done" or "skipped"
|
|
210
|
+
```
|
|
342
211
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
- testing instructions (manual + automated)
|
|
350
|
-
- detection methods (commands + indicators)
|
|
351
|
-
- estimatedEffort (human vs claudeCode with ROI)
|
|
212
|
+
### Agent 16: ARCH - Architecture
|
|
213
|
+
```
|
|
214
|
+
Scan for: Internal endpoints exposed, missing mTLS, network issues.
|
|
215
|
+
Write to .coverme/agents/ARCH.json
|
|
216
|
+
Return ONLY: "done" or "skipped"
|
|
217
|
+
```
|
|
352
218
|
|
|
353
|
-
|
|
219
|
+
### Agent 17: DESIGN - Design Decisions
|
|
220
|
+
```
|
|
221
|
+
Find documented design decisions that might look like bugs (intentional patterns).
|
|
222
|
+
Write to .coverme/agents/DESIGN.json
|
|
223
|
+
Return ONLY: "done" or "skipped"
|
|
224
|
+
```
|
|
354
225
|
|
|
355
|
-
###
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
226
|
+
### Agent 18: CTX - Context Validator
|
|
227
|
+
```
|
|
228
|
+
For critical findings from other agents, check deployment context.
|
|
229
|
+
Write to .coverme/agents/CTX.json
|
|
230
|
+
Return ONLY: "done" or "skipped"
|
|
231
|
+
```
|
|
360
232
|
|
|
361
|
-
###
|
|
233
|
+
### Agent 19: ENC - Enclave Security
|
|
234
|
+
```
|
|
235
|
+
FIRST: Check if enclave/TEE code exists.
|
|
236
|
+
If not: Write {"skipped":true} and return "skipped"
|
|
237
|
+
If yes: Scan for attestation issues.
|
|
238
|
+
Write to .coverme/agents/ENC.json
|
|
239
|
+
Return ONLY: "done" or "skipped"
|
|
240
|
+
```
|
|
362
241
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
"linesOfCode": 62501,
|
|
369
|
-
"agentCount": 1,
|
|
370
|
-
"scanDuration": "8m 30s",
|
|
371
|
-
|
|
372
|
-
"projectTree": "project/\n├── src/\n│ ├── routes/\n│ ├── services/\n│ └── middleware/\n├── tests/\n└── package.json",
|
|
373
|
-
|
|
374
|
-
"projectOverview": {
|
|
375
|
-
"name": "Project Name",
|
|
376
|
-
"type": "Backend API | Full Stack App | Microservices",
|
|
377
|
-
"stack": ["Node.js 18", "TypeScript", "PostgreSQL", "Redis"],
|
|
378
|
-
"purpose": "What this project does in 1-2 sentences",
|
|
379
|
-
"architecture": "Monolith | Microservices | Serverless | Layered",
|
|
380
|
-
"keyComponents": ["src/routes/", "src/services/", "src/middleware/"]
|
|
381
|
-
},
|
|
382
|
-
|
|
383
|
-
"executiveSummary": {
|
|
384
|
-
"headline": "X Critical + Y High security findings, Z quality issues",
|
|
385
|
-
"riskLevel": "CRITICAL | HIGH | MEDIUM | LOW",
|
|
386
|
-
"overview": "Professional 2-3 sentence summary. Describe architecture → security posture → main concerns.",
|
|
387
|
-
"topRisks": [
|
|
388
|
-
"SQL injection in user search (src/routes/users.ts:45) - full database access",
|
|
389
|
-
"Hardcoded AWS keys in git history (commit abc123) - account compromise",
|
|
390
|
-
"Silent payment errors (src/services/payment.ts:89) - financial loss"
|
|
391
|
-
],
|
|
392
|
-
"positives": [
|
|
393
|
-
"Post-quantum cryptography implemented (ML-KEM-768)",
|
|
394
|
-
"Proper password hashing with bcrypt cost 12",
|
|
395
|
-
"Comprehensive input validation on all API endpoints"
|
|
396
|
-
],
|
|
397
|
-
"recommendedActions": [
|
|
398
|
-
{
|
|
399
|
-
"priority": 1,
|
|
400
|
-
"action": "Rotate AWS keys exposed in git history, move to Secrets Manager",
|
|
401
|
-
"owner": "devops",
|
|
402
|
-
"effort": "1-2 hours"
|
|
403
|
-
},
|
|
404
|
-
{
|
|
405
|
-
"priority": 2,
|
|
406
|
-
"action": "Fix SQL injection by using parameterized queries",
|
|
407
|
-
"owner": "developer",
|
|
408
|
-
"effort": "2-3 hours"
|
|
409
|
-
}
|
|
410
|
-
]
|
|
411
|
-
},
|
|
412
|
-
|
|
413
|
-
"architectureOverview": {
|
|
414
|
-
"components": [
|
|
415
|
-
{
|
|
416
|
-
"name": "Frontend (Next.js)",
|
|
417
|
-
"type": "client",
|
|
418
|
-
"description": "React application with client-side encryption",
|
|
419
|
-
"files": ["frontend/app/", "frontend/components/"],
|
|
420
|
-
"trustLevel": "untrusted"
|
|
421
|
-
},
|
|
422
|
-
{
|
|
423
|
-
"name": "API Gateway (Express)",
|
|
424
|
-
"type": "service",
|
|
425
|
-
"description": "Authentication, rate limiting, payload routing",
|
|
426
|
-
"files": ["backend/src/routes/", "backend/src/middleware/"],
|
|
427
|
-
"trustLevel": "semi-trusted"
|
|
428
|
-
},
|
|
429
|
-
{
|
|
430
|
-
"name": "Database (PostgreSQL)",
|
|
431
|
-
"type": "database",
|
|
432
|
-
"description": "User data, sessions, application state",
|
|
433
|
-
"files": ["backend/src/models/"],
|
|
434
|
-
"trustLevel": "trusted"
|
|
435
|
-
}
|
|
436
|
-
],
|
|
437
|
-
"trustBoundaries": [
|
|
438
|
-
{
|
|
439
|
-
"name": "TB1: Internet → Frontend",
|
|
440
|
-
"from": "Internet (Attackers)",
|
|
441
|
-
"to": "Browser Application",
|
|
442
|
-
"protocol": "HTTPS",
|
|
443
|
-
"description": "Untrusted user input enters system",
|
|
444
|
-
"type": "external"
|
|
445
|
-
},
|
|
446
|
-
{
|
|
447
|
-
"name": "TB2: Frontend → API Gateway",
|
|
448
|
-
"from": "Browser",
|
|
449
|
-
"to": "Backend API",
|
|
450
|
-
"protocol": "HTTPS + JWT",
|
|
451
|
-
"description": "Authentication boundary - JWT validation required",
|
|
452
|
-
"type": "external"
|
|
453
|
-
},
|
|
454
|
-
{
|
|
455
|
-
"name": "TB3: API Gateway → Services",
|
|
456
|
-
"from": "API Gateway",
|
|
457
|
-
"to": "Business Logic",
|
|
458
|
-
"description": "Trusted internal boundary - service layer",
|
|
459
|
-
"type": "internal"
|
|
460
|
-
}
|
|
461
|
-
],
|
|
462
|
-
"criticalAssets": [
|
|
463
|
-
{
|
|
464
|
-
"name": "User Passwords",
|
|
465
|
-
"type": "credential",
|
|
466
|
-
"storage": "Database (bcrypt hashed)",
|
|
467
|
-
"description": "User authentication credentials - never stored plaintext",
|
|
468
|
-
"protection": "bcrypt cost 12"
|
|
469
|
-
},
|
|
470
|
-
{
|
|
471
|
-
"name": "JWT Signing Secret",
|
|
472
|
-
"type": "key",
|
|
473
|
-
"storage": "Environment variable JWT_SECRET",
|
|
474
|
-
"description": "Used to sign authentication tokens",
|
|
475
|
-
"protection": "Environment variable, rotated monthly"
|
|
476
|
-
},
|
|
477
|
-
{
|
|
478
|
-
"name": "Database Connection String",
|
|
479
|
-
"type": "credential",
|
|
480
|
-
"storage": "Environment variable DATABASE_URL",
|
|
481
|
-
"description": "PostgreSQL connection with admin privileges",
|
|
482
|
-
"protection": "Environment variable, encrypted at rest"
|
|
483
|
-
},
|
|
484
|
-
{
|
|
485
|
-
"name": "API Keys (Stripe, AWS)",
|
|
486
|
-
"type": "credential",
|
|
487
|
-
"storage": "Secrets Manager / .env",
|
|
488
|
-
"description": "Third-party service authentication",
|
|
489
|
-
"protection": "AWS Secrets Manager or gitignored .env"
|
|
490
|
-
}
|
|
491
|
-
],
|
|
492
|
-
"entryPoints": [
|
|
493
|
-
{
|
|
494
|
-
"path": "POST /api/auth/login",
|
|
495
|
-
"authentication": "none",
|
|
496
|
-
"description": "User authentication endpoint - rate limited",
|
|
497
|
-
"riskLevel": "high"
|
|
498
|
-
},
|
|
499
|
-
{
|
|
500
|
-
"path": "GET /api/users/:id",
|
|
501
|
-
"authentication": "JWT required",
|
|
502
|
-
"description": "User profile data - authorization check required",
|
|
503
|
-
"riskLevel": "medium"
|
|
504
|
-
},
|
|
505
|
-
{
|
|
506
|
-
"path": "POST /api/payments",
|
|
507
|
-
"authentication": "JWT required",
|
|
508
|
-
"description": "Payment processing - high value target",
|
|
509
|
-
"riskLevel": "critical"
|
|
510
|
-
}
|
|
511
|
-
],
|
|
512
|
-
"dataFlows": [
|
|
513
|
-
"Browser → HTTPS → API Gateway → JWT Validation → Service Layer → Repository → Database",
|
|
514
|
-
"Browser → File Upload → API Gateway → Virus Scan → S3 Bucket",
|
|
515
|
-
"API Gateway → External API (Stripe) → Payment Processing"
|
|
516
|
-
]
|
|
517
|
-
},
|
|
518
|
-
|
|
519
|
-
"findings": [
|
|
520
|
-
{
|
|
521
|
-
"id": "SEC-001",
|
|
522
|
-
"title": "SQL Injection in User Search Endpoint",
|
|
523
|
-
"severity": "critical",
|
|
524
|
-
"category": "security",
|
|
525
|
-
"file": "src/routes/users.ts",
|
|
526
|
-
"line": 45,
|
|
527
|
-
"endLine": 52,
|
|
528
|
-
"code": "const query = `SELECT * FROM users WHERE name = '${req.query.name}'`;",
|
|
529
|
-
"description": "User input from req.query.name is directly concatenated into SQL query without sanitization. An attacker can inject arbitrary SQL commands.",
|
|
530
|
-
|
|
531
|
-
"impact": "Complete database compromise. Attacker can:\n1. Extract all user data including passwords\n2. Modify or delete records\n3. Execute administrative operations\n4. Potential remote code execution via database extensions",
|
|
532
|
-
|
|
533
|
-
"businessImpact": {
|
|
534
|
-
"financial": "GDPR fine: €20M or 4% of revenue. Average data breach cost: $4.35M (IBM 2023)",
|
|
535
|
-
"reputation": "Customer trust loss: 6-12 months recovery. 65% customers leave after breach (PwC)",
|
|
536
|
-
"legal": "Class action lawsuit risk. SEC investigation if publicly traded",
|
|
537
|
-
"operational": "2-4 weeks incident response, forensics, customer notifications"
|
|
538
|
-
},
|
|
539
|
-
|
|
540
|
-
"realWorldExamples": [
|
|
541
|
-
"Equifax (2017): SQL injection → 147M records stolen → $700M settlement",
|
|
542
|
-
"TalkTalk (2015): SQL injection → 157K customers exposed → £400K fine",
|
|
543
|
-
"Your industry: 23% of companies experienced SQL injection in 2023 (Verizon DBIR)"
|
|
544
|
-
],
|
|
545
|
-
|
|
546
|
-
"attackChain": [
|
|
547
|
-
{"step": 1, "action": "Send: GET /api/users?name=' OR '1'='1' --", "result": "Returns all users (authentication bypass)"},
|
|
548
|
-
{"step": 2, "action": "Send: name=' UNION SELECT password,email FROM admins--", "result": "Extract admin credentials"},
|
|
549
|
-
{"step": 3, "action": "Send: name='; DROP TABLE users; --", "result": "Data destruction (if permissions allow)"},
|
|
550
|
-
{"step": 4, "action": "Send: name=' INTO OUTFILE '/var/www/shell.php'--", "result": "Remote code execution"}
|
|
551
|
-
],
|
|
552
|
-
|
|
553
|
-
"proofOfConcept": "# Test this vulnerability:\ncurl 'https://api.example.com/users?name=%27%20OR%20%271%27%3D%271' \\\n -H 'Authorization: Bearer $TOKEN'\n\n# Expected (vulnerable): Returns all users\n# Expected (fixed): Returns 400 Bad Request",
|
|
554
|
-
|
|
555
|
-
"recommendation": "Use parameterized queries:\n\n```typescript\n// ✅ SECURE - Parameterized query\nconst query = 'SELECT * FROM users WHERE name = $1';\nconst result = await db.query(query, [req.query.name]);\n```",
|
|
556
|
-
|
|
557
|
-
"quickFix": {
|
|
558
|
-
"description": "Add input validation (1 hour)",
|
|
559
|
-
"code": "// Quick temporary fix\nconst safeName = req.query.name.replace(/[^a-zA-Z0-9 ]/g, '');\nconst query = `SELECT * FROM users WHERE name = '${safeName}'`;",
|
|
560
|
-
"limitations": "Not foolproof - still vulnerable to advanced attacks"
|
|
561
|
-
},
|
|
562
|
-
|
|
563
|
-
"properFix": {
|
|
564
|
-
"description": "Switch to parameterized queries + add WAF (1 day)",
|
|
565
|
-
"code": "// Proper fix\nconst query = 'SELECT * FROM users WHERE name = $1';\nconst result = await db.query(query, [req.query.name]);",
|
|
566
|
-
"additionalSteps": [
|
|
567
|
-
"Add input validation middleware (Joi/Zod schema)",
|
|
568
|
-
"Enable SQL injection protection in WAF (Cloudflare/AWS WAF)",
|
|
569
|
-
"Add query logging for security monitoring",
|
|
570
|
-
"Run database user with minimal privileges (not root)"
|
|
571
|
-
]
|
|
572
|
-
},
|
|
573
|
-
|
|
574
|
-
"testing": {
|
|
575
|
-
"description": "How to verify the fix works",
|
|
576
|
-
"manual": [
|
|
577
|
-
"Test: curl 'https://api.example.com/users?name=%27%20OR%20%271%27%3D%271'",
|
|
578
|
-
"Expected: 400 Bad Request with error message",
|
|
579
|
-
"Test: curl 'https://api.example.com/users?name=John'",
|
|
580
|
-
"Expected: Returns user 'John' only"
|
|
581
|
-
],
|
|
582
|
-
"automated": "# Add security test\ntest('should reject SQL injection attempts', async () => {\n const response = await request(app)\n .get('/api/users?name=\\' OR \\'1\\'=\\'1')\n .expect(400);\n expect(response.body.error).toContain('Invalid input');\n});"
|
|
583
|
-
},
|
|
584
|
-
|
|
585
|
-
"detection": {
|
|
586
|
-
"description": "How to check if already exploited",
|
|
587
|
-
"commands": [
|
|
588
|
-
"# Check access logs for SQL injection patterns",
|
|
589
|
-
"grep -E \"(UNION|SELECT|INSERT|DROP|--|;)\" /var/log/nginx/access.log",
|
|
590
|
-
"# Check database audit logs",
|
|
591
|
-
"SELECT * FROM pg_stat_statements WHERE query LIKE '%UNION%' OR query LIKE '%--';"
|
|
592
|
-
],
|
|
593
|
-
"indicators": [
|
|
594
|
-
"Unusual SQL errors in application logs",
|
|
595
|
-
"Multiple failed queries from same IP",
|
|
596
|
-
"Database queries with suspicious patterns (UNION, --, ;)",
|
|
597
|
-
"Unexpected spike in database CPU usage"
|
|
598
|
-
]
|
|
599
|
-
},
|
|
600
|
-
|
|
601
|
-
"dread": {
|
|
602
|
-
"damage": 10,
|
|
603
|
-
"reproducibility": 10,
|
|
604
|
-
"exploitability": 9,
|
|
605
|
-
"affectedUsers": 10,
|
|
606
|
-
"discoverability": 8,
|
|
607
|
-
"score": 9.4
|
|
608
|
-
},
|
|
609
|
-
|
|
610
|
-
"cwe": "CWE-89",
|
|
611
|
-
"owasp": "A03:2021-Injection",
|
|
612
|
-
"cvss": "9.8 (Critical)",
|
|
613
|
-
|
|
614
|
-
"references": [
|
|
615
|
-
"https://owasp.org/www-community/attacks/SQL_Injection",
|
|
616
|
-
"https://cwe.mitre.org/data/definitions/89.html",
|
|
617
|
-
"https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html"
|
|
618
|
-
],
|
|
619
|
-
|
|
620
|
-
"evidence": [
|
|
621
|
-
"Input source: req.query.name (line 44) - no validation",
|
|
622
|
-
"Sink: db.query() (line 45) - string concatenation",
|
|
623
|
-
"No sanitization between source and sink",
|
|
624
|
-
"Endpoint is publicly accessible",
|
|
625
|
-
"Database user has full privileges (checked schema)"
|
|
626
|
-
],
|
|
627
|
-
|
|
628
|
-
"fixOwner": "developer",
|
|
629
|
-
"estimatedEffort": {
|
|
630
|
-
"human": "4-6 hours (research parameterized queries, update all SQL calls, write tests, deploy)",
|
|
631
|
-
"claudeCode": "15-20 minutes (finds all SQL concatenations, generates parameterized versions, writes tests)",
|
|
632
|
-
"roi": "18x faster with Claude Code"
|
|
633
|
-
},
|
|
634
|
-
"priority": 1
|
|
635
|
-
},
|
|
636
|
-
{
|
|
637
|
-
"id": "QUAL-001",
|
|
638
|
-
"title": "Silent Payment Error Handling - Financial Loss Risk",
|
|
639
|
-
"severity": "critical",
|
|
640
|
-
"category": "quality",
|
|
641
|
-
"file": "src/services/paymentService.ts",
|
|
642
|
-
"line": 89,
|
|
643
|
-
"endLine": 95,
|
|
644
|
-
"code": "try {\n await stripe.charges.create(charge);\n} catch (err) {\n console.error('Payment error:', err);\n}\nreturn { success: true };",
|
|
645
|
-
|
|
646
|
-
"description": "Payment errors are caught and logged but execution continues. The function returns success:true even when payment fails. Customer receives product without paying. This is a SILENT FAILURE - the most dangerous type of bug.",
|
|
647
|
-
|
|
648
|
-
"impact": "Direct financial loss. Orders are fulfilled without payment. Customer sees 'success' and receives product/service for $0.",
|
|
649
|
-
|
|
650
|
-
"businessImpact": {
|
|
651
|
-
"financial": "Stripe reports 3% payment failure rate. At 1000 orders/month × $50 avg = $1,500/month revenue loss = $18K/year",
|
|
652
|
-
"reputation": "Accounting discovers revenue discrepancy → loss of investor confidence",
|
|
653
|
-
"legal": "Incorrect financial reporting → potential audit/compliance issues",
|
|
654
|
-
"operational": "Manual reconciliation required to find unpaid orders"
|
|
655
|
-
},
|
|
656
|
-
|
|
657
|
-
"realWorldExamples": [
|
|
658
|
-
"Knight Capital (2012): Silent error handling → $440M loss in 45 minutes",
|
|
659
|
-
"Your scenario: Payment fails, user gets premium subscription free. Stripe dispute shows no payment.",
|
|
660
|
-
"Common pattern: 30% of payment bugs are silent failures (Sentry data 2023)"
|
|
661
|
-
],
|
|
662
|
-
|
|
663
|
-
"attackChain": [
|
|
664
|
-
{"step": 1, "action": "User submits order for $100 product", "result": "Order processing begins"},
|
|
665
|
-
{"step": 2, "action": "Stripe payment fails (network error, card declined, etc)", "result": "Exception thrown, caught silently"},
|
|
666
|
-
{"step": 3, "action": "Code continues, returns {success: true}", "result": "User sees success message"},
|
|
667
|
-
{"step": 4, "action": "Fulfillment system processes 'successful' order", "result": "Product shipped/service activated for $0"}
|
|
668
|
-
],
|
|
669
|
-
|
|
670
|
-
"proofOfConcept": "// Reproduce the bug:\n// 1. Set STRIPE_TEST_MODE=true\n// 2. Use test card 4000000000000341 (card declined)\n// 3. Submit order\n// 4. Observe: Payment fails but order succeeds\n\nawait fetch('/api/orders', {\n method: 'POST',\n body: JSON.stringify({\n cardNumber: '4000000000000341', // Test card that declines\n amount: 100\n })\n});\n// Result: {success: true} even though payment failed",
|
|
671
|
-
|
|
672
|
-
"recommendation": "Rethrow error or return failure:\n\n```typescript\n// ✅ PROPER ERROR HANDLING\ntry {\n const charge = await stripe.charges.create(chargeData);\n await db.orders.update(orderId, { status: 'paid', chargeId: charge.id });\n return { success: true, chargeId: charge.id };\n} catch (err) {\n // Log with context\n logger.error('Payment failed', { \n orderId, \n amount, \n error: err.message,\n userId \n });\n \n // Update order status\n await db.orders.update(orderId, { status: 'payment_failed' });\n \n // Return failure to caller\n throw new PaymentError('Payment processing failed', { cause: err });\n}\n```",
|
|
673
|
-
|
|
674
|
-
"quickFix": {
|
|
675
|
-
"description": "Add return statement in catch (30 minutes)",
|
|
676
|
-
"code": "try {\n await stripe.charges.create(charge);\n} catch (err) {\n console.error('Payment error:', err);\n return { success: false, error: 'Payment failed' }; // FIX: Return failure\n}\nreturn { success: true };",
|
|
677
|
-
"limitations": "Still loses error details, no proper logging, no order status update"
|
|
678
|
-
},
|
|
679
|
-
|
|
680
|
-
"properFix": {
|
|
681
|
-
"description": "Comprehensive error handling with transaction rollback (4 hours)",
|
|
682
|
-
"code": "async function processPayment(orderId, chargeData) {\n const transaction = await db.transaction();\n \n try {\n // 1. Charge the card\n const charge = await stripe.charges.create(chargeData);\n \n // 2. Update order in transaction\n await transaction.orders.update(orderId, { \n status: 'paid',\n chargeId: charge.id,\n paidAt: new Date()\n });\n \n await transaction.commit();\n \n return { success: true, chargeId: charge.id };\n \n } catch (err) {\n // Rollback database changes\n await transaction.rollback();\n \n // Structured logging\n logger.error('Payment failed', {\n orderId,\n userId: chargeData.customer,\n amount: chargeData.amount,\n currency: chargeData.currency,\n errorType: err.type,\n errorMessage: err.message,\n stripeRequestId: err.requestId\n });\n \n // Update order status\n await db.orders.update(orderId, { \n status: 'payment_failed',\n failureReason: err.message \n });\n \n // Throw typed error\n throw new PaymentError('Payment processing failed', { \n cause: err,\n orderId,\n retryable: err.type === 'card_error'\n });\n }\n}",
|
|
683
|
-
"additionalSteps": [
|
|
684
|
-
"Add payment monitoring/alerting (e.g., Sentry, DataDog)",
|
|
685
|
-
"Implement dead letter queue for failed payments",
|
|
686
|
-
"Add manual reconciliation job (daily check: orders vs Stripe charges)",
|
|
687
|
-
"Create customer notification for payment failures"
|
|
688
|
-
]
|
|
689
|
-
},
|
|
690
|
-
|
|
691
|
-
"testing": {
|
|
692
|
-
"description": "Test all error scenarios",
|
|
693
|
-
"manual": [
|
|
694
|
-
"Test 1: Use Stripe test card 4000000000000341 (card declined) → should return error",
|
|
695
|
-
"Test 2: Disable internet → should handle network error",
|
|
696
|
-
"Test 3: Invalid API key → should catch auth error",
|
|
697
|
-
"Test 4: Check database: failed orders should have status='payment_failed'"
|
|
698
|
-
],
|
|
699
|
-
"automated": "describe('Payment error handling', () => {\n it('should fail order when payment declines', async () => {\n // Mock Stripe to throw error\n stripe.charges.create.mockRejectedValue(\n new Error('card_declined')\n );\n \n await expect(\n processPayment(orderId, chargeData)\n ).rejects.toThrow(PaymentError);\n \n // Verify order status updated\n const order = await db.orders.find(orderId);\n expect(order.status).toBe('payment_failed');\n });\n \n it('should not fulfill order on payment failure', async () => {\n stripe.charges.create.mockRejectedValue(new Error());\n \n try {\n await processPayment(orderId, chargeData);\n } catch (err) {\n // Expected\n }\n \n const order = await db.orders.find(orderId);\n expect(order.fulfilledAt).toBeNull();\n });\n});"
|
|
700
|
-
},
|
|
701
|
-
|
|
702
|
-
"detection": {
|
|
703
|
-
"description": "Find orders that were fulfilled without payment",
|
|
704
|
-
"commands": [
|
|
705
|
-
"# Find orders with status='success' but no Stripe charge",
|
|
706
|
-
"SELECT * FROM orders WHERE status = 'completed' AND charge_id IS NULL;",
|
|
707
|
-
"",
|
|
708
|
-
"# Check logs for silent payment errors",
|
|
709
|
-
"grep 'Payment error' /var/log/app.log | grep -v 'PaymentError thrown'",
|
|
710
|
-
"",
|
|
711
|
-
"# Reconciliation: Compare orders vs Stripe charges",
|
|
712
|
-
"node scripts/reconcile-payments.js --date 2026-02-01"
|
|
713
|
-
],
|
|
714
|
-
"indicators": [
|
|
715
|
-
"Orders table: status='completed' but charge_id is NULL",
|
|
716
|
-
"Stripe dashboard: Fewer charges than completed orders",
|
|
717
|
-
"Revenue mismatch: Reported revenue < Stripe deposits",
|
|
718
|
-
"Customer support: Users report being charged $0"
|
|
719
|
-
]
|
|
720
|
-
},
|
|
721
|
-
|
|
722
|
-
"references": [
|
|
723
|
-
"https://stripe.com/docs/error-handling",
|
|
724
|
-
"https://martinfowler.com/articles/replaceThrowWithNotification.html"
|
|
725
|
-
],
|
|
726
|
-
|
|
727
|
-
"evidence": [
|
|
728
|
-
"catch block at line 91 only logs - no rethrow, no return false",
|
|
729
|
-
"No return/throw in catch block",
|
|
730
|
-
"Success returned at line 95 regardless of payment result",
|
|
731
|
-
"No database rollback on payment failure",
|
|
732
|
-
"Checked Stripe webhook logs: confirms payment failures happen but are ignored"
|
|
733
|
-
],
|
|
734
|
-
|
|
735
|
-
"fixOwner": "developer",
|
|
736
|
-
"estimatedEffort": {
|
|
737
|
-
"human": "4-6 hours (identify all error paths, add transaction handling, write error tests, manual reconciliation check)",
|
|
738
|
-
"claudeCode": "25-30 minutes (finds all try-catch blocks, adds proper error handling, generates test cases)",
|
|
739
|
-
"roi": "12x faster with Claude Code"
|
|
740
|
-
},
|
|
741
|
-
"priority": 1
|
|
742
|
-
}
|
|
743
|
-
],
|
|
744
|
-
|
|
745
|
-
"qualityReview": {
|
|
746
|
-
"deleteItems": [
|
|
747
|
-
{
|
|
748
|
-
"file": "src/legacy/oldAuth.ts",
|
|
749
|
-
"lines": 450,
|
|
750
|
-
"description": "Entire file unused - no imports found in codebase"
|
|
751
|
-
}
|
|
752
|
-
],
|
|
753
|
-
"mergeItems": [
|
|
754
|
-
{
|
|
755
|
-
"file": "src/utils/dateFormat.ts + src/helpers/formatDate.ts",
|
|
756
|
-
"description": "Identical date formatting logic in 2 files (180 lines total)"
|
|
757
|
-
}
|
|
758
|
-
],
|
|
759
|
-
"simplifyItems": [
|
|
760
|
-
{
|
|
761
|
-
"file": "src/services/userService.ts",
|
|
762
|
-
"description": "1000+ line function should be split into smaller functions"
|
|
763
|
-
}
|
|
764
|
-
],
|
|
765
|
-
"totalLinesRemovable": 630,
|
|
766
|
-
"percentageOfCodebase": 1.0
|
|
767
|
-
},
|
|
768
|
-
|
|
769
|
-
"positiveObservations": [
|
|
770
|
-
{
|
|
771
|
-
"title": "Proper Password Hashing",
|
|
772
|
-
"description": "Uses bcrypt with cost factor 12 in src/auth/password.ts:23. Passwords are never stored in plaintext."
|
|
773
|
-
},
|
|
774
|
-
{
|
|
775
|
-
"title": "Rate Limiting Implemented",
|
|
776
|
-
"description": "Express-rate-limit configured on all auth endpoints (src/middleware/rateLimit.ts:15) - prevents brute force."
|
|
777
|
-
},
|
|
778
|
-
{
|
|
779
|
-
"title": "Comprehensive Input Validation",
|
|
780
|
-
"description": "Joi schemas defined for all API inputs (src/validators/) - prevents injection attacks."
|
|
781
|
-
}
|
|
782
|
-
],
|
|
783
|
-
|
|
784
|
-
"summary": {
|
|
785
|
-
"critical": 2,
|
|
786
|
-
"high": 5,
|
|
787
|
-
"medium": 8,
|
|
788
|
-
"low": 3,
|
|
789
|
-
"total": 18
|
|
790
|
-
}
|
|
791
|
-
}
|
|
242
|
+
### Agent 20: EXEC - Executive Summary
|
|
243
|
+
```
|
|
244
|
+
After scanning, generate executive summary with top risks and positives.
|
|
245
|
+
Write to .coverme/agents/EXEC.json
|
|
246
|
+
Return ONLY: "done"
|
|
792
247
|
```
|
|
793
248
|
|
|
794
|
-
###
|
|
249
|
+
### Agent 21: DUP - Duplicate Finder
|
|
250
|
+
```
|
|
251
|
+
Find existing solutions in codebase that could fix other findings.
|
|
252
|
+
Write to .coverme/agents/DUP.json
|
|
253
|
+
Return ONLY: "done" or "skipped"
|
|
254
|
+
```
|
|
795
255
|
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
256
|
+
### Agent 22: POSITIVE - Good Patterns
|
|
257
|
+
```
|
|
258
|
+
Find positive security patterns and good practices in the codebase.
|
|
259
|
+
Write to .coverme/agents/POSITIVE.json
|
|
260
|
+
Return ONLY: "done"
|
|
261
|
+
```
|
|
802
262
|
|
|
803
|
-
|
|
804
|
-
- **Reproducibility**: How consistently exploitable
|
|
805
|
-
- **Exploitability**: Skill level needed
|
|
806
|
-
- **Affected Users**: Scope of impact
|
|
807
|
-
- **Discoverability**: How easy to find
|
|
808
|
-
- **Score**: Average of all five
|
|
263
|
+
---
|
|
809
264
|
|
|
810
|
-
|
|
265
|
+
## AI-Generated Code Detection Agents (23-31)
|
|
811
266
|
|
|
812
|
-
|
|
267
|
+
These agents specifically target vulnerabilities common in AI-generated code.
|
|
813
268
|
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
269
|
+
### Agent 23: ASSUME - AI Assumptions (CRITICAL)
|
|
270
|
+
```
|
|
271
|
+
AI code makes dangerous implicit assumptions. Scan for:
|
|
272
|
+
|
|
273
|
+
1. **Non-null assertions**: data!.field, user!.id (TypeScript !)
|
|
274
|
+
2. **Unsafe casts**: as any, as unknown, type assertions without validation
|
|
275
|
+
3. **Unvalidated JSON**: JSON.parse() without try/catch or schema validation
|
|
276
|
+
4. **Trusted input**: req.body used directly without validation (zod, joi, yup)
|
|
277
|
+
5. **Array assumptions**: arr[0] without checking length, arr.map without null check
|
|
278
|
+
6. **Object assumptions**: obj.field without checking obj exists
|
|
279
|
+
7. **Destructuring without defaults**: const {a, b} = data (what if data is null?)
|
|
280
|
+
8. **Assumed authentication**: Routes using req.user without auth middleware
|
|
281
|
+
9. **Assumed types**: parseInt(x) without NaN check, Number(x) used blindly
|
|
282
|
+
10. **Assumed existence**: await db.findOne() used without null check
|
|
283
|
+
|
|
284
|
+
Severity:
|
|
285
|
+
- CRITICAL: Auth/payment code with assumptions
|
|
286
|
+
- HIGH: Data mutation with unchecked input
|
|
287
|
+
- MEDIUM: API responses with assumptions
|
|
288
|
+
- LOW: Internal utility code
|
|
289
|
+
|
|
290
|
+
Write to .coverme/agents/ASSUME.json:
|
|
291
|
+
[{"id":"ASSUME-001","title":"Unvalidated req.body in user update","severity":"high","file":"src/api/users.ts","line":45,"code":"const { email, name } = req.body","assumption":"Input is valid object with email and name","exploit":"Send malformed JSON or missing fields","recommendation":"Add zod schema validation"}]
|
|
292
|
+
|
|
293
|
+
Return ONLY: "done" or "skipped"
|
|
820
294
|
```
|
|
821
295
|
|
|
822
|
-
|
|
296
|
+
### Agent 24: TRUST - Trust Boundary Violations (CRITICAL)
|
|
297
|
+
```
|
|
298
|
+
AI rarely identifies trust boundaries. Scan for:
|
|
299
|
+
|
|
300
|
+
1. **Missing auth middleware**: app.post/get/put/delete without auth check
|
|
301
|
+
2. **Admin routes unprotected**: /admin/*, /internal/* without role check
|
|
302
|
+
3. **Internal service exposure**: Internal APIs accessible from public routes
|
|
303
|
+
4. **Header trust**: Using x-user-id, x-role from headers without verification
|
|
304
|
+
5. **Forwarded input**: User input passed to internal services without sanitization
|
|
305
|
+
6. **Missing role checks**: Actions performed without checking user.role
|
|
306
|
+
7. **Tenant isolation missing**: Multi-tenant data accessed without tenant filter
|
|
307
|
+
8. **Service-to-service trust**: Internal calls without mTLS or API keys
|
|
308
|
+
9. **Webhook endpoints**: /webhook/* without signature verification
|
|
309
|
+
10. **File upload paths**: User-controlled paths without sanitization
|
|
310
|
+
|
|
311
|
+
For each finding, identify:
|
|
312
|
+
- What trust boundary is violated
|
|
313
|
+
- Who can exploit it (anonymous, authenticated, admin)
|
|
314
|
+
- What they can access/do
|
|
315
|
+
|
|
316
|
+
Write to .coverme/agents/TRUST.json:
|
|
317
|
+
[{"id":"TRUST-001","title":"Admin endpoint without role check","severity":"critical","file":"src/routes/admin.ts","line":12,"code":"app.post('/admin/delete-user', async (req,res) => { await deleteUser(req.body.id) })","boundary":"Admin actions accessible to any authenticated user","exploit":"Any logged-in user can delete other users","recommendation":"Add requireRole('admin') middleware"}]
|
|
318
|
+
|
|
319
|
+
Return ONLY: "done" or "skipped"
|
|
320
|
+
```
|
|
823
321
|
|
|
824
|
-
|
|
322
|
+
### Agent 25: PARTIAL - Partial Security Implementation
|
|
323
|
+
```
|
|
324
|
+
AI implements "half security" - looks secure but isn't. Scan for:
|
|
325
|
+
|
|
326
|
+
1. **bcrypt without proper cost**: bcrypt.hash(pwd, 1) or no salt rounds
|
|
327
|
+
2. **JWT without expiration**: jwt.sign() without expiresIn
|
|
328
|
+
3. **JWT without verification**: jwt.decode() instead of jwt.verify()
|
|
329
|
+
4. **Rate limiting without IP**: Rate limit by user but not IP (pre-auth attacks)
|
|
330
|
+
5. **CSRF token generated but not checked**: Token created but middleware missing
|
|
331
|
+
6. **CORS with wildcard**: Access-Control-Allow-Origin: * with credentials
|
|
332
|
+
7. **Helmet without CSP**: Using helmet() but no Content-Security-Policy
|
|
333
|
+
8. **HTTPS redirect missing**: No force-ssl or redirect middleware
|
|
334
|
+
9. **Cookie without flags**: Missing httpOnly, secure, sameSite
|
|
335
|
+
10. **Encryption without IV**: AES without initialization vector
|
|
336
|
+
11. **Password validation weak**: Only length check, no complexity
|
|
337
|
+
12. **Session without rotation**: No session regeneration on auth change
|
|
338
|
+
|
|
339
|
+
Write to .coverme/agents/PARTIAL.json:
|
|
340
|
+
[{"id":"PARTIAL-001","title":"JWT signed but never expires","severity":"high","file":"src/auth/token.ts","line":23,"code":"jwt.sign(payload, secret)","issue":"Token has no expiration","impact":"Stolen tokens valid forever","recommendation":"Add expiresIn: '1h' or similar"}]
|
|
341
|
+
|
|
342
|
+
Return ONLY: "done" or "skipped"
|
|
343
|
+
```
|
|
825
344
|
|
|
826
|
-
###
|
|
345
|
+
### Agent 26: GENERR - Over-Generalized Errors
|
|
346
|
+
```
|
|
347
|
+
AI hides errors behind generic messages. Scan for:
|
|
348
|
+
|
|
349
|
+
1. **Generic catch-all**: catch(e) { return { error: "Something went wrong" } }
|
|
350
|
+
2. **Lost error context**: catch(e) { throw new Error("Failed") } - original e lost
|
|
351
|
+
3. **Boolean error returns**: return false instead of throwing
|
|
352
|
+
4. **Silent status codes**: return res.status(500) without logging
|
|
353
|
+
5. **Error message swallowing**: catch(e) { console.log("error") } - e not logged
|
|
354
|
+
6. **Missing error types**: All errors thrown as generic Error, not typed
|
|
355
|
+
7. **No error codes**: Errors without codes for client handling
|
|
356
|
+
8. **Audit trail gaps**: Security errors not logged differently
|
|
357
|
+
9. **User-facing stack traces**: In dev mode, stack traces leak to client
|
|
358
|
+
10. **Missing error boundaries**: React without ErrorBoundary, no global handler
|
|
359
|
+
|
|
360
|
+
Impact analysis:
|
|
361
|
+
- Security errors hidden = attacks go undetected
|
|
362
|
+
- Missing audit = compliance failure
|
|
363
|
+
- Generic errors = impossible debugging
|
|
364
|
+
|
|
365
|
+
Write to .coverme/agents/GENERR.json:
|
|
366
|
+
[{"id":"GENERR-001","title":"Auth failure returns generic error","severity":"high","file":"src/auth/login.ts","line":34,"code":"catch(e) { return { success: false, error: 'Login failed' } }","issue":"Cannot distinguish wrong password vs account locked vs brute force","recommendation":"Log detailed error server-side, return error code to client"}]
|
|
367
|
+
|
|
368
|
+
Return ONLY: "done" or "skipped"
|
|
369
|
+
```
|
|
827
370
|
|
|
828
|
-
|
|
829
|
-
|
|
371
|
+
### Agent 27: CLONE - Copy-Paste Vulnerabilities
|
|
372
|
+
```
|
|
373
|
+
AI duplicates code blocks, spreading bugs. Scan for:
|
|
374
|
+
|
|
375
|
+
1. **Near-identical functions**: Functions >80% similar in different files
|
|
376
|
+
2. **Duplicated middleware**: Same auth/validation logic repeated
|
|
377
|
+
3. **Copy-pasted API handlers**: Similar CRUD operations with slight changes
|
|
378
|
+
4. **Repeated validation**: Same validation rules in multiple places
|
|
379
|
+
5. **Duplicated error handling**: Same try/catch pattern everywhere
|
|
380
|
+
6. **Config duplication**: Same config values hardcoded in multiple files
|
|
381
|
+
7. **SQL query duplication**: Same queries in different files
|
|
382
|
+
8. **Duplicated security checks**: Same role check logic repeated
|
|
383
|
+
|
|
384
|
+
Why this matters:
|
|
385
|
+
- Fix in one place, bug remains in copies
|
|
386
|
+
- Inconsistent behavior across duplicates
|
|
387
|
+
- Maintenance nightmare
|
|
388
|
+
|
|
389
|
+
Write to .coverme/agents/CLONE.json:
|
|
390
|
+
[{"id":"CLONE-001","title":"Auth check duplicated in 5 files","severity":"medium","files":["src/api/users.ts:12","src/api/orders.ts:8","src/api/products.ts:15"],"pattern":"if (!req.user) return res.status(401)","issue":"Auth logic duplicated, inconsistent in orders.ts","recommendation":"Extract to requireAuth middleware"}]
|
|
391
|
+
|
|
392
|
+
Return ONLY: "done" or "skipped"
|
|
830
393
|
```
|
|
831
394
|
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
395
|
+
### Agent 28: HARDCODE - Hardcoded Logic Vulnerabilities
|
|
396
|
+
```
|
|
397
|
+
AI hardcodes values that should be configurable/validated. Scan for:
|
|
398
|
+
|
|
399
|
+
1. **Role checks with strings**: if (user.role === "admin") - role from where?
|
|
400
|
+
2. **Hardcoded IDs**: if (userId === "123") or specific UUIDs
|
|
401
|
+
3. **Magic numbers**: if (amount > 10000) without named constant
|
|
402
|
+
4. **Hardcoded URLs**: fetch("https://api.example.com") in code
|
|
403
|
+
5. **Hardcoded credentials**: Even in dev, password = "admin123"
|
|
404
|
+
6. **Hardcoded feature flags**: if (process.env.NODE_ENV === "production")
|
|
405
|
+
7. **Hardcoded timeouts**: setTimeout(fn, 5000) without config
|
|
406
|
+
8. **Hardcoded limits**: if (items.length > 100) without constant
|
|
407
|
+
9. **Hardcoded paths**: fs.readFile("/var/app/config.json")
|
|
408
|
+
10. **Hardcoded emails/domains**: admin@company.com in code
|
|
409
|
+
|
|
410
|
+
Security impact:
|
|
411
|
+
- Role checks bypassable if role source is tainted
|
|
412
|
+
- IDs expose internal structure
|
|
413
|
+
- Can't rotate credentials without code change
|
|
414
|
+
|
|
415
|
+
Write to .coverme/agents/HARDCODE.json:
|
|
416
|
+
[{"id":"HARDCODE-001","title":"Admin role check trusts user-provided role","severity":"critical","file":"src/middleware/admin.ts","line":5,"code":"if (req.user.role === 'admin')","issue":"role comes from JWT claims which user might control","recommendation":"Verify role from database, not token"}]
|
|
417
|
+
|
|
418
|
+
Return ONLY: "done" or "skipped"
|
|
419
|
+
```
|
|
837
420
|
|
|
838
|
-
###
|
|
421
|
+
### Agent 29: AISTYLE - AI Code Style Heuristics
|
|
422
|
+
```
|
|
423
|
+
Identify code that shows signs of AI generation, then audit harder. Scan for:
|
|
424
|
+
|
|
425
|
+
DETECTION PATTERNS (AI-generated code often has):
|
|
426
|
+
1. **Excessive comments**: // This function does X, // Check if Y
|
|
427
|
+
2. **Over-engineering**: Simple task with complex abstraction
|
|
428
|
+
3. **Inconsistent style**: Mixed patterns in same file
|
|
429
|
+
4. **TODO/FIXME clusters**: Multiple incomplete items
|
|
430
|
+
5. **Heavy use of any**: TypeScript with lots of any/unknown
|
|
431
|
+
6. **console.log in production**: Debug statements left in
|
|
432
|
+
7. **Default values everywhere**: value ?? defaultValue pattern
|
|
433
|
+
8. **Try-catch wrapping everything**: Even simple operations
|
|
434
|
+
9. **Unused imports/variables**: Dead code not cleaned up
|
|
435
|
+
10. **Generic function names**: handleClick, processData, doSomething
|
|
436
|
+
|
|
437
|
+
For detected AI-style code, perform DEEPER AUDIT:
|
|
438
|
+
- Check all assumptions
|
|
439
|
+
- Verify error handling
|
|
440
|
+
- Look for edge cases
|
|
441
|
+
- Check security controls
|
|
442
|
+
|
|
443
|
+
Write to .coverme/agents/AISTYLE.json:
|
|
444
|
+
[{"id":"AISTYLE-001","title":"AI-generated payment handler needs audit","severity":"high","file":"src/payments/process.ts","indicators":["excessive comments","try-catch everything","multiple TODO"],"concerns":["Error handling hides failures","No idempotency key","Missing amount validation"],"recommendation":"Manual security review required"}]
|
|
445
|
+
|
|
446
|
+
Return ONLY: "done" or "skipped"
|
|
447
|
+
```
|
|
839
448
|
|
|
840
|
-
|
|
841
|
-
|
|
449
|
+
### Agent 30: DEPMIS - Dependency Misuse
|
|
450
|
+
```
|
|
451
|
+
AI imports libraries but uses them incorrectly. Scan for:
|
|
452
|
+
|
|
453
|
+
1. **crypto misuse**: createHash without proper algorithm, no HMAC for auth
|
|
454
|
+
2. **JWT misuse**: jwt.decode() for auth (should be verify), algorithm confusion
|
|
455
|
+
3. **bcrypt misuse**: compareSync in async code, low rounds
|
|
456
|
+
4. **axios misuse**: No timeout, no abort controller, no retry
|
|
457
|
+
5. **fetch misuse**: No error handling for non-2xx, no timeout
|
|
458
|
+
6. **SQL client misuse**: String concatenation instead of parameterized
|
|
459
|
+
7. **Redis misuse**: No auth, KEYS in production, no TTL
|
|
460
|
+
8. **fs misuse**: Sync operations blocking event loop, no path sanitization
|
|
461
|
+
9. **child_process misuse**: exec with user input (command injection)
|
|
462
|
+
10. **path misuse**: path.join with user input without sanitization
|
|
463
|
+
|
|
464
|
+
Write to .coverme/agents/DEPMIS.json:
|
|
465
|
+
[{"id":"DEPMIS-001","title":"JWT decoded but not verified","severity":"critical","file":"src/auth/middleware.ts","line":18,"code":"const user = jwt.decode(token)","issue":"decode() doesn't verify signature, attacker can forge tokens","recommendation":"Use jwt.verify(token, secret) instead"}]
|
|
466
|
+
|
|
467
|
+
Return ONLY: "done" or "skipped"
|
|
842
468
|
```
|
|
843
469
|
|
|
844
|
-
|
|
470
|
+
### Agent 31: LOGICGAP - Logic Gaps (CRITICAL)
|
|
471
|
+
```
|
|
472
|
+
AI creates early returns without proper handling. Scan for:
|
|
473
|
+
|
|
474
|
+
1. **Silent returns**: if (!user) return; - no log, no error, no audit
|
|
475
|
+
2. **Missing else**: if (condition) { action } with no else handling
|
|
476
|
+
3. **Incomplete state machines**: Enum/status with unhandled cases
|
|
477
|
+
4. **Missing default**: switch without default case
|
|
478
|
+
5. **Null returns**: return null without caller handling
|
|
479
|
+
6. **Incomplete cleanup**: Resource opened but not closed on error path
|
|
480
|
+
7. **Transaction gaps**: DB operations without proper rollback
|
|
481
|
+
8. **Missing finally**: try/catch without finally for cleanup
|
|
482
|
+
9. **Event handler gaps**: addEventListener without removeEventListener
|
|
483
|
+
10. **Incomplete validation**: Some fields validated, others not
|
|
484
|
+
|
|
485
|
+
For each gap, analyze:
|
|
486
|
+
- What happens when the gap is hit
|
|
487
|
+
- Can attacker trigger the gap
|
|
488
|
+
- What's the impact
|
|
489
|
+
|
|
490
|
+
Write to .coverme/agents/LOGICGAP.json:
|
|
491
|
+
[{"id":"LOGICGAP-001","title":"Silent return on missing user","severity":"high","file":"src/api/profile.ts","line":23,"code":"if (!user) return","issue":"No logging, no 404 response, client hangs","exploit":"Probe for valid user IDs by timing differences","recommendation":"return res.status(404).json({error: 'Not found'}) and log attempt"}]
|
|
492
|
+
|
|
493
|
+
Return ONLY: "done" or "skipped"
|
|
494
|
+
```
|
|
845
495
|
|
|
846
496
|
---
|
|
847
497
|
|
|
848
|
-
##
|
|
849
|
-
|
|
850
|
-
Before finishing:
|
|
498
|
+
## Phase 2: Wait for Agents
|
|
851
499
|
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
- [ ] Every critical/high finding has attack chain
|
|
855
|
-
- [ ] Searched for silent failures (empty catch, console.log only)
|
|
856
|
-
- [ ] Checked git history for hardcoded secrets
|
|
857
|
-
- [ ] Looked for N+1 queries in database code
|
|
858
|
-
- [ ] Verified dead code claims (really not used?)
|
|
859
|
-
- [ ] Found code duplications (listed ALL locations)
|
|
860
|
-
- [ ] Executive summary is professional and specific
|
|
861
|
-
- [ ] Architecture overview describes trust boundaries
|
|
862
|
-
- [ ] Positive observations have specific evidence
|
|
863
|
-
- [ ] `coverme report` generated HTML successfully
|
|
500
|
+
Wait for ALL background agents using `AgentOutputTool`.
|
|
501
|
+
Each should return only "done" or "skipped".
|
|
864
502
|
|
|
865
503
|
---
|
|
866
504
|
|
|
867
|
-
##
|
|
505
|
+
## Phase 2.5: Adversarial Review (CRITICAL)
|
|
868
506
|
|
|
869
|
-
|
|
507
|
+
After all agents complete, run ONE final agent with this mindset:
|
|
870
508
|
|
|
871
|
-
|
|
509
|
+
### Agent 32: ADVERSARIAL - Systemic Weakness Review
|
|
510
|
+
```
|
|
511
|
+
IMPORTANT: This agent runs AFTER reading all other agent findings.
|
|
512
|
+
|
|
513
|
+
ASSUME: This entire codebase was written by a junior developer
|
|
514
|
+
under deadline pressure using AI autocomplete.
|
|
515
|
+
|
|
516
|
+
Your mission: Find SYSTEMIC weaknesses, not just individual bugs.
|
|
517
|
+
|
|
518
|
+
1. **Pattern Analysis**:
|
|
519
|
+
- What security controls are MISSING across the codebase?
|
|
520
|
+
- What patterns suggest "happy path only" thinking?
|
|
521
|
+
- Where is defensive programming absent?
|
|
522
|
+
|
|
523
|
+
2. **Attack Surface Summary**:
|
|
524
|
+
- List all entry points (APIs, webhooks, file uploads, etc.)
|
|
525
|
+
- Which have weakest protection?
|
|
526
|
+
- What can an attacker do without authentication?
|
|
527
|
+
|
|
528
|
+
3. **Business Logic Abuse**:
|
|
529
|
+
- Can users get free money/credits/access?
|
|
530
|
+
- Can users manipulate pricing/quantities?
|
|
531
|
+
- Can users access other users' data?
|
|
532
|
+
- Can users escalate privileges?
|
|
533
|
+
|
|
534
|
+
4. **Economic Attacks** (AI never thinks about these):
|
|
535
|
+
- Resource exhaustion (create unlimited X)
|
|
536
|
+
- Referral abuse
|
|
537
|
+
- Trial abuse
|
|
538
|
+
- Rate limit bypass for profit
|
|
539
|
+
|
|
540
|
+
5. **Chain Attacks**:
|
|
541
|
+
- Which LOW findings combine into HIGH/CRITICAL?
|
|
542
|
+
- What's the worst-case attack scenario?
|
|
543
|
+
|
|
544
|
+
6. **Missing Controls Checklist**:
|
|
545
|
+
[ ] Input validation on all endpoints
|
|
546
|
+
[ ] Output encoding for all user data
|
|
547
|
+
[ ] Authentication on all non-public routes
|
|
548
|
+
[ ] Authorization checks for all resources
|
|
549
|
+
[ ] Rate limiting on all endpoints
|
|
550
|
+
[ ] Audit logging for security events
|
|
551
|
+
[ ] Error handling that doesn't leak info
|
|
552
|
+
[ ] CSRF protection on state-changing operations
|
|
553
|
+
|
|
554
|
+
Write to .coverme/agents/ADVERSARIAL.json:
|
|
872
555
|
{
|
|
873
|
-
"
|
|
874
|
-
"
|
|
875
|
-
"
|
|
876
|
-
"
|
|
877
|
-
"
|
|
878
|
-
"
|
|
879
|
-
"endLine": 34,
|
|
880
|
-
"code": "jwt.verify(token, secret, { algorithms: ['HS256', 'none'] })",
|
|
881
|
-
|
|
882
|
-
"description": "JWT verification explicitly allows the 'none' algorithm. An attacker can forge tokens by removing the signature and setting alg='none'. This is a COMPLETE authentication bypass.",
|
|
883
|
-
|
|
884
|
-
"impact": "Total authentication bypass. Attacker can:\n1. Impersonate any user (including admins)\n2. Access all protected endpoints\n3. Modify/delete any data\n4. Create backdoor admin accounts",
|
|
885
|
-
|
|
886
|
-
"businessImpact": {
|
|
887
|
-
"financial": "Complete data breach. GDPR fine: €20M or 4% revenue. Average breach cost: $4.35M",
|
|
888
|
-
"reputation": "Loss of customer trust. 81% users abandon service after auth breach (Okta 2023)",
|
|
889
|
-
"legal": "Class action lawsuit risk. Negligence claim - 'none' algorithm is well-known vulnerability",
|
|
890
|
-
"operational": "Full incident response, forensics, password reset for all users, potential service shutdown"
|
|
891
|
-
},
|
|
892
|
-
|
|
893
|
-
"realWorldExamples": [
|
|
894
|
-
"Auth0 CVE-2015-9235: 'none' algorithm allowed → millions of tokens compromised",
|
|
895
|
-
"Pfsense (2018): JWT 'none' bypass → full admin access to firewall configs",
|
|
896
|
-
"Your scenario: Attacker becomes admin, exports entire customer database, posts on dark web"
|
|
897
|
-
],
|
|
898
|
-
|
|
899
|
-
"attackChain": [
|
|
900
|
-
{"step": 1, "action": "Register normal user account, capture JWT from /api/login", "result": "Valid token: eyJhbGc..."},
|
|
901
|
-
{"step": 2, "action": "Base64 decode header, change {\"alg\":\"HS256\"} to {\"alg\":\"none\"}", "result": "Forged header"},
|
|
902
|
-
{"step": 3, "action": "Change payload to {\"userId\":1,\"role\":\"admin\"}, remove signature", "result": "Admin token without signature"},
|
|
903
|
-
{"step": 4, "action": "Send to /api/admin/users with forged token", "result": "Returns all users - authentication bypassed"}
|
|
904
|
-
],
|
|
905
|
-
|
|
906
|
-
"proofOfConcept": "# Exploit the vulnerability:\n\n# 1. Get valid token\nTOKEN=$(curl -X POST https://api.example.com/login \\\n -d '{\"email\":\"attacker@evil.com\",\"password\":\"pass123\"}' | jq -r .token)\n\n# 2. Forge admin token (Python)\npython3 << EOF\nimport base64\nimport json\n\n# Decode original token parts\nheader = {\"alg\": \"none\", \"typ\": \"JWT\"}\npayload = {\"userId\": 1, \"role\": \"admin\", \"exp\": 9999999999}\n\n# Encode without signature\nforged = base64.urlsafe_b64encode(json.dumps(header).encode()).rstrip(b'=') + b'.'\nforged += base64.urlsafe_b64encode(json.dumps(payload).encode()).rstrip(b'=') + b'.'\n\nprint(forged.decode())\nEOF\n\n# 3. Use forged token\ncurl https://api.example.com/admin/users \\\n -H \"Authorization: Bearer eyJhbGc...\" \\\n # Result: Full user database returned",
|
|
907
|
-
|
|
908
|
-
"recommendation": "Remove 'none' from algorithms array:\n\n```typescript\n// ✅ SECURE - Only allow HS256\njwt.verify(token, secret, { algorithms: ['HS256'] })\n```",
|
|
909
|
-
|
|
910
|
-
"quickFix": {
|
|
911
|
-
"description": "Remove 'none' from algorithms array (5 minutes)",
|
|
912
|
-
"code": "jwt.verify(token, secret, { algorithms: ['HS256'] })",
|
|
913
|
-
"limitations": "Still using symmetric key (HS256) - shared between services. Consider asymmetric (RS256) for multi-service architecture."
|
|
914
|
-
},
|
|
915
|
-
|
|
916
|
-
"properFix": {
|
|
917
|
-
"description": "Upgrade to RS256 with public/private key pairs (4 hours)",
|
|
918
|
-
"code": "// Generate key pair (run once)\n// openssl genrsa -out private.key 2048\n// openssl rsa -in private.key -pubout -out public.key\n\nimport fs from 'fs';\nimport jwt from 'jsonwebtoken';\n\nconst publicKey = fs.readFileSync('public.key');\n\n// Verify with public key only\nfunction verifyToken(token: string) {\n try {\n const decoded = jwt.verify(token, publicKey, {\n algorithms: ['RS256'], // Only asymmetric\n issuer: 'your-service',\n audience: 'your-api'\n });\n return decoded;\n } catch (err) {\n throw new AuthError('Invalid token', { cause: err });\n }\n}",
|
|
919
|
-
"additionalSteps": [
|
|
920
|
-
"Store private key in secure vault (AWS Secrets Manager, HashiCorp Vault)",
|
|
921
|
-
"Add key rotation policy (rotate every 90 days)",
|
|
922
|
-
"Implement token revocation list (Redis with TTL)",
|
|
923
|
-
"Add JWT ID (jti) claim for replay protection",
|
|
924
|
-
"Monitor for suspicious token patterns (e.g., expired tokens, wrong issuer)"
|
|
925
|
-
]
|
|
926
|
-
},
|
|
927
|
-
|
|
928
|
-
"testing": {
|
|
929
|
-
"description": "Verify the fix prevents 'none' algorithm attacks",
|
|
930
|
-
"manual": [
|
|
931
|
-
"Test 1: Forge token with alg='none' → should reject with 'invalid algorithm'",
|
|
932
|
-
"Test 2: Valid HS256 token → should work",
|
|
933
|
-
"Test 3: Token with wrong signature → should reject",
|
|
934
|
-
"Test 4: Expired token → should reject"
|
|
935
|
-
],
|
|
936
|
-
"automated": "describe('JWT security', () => {\n it('should reject none algorithm', () => {\n const forgedToken = 'eyJhbGciOiJub25lIn0.eyJ1c2VySWQiOjF9.';\n \n expect(() => {\n verifyToken(forgedToken);\n }).toThrow('invalid algorithm');\n });\n \n it('should only accept HS256', () => {\n const validToken = jwt.sign({ userId: 1 }, secret, { algorithm: 'HS256' });\n const decoded = verifyToken(validToken);\n expect(decoded.userId).toBe(1);\n \n // RS256 should fail\n const rs256Token = jwt.sign({ userId: 1 }, privateKey, { algorithm: 'RS256' });\n expect(() => verifyToken(rs256Token)).toThrow();\n });\n});"
|
|
937
|
-
},
|
|
938
|
-
|
|
939
|
-
"detection": {
|
|
940
|
-
"description": "Check if this vulnerability was already exploited",
|
|
941
|
-
"commands": [
|
|
942
|
-
"# Check logs for tokens with 'none' algorithm",
|
|
943
|
-
"grep 'eyJhbGciOiJub25lIi' /var/log/nginx/access.log",
|
|
944
|
-
"",
|
|
945
|
-
"# Decode suspicious tokens from logs",
|
|
946
|
-
"cat access.log | grep 'Authorization: Bearer' | cut -d' ' -f3 | while read token; do",
|
|
947
|
-
" echo $token | cut -d. -f1 | base64 -d",
|
|
948
|
-
"done | grep '\"alg\":\"none\"'",
|
|
949
|
-
"",
|
|
950
|
-
"# Check for admin actions from non-admin users",
|
|
951
|
-
"SELECT * FROM audit_log WHERE action LIKE 'admin.%' AND user_id NOT IN (SELECT id FROM users WHERE role='admin');"
|
|
952
|
-
],
|
|
953
|
-
"indicators": [
|
|
954
|
-
"Tokens in logs with alg='none' in header",
|
|
955
|
-
"Admin actions performed by non-admin user IDs",
|
|
956
|
-
"Unusual API access patterns (e.g., all endpoints accessed by one user)",
|
|
957
|
-
"Failed JWT verification errors followed by successful requests"
|
|
958
|
-
]
|
|
959
|
-
},
|
|
960
|
-
|
|
961
|
-
"dread": {
|
|
962
|
-
"damage": 10,
|
|
963
|
-
"reproducibility": 10,
|
|
964
|
-
"exploitability": 9,
|
|
965
|
-
"affectedUsers": 10,
|
|
966
|
-
"discoverability": 7,
|
|
967
|
-
"score": 9.2
|
|
968
|
-
},
|
|
969
|
-
|
|
970
|
-
"cwe": "CWE-347",
|
|
971
|
-
"owasp": "A02:2021-Cryptographic Failures",
|
|
972
|
-
"cvss": "9.8 (Critical)",
|
|
973
|
-
|
|
974
|
-
"references": [
|
|
975
|
-
"https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/",
|
|
976
|
-
"https://cwe.mitre.org/data/definitions/347.html",
|
|
977
|
-
"https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/06-Session_Management_Testing/10-Testing_JSON_Web_Tokens"
|
|
978
|
-
],
|
|
979
|
-
|
|
980
|
-
"evidence": [
|
|
981
|
-
"algorithms array at line 34 includes 'none'",
|
|
982
|
-
"No additional signature validation",
|
|
983
|
-
"Endpoint /api/admin uses this middleware (routes.ts:89)",
|
|
984
|
-
"No issuer/audience validation - accepts any token structure",
|
|
985
|
-
"Secret key hardcoded in config file (not rotated)"
|
|
986
|
-
],
|
|
987
|
-
|
|
988
|
-
"fixOwner": "developer",
|
|
989
|
-
"estimatedEffort": {
|
|
990
|
-
"human": "4-6 hours (research JWT best practices, implement RS256, generate key pairs, update auth flow, test)",
|
|
991
|
-
"claudeCode": "20-30 minutes (updates jwt.verify config, generates RS256 implementation, creates key management code, writes tests)",
|
|
992
|
-
"roi": "12x faster with Claude Code"
|
|
993
|
-
},
|
|
994
|
-
"priority": 1
|
|
556
|
+
"systemicWeaknesses": ["..."],
|
|
557
|
+
"missingControls": ["..."],
|
|
558
|
+
"attackSurface": {"unauthenticated": [...], "authenticated": [...]},
|
|
559
|
+
"worstCaseScenario": "...",
|
|
560
|
+
"chainAttacks": [{"chain": [...], "impact": "..."}],
|
|
561
|
+
"prioritizedRisks": ["..."]
|
|
995
562
|
}
|
|
563
|
+
|
|
564
|
+
Return ONLY: "done"
|
|
996
565
|
```
|
|
997
566
|
|
|
998
|
-
|
|
567
|
+
---
|
|
999
568
|
|
|
1000
|
-
|
|
1001
|
-
{
|
|
1002
|
-
"id": "PERF-001",
|
|
1003
|
-
"title": "N+1 Query in User Dashboard - 3000ms Page Load",
|
|
1004
|
-
"severity": "high",
|
|
1005
|
-
"category": "performance",
|
|
1006
|
-
"file": "src/controllers/dashboardController.ts",
|
|
1007
|
-
"line": 45,
|
|
1008
|
-
"endLine": 52,
|
|
1009
|
-
"code": "const users = await User.findAll();\nfor (const user of users) {\n user.orders = await Order.findByUserId(user.id);\n}",
|
|
1010
|
-
|
|
1011
|
-
"description": "Dashboard loads all users (1,000+) then makes individual database query for each user's orders. 1 query to get users + 1,000 queries for orders = 1,001 total queries. At 3ms per query = 3+ seconds page load.",
|
|
1012
|
-
|
|
1013
|
-
"impact": "Severe performance degradation. Page load time increases linearly with user count:\n- 100 users: 300ms\n- 1,000 users: 3,000ms (current)\n- 10,000 users: 30,000ms (unusable)\n\nDatabase CPU spikes to 90% during peak hours. Users abandon page before it loads.",
|
|
1014
|
-
|
|
1015
|
-
"businessImpact": {
|
|
1016
|
-
"financial": "53% users abandon pages loading >3s (Google). At 10k visits/day × $50 conversion = $265k/year lost revenue",
|
|
1017
|
-
"reputation": "Poor reviews mentioning 'slow dashboard'. PageSpeed score: 23/100",
|
|
1018
|
-
"operational": "Database overload causes cascading failures. RDS CPU alerts firing 20x/day",
|
|
1019
|
-
"scalability": "Cannot scale past 1,000 users without major infrastructure upgrade"
|
|
1020
|
-
},
|
|
1021
|
-
|
|
1022
|
-
"realWorldExamples": [
|
|
1023
|
-
"Shopify (2015): N+1 queries → 20s checkout → fixed with eager loading → 2s",
|
|
1024
|
-
"Your scenario: Admin dashboard times out during business hours",
|
|
1025
|
-
"Industry data: N+1 queries are #2 cause of slow Rails apps (Rails community survey)"
|
|
1026
|
-
],
|
|
1027
|
-
|
|
1028
|
-
"attackChain": [
|
|
1029
|
-
{"step": 1, "action": "Normal user visits /dashboard", "result": "Triggers 1,001 database queries"},
|
|
1030
|
-
{"step": 2, "action": "Attacker sends 10 concurrent requests", "result": "10,010 queries → database CPU 95%"},
|
|
1031
|
-
{"step": 3, "action": "Legitimate users affected", "result": "All API requests slow down"},
|
|
1032
|
-
{"step": 4, "action": "Attacker continues requests", "result": "Accidental DoS - database becomes unresponsive"}
|
|
1033
|
-
],
|
|
1034
|
-
|
|
1035
|
-
"proofOfConcept": "# Measure the N+1 problem:\n\n# 1. Enable query logging\nDATABASE_LOG_QUERIES=true npm start\n\n# 2. Load dashboard\ncurl https://api.example.com/dashboard\n\n# 3. Count queries in log\ngrep 'SELECT.*FROM orders' logs/db.log | wc -l\n# Result: 1000+ queries\n\n# 4. Measure timing\ntime curl https://api.example.com/dashboard\n# Result: real 3.2s",
|
|
1036
|
-
|
|
1037
|
-
"recommendation": "Use eager loading (JOIN) to fetch all data in one query:\n\n```typescript\n// ✅ OPTIMIZED - Single query with JOIN\nconst users = await User.findAll({\n include: [{\n model: Order,\n as: 'orders'\n }]\n});\n\n// SQL generated:\n// SELECT users.*, orders.*\n// FROM users\n// LEFT JOIN orders ON orders.user_id = users.id\n// (1 query instead of 1,001)\n```",
|
|
1038
|
-
|
|
1039
|
-
"quickFix": {
|
|
1040
|
-
"description": "Add eager loading to existing query (30 minutes)",
|
|
1041
|
-
"code": "const users = await User.findAll({\n include: ['orders'] // Sequelize eager loading\n});",
|
|
1042
|
-
"limitations": "Still loads all users - may be slow with 10k+ users. Pagination recommended."
|
|
1043
|
-
},
|
|
1044
|
-
|
|
1045
|
-
"properFix": {
|
|
1046
|
-
"description": "Eager loading + pagination + caching (4 hours)",
|
|
1047
|
-
"code": "// Proper solution with pagination\nasync function getDashboard(page = 1, limit = 50) {\n const cacheKey = `dashboard:${page}`;\n \n // Check cache first\n const cached = await redis.get(cacheKey);\n if (cached) return JSON.parse(cached);\n \n // Single query with JOIN + pagination\n const users = await User.findAll({\n include: [{\n model: Order,\n as: 'orders',\n limit: 10 // Limit orders per user\n }],\n limit,\n offset: (page - 1) * limit,\n order: [['createdAt', 'DESC']]\n });\n \n // Cache for 5 minutes\n await redis.setex(cacheKey, 300, JSON.stringify(users));\n \n return users;\n}",
|
|
1048
|
-
"additionalSteps": [
|
|
1049
|
-
"Add database index on orders.user_id (if missing)",
|
|
1050
|
-
"Consider materialized view for dashboard data",
|
|
1051
|
-
"Add connection pooling (min: 5, max: 20)",
|
|
1052
|
-
"Set up read replicas for heavy queries",
|
|
1053
|
-
"Monitor query performance with APM (DataDog, New Relic)"
|
|
1054
|
-
]
|
|
1055
|
-
},
|
|
1056
|
-
|
|
1057
|
-
"testing": {
|
|
1058
|
-
"description": "Verify performance improvement",
|
|
1059
|
-
"manual": [
|
|
1060
|
-
"Test 1: Load dashboard, check DB logs → should see 1-2 queries (not 1000+)",
|
|
1061
|
-
"Test 2: Use Chrome DevTools → Time to First Byte should be <500ms",
|
|
1062
|
-
"Test 3: Run with 10k users in test DB → should still load <1s",
|
|
1063
|
-
"Test 4: Check database CPU during load → should stay <50%"
|
|
1064
|
-
],
|
|
1065
|
-
"automated": "describe('Dashboard performance', () => {\n it('should use eager loading (no N+1)', async () => {\n // Track queries\n const queries = [];\n db.on('query', q => queries.push(q));\n \n await getDashboard();\n \n // Should be 1 SELECT with JOIN\n expect(queries.length).toBeLessThan(5);\n expect(queries[0]).toContain('JOIN orders');\n });\n \n it('should load dashboard in <500ms', async () => {\n const start = Date.now();\n await getDashboard();\n const duration = Date.now() - start;\n \n expect(duration).toBeLessThan(500);\n });\n});"
|
|
1066
|
-
},
|
|
1067
|
-
|
|
1068
|
-
"detection": {
|
|
1069
|
-
"description": "Find other N+1 query problems in codebase",
|
|
1070
|
-
"commands": [
|
|
1071
|
-
"# Find loops with database queries inside",
|
|
1072
|
-
"grep -r 'for.*await.*find' src/",
|
|
1073
|
-
"grep -r '.map.*await' src/",
|
|
1074
|
-
"",
|
|
1075
|
-
"# Check database slow query log",
|
|
1076
|
-
"cat /var/log/postgresql/slow-queries.log | grep 'SELECT.*FROM orders'",
|
|
1077
|
-
"",
|
|
1078
|
-
"# Use database profiler",
|
|
1079
|
-
"npm install --save-dev sequelize-profiler",
|
|
1080
|
-
"# Add to app: db.use(require('sequelize-profiler'))"
|
|
1081
|
-
],
|
|
1082
|
-
"indicators": [
|
|
1083
|
-
"Database query count proportional to result set size",
|
|
1084
|
-
"Slow query log shows same query repeated 100+ times",
|
|
1085
|
-
"APM shows 'database' taking 80%+ of response time",
|
|
1086
|
-
"Database CPU spikes during list page loads"
|
|
1087
|
-
]
|
|
1088
|
-
},
|
|
1089
|
-
|
|
1090
|
-
"dread": {
|
|
1091
|
-
"damage": 7,
|
|
1092
|
-
"reproducibility": 10,
|
|
1093
|
-
"exploitability": 10,
|
|
1094
|
-
"affectedUsers": 10,
|
|
1095
|
-
"discoverability": 8,
|
|
1096
|
-
"score": 9.0
|
|
1097
|
-
},
|
|
1098
|
-
|
|
1099
|
-
"references": [
|
|
1100
|
-
"https://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations",
|
|
1101
|
-
"https://sequelize.org/docs/v6/advanced-association-concepts/eager-loading/",
|
|
1102
|
-
"https://use-the-index-luke.com/"
|
|
1103
|
-
],
|
|
1104
|
-
|
|
1105
|
-
"evidence": [
|
|
1106
|
-
"Loop at line 46 calls Order.findByUserId() inside",
|
|
1107
|
-
"No 'include' option in User.findAll() query",
|
|
1108
|
-
"APM data shows 1,247 queries for single dashboard load",
|
|
1109
|
-
"Database slow query log: 'SELECT * FROM orders WHERE user_id = ?' appears 1000+ times",
|
|
1110
|
-
"PageSpeed Insights: Time to Interactive = 3.2s"
|
|
1111
|
-
],
|
|
1112
|
-
|
|
1113
|
-
"fixOwner": "developer",
|
|
1114
|
-
"estimatedEffort": {
|
|
1115
|
-
"human": "3-4 hours (find all N+1 queries, research eager loading, implement pagination, add caching, performance test)",
|
|
1116
|
-
"claudeCode": "15-20 minutes (detects N+1 patterns, converts to eager loading, adds pagination and caching, generates performance tests)",
|
|
1117
|
-
"roi": "12x faster with Claude Code"
|
|
1118
|
-
},
|
|
1119
|
-
"priority": 1
|
|
1120
|
-
}
|
|
1121
|
-
```
|
|
569
|
+
## Phase 3: Aggregate Results
|
|
1122
570
|
|
|
1123
|
-
|
|
571
|
+
**CRITICAL: Use Write tool directly, NOT bash heredoc**
|
|
1124
572
|
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
"title": "Payment Secrets Hardcoded in Repository - Exposure Risk",
|
|
1129
|
-
"severity": "critical",
|
|
1130
|
-
"category": "architecture",
|
|
1131
|
-
"file": "src/config/payment.ts",
|
|
1132
|
-
"line": 12,
|
|
1133
|
-
"endLine": 12,
|
|
1134
|
-
"code": "const STRIPE_SECRET_KEY = 'sk_live_51Hqr2x...'",
|
|
1135
|
-
|
|
1136
|
-
"description": "Stripe LIVE secret key hardcoded in source code. Key has been committed to git history (commit abc123). Anyone with repository access can process payments, issue refunds, export customer data.",
|
|
1137
|
-
|
|
1138
|
-
"impact": "Complete payment system compromise:\n1. Process fraudulent charges\n2. Issue refunds to attacker's accounts\n3. Export all customer payment data (PCI violation)\n4. Delete customer payment methods\n5. Key exposed in git history - even if removed now, still accessible",
|
|
1139
|
-
|
|
1140
|
-
"businessImpact": {
|
|
1141
|
-
"financial": "Fraudulent charges/refunds = unlimited financial loss. Stripe may suspend account. PCI Level 1 fine: $5k-$100k/month",
|
|
1142
|
-
"reputation": "PCI compliance failure = cannot process credit cards. Customer data breach = loss of trust",
|
|
1143
|
-
"legal": "PCI DSS violation = potential lawsuits. FTC investigation. Payment processor termination",
|
|
1144
|
-
"operational": "Emergency key rotation, customer notification, forensic investigation, potential service shutdown"
|
|
1145
|
-
},
|
|
1146
|
-
|
|
1147
|
-
"realWorldExamples": [
|
|
1148
|
-
"Uber (2016): AWS keys in GitHub → 57M users exposed → $148M settlement",
|
|
1149
|
-
"Twitter (2020): API keys leaked → account takeovers including Obama, Biden",
|
|
1150
|
-
"Your risk: Developer laptop stolen → attacker has payment keys → can issue refunds to themselves"
|
|
1151
|
-
],
|
|
1152
|
-
|
|
1153
|
-
"attackChain": [
|
|
1154
|
-
{"step": 1, "action": "Clone repository or access via ex-employee's account", "result": "Source code with secret key"},
|
|
1155
|
-
{"step": 2, "action": "Use key to list all customers: curl https://api.stripe.com/v1/customers -u sk_live_...", "result": "Export entire customer database"},
|
|
1156
|
-
{"step": 3, "action": "Issue refunds to attacker-controlled accounts", "result": "$10k+ fraudulent refunds"},
|
|
1157
|
-
{"step": 4, "action": "Even if key rotated, check git history: git log -p config/payment.ts", "result": "Original key still in commits"}
|
|
1158
|
-
],
|
|
1159
|
-
|
|
1160
|
-
"proofOfConcept": "# Exploit hardcoded secret:\n\n# 1. Find the key in code\ngrep -r 'sk_live' .\n# Result: src/config/payment.ts:12:const STRIPE_SECRET_KEY = 'sk_live_51Hqr2x...'\n\n# 2. Check git history (even if removed)\ngit log --all -p | grep 'sk_live'\n# Result: Found in commits abc123, def456, ghi789\n\n# 3. Use the key to issue refund\ncurl https://api.stripe.com/v1/refunds \\\n -u sk_live_51Hqr2x...: \\\n -d charge=ch_xyz123 \\\n -d amount=10000\n# Result: $100 refunded to attacker's card",
|
|
1161
|
-
|
|
1162
|
-
"recommendation": "Move secrets to environment variables and secret manager:\n\n```typescript\n// ✅ SECURE - Load from environment\nconst STRIPE_SECRET_KEY = process.env.STRIPE_SECRET_KEY;\n\nif (!STRIPE_SECRET_KEY) {\n throw new Error('STRIPE_SECRET_KEY environment variable required');\n}\n```",
|
|
1163
|
-
|
|
1164
|
-
"quickFix": {
|
|
1165
|
-
"description": "Move to .env file (NOT committed) - 1 hour",
|
|
1166
|
-
"code": "// .env (add to .gitignore)\nSTRIPE_SECRET_KEY=sk_live_51Hqr2x...\n\n// src/config/payment.ts\nimport dotenv from 'dotenv';\ndotenv.config();\n\nconst STRIPE_SECRET_KEY = process.env.STRIPE_SECRET_KEY;",
|
|
1167
|
-
"limitations": ".env still on server filesystem. If server compromised, key exposed. Better: use secret manager."
|
|
1168
|
-
},
|
|
1169
|
-
|
|
1170
|
-
"properFix": {
|
|
1171
|
-
"description": "Migrate to AWS Secrets Manager with key rotation (1 day)",
|
|
1172
|
-
"code": "import { SecretsManagerClient, GetSecretValueCommand } from '@aws-sdk/client-secrets-manager';\n\nconst client = new SecretsManagerClient({ region: 'us-east-1' });\n\n// Fetch secret from AWS Secrets Manager\nasync function getStripeKey(): Promise<string> {\n const response = await client.send(\n new GetSecretValueCommand({ SecretId: 'prod/stripe/secret_key' })\n );\n \n if (!response.SecretString) {\n throw new Error('Stripe secret not found in Secrets Manager');\n }\n \n return JSON.parse(response.SecretString).STRIPE_SECRET_KEY;\n}\n\n// Cache for 5 minutes (secrets manager charges per request)\nlet cachedKey: string | null = null;\nlet cacheExpiry = 0;\n\nexport async function getPaymentKey(): Promise<string> {\n if (cachedKey && Date.now() < cacheExpiry) {\n return cachedKey;\n }\n \n cachedKey = await getStripeKey();\n cacheExpiry = Date.now() + 5 * 60 * 1000;\n return cachedKey;\n}",
|
|
1173
|
-
"additionalSteps": [
|
|
1174
|
-
"Rotate Stripe secret key IMMEDIATELY (current key is compromised)",
|
|
1175
|
-
"Enable automatic key rotation in AWS Secrets Manager (90 days)",
|
|
1176
|
-
"Remove key from ALL git history: git filter-branch or BFG Repo-Cleaner",
|
|
1177
|
-
"Audit Stripe logs for suspicious activity (past 90 days)",
|
|
1178
|
-
"Set up IAM roles - only production servers can read secrets",
|
|
1179
|
-
"Enable CloudTrail logging for secret access",
|
|
1180
|
-
"Add alerts for secret access from unexpected IPs",
|
|
1181
|
-
"Document key rotation runbook"
|
|
1182
|
-
]
|
|
1183
|
-
},
|
|
1184
|
-
|
|
1185
|
-
"testing": {
|
|
1186
|
-
"description": "Verify secrets are properly secured",
|
|
1187
|
-
"manual": [
|
|
1188
|
-
"Test 1: grep -r 'sk_live' . → should return 0 results",
|
|
1189
|
-
"Test 2: git log --all -p | grep 'sk_live' → check if still in history",
|
|
1190
|
-
"Test 3: docker run --rm app → should fail with 'STRIPE_SECRET_KEY required'",
|
|
1191
|
-
"Test 4: AWS Secrets Manager console → verify secret exists",
|
|
1192
|
-
"Test 5: Attempt to access secret from dev laptop → should fail (IAM)"
|
|
1193
|
-
],
|
|
1194
|
-
"automated": "describe('Secret management', () => {\n it('should not have hardcoded secrets', () => {\n const files = glob.sync('**/*.{ts,js}');\n files.forEach(file => {\n const content = fs.readFileSync(file, 'utf8');\n expect(content).not.toMatch(/sk_live_[a-zA-Z0-9]{32}/);\n expect(content).not.toMatch(/pk_live_[a-zA-Z0-9]{32}/);\n });\n });\n \n it('should require environment variables', () => {\n delete process.env.STRIPE_SECRET_KEY;\n expect(() => require('./config/payment')).toThrow('STRIPE_SECRET_KEY');\n });\n});"
|
|
1195
|
-
},
|
|
1196
|
-
|
|
1197
|
-
"detection": {
|
|
1198
|
-
"description": "Find ALL hardcoded secrets in codebase",
|
|
1199
|
-
"commands": [
|
|
1200
|
-
"# Find Stripe keys",
|
|
1201
|
-
"git log --all -p | grep -E 'sk_live_[a-zA-Z0-9]+'",
|
|
1202
|
-
"",
|
|
1203
|
-
"# Find AWS keys",
|
|
1204
|
-
"git log --all -p | grep -E 'AKIA[A-Z0-9]{16}'",
|
|
1205
|
-
"",
|
|
1206
|
-
"# Find generic secrets (high entropy strings)",
|
|
1207
|
-
"trufflehog git file://. --only-verified",
|
|
1208
|
-
"",
|
|
1209
|
-
"# Use automated scanner",
|
|
1210
|
-
"npm install -g detect-secrets",
|
|
1211
|
-
"detect-secrets scan --all-files",
|
|
1212
|
-
"",
|
|
1213
|
-
"# Check Stripe for unauthorized activity",
|
|
1214
|
-
"# Login to Stripe dashboard → Developers → Logs → Filter by IP address"
|
|
1215
|
-
],
|
|
1216
|
-
"indicators": [
|
|
1217
|
-
"Stripe keys (sk_live_, pk_live_) in source code",
|
|
1218
|
-
"AWS credentials (AKIA...) in config files",
|
|
1219
|
-
"High entropy strings (40+ random chars) in code",
|
|
1220
|
-
"Suspicious Stripe activity: refunds from unknown IPs, customer exports",
|
|
1221
|
-
"GitHub secret scanning alerts (if repo is on GitHub)"
|
|
1222
|
-
]
|
|
1223
|
-
},
|
|
1224
|
-
|
|
1225
|
-
"dread": {
|
|
1226
|
-
"damage": 10,
|
|
1227
|
-
"reproducibility": 10,
|
|
1228
|
-
"exploitability": 10,
|
|
1229
|
-
"affectedUsers": 10,
|
|
1230
|
-
"discoverability": 9,
|
|
1231
|
-
"score": 9.8
|
|
1232
|
-
},
|
|
1233
|
-
|
|
1234
|
-
"cwe": "CWE-798",
|
|
1235
|
-
"owasp": "A02:2021-Cryptographic Failures",
|
|
1236
|
-
"cvss": "10.0 (Critical)",
|
|
1237
|
-
|
|
1238
|
-
"references": [
|
|
1239
|
-
"https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html",
|
|
1240
|
-
"https://owasp.org/www-community/vulnerabilities/Use_of_hard-coded_password",
|
|
1241
|
-
"https://stripe.com/docs/keys#safe-keys"
|
|
1242
|
-
],
|
|
1243
|
-
|
|
1244
|
-
"evidence": [
|
|
1245
|
-
"Line 12: const STRIPE_SECRET_KEY = 'sk_live_51Hqr2x...'",
|
|
1246
|
-
"Git history shows key in 14 commits dating back 6 months",
|
|
1247
|
-
"Repository has 23 contributors (all have access to key)",
|
|
1248
|
-
"No .gitignore entry for config files",
|
|
1249
|
-
"GitHub shows 'Secret scanning alert' for this repository"
|
|
1250
|
-
],
|
|
1251
|
-
|
|
1252
|
-
"fixOwner": "devops + developer",
|
|
1253
|
-
"estimatedEffort": {
|
|
1254
|
-
"human": "1-2 days (setup AWS Secrets Manager, migrate all secrets, update deployment scripts, rotate keys, audit git history, cleanup with BFG)",
|
|
1255
|
-
"claudeCode": "1-2 hours (finds all secrets, generates Secrets Manager integration, updates code, creates rotation scripts, provides git cleanup commands)",
|
|
1256
|
-
"roi": "12x faster with Claude Code"
|
|
1257
|
-
},
|
|
1258
|
-
"priority": 1
|
|
1259
|
-
}
|
|
573
|
+
1. List agent files:
|
|
574
|
+
```bash
|
|
575
|
+
ls .coverme/agents/*.json 2>/dev/null | head -30
|
|
1260
576
|
```
|
|
1261
577
|
|
|
1262
|
-
|
|
578
|
+
2. Read each agent JSON file using the Read tool (in parallel if possible)
|
|
1263
579
|
|
|
580
|
+
3. **Use the Write tool** to save `.coverme/scan.json` with this structure:
|
|
1264
581
|
```json
|
|
1265
582
|
{
|
|
1266
|
-
"
|
|
1267
|
-
"
|
|
1268
|
-
"
|
|
1269
|
-
"
|
|
583
|
+
"projectName": "from package.json or folder name",
|
|
584
|
+
"scanDate": "ISO timestamp",
|
|
585
|
+
"filesScanned": N,
|
|
586
|
+
"linesOfCode": N,
|
|
587
|
+
"findings": [merged from all agent files, deduplicated],
|
|
588
|
+
"positiveObservations": [from POSITIVE.json],
|
|
589
|
+
"summary": {"critical":N,"high":N,"medium":N,"low":N}
|
|
1270
590
|
}
|
|
1271
591
|
```
|
|
1272
592
|
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
1. **CREATE DETAILED FINDINGS** - DO NOT just write executiveSummary! You MUST populate the `findings` array with full finding objects!
|
|
1278
|
-
2. **Silent failures are CRITICAL** - They hide production bugs in payments, auth, data
|
|
1279
|
-
3. **Read actual code** - Don't guess, read the files
|
|
1280
|
-
4. **Check git history** - Secrets may have been removed but still exposed
|
|
1281
|
-
5. **Think like an attacker** - How would you exploit this?
|
|
1282
|
-
6. **Be specific** - File:line, code snippets, attack chains
|
|
1283
|
-
7. **DREAD + Attack Chain** - Required for critical/high
|
|
1284
|
-
8. **Quality over quantity** - 10 solid findings > 50 vague ones
|
|
1285
|
-
9. **Architecture matters** - Trust boundaries, data flow, scalability
|
|
1286
|
-
10. **Performance impacts security** - N+1 queries → DoS, memory leaks → crashes
|
|
1287
|
-
11. **Include ROI estimates** - human vs claudeCode time for every finding
|
|
1288
|
-
12. **Run `coverme report`** - Not done until HTML opens!
|
|
593
|
+
**IMPORTANT**:
|
|
594
|
+
- Use Write tool, not bash echo/cat
|
|
595
|
+
- Keep max 50 findings (prioritize by severity)
|
|
596
|
+
- Max 3 code snippets per finding
|
|
1289
597
|
|
|
1290
598
|
---
|
|
1291
599
|
|
|
1292
|
-
|
|
600
|
+
## Phase 4: Generate Report
|
|
1293
601
|
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
-
|
|
1297
|
-
|
|
602
|
+
```bash
|
|
603
|
+
TIMESTAMP=$(date +%Y-%m-%d_%H-%M-%S)
|
|
604
|
+
npx coverme-scanner report .coverme/scan.json -f html -o ".coverme/report_$TIMESTAMP.html"
|
|
605
|
+
open ".coverme/report_$TIMESTAMP.html"
|
|
606
|
+
```
|
|
1298
607
|
|
|
1299
608
|
---
|
|
1300
609
|
|
|
1301
|
-
|
|
610
|
+
## DONE
|
|
611
|
+
|
|
612
|
+
Tell user: "Scan complete! Report opened."
|