@darrenjcoxon/vibeguard 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/LICENSE +21 -0
- package/README.md +58 -0
- package/dist/agent-report.d.ts +36 -0
- package/dist/agent-report.d.ts.map +1 -0
- package/dist/agent-report.js +329 -0
- package/dist/agent-report.js.map +1 -0
- package/dist/ai-summary.d.ts +55 -0
- package/dist/ai-summary.d.ts.map +1 -0
- package/dist/ai-summary.js +267 -0
- package/dist/ai-summary.js.map +1 -0
- package/dist/cli.d.ts +9 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +328 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/orchestrator.d.ts +63 -0
- package/dist/orchestrator.d.ts.map +1 -0
- package/dist/orchestrator.js +331 -0
- package/dist/orchestrator.js.map +1 -0
- package/dist/scanners/complexity.d.ts +48 -0
- package/dist/scanners/complexity.d.ts.map +1 -0
- package/dist/scanners/complexity.js +512 -0
- package/dist/scanners/complexity.js.map +1 -0
- package/dist/scanners/eslint.d.ts +21 -0
- package/dist/scanners/eslint.d.ts.map +1 -0
- package/dist/scanners/eslint.js +196 -0
- package/dist/scanners/eslint.js.map +1 -0
- package/dist/scanners/gitleaks.d.ts +21 -0
- package/dist/scanners/gitleaks.d.ts.map +1 -0
- package/dist/scanners/gitleaks.js +158 -0
- package/dist/scanners/gitleaks.js.map +1 -0
- package/dist/scanners/index.d.ts +56 -0
- package/dist/scanners/index.d.ts.map +1 -0
- package/dist/scanners/index.js +71 -0
- package/dist/scanners/index.js.map +1 -0
- package/dist/scanners/npm-audit.d.ts +19 -0
- package/dist/scanners/npm-audit.d.ts.map +1 -0
- package/dist/scanners/npm-audit.js +176 -0
- package/dist/scanners/npm-audit.js.map +1 -0
- package/dist/scanners/semgrep.d.ts +22 -0
- package/dist/scanners/semgrep.d.ts.map +1 -0
- package/dist/scanners/semgrep.js +175 -0
- package/dist/scanners/semgrep.js.map +1 -0
- package/dist/types.d.ts +522 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +194 -0
- package/dist/types.js.map +1 -0
- package/package.json +53 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Kompass Education
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Vibeguard 🛡️
|
|
2
|
+
|
|
3
|
+
Scan your code for security issues. Get a `FIXES.md` file. Give it to Claude Code or Cursor to fix everything.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @darrenjcoxon/vibeguard
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
That's it. Vibeguard automatically installs Semgrep and Gitleaks on first run.
|
|
12
|
+
|
|
13
|
+
## Use
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
cd your-project
|
|
17
|
+
vibeguard
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
This will:
|
|
21
|
+
1. Auto-install any missing scanning tools
|
|
22
|
+
2. Scan for security vulnerabilities, secrets, bad dependencies, code quality issues
|
|
23
|
+
3. Create `FIXES.md` in your project
|
|
24
|
+
4. Tell your AI agent: *"Fix all the issues in FIXES.md"*
|
|
25
|
+
|
|
26
|
+
## What It Finds
|
|
27
|
+
|
|
28
|
+
| Scanner | Issues |
|
|
29
|
+
|---------|--------|
|
|
30
|
+
| **Semgrep** | SQL injection, XSS, command injection, path traversal |
|
|
31
|
+
| **Gitleaks** | API keys, passwords, tokens, secrets |
|
|
32
|
+
| **npm audit** | Vulnerable dependencies |
|
|
33
|
+
| **ESLint** | Code quality issues |
|
|
34
|
+
| **Complexity** | Complex code, TODOs, debug statements |
|
|
35
|
+
|
|
36
|
+
## Commands
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
vibeguard # Scan current directory
|
|
40
|
+
vibeguard /path/to/project # Scan specific path
|
|
41
|
+
vibeguard setup # Manually install scanning tools
|
|
42
|
+
vibeguard check # Check which tools are installed
|
|
43
|
+
vibeguard --no-fixes # Skip FIXES.md generation
|
|
44
|
+
vibeguard --ci # CI mode: exit 1 on high/critical issues
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## CI/CD
|
|
48
|
+
|
|
49
|
+
```yaml
|
|
50
|
+
# GitHub Actions
|
|
51
|
+
- run: |
|
|
52
|
+
npm install -g @darrenjcoxon/vibeguard
|
|
53
|
+
vibeguard --ci
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## License
|
|
57
|
+
|
|
58
|
+
MIT
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Report Generator
|
|
3
|
+
*
|
|
4
|
+
* Generates markdown reports optimized for AI coding agents (Claude Code, Cursor, etc.)
|
|
5
|
+
* to automatically fix security and quality issues
|
|
6
|
+
*/
|
|
7
|
+
import { ScanReport, SeverityLevel } from './types.js';
|
|
8
|
+
export interface AgentReportOptions {
|
|
9
|
+
outputPath?: string;
|
|
10
|
+
includeSnippets?: boolean;
|
|
11
|
+
maxFindings?: number;
|
|
12
|
+
groupByFile?: boolean;
|
|
13
|
+
prioritySeverities?: SeverityLevel[];
|
|
14
|
+
}
|
|
15
|
+
export declare class AgentReportGenerator {
|
|
16
|
+
/**
|
|
17
|
+
* Generate an agent-friendly markdown report
|
|
18
|
+
*/
|
|
19
|
+
generate(report: ScanReport, options?: AgentReportOptions): string;
|
|
20
|
+
/**
|
|
21
|
+
* Generate and save the report
|
|
22
|
+
*/
|
|
23
|
+
generateAndSave(report: ScanReport, outputPath: string, options?: AgentReportOptions): string;
|
|
24
|
+
private generateHeader;
|
|
25
|
+
private generateQuickStats;
|
|
26
|
+
private generateInstructions;
|
|
27
|
+
private generateFindingsByFile;
|
|
28
|
+
private generateFindingsList;
|
|
29
|
+
private formatFinding;
|
|
30
|
+
private getSeverityEmoji;
|
|
31
|
+
private getFixExample;
|
|
32
|
+
private generateChecklist;
|
|
33
|
+
private generateFooter;
|
|
34
|
+
}
|
|
35
|
+
export default AgentReportGenerator;
|
|
36
|
+
//# sourceMappingURL=agent-report.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-report.d.ts","sourceRoot":"","sources":["../src/agent-report.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAW,aAAa,EAAE,MAAM,YAAY,CAAC;AAGhE,MAAM,WAAW,kBAAkB;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,kBAAkB,CAAC,EAAE,aAAa,EAAE,CAAC;CACtC;AAED,qBAAa,oBAAoB;IAE/B;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,GAAE,kBAAuB,GAAG,MAAM;IA6BtE;;OAEG;IACH,eAAe,CAAC,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,GAAE,kBAAuB,GAAG,MAAM;IAMjG,OAAO,CAAC,cAAc;IAetB,OAAO,CAAC,kBAAkB;IAkB1B,OAAO,CAAC,oBAAoB;IA0B5B,OAAO,CAAC,sBAAsB;IA4B9B,OAAO,CAAC,oBAAoB;IAU5B,OAAO,CAAC,aAAa;IAuDrB,OAAO,CAAC,gBAAgB;IAWxB,OAAO,CAAC,aAAa;IAqGrB,OAAO,CAAC,iBAAiB;IAsCzB,OAAO,CAAC,cAAc;CAwBvB;AAED,eAAe,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Report Generator
|
|
3
|
+
*
|
|
4
|
+
* Generates markdown reports optimized for AI coding agents (Claude Code, Cursor, etc.)
|
|
5
|
+
* to automatically fix security and quality issues
|
|
6
|
+
*/
|
|
7
|
+
import { writeFileSync } from 'fs';
|
|
8
|
+
export class AgentReportGenerator {
|
|
9
|
+
/**
|
|
10
|
+
* Generate an agent-friendly markdown report
|
|
11
|
+
*/
|
|
12
|
+
generate(report, options = {}) {
|
|
13
|
+
const { includeSnippets = true, maxFindings = 50, groupByFile = true, prioritySeverities = ['critical', 'high', 'medium'] } = options;
|
|
14
|
+
// Filter to priority findings
|
|
15
|
+
const priorityFindings = report.findings
|
|
16
|
+
.filter(f => prioritySeverities.includes(f.severity))
|
|
17
|
+
.slice(0, maxFindings);
|
|
18
|
+
let md = this.generateHeader(report);
|
|
19
|
+
md += this.generateQuickStats(report);
|
|
20
|
+
md += this.generateInstructions();
|
|
21
|
+
if (groupByFile) {
|
|
22
|
+
md += this.generateFindingsByFile(priorityFindings, includeSnippets);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
md += this.generateFindingsList(priorityFindings, includeSnippets);
|
|
26
|
+
}
|
|
27
|
+
md += this.generateChecklist(priorityFindings);
|
|
28
|
+
md += this.generateFooter(report);
|
|
29
|
+
return md;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Generate and save the report
|
|
33
|
+
*/
|
|
34
|
+
generateAndSave(report, outputPath, options = {}) {
|
|
35
|
+
const markdown = this.generate(report, options);
|
|
36
|
+
writeFileSync(outputPath, markdown, 'utf-8');
|
|
37
|
+
return outputPath;
|
|
38
|
+
}
|
|
39
|
+
generateHeader(report) {
|
|
40
|
+
return `# 🔧 Code Fixes Required
|
|
41
|
+
|
|
42
|
+
> **This report is designed for AI coding agents (Claude Code, Cursor, Copilot, etc.)**
|
|
43
|
+
> Copy this entire file and ask your AI agent to fix these issues.
|
|
44
|
+
|
|
45
|
+
**Project:** \`${report.target.path}\`
|
|
46
|
+
**Scanned:** ${new Date(report.timestamp).toLocaleString()}
|
|
47
|
+
**Quality Gate:** ${report.summary.passesQualityGate ? '✅ PASSED' : '❌ FAILED'}
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
`;
|
|
52
|
+
}
|
|
53
|
+
generateQuickStats(report) {
|
|
54
|
+
const { summary } = report;
|
|
55
|
+
return `## 📊 Summary
|
|
56
|
+
|
|
57
|
+
| Severity | Count | Action |
|
|
58
|
+
|----------|-------|--------|
|
|
59
|
+
| 🔴 Critical | ${summary.bySeverity['critical'] || 0} | **Fix immediately** |
|
|
60
|
+
| 🟠 High | ${summary.bySeverity['high'] || 0} | **Fix before merge** |
|
|
61
|
+
| 🟡 Medium | ${summary.bySeverity['medium'] || 0} | Fix when possible |
|
|
62
|
+
| 🔵 Low | ${summary.bySeverity['low'] || 0} | Consider fixing |
|
|
63
|
+
|
|
64
|
+
**Total issues to fix:** ${(summary.bySeverity['critical'] || 0) + (summary.bySeverity['high'] || 0) + (summary.bySeverity['medium'] || 0)}
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
`;
|
|
69
|
+
}
|
|
70
|
+
generateInstructions() {
|
|
71
|
+
return `## 🤖 Instructions for AI Agent
|
|
72
|
+
|
|
73
|
+
Please fix the issues listed below. For each issue:
|
|
74
|
+
|
|
75
|
+
1. **Read** the description and understand the vulnerability/problem
|
|
76
|
+
2. **Locate** the file and line number specified
|
|
77
|
+
3. **Apply** the suggested fix or implement a secure alternative
|
|
78
|
+
4. **Verify** the fix doesn't break existing functionality
|
|
79
|
+
|
|
80
|
+
### Priority Order
|
|
81
|
+
Fix issues in this order: Critical → High → Medium
|
|
82
|
+
|
|
83
|
+
### General Guidelines
|
|
84
|
+
- **SQL Injection**: Use parameterized queries or prepared statements
|
|
85
|
+
- **XSS**: Sanitize/escape user input, use template engines with auto-escaping
|
|
86
|
+
- **Command Injection**: Avoid \`exec()\` with user input, use safe APIs
|
|
87
|
+
- **Path Traversal**: Validate and sanitize file paths, use allowlists
|
|
88
|
+
- **Hardcoded Secrets**: Move to environment variables or secret managers
|
|
89
|
+
- **Eval Usage**: Replace with safer alternatives like \`JSON.parse()\`
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
`;
|
|
94
|
+
}
|
|
95
|
+
generateFindingsByFile(findings, includeSnippets) {
|
|
96
|
+
// Group findings by file
|
|
97
|
+
const byFile = new Map();
|
|
98
|
+
for (const finding of findings) {
|
|
99
|
+
const file = finding.file;
|
|
100
|
+
if (!byFile.has(file)) {
|
|
101
|
+
byFile.set(file, []);
|
|
102
|
+
}
|
|
103
|
+
byFile.get(file).push(finding);
|
|
104
|
+
}
|
|
105
|
+
let md = `## 🔍 Issues by File\n\n`;
|
|
106
|
+
for (const [file, fileFindings] of byFile) {
|
|
107
|
+
// Sort by line number within file
|
|
108
|
+
fileFindings.sort((a, b) => (a.line || 0) - (b.line || 0));
|
|
109
|
+
md += `### 📄 \`${file}\`\n\n`;
|
|
110
|
+
for (const finding of fileFindings) {
|
|
111
|
+
md += this.formatFinding(finding, includeSnippets);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return md;
|
|
115
|
+
}
|
|
116
|
+
generateFindingsList(findings, includeSnippets) {
|
|
117
|
+
let md = `## 🔍 All Issues\n\n`;
|
|
118
|
+
for (const finding of findings) {
|
|
119
|
+
md += this.formatFinding(finding, includeSnippets);
|
|
120
|
+
}
|
|
121
|
+
return md;
|
|
122
|
+
}
|
|
123
|
+
formatFinding(finding, includeSnippets) {
|
|
124
|
+
const severityEmoji = this.getSeverityEmoji(finding.severity);
|
|
125
|
+
const lineInfo = finding.line ? `:${finding.line}` : '';
|
|
126
|
+
let md = `#### ${severityEmoji} ${finding.title}
|
|
127
|
+
|
|
128
|
+
**Location:** \`${finding.file}${lineInfo}\`
|
|
129
|
+
**Severity:** ${finding.severity.toUpperCase()}
|
|
130
|
+
**Category:** ${finding.category}
|
|
131
|
+
`;
|
|
132
|
+
if (finding.cwe) {
|
|
133
|
+
md += `**CWE:** ${finding.cwe} \n`;
|
|
134
|
+
}
|
|
135
|
+
md += `
|
|
136
|
+
**Problem:**
|
|
137
|
+
${finding.description}
|
|
138
|
+
|
|
139
|
+
`;
|
|
140
|
+
if (finding.snippet && includeSnippets) {
|
|
141
|
+
md += `**Current Code:**
|
|
142
|
+
\`\`\`javascript
|
|
143
|
+
${finding.snippet}
|
|
144
|
+
\`\`\`
|
|
145
|
+
|
|
146
|
+
`;
|
|
147
|
+
}
|
|
148
|
+
if (finding.suggestion) {
|
|
149
|
+
md += `**Fix:**
|
|
150
|
+
${finding.suggestion}
|
|
151
|
+
|
|
152
|
+
`;
|
|
153
|
+
}
|
|
154
|
+
// Add specific fix examples for common issues
|
|
155
|
+
const fixExample = this.getFixExample(finding);
|
|
156
|
+
if (fixExample) {
|
|
157
|
+
md += `**Example Fix:**
|
|
158
|
+
\`\`\`javascript
|
|
159
|
+
${fixExample}
|
|
160
|
+
\`\`\`
|
|
161
|
+
|
|
162
|
+
`;
|
|
163
|
+
}
|
|
164
|
+
md += `---
|
|
165
|
+
|
|
166
|
+
`;
|
|
167
|
+
return md;
|
|
168
|
+
}
|
|
169
|
+
getSeverityEmoji(severity) {
|
|
170
|
+
const emojis = {
|
|
171
|
+
critical: '🔴',
|
|
172
|
+
high: '🟠',
|
|
173
|
+
medium: '🟡',
|
|
174
|
+
low: '🔵',
|
|
175
|
+
info: 'ℹ️'
|
|
176
|
+
};
|
|
177
|
+
return emojis[severity];
|
|
178
|
+
}
|
|
179
|
+
getFixExample(finding) {
|
|
180
|
+
const ruleId = finding.ruleId?.toLowerCase() || '';
|
|
181
|
+
const title = finding.title.toLowerCase();
|
|
182
|
+
// SQL Injection
|
|
183
|
+
if (ruleId.includes('sql') || title.includes('sql-injection')) {
|
|
184
|
+
return `// Instead of string concatenation:
|
|
185
|
+
// const query = "SELECT * FROM users WHERE id = " + userId;
|
|
186
|
+
|
|
187
|
+
// Use parameterized queries:
|
|
188
|
+
const query = "SELECT * FROM users WHERE id = ?";
|
|
189
|
+
db.query(query, [userId]);`;
|
|
190
|
+
}
|
|
191
|
+
// Command Injection
|
|
192
|
+
if (ruleId.includes('child-process') || ruleId.includes('command')) {
|
|
193
|
+
return `// Instead of:
|
|
194
|
+
// exec("ls " + userInput);
|
|
195
|
+
|
|
196
|
+
// Use execFile with arguments array:
|
|
197
|
+
const { execFile } = require('child_process');
|
|
198
|
+
execFile('ls', [sanitizedPath], (err, stdout) => {
|
|
199
|
+
console.log(stdout);
|
|
200
|
+
});`;
|
|
201
|
+
}
|
|
202
|
+
// XSS
|
|
203
|
+
if (ruleId.includes('xss') || title.includes('xss') || ruleId.includes('raw-html')) {
|
|
204
|
+
return `// Instead of:
|
|
205
|
+
// res.send(\`<h1>Results for: \${query}</h1>\`);
|
|
206
|
+
|
|
207
|
+
// Use a template engine with auto-escaping, or sanitize:
|
|
208
|
+
const sanitizeHtml = require('sanitize-html');
|
|
209
|
+
const safeQuery = sanitizeHtml(query);
|
|
210
|
+
res.send(\`<h1>Results for: \${safeQuery}</h1>\`);
|
|
211
|
+
|
|
212
|
+
// Or better, use res.render() with a template engine`;
|
|
213
|
+
}
|
|
214
|
+
// Path Traversal
|
|
215
|
+
if (ruleId.includes('path-traversal') || ruleId.includes('sendfile')) {
|
|
216
|
+
return `// Instead of:
|
|
217
|
+
// const filePath = path.join('/var/www/files', filename);
|
|
218
|
+
|
|
219
|
+
// Validate the resolved path stays within allowed directory:
|
|
220
|
+
const path = require('path');
|
|
221
|
+
const baseDir = '/var/www/files';
|
|
222
|
+
const filePath = path.join(baseDir, filename);
|
|
223
|
+
const resolvedPath = path.resolve(filePath);
|
|
224
|
+
|
|
225
|
+
if (!resolvedPath.startsWith(baseDir)) {
|
|
226
|
+
return res.status(403).send('Access denied');
|
|
227
|
+
}
|
|
228
|
+
res.sendFile(resolvedPath);`;
|
|
229
|
+
}
|
|
230
|
+
// Eval
|
|
231
|
+
if (ruleId.includes('eval') || title.includes('eval')) {
|
|
232
|
+
return `// Instead of:
|
|
233
|
+
// eval(userCode);
|
|
234
|
+
|
|
235
|
+
// For JSON parsing:
|
|
236
|
+
const data = JSON.parse(jsonString);
|
|
237
|
+
|
|
238
|
+
// For dynamic property access:
|
|
239
|
+
const value = obj[propertyName];
|
|
240
|
+
|
|
241
|
+
// For math expressions, use a safe parser:
|
|
242
|
+
const mathjs = require('mathjs');
|
|
243
|
+
const result = mathjs.evaluate(expression);`;
|
|
244
|
+
}
|
|
245
|
+
// Hardcoded secrets
|
|
246
|
+
if (finding.category === 'secret' || ruleId.includes('secret') || ruleId.includes('password')) {
|
|
247
|
+
return `// Instead of:
|
|
248
|
+
// const API_KEY = "sk-1234567890";
|
|
249
|
+
|
|
250
|
+
// Use environment variables:
|
|
251
|
+
const API_KEY = process.env.API_KEY;
|
|
252
|
+
|
|
253
|
+
// Or use a secrets manager:
|
|
254
|
+
const { SecretManagerServiceClient } = require('@google-cloud/secret-manager');`;
|
|
255
|
+
}
|
|
256
|
+
// CSRF
|
|
257
|
+
if (ruleId.includes('csrf') || ruleId.includes('csurf')) {
|
|
258
|
+
return `// Add CSRF protection middleware:
|
|
259
|
+
const csrf = require('csurf');
|
|
260
|
+
const csrfProtection = csrf({ cookie: true });
|
|
261
|
+
|
|
262
|
+
app.use(csrfProtection);
|
|
263
|
+
|
|
264
|
+
// Include token in forms:
|
|
265
|
+
app.get('/form', (req, res) => {
|
|
266
|
+
res.render('form', { csrfToken: req.csrfToken() });
|
|
267
|
+
});`;
|
|
268
|
+
}
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
271
|
+
generateChecklist(findings) {
|
|
272
|
+
let md = `## ✅ Fix Checklist
|
|
273
|
+
|
|
274
|
+
Use this checklist to track your progress:
|
|
275
|
+
|
|
276
|
+
`;
|
|
277
|
+
const critical = findings.filter(f => f.severity === 'critical');
|
|
278
|
+
const high = findings.filter(f => f.severity === 'high');
|
|
279
|
+
const medium = findings.filter(f => f.severity === 'medium');
|
|
280
|
+
if (critical.length > 0) {
|
|
281
|
+
md += `### Critical (Must Fix)\n`;
|
|
282
|
+
for (const f of critical) {
|
|
283
|
+
md += `- [ ] ${f.title} in \`${f.file}${f.line ? `:${f.line}` : ''}\`\n`;
|
|
284
|
+
}
|
|
285
|
+
md += '\n';
|
|
286
|
+
}
|
|
287
|
+
if (high.length > 0) {
|
|
288
|
+
md += `### High Priority\n`;
|
|
289
|
+
for (const f of high) {
|
|
290
|
+
md += `- [ ] ${f.title} in \`${f.file}${f.line ? `:${f.line}` : ''}\`\n`;
|
|
291
|
+
}
|
|
292
|
+
md += '\n';
|
|
293
|
+
}
|
|
294
|
+
if (medium.length > 0) {
|
|
295
|
+
md += `### Medium Priority\n`;
|
|
296
|
+
for (const f of medium) {
|
|
297
|
+
md += `- [ ] ${f.title} in \`${f.file}${f.line ? `:${f.line}` : ''}\`\n`;
|
|
298
|
+
}
|
|
299
|
+
md += '\n';
|
|
300
|
+
}
|
|
301
|
+
return md;
|
|
302
|
+
}
|
|
303
|
+
generateFooter(report) {
|
|
304
|
+
return `---
|
|
305
|
+
|
|
306
|
+
## 🔄 After Fixing
|
|
307
|
+
|
|
308
|
+
Once you've fixed the issues:
|
|
309
|
+
|
|
310
|
+
1. **Run the scan again** to verify fixes:
|
|
311
|
+
\`\`\`bash
|
|
312
|
+
vibeguard scan ${report.target.path}
|
|
313
|
+
\`\`\`
|
|
314
|
+
|
|
315
|
+
2. **Commit your changes** with a descriptive message:
|
|
316
|
+
\`\`\`bash
|
|
317
|
+
git commit -m "fix: resolve security vulnerabilities from Vibeguard scan"
|
|
318
|
+
\`\`\`
|
|
319
|
+
|
|
320
|
+
3. **Review the changes** to ensure no functionality was broken
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
*Generated by [Vibeguard](https://github.com/kompass-edu/vibeguard) - AI-powered code security scanner*
|
|
325
|
+
`;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
export default AgentReportGenerator;
|
|
329
|
+
//# sourceMappingURL=agent-report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-report.js","sourceRoot":"","sources":["../src/agent-report.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Summary Generator
|
|
3
|
+
*
|
|
4
|
+
* Uses Claude to generate intelligent summaries and recommendations
|
|
5
|
+
*/
|
|
6
|
+
import { ScanReport } from './types.js';
|
|
7
|
+
export interface AISummaryConfig {
|
|
8
|
+
apiKey?: string;
|
|
9
|
+
model?: string;
|
|
10
|
+
maxTokens?: number;
|
|
11
|
+
}
|
|
12
|
+
export declare class AISummaryGenerator {
|
|
13
|
+
private client;
|
|
14
|
+
private model;
|
|
15
|
+
private maxTokens;
|
|
16
|
+
constructor(config?: AISummaryConfig);
|
|
17
|
+
/**
|
|
18
|
+
* Check if AI summarization is available
|
|
19
|
+
*/
|
|
20
|
+
isAvailable(): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Generate an AI summary of the scan report
|
|
23
|
+
*/
|
|
24
|
+
generateSummary(report: ScanReport): Promise<string>;
|
|
25
|
+
/**
|
|
26
|
+
* Generate AI recommendations for fixing issues
|
|
27
|
+
*/
|
|
28
|
+
generateRecommendations(report: ScanReport): Promise<string[]>;
|
|
29
|
+
/**
|
|
30
|
+
* Generate a PR comment summary
|
|
31
|
+
*/
|
|
32
|
+
generatePRComment(report: ScanReport): Promise<string>;
|
|
33
|
+
/**
|
|
34
|
+
* Build the summary prompt
|
|
35
|
+
*/
|
|
36
|
+
private buildSummaryPrompt;
|
|
37
|
+
/**
|
|
38
|
+
* Build the recommendations prompt
|
|
39
|
+
*/
|
|
40
|
+
private buildRecommendationsPrompt;
|
|
41
|
+
/**
|
|
42
|
+
* Build the PR comment prompt
|
|
43
|
+
*/
|
|
44
|
+
private buildPRCommentPrompt;
|
|
45
|
+
/**
|
|
46
|
+
* Summarize findings for prompts
|
|
47
|
+
*/
|
|
48
|
+
private summarizeFindings;
|
|
49
|
+
/**
|
|
50
|
+
* Generate a fallback PR comment without AI
|
|
51
|
+
*/
|
|
52
|
+
private generateFallbackPRComment;
|
|
53
|
+
}
|
|
54
|
+
export default AISummaryGenerator;
|
|
55
|
+
//# sourceMappingURL=ai-summary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-summary.d.ts","sourceRoot":"","sources":["../src/ai-summary.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,UAAU,EAAW,MAAM,YAAY,CAAC;AAEjD,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,SAAS,CAAS;gBAEd,MAAM,GAAE,eAAoB;IAWxC;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB;;OAEG;IACG,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;IA4B1D;;OAEG;IACG,uBAAuB,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAkCpE;;OAEG;IACG,iBAAiB,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;IA2B5D;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAmC1B;;OAEG;IACH,OAAO,CAAC,0BAA0B;IA0BlC;;OAEG;IACH,OAAO,CAAC,oBAAoB;IA2B5B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IASzB;;OAEG;IACH,OAAO,CAAC,yBAAyB;CAwDlC;AAED,eAAe,kBAAkB,CAAC"}
|