vettcode-cli 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +20 -0
- package/LICENSE +21 -0
- package/README.md +286 -0
- package/dist/ast-extractor.js +519 -0
- package/dist/cli-scan-orchestrator.js +336 -0
- package/dist/cli.js +208 -0
- package/dist/control-flow-analyzer.js +184 -0
- package/dist/data-flow-analyzer.js +197 -0
- package/dist/enhanced-patterns.js +457 -0
- package/dist/file-collector.js +132 -0
- package/dist/ignore-patterns.js +225 -0
- package/dist/openrouter.js +311 -0
- package/dist/patterns.js +248 -0
- package/dist/prompts.js +144 -0
- package/dist/reference-graph.js +415 -0
- package/dist/report-generator.js +128 -0
- package/dist/scan-priority.js +49 -0
- package/dist/smart-scan-orchestrator.js +878 -0
- package/dist/static-analyzer.js +1681 -0
- package/dist/types.js +2 -0
- package/dist/verification-layer.js +525 -0
- package/package.json +61 -0
package/dist/patterns.js
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Security Patterns - Comprehensive vulnerability detection patterns
|
|
4
|
+
* Adapted from Vettcode-engine for CLI use
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.ALL_PATTERNS = exports.SECURITY_HEADER_PATTERNS = exports.ERROR_HANDLING_PATTERNS = exports.DATABASE_PATTERNS = exports.CRYPTO_PATTERNS = exports.REACT_PATTERNS = exports.AUTH_PATTERNS = exports.PATH_TRAVERSAL_PATTERNS = exports.COMMAND_INJECTION_PATTERNS = exports.XSS_PATTERNS = exports.SQL_INJECTION_PATTERNS = void 0;
|
|
8
|
+
// SQL Injection Patterns
|
|
9
|
+
exports.SQL_INJECTION_PATTERNS = [
|
|
10
|
+
{
|
|
11
|
+
id: "sql-injection-template-literal",
|
|
12
|
+
regex: /(?:execute|query|raw)\s*\(\s*`[^`]*\$\{[^}]+\}[^`]*`/gi,
|
|
13
|
+
severity: "critical",
|
|
14
|
+
category: "security",
|
|
15
|
+
title: "SQL Injection via Template Literal",
|
|
16
|
+
description: "SQL query uses template literal with user input",
|
|
17
|
+
confidence: "high",
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
id: "sql-injection-string-concat-plus",
|
|
21
|
+
regex: /(?:execute|query|raw)\s*\(\s*['"][^'"]*['"]\s*\+\s*(?:req\.|params\.|query\.|body\.)/gi,
|
|
22
|
+
severity: "critical",
|
|
23
|
+
category: "security",
|
|
24
|
+
title: "SQL Injection via String Concatenation",
|
|
25
|
+
description: "SQL query concatenates user input directly",
|
|
26
|
+
confidence: "high",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: "sql-injection-where-clause",
|
|
30
|
+
regex: /WHERE\s+[^=]+\s*=\s*['"]?\$\{|WHERE\s+[^=]+\s*=\s*['"]\s*\+/gi,
|
|
31
|
+
severity: "critical",
|
|
32
|
+
category: "security",
|
|
33
|
+
title: "SQL Injection in WHERE Clause",
|
|
34
|
+
description: "WHERE clause uses unsanitized user input",
|
|
35
|
+
confidence: "high",
|
|
36
|
+
},
|
|
37
|
+
];
|
|
38
|
+
// XSS Patterns
|
|
39
|
+
exports.XSS_PATTERNS = [
|
|
40
|
+
{
|
|
41
|
+
id: "xss-react-dangerously-set-html",
|
|
42
|
+
regex: /dangerouslySetInnerHTML\s*=\s*\{\s*\{?\s*__html\s*:\s*(?!DOMPurify)/gi,
|
|
43
|
+
severity: "high",
|
|
44
|
+
category: "security",
|
|
45
|
+
title: "XSS via dangerouslySetInnerHTML Without Sanitization",
|
|
46
|
+
description: "React component uses dangerouslySetInnerHTML without DOMPurify",
|
|
47
|
+
confidence: "high",
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
id: "xss-dom-innerhtml",
|
|
51
|
+
regex: /\.innerHTML\s*=\s*(?!['"`]|DOMPurify)/gi,
|
|
52
|
+
severity: "high",
|
|
53
|
+
category: "security",
|
|
54
|
+
title: "XSS via innerHTML Assignment",
|
|
55
|
+
description: "Direct innerHTML assignment without sanitization",
|
|
56
|
+
confidence: "medium",
|
|
57
|
+
},
|
|
58
|
+
];
|
|
59
|
+
// Command Injection Patterns
|
|
60
|
+
exports.COMMAND_INJECTION_PATTERNS = [
|
|
61
|
+
{
|
|
62
|
+
id: "command-injection-exec",
|
|
63
|
+
regex: /(?:exec|execSync|spawn|spawnSync)\s*\(\s*[`'"]?[^`'"]*\$\{/gi,
|
|
64
|
+
severity: "critical",
|
|
65
|
+
category: "security",
|
|
66
|
+
title: "Command Injection via exec/spawn",
|
|
67
|
+
description: "Shell command execution with user input",
|
|
68
|
+
confidence: "high",
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
id: "command-injection-eval",
|
|
72
|
+
regex: /eval\s*\(\s*(?:req\.|params\.|query\.|body\.)/gi,
|
|
73
|
+
severity: "critical",
|
|
74
|
+
category: "security",
|
|
75
|
+
title: "Code Injection via eval",
|
|
76
|
+
description: "eval() called with user input",
|
|
77
|
+
confidence: "high",
|
|
78
|
+
},
|
|
79
|
+
];
|
|
80
|
+
// Path Traversal Patterns
|
|
81
|
+
exports.PATH_TRAVERSAL_PATTERNS = [
|
|
82
|
+
{
|
|
83
|
+
id: "path-traversal-fs-read",
|
|
84
|
+
regex: /fs\.(?:readFile|readFileSync|createReadStream)\s*\([^)]*(?:req\.|params\.|query\.)/gi,
|
|
85
|
+
severity: "critical",
|
|
86
|
+
category: "security",
|
|
87
|
+
title: "Path Traversal in File Read",
|
|
88
|
+
description: "File read operation with unsanitized user input",
|
|
89
|
+
confidence: "high",
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
id: "path-traversal-fs-write",
|
|
93
|
+
regex: /fs\.(?:writeFile|writeFileSync|createWriteStream)\s*\([^)]*(?:req\.|params\.|query\.)/gi,
|
|
94
|
+
severity: "critical",
|
|
95
|
+
category: "security",
|
|
96
|
+
title: "Path Traversal in File Write",
|
|
97
|
+
description: "File write operation with unsanitized user input",
|
|
98
|
+
confidence: "high",
|
|
99
|
+
},
|
|
100
|
+
];
|
|
101
|
+
// Authentication Patterns
|
|
102
|
+
exports.AUTH_PATTERNS = [
|
|
103
|
+
{
|
|
104
|
+
id: "weak-jwt-secret",
|
|
105
|
+
regex: /jwt\.sign\s*\([^)]*,\s*['"](?:secret|password|123|test)['"]/gi,
|
|
106
|
+
severity: "critical",
|
|
107
|
+
category: "security",
|
|
108
|
+
title: "Weak JWT Secret",
|
|
109
|
+
description: "JWT signed with weak or hardcoded secret",
|
|
110
|
+
confidence: "high",
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
id: "bcrypt-low-rounds",
|
|
114
|
+
regex: /bcrypt\.hash\w*\s*\([^)]*,\s*([1-9]|10)\s*\)/gi,
|
|
115
|
+
severity: "high",
|
|
116
|
+
category: "security",
|
|
117
|
+
title: "Weak bcrypt Rounds",
|
|
118
|
+
description: "bcrypt rounds < 10 is too weak",
|
|
119
|
+
confidence: "high",
|
|
120
|
+
},
|
|
121
|
+
];
|
|
122
|
+
// React Patterns
|
|
123
|
+
exports.REACT_PATTERNS = [
|
|
124
|
+
{
|
|
125
|
+
id: "react-useeffect-missing-deps",
|
|
126
|
+
regex: /useEffect\s*\([^)]*\)\s*,\s*\[\s*\]/gi,
|
|
127
|
+
severity: "medium",
|
|
128
|
+
category: "react",
|
|
129
|
+
title: "useEffect with Empty Dependency Array",
|
|
130
|
+
description: "useEffect may have missing dependencies",
|
|
131
|
+
confidence: "low",
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
id: "react-key-index",
|
|
135
|
+
regex: /key\s*=\s*\{\s*(?:index|i|idx)\s*\}/gi,
|
|
136
|
+
severity: "low",
|
|
137
|
+
category: "react",
|
|
138
|
+
title: "Using Array Index as React Key",
|
|
139
|
+
description: "Array index as key can cause rendering issues",
|
|
140
|
+
confidence: "medium",
|
|
141
|
+
},
|
|
142
|
+
];
|
|
143
|
+
// Cryptography Patterns
|
|
144
|
+
exports.CRYPTO_PATTERNS = [
|
|
145
|
+
{
|
|
146
|
+
id: "crypto-weak-algorithm-md5",
|
|
147
|
+
regex: /crypto\.createHash\s*\(\s*['"]md5['"]\s*\)/gi,
|
|
148
|
+
severity: "high",
|
|
149
|
+
category: "security",
|
|
150
|
+
title: "Weak Cryptographic Algorithm: MD5",
|
|
151
|
+
description: "MD5 is cryptographically broken",
|
|
152
|
+
confidence: "high",
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
id: "crypto-weak-algorithm-sha1",
|
|
156
|
+
regex: /crypto\.createHash\s*\(\s*['"]sha1['"]\s*\)/gi,
|
|
157
|
+
severity: "high",
|
|
158
|
+
category: "security",
|
|
159
|
+
title: "Weak Cryptographic Algorithm: SHA1",
|
|
160
|
+
description: "SHA1 is deprecated and insecure",
|
|
161
|
+
confidence: "high",
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
id: "crypto-weak-random",
|
|
165
|
+
regex: /Math\.random\s*\(\s*\)/gi,
|
|
166
|
+
severity: "medium",
|
|
167
|
+
category: "security",
|
|
168
|
+
title: "Weak Random Number Generation",
|
|
169
|
+
description: "Math.random() is not cryptographically secure",
|
|
170
|
+
confidence: "low",
|
|
171
|
+
},
|
|
172
|
+
];
|
|
173
|
+
// Database Patterns
|
|
174
|
+
exports.DATABASE_PATTERNS = [
|
|
175
|
+
{
|
|
176
|
+
id: "db-query-no-limit",
|
|
177
|
+
regex: /\.find\s*\(\s*\{[^}]*\}\s*\)(?![\s\S]{0,100}\.limit)/gi,
|
|
178
|
+
severity: "high",
|
|
179
|
+
category: "performance",
|
|
180
|
+
title: "Database Query Without Limit",
|
|
181
|
+
description: "Query can return unlimited results causing OOM",
|
|
182
|
+
confidence: "medium",
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
id: "db-n-plus-one",
|
|
186
|
+
regex: /for\s*\([^)]*\)\s*\{[^}]*(?:find|findOne|query)\s*\(/gi,
|
|
187
|
+
severity: "high",
|
|
188
|
+
category: "performance",
|
|
189
|
+
title: "Potential N+1 Query Problem",
|
|
190
|
+
description: "Database query inside loop causes N+1 problem",
|
|
191
|
+
confidence: "low",
|
|
192
|
+
},
|
|
193
|
+
];
|
|
194
|
+
// Error Handling Patterns
|
|
195
|
+
exports.ERROR_HANDLING_PATTERNS = [
|
|
196
|
+
{
|
|
197
|
+
id: "empty-catch-block",
|
|
198
|
+
regex: /catch\s*\([^)]*\)\s*\{\s*\}/gi,
|
|
199
|
+
severity: "medium",
|
|
200
|
+
category: "production",
|
|
201
|
+
title: "Empty Catch Block",
|
|
202
|
+
description: "Error caught but not handled",
|
|
203
|
+
confidence: "high",
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
id: "throw-string",
|
|
207
|
+
regex: /throw\s+['"][^'"]+['"]/gi,
|
|
208
|
+
severity: "low",
|
|
209
|
+
category: "code-quality",
|
|
210
|
+
title: "Throwing String Instead of Error",
|
|
211
|
+
description: "Should throw Error objects, not strings",
|
|
212
|
+
confidence: "high",
|
|
213
|
+
},
|
|
214
|
+
];
|
|
215
|
+
// Security Header Patterns
|
|
216
|
+
exports.SECURITY_HEADER_PATTERNS = [
|
|
217
|
+
{
|
|
218
|
+
id: "missing-helmet",
|
|
219
|
+
regex: /express\s*\(\s*\)(?![\s\S]{0,500}helmet)/gi,
|
|
220
|
+
severity: "high",
|
|
221
|
+
category: "security",
|
|
222
|
+
title: "Express App Without Helmet",
|
|
223
|
+
description: "Missing security headers middleware",
|
|
224
|
+
confidence: "medium",
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
id: "cors-allow-all",
|
|
228
|
+
regex: /Access-Control-Allow-Origin['"]?\s*:\s*['"]?\*/gi,
|
|
229
|
+
severity: "high",
|
|
230
|
+
category: "security",
|
|
231
|
+
title: "CORS Allows All Origins",
|
|
232
|
+
description: "Wildcard CORS policy is insecure",
|
|
233
|
+
confidence: "high",
|
|
234
|
+
},
|
|
235
|
+
];
|
|
236
|
+
// Export all patterns combined
|
|
237
|
+
exports.ALL_PATTERNS = [
|
|
238
|
+
...exports.SQL_INJECTION_PATTERNS,
|
|
239
|
+
...exports.XSS_PATTERNS,
|
|
240
|
+
...exports.COMMAND_INJECTION_PATTERNS,
|
|
241
|
+
...exports.PATH_TRAVERSAL_PATTERNS,
|
|
242
|
+
...exports.AUTH_PATTERNS,
|
|
243
|
+
...exports.REACT_PATTERNS,
|
|
244
|
+
...exports.CRYPTO_PATTERNS,
|
|
245
|
+
...exports.DATABASE_PATTERNS,
|
|
246
|
+
...exports.ERROR_HANDLING_PATTERNS,
|
|
247
|
+
...exports.SECURITY_HEADER_PATTERNS,
|
|
248
|
+
];
|
package/dist/prompts.js
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SYNTHESIS_SYSTEM_PROMPT = exports.BATCH_SYSTEM_PROMPT = void 0;
|
|
4
|
+
exports.buildSmartBatchUserPrompt = buildSmartBatchUserPrompt;
|
|
5
|
+
exports.buildSynthesisUserPrompt = buildSynthesisUserPrompt;
|
|
6
|
+
exports.getAnalysisPrompt = getAnalysisPrompt;
|
|
7
|
+
exports.BATCH_SYSTEM_PROMPT = `You are Vettcode Engine — a ruthless, expert application security and production-readiness auditor.
|
|
8
|
+
|
|
9
|
+
You receive:
|
|
10
|
+
1. HIGH-RISK CODE SECTIONS extracted via AST analysis (not full files)
|
|
11
|
+
2. STATIC ANALYSIS FINDINGS that need verification
|
|
12
|
+
|
|
13
|
+
Your job:
|
|
14
|
+
- Verify static findings (confirm if they're real vulnerabilities or false positives)
|
|
15
|
+
- Analyze the high-risk code sections for additional issues
|
|
16
|
+
- Report REAL issues only. Do not invent problems.
|
|
17
|
+
- Be harsh but accurate.
|
|
18
|
+
|
|
19
|
+
Detect and report:
|
|
20
|
+
- Security vulnerabilities (injection, XSS, CSRF, auth bypass, secrets in code, insecure crypto, SSRF, path traversal, IDOR, etc.)
|
|
21
|
+
- Production failures waiting to happen (missing error handling, unhandled promises, race conditions, memory leaks, missing timeouts, bad retries)
|
|
22
|
+
- Type/logic errors and wrong assumptions that can crash the app or corrupt data
|
|
23
|
+
- Database risks (SQL injection, N+1, missing transactions, connection leaks, migration hazards, missing indexes on hot paths)
|
|
24
|
+
- Misconfiguration (debug in prod, open CORS, weak session settings)
|
|
25
|
+
- Reliability and scalability issues
|
|
26
|
+
|
|
27
|
+
For static findings:
|
|
28
|
+
- If the code shows proper mitigation (parameterized queries, sanitization, auth middleware), mark as FALSE POSITIVE
|
|
29
|
+
- If the vulnerability is real, CONFIRM it and provide detailed evidence
|
|
30
|
+
- Add context the static analyzer couldn't see
|
|
31
|
+
|
|
32
|
+
Respond with ONLY valid JSON (no markdown fences):
|
|
33
|
+
{
|
|
34
|
+
"findings": [
|
|
35
|
+
{
|
|
36
|
+
"id": "unique-kebab-id",
|
|
37
|
+
"severity": "critical|high|medium|low|info",
|
|
38
|
+
"category": "security|production|typing|logic|database|performance|reliability|configuration|other",
|
|
39
|
+
"title": "short title",
|
|
40
|
+
"description": "detailed explanation",
|
|
41
|
+
"file": "relative/path",
|
|
42
|
+
"line": 0,
|
|
43
|
+
"evidence": "code snippet or behavior",
|
|
44
|
+
"mitigation": "how to fix now",
|
|
45
|
+
"prevention": "how to stop recurrence",
|
|
46
|
+
"confidence": "high|medium|low",
|
|
47
|
+
"source": "static-verified|static-rejected|ai-discovered"
|
|
48
|
+
}
|
|
49
|
+
],
|
|
50
|
+
"notes": "brief batch-level observations",
|
|
51
|
+
"partialScore": 0
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
partialScore is 0-100 for THIS batch only, strict.`;
|
|
55
|
+
exports.SYNTHESIS_SYSTEM_PROMPT = `You are Vettcode Engine synthesizing a final audit report.
|
|
56
|
+
|
|
57
|
+
You receive:
|
|
58
|
+
1. HIGH-CONFIDENCE static analysis findings (already verified)
|
|
59
|
+
2. AI-analyzed findings (verified static + newly discovered)
|
|
60
|
+
|
|
61
|
+
Rules:
|
|
62
|
+
- Merge duplicate findings; keep the strongest severity
|
|
63
|
+
- Prioritize high-confidence findings
|
|
64
|
+
- The overall score (0-100) must be STRICT and HONEST. No sugar-coating.
|
|
65
|
+
- Critical blockers: 0-25
|
|
66
|
+
- Major issues: 25-50
|
|
67
|
+
- Moderate issues: 50-70
|
|
68
|
+
- Minor issues: 70-85
|
|
69
|
+
- Excellent: 85-95
|
|
70
|
+
- Perfect (rare): 95-100
|
|
71
|
+
- grade: letter A+ through F matching the score harshly
|
|
72
|
+
- executiveVerdict: 2-4 blunt sentences a CTO would read
|
|
73
|
+
- criticalBlockers: issues that MUST be fixed before any production deploy
|
|
74
|
+
|
|
75
|
+
Respond with ONLY valid JSON (no markdown):
|
|
76
|
+
{
|
|
77
|
+
"score": 0,
|
|
78
|
+
"grade": "F",
|
|
79
|
+
"summary": "overview",
|
|
80
|
+
"executiveVerdict": "blunt verdict",
|
|
81
|
+
"findings": [... same finding schema ...],
|
|
82
|
+
"strengths": ["only genuine strengths"],
|
|
83
|
+
"criticalBlockers": ["..."],
|
|
84
|
+
"methodology": {
|
|
85
|
+
"staticAnalysisFindings": 0,
|
|
86
|
+
"aiVerifiedFindings": 0,
|
|
87
|
+
"aiDiscoveredFindings": 0,
|
|
88
|
+
"falsePositivesRejected": 0
|
|
89
|
+
}
|
|
90
|
+
}`;
|
|
91
|
+
function buildSmartBatchUserPrompt(projectName, batchIndex, totalBatches, smartContext, staticFindings) {
|
|
92
|
+
let prompt = `Project: ${projectName}
|
|
93
|
+
Batch: ${batchIndex + 1} of ${totalBatches}
|
|
94
|
+
|
|
95
|
+
=== STATIC ANALYSIS FINDINGS TO VERIFY ===
|
|
96
|
+
${staticFindings.length > 0 ? JSON.stringify(staticFindings, null, 2) : "None in this batch"}
|
|
97
|
+
|
|
98
|
+
=== HIGH-RISK CODE SECTIONS (AST-EXTRACTED) ===
|
|
99
|
+
${smartContext}
|
|
100
|
+
|
|
101
|
+
INSTRUCTIONS:
|
|
102
|
+
1. Verify each static finding - check if the vulnerability is real or mitigated
|
|
103
|
+
2. Analyze the high-risk code sections for additional issues
|
|
104
|
+
3. Report only confirmed, real vulnerabilities`;
|
|
105
|
+
return prompt;
|
|
106
|
+
}
|
|
107
|
+
function buildSynthesisUserPrompt(projectName, stats, staticFindings, batchResults) {
|
|
108
|
+
return `Project: ${projectName}
|
|
109
|
+
|
|
110
|
+
=== SCAN STATISTICS ===
|
|
111
|
+
Files scanned: ${stats.files}
|
|
112
|
+
Total lines: ${stats.lines}
|
|
113
|
+
High-risk lines extracted: ${stats.extractedLines} (${stats.compressionRatio}% compression)
|
|
114
|
+
Paths ignored (deps/build): ${stats.ignored}
|
|
115
|
+
|
|
116
|
+
=== HIGH-CONFIDENCE STATIC FINDINGS ===
|
|
117
|
+
${JSON.stringify(staticFindings, null, 2)}
|
|
118
|
+
|
|
119
|
+
=== AI BATCH ANALYSIS RESULTS ===
|
|
120
|
+
${batchResults}
|
|
121
|
+
|
|
122
|
+
Produce the final merged Vettcode report with strict 0-100 score.`;
|
|
123
|
+
}
|
|
124
|
+
function getAnalysisPrompt(projectName, batch, batchIndex) {
|
|
125
|
+
let prompt = `Project: ${projectName}
|
|
126
|
+
Batch: ${batchIndex + 1}
|
|
127
|
+
|
|
128
|
+
=== STATIC ANALYSIS FINDINGS TO VERIFY ===
|
|
129
|
+
${batch.staticFindings.length > 0 ? JSON.stringify(batch.staticFindings, null, 2) : "None in this batch"}
|
|
130
|
+
|
|
131
|
+
=== HIGH-RISK CODE SECTIONS (AST-EXTRACTED) ===
|
|
132
|
+
`;
|
|
133
|
+
for (const extracted of batch.sections) {
|
|
134
|
+
prompt += `\n--- ${extracted.file} ---\n`;
|
|
135
|
+
for (const section of extracted.sections) {
|
|
136
|
+
prompt += `\nLine ${section.startLine}-${section.endLine} (Type: ${section.type}):\n${section.code}\n`;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
prompt += `\nINSTRUCTIONS:
|
|
140
|
+
1. Verify each static finding - check if the vulnerability is real or mitigated
|
|
141
|
+
2. Analyze the high-risk code sections for additional issues
|
|
142
|
+
3. Report only confirmed, real vulnerabilities`;
|
|
143
|
+
return prompt;
|
|
144
|
+
}
|