codeprobe-scanner 1.0.9 → 1.0.11
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/README.md +202 -8
- package/package.json +2 -2
- package/src/cli/commands/scan-with-fix.ts +100 -74
- package/src/engine/index.ts +5 -2
package/README.md
CHANGED
|
@@ -1,15 +1,209 @@
|
|
|
1
|
-
#
|
|
1
|
+
# CodeProbe
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Automated vulnerability scanner for Node.js / npm projects. Scans dependencies against OSV.dev and the GitHub Advisory Database, verifies exploits in isolated sandboxes, and optionally auto-patches vulnerable packages.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm install -g codeprobe-scanner
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Or run without installing:
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
npx codeprobe-scanner scan
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
# Scan the current directory
|
|
21
|
+
codeprobe scan
|
|
22
|
+
|
|
23
|
+
# Scan a specific project
|
|
24
|
+
codeprobe scan ./my-app
|
|
25
|
+
|
|
26
|
+
# Scan and auto-fix vulnerabilities
|
|
27
|
+
codeprobe scan --fix
|
|
28
|
+
|
|
29
|
+
# Output results as JSON
|
|
30
|
+
codeprobe scan --json > report.json
|
|
31
|
+
|
|
32
|
+
# Show the last scan report
|
|
33
|
+
codeprobe report
|
|
7
34
|
```
|
|
8
35
|
|
|
9
|
-
|
|
36
|
+
## Commands
|
|
37
|
+
|
|
38
|
+
### `codeprobe scan [path]`
|
|
39
|
+
|
|
40
|
+
Scans a repository for known CVEs in its npm dependencies.
|
|
41
|
+
|
|
42
|
+
| Flag | Description |
|
|
43
|
+
|------|-------------|
|
|
44
|
+
| `--fix` | Auto-fix: upgrades vulnerable packages, creates a git branch and commit |
|
|
45
|
+
| `--json` | Print results as JSON (pipe-friendly) |
|
|
46
|
+
| `--verbose` | Show detailed phase-by-phase logs |
|
|
47
|
+
|
|
48
|
+
**What it does:**
|
|
49
|
+
|
|
50
|
+
1. Parses `package.json` / `package-lock.json` / `bun.lock` for installed packages and versions
|
|
51
|
+
2. Queries **OSV.dev** for CVEs matching each package+version
|
|
52
|
+
3. Cross-references the **GitHub Advisory Database** for additional intelligence
|
|
53
|
+
4. Runs exploit verification in an isolated **Daytona sandbox** (when configured)
|
|
54
|
+
5. Saves the report to `~/.codeprobe/scans/<scan-id>.json`
|
|
55
|
+
6. Displays a risk score, CVE table, and recent npm threat feed
|
|
10
56
|
|
|
11
|
-
|
|
12
|
-
|
|
57
|
+
**Exit codes:**
|
|
58
|
+
|
|
59
|
+
| Code | Meaning |
|
|
60
|
+
|------|---------|
|
|
61
|
+
| `0` | No vulnerabilities found |
|
|
62
|
+
| `1` | Vulnerabilities found |
|
|
63
|
+
| `2` | Scan failed |
|
|
64
|
+
|
|
65
|
+
### `codeprobe report`
|
|
66
|
+
|
|
67
|
+
Displays the most recent scan results from `~/.codeprobe/scans/latest.json`.
|
|
68
|
+
|
|
69
|
+
### `codeprobe config set <key> <value>`
|
|
70
|
+
|
|
71
|
+
Saves a configuration value to `~/.codeprobe/config.json`.
|
|
72
|
+
|
|
73
|
+
```sh
|
|
74
|
+
codeprobe config set bright_data_api_key YOUR_KEY
|
|
75
|
+
codeprobe config set daytona_api_key YOUR_KEY
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Configuration
|
|
79
|
+
|
|
80
|
+
CodeProbe works out of the box with zero configuration using public APIs. Optional integrations unlock deeper exploit verification.
|
|
81
|
+
|
|
82
|
+
### Environment Variables
|
|
83
|
+
|
|
84
|
+
| Variable | Description |
|
|
85
|
+
|----------|-------------|
|
|
86
|
+
| `BRIGHT_DATA_API_KEY` | Bright Data scraping proxy (optional) |
|
|
87
|
+
| `DAYTONA_API_KEY` | Daytona sandbox for exploit verification (optional) |
|
|
88
|
+
| `NOSANA_API_KEY` | Nosana LLM for AI-assisted analysis (optional) |
|
|
89
|
+
| `GITHUB_TOKEN` | GitHub token for higher Advisory API rate limits |
|
|
90
|
+
| `PORT` | API server port (default: `3000`) |
|
|
91
|
+
|
|
92
|
+
Create a `.env` file in your project root or export variables in your shell.
|
|
93
|
+
|
|
94
|
+
## How It Works
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
package.json / lockfile
|
|
98
|
+
↓
|
|
99
|
+
Dependency Parser
|
|
100
|
+
↓
|
|
101
|
+
OSV.dev + GitHub Advisory DB ──→ CVE list
|
|
102
|
+
↓
|
|
103
|
+
Sandbox Exploit Verification ──→ Confirmed / Theoretical
|
|
104
|
+
↓
|
|
105
|
+
Risk Score + Report
|
|
13
106
|
```
|
|
14
107
|
|
|
15
|
-
|
|
108
|
+
- **Risk score** = (confirmed exploitable × 10) + (theoretical × 3)
|
|
109
|
+
- Scans are saved locally at `~/.codeprobe/scans/`
|
|
110
|
+
- `latest.json` always points to the most recent scan
|
|
111
|
+
|
|
112
|
+
## Auto-Fix (`--fix`)
|
|
113
|
+
|
|
114
|
+
When `--fix` is passed, CodeProbe:
|
|
115
|
+
|
|
116
|
+
1. Identifies vulnerable packages that have a patched version available
|
|
117
|
+
2. Updates `package.json` to the safe version
|
|
118
|
+
3. Runs `bun install` (or `npm install`) to apply the change
|
|
119
|
+
4. Creates a git commit on a new branch: `codeprobe-fix/<scan-id>`
|
|
120
|
+
|
|
121
|
+
Review the branch and open a PR — no changes are pushed automatically.
|
|
122
|
+
|
|
123
|
+
## API Server
|
|
124
|
+
|
|
125
|
+
Start the REST API server:
|
|
126
|
+
|
|
127
|
+
```sh
|
|
128
|
+
bun run src/api/server.ts
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
| Endpoint | Method | Description |
|
|
132
|
+
|----------|--------|-------------|
|
|
133
|
+
| `POST /api/scan` | POST | Trigger a scan (`{ "repoPath": "./path" }`) |
|
|
134
|
+
| `GET /api/scans` | GET | List all past scans (requires auth) |
|
|
135
|
+
| `GET /api/scans/:id` | GET | Get a specific scan (requires auth) |
|
|
136
|
+
| `GET /api/auth/github` | GET | GitHub OAuth callback |
|
|
137
|
+
| `GET /api/auth/logout` | GET | Logout |
|
|
138
|
+
|
|
139
|
+
Authentication: pass a `Bearer <token>` header. In development mode any non-empty token is accepted.
|
|
140
|
+
|
|
141
|
+
## Docker
|
|
142
|
+
|
|
143
|
+
```sh
|
|
144
|
+
docker build -t codeprobe .
|
|
145
|
+
docker run -e PORT=8080 -p 8080:8080 codeprobe
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## GitHub Actions
|
|
149
|
+
|
|
150
|
+
Add CodeProbe to your CI pipeline:
|
|
151
|
+
|
|
152
|
+
```yaml
|
|
153
|
+
# .github/workflows/codeprobe-scan.yml
|
|
154
|
+
name: Security Scan
|
|
155
|
+
on: [push, pull_request]
|
|
156
|
+
jobs:
|
|
157
|
+
scan:
|
|
158
|
+
runs-on: ubuntu-latest
|
|
159
|
+
steps:
|
|
160
|
+
- uses: actions/checkout@v3
|
|
161
|
+
- run: npx codeprobe-scanner scan --json > report.json
|
|
162
|
+
- uses: actions/upload-artifact@v3
|
|
163
|
+
with:
|
|
164
|
+
name: security-report
|
|
165
|
+
path: report.json
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Output Example
|
|
169
|
+
|
|
170
|
+
```
|
|
171
|
+
╔══════════════════════════════════════════╗
|
|
172
|
+
║ CodeProbe Scanner ║
|
|
173
|
+
╚══════════════════════════════════════════╝
|
|
174
|
+
|
|
175
|
+
SCAN COMPLETE
|
|
176
|
+
Risk Score: 🔴 HIGH (43)
|
|
177
|
+
Confirmed Exploitable: 2 | Theoretical Risk: 5
|
|
178
|
+
Patches Available: 3
|
|
179
|
+
Duration: 8.3s
|
|
180
|
+
|
|
181
|
+
CVE Details:
|
|
182
|
+
CVE-2022-29078: ejs 3.1.6 [CRITICAL] ✓ CONFIRMED EXPLOITABLE
|
|
183
|
+
→ Patch available: 3.1.7
|
|
184
|
+
CVE-2023-44487: http2-server 1.0.0 [HIGH] ✓ CONFIRMED EXPLOITABLE
|
|
185
|
+
→ Patch available: 1.0.1
|
|
186
|
+
|
|
187
|
+
🌐 Recent npm Security Threats (GitHub Advisory Database):
|
|
188
|
+
CRITICAL lodash - Prototype Pollution
|
|
189
|
+
HIGH axios - SSRF via redirect
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## Project Structure
|
|
193
|
+
|
|
194
|
+
```
|
|
195
|
+
src/
|
|
196
|
+
├── cli/ # CLI entry point and commands (scan, report, config)
|
|
197
|
+
├── engine/ # Core scanner: parser, scraper, sandbox, patcher
|
|
198
|
+
├── api/ # REST API server
|
|
199
|
+
├── shared/ # Types, constants, utilities
|
|
200
|
+
├── integrations/ # VideoDB, Daytona, Nosana integrations
|
|
201
|
+
├── bot/ # Bot server
|
|
202
|
+
└── mcp/ # MCP server
|
|
203
|
+
bin/
|
|
204
|
+
└── codeprobe.cjs # CLI binary entry point
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## License
|
|
208
|
+
|
|
209
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeprobe-scanner",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.11",
|
|
4
4
|
"description": "Automated vulnerability scanner with exploit verification and video evidence",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"@daytona/sdk": "^0.187.0",
|
|
17
|
-
"axios": "^1.
|
|
17
|
+
"axios": "^1.16.0",
|
|
18
18
|
"chalk": "^5.3.0",
|
|
19
19
|
"cli-table3": "^0.6.3",
|
|
20
20
|
"dayjs": "^1.11.10",
|
|
@@ -1,22 +1,16 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { execSync } from 'child_process';
|
|
3
|
+
import { readFileSync, writeFileSync } from 'fs';
|
|
4
|
+
import path from 'path';
|
|
3
5
|
import dayjs from 'dayjs';
|
|
4
6
|
import { Report } from '../../shared/types.js';
|
|
5
7
|
import { ProgressLogger } from '../progress.js';
|
|
6
8
|
import { GitError, handleError } from '../errors.js';
|
|
7
9
|
import { EXIT_CODES } from '../../shared/constants.js';
|
|
8
10
|
|
|
9
|
-
function getGitStatus(): string {
|
|
10
|
-
try {
|
|
11
|
-
return execSync('git status --porcelain', { encoding: 'utf-8' });
|
|
12
|
-
} catch {
|
|
13
|
-
throw new GitError('Not a git repository');
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
11
|
function checkGitRepo(): boolean {
|
|
18
12
|
try {
|
|
19
|
-
execSync('git rev-parse --git-dir', { encoding: 'utf-8' });
|
|
13
|
+
execSync('git rev-parse --git-dir', { encoding: 'utf-8', stdio: 'pipe' });
|
|
20
14
|
return true;
|
|
21
15
|
} catch {
|
|
22
16
|
return false;
|
|
@@ -24,25 +18,48 @@ function checkGitRepo(): boolean {
|
|
|
24
18
|
}
|
|
25
19
|
|
|
26
20
|
function isGitDirty(): boolean {
|
|
27
|
-
|
|
28
|
-
|
|
21
|
+
try {
|
|
22
|
+
const status = execSync('git status --porcelain', { encoding: 'utf-8', stdio: 'pipe' });
|
|
23
|
+
return status.trim().length > 0;
|
|
24
|
+
} catch {
|
|
25
|
+
throw new GitError('Not a git repository');
|
|
26
|
+
}
|
|
29
27
|
}
|
|
30
28
|
|
|
31
29
|
function createBranch(name: string): void {
|
|
32
30
|
try {
|
|
33
|
-
execSync(`git checkout -b ${name}`, { encoding: 'utf-8' });
|
|
34
|
-
} catch
|
|
31
|
+
execSync(`git checkout -b ${name}`, { encoding: 'utf-8', stdio: 'pipe' });
|
|
32
|
+
} catch {
|
|
35
33
|
throw new GitError(`Failed to create branch: ${name}`);
|
|
36
34
|
}
|
|
37
35
|
}
|
|
38
36
|
|
|
39
|
-
function
|
|
37
|
+
function commitAndPush(message: string, branchName: string): void {
|
|
38
|
+
execSync('git add package.json', { encoding: 'utf-8', stdio: 'pipe' });
|
|
39
|
+
execSync(`git commit -m "${message}"`, { encoding: 'utf-8', stdio: 'pipe' });
|
|
40
40
|
try {
|
|
41
|
-
execSync(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
execSync(`git push -u origin ${branchName}`, { encoding: 'utf-8', stdio: 'pipe' });
|
|
42
|
+
} catch {
|
|
43
|
+
// Push failed — not fatal, user can push manually
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function applyVersionBumps(
|
|
48
|
+
repoPath: string,
|
|
49
|
+
bumps: Array<{ package: string; from: string; to: string }>
|
|
50
|
+
): void {
|
|
51
|
+
const pkgPath = path.join(repoPath, 'package.json');
|
|
52
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
53
|
+
|
|
54
|
+
for (const bump of bumps) {
|
|
55
|
+
if (pkg.dependencies?.[bump.package]) {
|
|
56
|
+
pkg.dependencies[bump.package] = `^${bump.to}`;
|
|
57
|
+
} else if (pkg.devDependencies?.[bump.package]) {
|
|
58
|
+
pkg.devDependencies[bump.package] = `^${bump.to}`;
|
|
59
|
+
}
|
|
45
60
|
}
|
|
61
|
+
|
|
62
|
+
writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
|
|
46
63
|
}
|
|
47
64
|
|
|
48
65
|
export async function scanWithFixCommand(
|
|
@@ -52,72 +69,81 @@ export async function scanWithFixCommand(
|
|
|
52
69
|
): Promise<void> {
|
|
53
70
|
console.log('');
|
|
54
71
|
logger.printSeparator();
|
|
55
|
-
logger.logPhaseStart('git', 'Preparing to apply patches');
|
|
56
72
|
|
|
57
|
-
|
|
58
|
-
// Check git repo exists
|
|
59
|
-
if (!checkGitRepo()) {
|
|
60
|
-
throw new GitError('Not a git repository. Run: git init');
|
|
61
|
-
}
|
|
73
|
+
const repoPath = path.resolve(args[0] || '.');
|
|
62
74
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
75
|
+
// Collect CVEs that have a known fixed version
|
|
76
|
+
const fixable = report.scan.cves.filter(
|
|
77
|
+
(cve) => cve.version_fixed && cve.version_fixed.trim() !== ''
|
|
78
|
+
);
|
|
68
79
|
|
|
69
|
-
|
|
70
|
-
|
|
80
|
+
if (fixable.length === 0) {
|
|
81
|
+
console.log(chalk.yellow('⚠️ No CVEs with known fixes found.'));
|
|
82
|
+
console.log(chalk.dim(' All vulnerabilities are either unpatched or already on the latest version.'));
|
|
83
|
+
process.exit(EXIT_CODES.SUCCESS);
|
|
84
|
+
}
|
|
71
85
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
86
|
+
// Deduplicate: one bump per package (use highest fixed version)
|
|
87
|
+
const bumpMap = new Map<string, { from: string; to: string; cves: string[] }>();
|
|
88
|
+
for (const cve of fixable) {
|
|
89
|
+
const existing = bumpMap.get(cve.package);
|
|
90
|
+
if (!existing) {
|
|
91
|
+
bumpMap.set(cve.package, {
|
|
92
|
+
from: cve.version_vulnerable,
|
|
93
|
+
to: cve.version_fixed!,
|
|
94
|
+
cves: [cve.id],
|
|
95
|
+
});
|
|
96
|
+
} else {
|
|
97
|
+
existing.cves.push(cve.id);
|
|
75
98
|
}
|
|
99
|
+
}
|
|
76
100
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
101
|
+
const bumps = Array.from(bumpMap.entries()).map(([pkg, info]) => ({
|
|
102
|
+
package: pkg,
|
|
103
|
+
...info,
|
|
104
|
+
}));
|
|
105
|
+
|
|
106
|
+
// Show what will be changed
|
|
107
|
+
console.log(chalk.bold(`\n📦 ${bumps.length} package(s) can be updated:\n`));
|
|
108
|
+
for (const b of bumps) {
|
|
109
|
+
console.log(
|
|
110
|
+
` ${chalk.cyan(b.package)}: ${chalk.red(b.from)} → ${chalk.green(b.to)}`
|
|
111
|
+
);
|
|
112
|
+
console.log(chalk.dim(` Fixes: ${b.cves.slice(0, 3).join(', ')}${b.cves.length > 3 ? ` +${b.cves.length - 3} more` : ''}`));
|
|
113
|
+
}
|
|
80
114
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
115
|
+
// Check git repo
|
|
116
|
+
if (!checkGitRepo()) {
|
|
117
|
+
console.log(chalk.yellow('\n⚠️ Not a git repository — applying fixes without committing.'));
|
|
118
|
+
applyVersionBumps(repoPath, bumps);
|
|
119
|
+
console.log(chalk.green('\n✓ package.json updated. Run your package manager to install.'));
|
|
120
|
+
process.exit(EXIT_CODES.SUCCESS);
|
|
121
|
+
}
|
|
84
122
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
123
|
+
if (isGitDirty()) {
|
|
124
|
+
console.log(chalk.yellow('\n⚠️ Uncommitted changes detected — applying fixes without committing.'));
|
|
125
|
+
applyVersionBumps(repoPath, bumps);
|
|
126
|
+
console.log(chalk.green('\n✓ package.json updated. Commit when ready.'));
|
|
127
|
+
process.exit(EXIT_CODES.SUCCESS);
|
|
128
|
+
}
|
|
88
129
|
|
|
89
|
-
|
|
130
|
+
// Create branch and apply fixes
|
|
131
|
+
const branchName = `codeprobe-fix-${dayjs().format('YYYY-MM-DD-HHmmss')}`;
|
|
132
|
+
console.log(chalk.dim(`\nCreating branch: ${branchName}`));
|
|
133
|
+
createBranch(branchName);
|
|
90
134
|
|
|
91
|
-
|
|
92
|
-
|
|
135
|
+
applyVersionBumps(repoPath, bumps);
|
|
136
|
+
console.log(chalk.green('\n✓ package.json updated'));
|
|
93
137
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
logger.logPhaseComplete('patch', `Patched ${cve.package}: ${cve.version_vulnerable} → ${cve.patch_version}`);
|
|
97
|
-
}
|
|
138
|
+
const commitMsg = `security: bump ${bumps.length} vulnerable package(s) via codeprobe\\n\\n${bumps.map(b => `- ${b.package}: ${b.from} -> ${b.to}`).join('\\n')}`;
|
|
139
|
+
commitAndPush(commitMsg, branchName);
|
|
98
140
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
commitChanges(commitMsg);
|
|
108
|
-
logger.logPhaseComplete('git', 'Changes committed');
|
|
109
|
-
|
|
110
|
-
// Show what to do next
|
|
111
|
-
console.log('');
|
|
112
|
-
console.log(chalk.green('✓ Patches applied successfully!'));
|
|
113
|
-
console.log(chalk.cyan(`\nNext steps:`));
|
|
114
|
-
console.log(chalk.cyan(` 1. Review changes: git diff main`));
|
|
115
|
-
console.log(chalk.cyan(` 2. Push branch: git push -u origin ${branchName}`));
|
|
116
|
-
console.log(chalk.cyan(` 3. Create PR on GitHub`));
|
|
117
|
-
|
|
118
|
-
logger.printSeparator();
|
|
119
|
-
process.exit(EXIT_CODES.SUCCESS);
|
|
120
|
-
} catch (error) {
|
|
121
|
-
handleError(error, logger, true);
|
|
122
|
-
}
|
|
141
|
+
console.log(chalk.bold.green(`\n✨ Done! Branch '${branchName}' created and pushed.\n`));
|
|
142
|
+
console.log(chalk.cyan('Next steps:'));
|
|
143
|
+
console.log(` 1. Run your package manager: ${chalk.white('bun install')} or ${chalk.white('npm install')}`);
|
|
144
|
+
console.log(` 2. Open a PR from branch: ${chalk.white(branchName)}`);
|
|
145
|
+
console.log('');
|
|
146
|
+
|
|
147
|
+
logger.printSeparator();
|
|
148
|
+
process.exit(EXIT_CODES.SUCCESS);
|
|
123
149
|
}
|
package/src/engine/index.ts
CHANGED
|
@@ -61,10 +61,13 @@ export class CodeProbeEngine {
|
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
// Step 7: Generate patches
|
|
64
|
+
// Step 7: Generate patches for exploitable CVEs + any HIGH/CRITICAL with a known fix version
|
|
65
65
|
console.log("\x1b[33m[Nosana]\x1b[0m 🔧 Generating patches with LLM...");
|
|
66
66
|
await this.patcher.loadPrebakedPatches();
|
|
67
|
-
const
|
|
67
|
+
const patchCandidates = matchedCves.filter((c) =>
|
|
68
|
+
c.exploitable || ((c.severity === "CRITICAL" || c.severity === "HIGH") && c.version_fixed)
|
|
69
|
+
);
|
|
70
|
+
const patches = await this.patcher.generateAllPatches(patchCandidates);
|
|
68
71
|
for (const cve of matchedCves) {
|
|
69
72
|
if (patches.has(cve.id)) {
|
|
70
73
|
cve.patch_diff = patches.get(cve.id);
|