codeprobe-scanner 1.0.19 → 1.0.21
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 +367 -131
- package/package.json +1 -1
- package/src/cli/commands/scan.ts +62 -0
- package/src/engine/code-fixer.ts +58 -39
- package/src/engine/index.ts +1 -1
- package/src/engine/patcher.ts +14 -17
package/README.md
CHANGED
|
@@ -1,156 +1,381 @@
|
|
|
1
|
-
# CodeProbe
|
|
1
|
+
# CodeProbe Scanner 🔍
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Full-stack vulnerability scanner with automatic code fixing and Kimi AI patch generation.**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
CodeProbe is an advanced security scanner that analyzes both your npm dependencies AND your actual source code to find and automatically fix security vulnerabilities. It combines CVE detection, SAST analysis, and AI-powered patch generation into one unified tool.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## ✨ Key Features
|
|
8
|
+
|
|
9
|
+
### 🔍 Dual-Layer Vulnerability Detection
|
|
10
|
+
- **Dependency Scanning** — Checks npm packages against OSV.dev + npm advisory databases
|
|
11
|
+
- **Source Code Analysis (SAST)** — Scans actual code for 7+ vulnerability patterns
|
|
12
|
+
|
|
13
|
+
### 🔐 Detects & Fixes
|
|
14
|
+
- Hardcoded secrets → Replaced with `process.env`
|
|
15
|
+
- SQL injection patterns
|
|
16
|
+
- Command injection vulnerabilities
|
|
17
|
+
- XSS vulnerabilities
|
|
18
|
+
- Path traversal issues
|
|
19
|
+
- Insecure random generation
|
|
20
|
+
- Insecure eval/Function() usage
|
|
21
|
+
|
|
22
|
+
### 🔧 Automatic Fixing
|
|
23
|
+
- **Source Code Fixes** — Repairs vulnerabilities in your code automatically
|
|
24
|
+
- **Package Updates** — Suggests and applies secure versions
|
|
25
|
+
- **Kimi LLM Integration** — Generates intelligent patches using AI
|
|
26
|
+
|
|
27
|
+
### 🏗️ Recursive Scanning
|
|
28
|
+
- Automatically finds all `package.json` files in subdirectories
|
|
29
|
+
- Perfect for monorepos and multi-package projects
|
|
30
|
+
- Aggregates results across all packages
|
|
31
|
+
|
|
32
|
+
### 📊 Comprehensive Reporting
|
|
33
|
+
- Risk score calculation (0-10)
|
|
34
|
+
- CVE severity and exploitability
|
|
35
|
+
- Proof-of-concept recordings
|
|
36
|
+
- Recent security threat alerts
|
|
37
|
+
|
|
38
|
+
## 🚀 Installation
|
|
39
|
+
|
|
40
|
+
### Global Installation
|
|
41
|
+
```bash
|
|
8
42
|
npm install -g codeprobe-scanner
|
|
9
43
|
```
|
|
10
44
|
|
|
11
|
-
|
|
45
|
+
### Project Installation
|
|
46
|
+
```bash
|
|
47
|
+
npm install --save-dev codeprobe-scanner
|
|
48
|
+
```
|
|
12
49
|
|
|
13
|
-
|
|
14
|
-
|
|
50
|
+
### Run Without Installing
|
|
51
|
+
```bash
|
|
52
|
+
npx codeprobe-scanner scan .
|
|
15
53
|
```
|
|
16
54
|
|
|
17
|
-
## Quick Start
|
|
55
|
+
## ⚡ Quick Start
|
|
18
56
|
|
|
19
|
-
|
|
20
|
-
# Scan the current directory
|
|
21
|
-
codeprobe scan
|
|
57
|
+
### 1. Set Up Kimi API (Recommended)
|
|
22
58
|
|
|
23
|
-
|
|
24
|
-
codeprobe scan ./my-app
|
|
59
|
+
Get your API key from [Kimi Platform](https://kimi.moonshot.cn):
|
|
25
60
|
|
|
26
|
-
|
|
27
|
-
|
|
61
|
+
```bash
|
|
62
|
+
# Option A: CLI Configuration
|
|
63
|
+
codeprobe config set kimi_api_key sk-YOUR_KEY_HERE
|
|
28
64
|
|
|
29
|
-
#
|
|
30
|
-
|
|
65
|
+
# Option B: Environment Variable
|
|
66
|
+
export KIMI_API_KEY=sk-YOUR_KEY_HERE
|
|
31
67
|
|
|
32
|
-
#
|
|
33
|
-
codeprobe
|
|
68
|
+
# Option C: Manual Configuration
|
|
69
|
+
# Edit ~/.codeprobe/config.json and add your key
|
|
34
70
|
```
|
|
35
71
|
|
|
36
|
-
|
|
72
|
+
### 2. Scan Your Project
|
|
37
73
|
|
|
38
|
-
|
|
74
|
+
**Find vulnerabilities:**
|
|
75
|
+
```bash
|
|
76
|
+
codeprobe scan .
|
|
77
|
+
```
|
|
39
78
|
|
|
40
|
-
|
|
79
|
+
**Find AND fix vulnerabilities:**
|
|
80
|
+
```bash
|
|
81
|
+
codeprobe scan . --fix
|
|
82
|
+
```
|
|
41
83
|
|
|
42
|
-
|
|
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 |
|
|
84
|
+
## 📖 Usage Examples
|
|
47
85
|
|
|
48
|
-
|
|
86
|
+
### Basic Vulnerability Scan
|
|
87
|
+
```bash
|
|
88
|
+
$ codeprobe scan .
|
|
49
89
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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
|
|
90
|
+
⚡ CodeProbe v1.0.20
|
|
91
|
+
🔍 Searching for package.json files...
|
|
92
|
+
Found 1 package.json file(s)
|
|
56
93
|
|
|
57
|
-
|
|
94
|
+
📂 Scanning: .
|
|
95
|
+
📦 Parsing dependencies...
|
|
96
|
+
Found 8 dependencies
|
|
97
|
+
🔍 Checking OSV.dev + npm advisory database...
|
|
98
|
+
Found 13 CVEs
|
|
58
99
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
| `0` | No vulnerabilities found |
|
|
62
|
-
| `1` | Vulnerabilities found |
|
|
63
|
-
| `2` | Scan failed |
|
|
100
|
+
🔐 Analyzing source code for vulnerabilities...
|
|
101
|
+
Found 4 potential vulnerabilities
|
|
64
102
|
|
|
65
|
-
|
|
103
|
+
────────────────────────────────────────────
|
|
104
|
+
SCAN COMPLETE
|
|
105
|
+
Risk Score: 2.2/10 (LOW)
|
|
106
|
+
Confirmed Exploitable: 0 | Theoretical Risk: 13
|
|
107
|
+
Patches Available: 1/13
|
|
108
|
+
Duration: 1s
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Automatic Vulnerability Fixing
|
|
112
|
+
```bash
|
|
113
|
+
$ codeprobe scan . --fix
|
|
66
114
|
|
|
67
|
-
|
|
115
|
+
🔧 Applying source code fixes...
|
|
116
|
+
✓ Fixed 1 issues in server.js
|
|
117
|
+
✓ Fixed 3 issues in seed.js
|
|
118
|
+
Applied 4 code fixes
|
|
68
119
|
|
|
69
|
-
|
|
120
|
+
📝 Fixed vulnerabilities:
|
|
121
|
+
- server.js:28 - Hardcoded Secret
|
|
122
|
+
- seed.js:16 - Hardcoded Secret
|
|
123
|
+
- seed.js:17 - Hardcoded Secret
|
|
124
|
+
- seed.js:18 - Hardcoded Secret
|
|
125
|
+
```
|
|
70
126
|
|
|
71
|
-
|
|
127
|
+
### Undo AI Changes
|
|
128
|
+
```bash
|
|
129
|
+
$ codeprobe scan . --undo
|
|
72
130
|
|
|
73
|
-
|
|
131
|
+
↩️ Reverting AI-made changes...
|
|
132
|
+
|
|
133
|
+
📦 Reverting package.json updates...
|
|
134
|
+
✓ package.json reverted
|
|
135
|
+
🔧 Reverting source code fixes...
|
|
136
|
+
✓ All code changes reverted
|
|
137
|
+
|
|
138
|
+
✓ Undo complete! Review changes with: git status
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Configuration Management
|
|
142
|
+
```bash
|
|
143
|
+
# Set API keys
|
|
144
|
+
codeprobe config set kimi_api_key sk-YOUR_KEY
|
|
145
|
+
codeprobe config set github_token ghp_YOUR_TOKEN
|
|
74
146
|
codeprobe config set bright_data_api_key YOUR_KEY
|
|
75
|
-
|
|
147
|
+
|
|
148
|
+
# View configuration
|
|
149
|
+
codeprobe config get kimi_api_key
|
|
150
|
+
|
|
151
|
+
# Clear configuration
|
|
152
|
+
codeprobe config clear kimi_api_key
|
|
76
153
|
```
|
|
77
154
|
|
|
78
|
-
##
|
|
155
|
+
## 🛠️ Commands
|
|
156
|
+
|
|
157
|
+
### `codeprobe scan [path]`
|
|
79
158
|
|
|
80
|
-
|
|
159
|
+
Scans for vulnerabilities in dependencies and source code.
|
|
81
160
|
|
|
82
|
-
|
|
161
|
+
| Flag | Description |
|
|
162
|
+
|------|-------------|
|
|
163
|
+
| `--fix` | Auto-fix vulnerabilities in code + update packages |
|
|
164
|
+
| `--undo` | Revert all AI-made changes from the last scan |
|
|
165
|
+
| `--json` | Output results as JSON |
|
|
166
|
+
| `--verbose` | Show detailed logs |
|
|
83
167
|
|
|
84
|
-
|
|
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`) |
|
|
168
|
+
### `codeprobe report`
|
|
91
169
|
|
|
92
|
-
|
|
170
|
+
Shows the last scan results from `~/.codeprobe/scans/latest.json`.
|
|
93
171
|
|
|
94
|
-
|
|
172
|
+
### `codeprobe config`
|
|
95
173
|
|
|
174
|
+
Manage configuration:
|
|
175
|
+
```bash
|
|
176
|
+
codeprobe config set <key> <value>
|
|
177
|
+
codeprobe config get <key>
|
|
178
|
+
codeprobe config clear <key>
|
|
96
179
|
```
|
|
97
|
-
|
|
180
|
+
|
|
181
|
+
## 🔐 How It Works
|
|
182
|
+
|
|
183
|
+
### Scan Pipeline
|
|
184
|
+
|
|
185
|
+
```
|
|
186
|
+
1️⃣ Discovery
|
|
187
|
+
Find all package.json files recursively
|
|
188
|
+
↓
|
|
189
|
+
2️⃣ Dependency Scanning
|
|
190
|
+
Parse packages → Check CVE databases
|
|
98
191
|
↓
|
|
99
|
-
|
|
192
|
+
3️⃣ Source Code Analysis
|
|
193
|
+
Scan .ts/.js files → Detect security patterns
|
|
100
194
|
↓
|
|
101
|
-
|
|
195
|
+
4️⃣ Exploit Verification
|
|
196
|
+
Test vulnerabilities in sandboxes (Daytona)
|
|
102
197
|
↓
|
|
103
|
-
|
|
198
|
+
5️⃣ Patch Generation
|
|
199
|
+
Generate fixes using Kimi LLM
|
|
104
200
|
↓
|
|
105
|
-
|
|
201
|
+
6️⃣ Risk Scoring & Reporting
|
|
202
|
+
Calculate risk → Save results
|
|
203
|
+
↓
|
|
204
|
+
7️⃣ Auto-Fixing (if --fix flag)
|
|
205
|
+
Replace secrets → Update packages → Commit
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## 📋 Vulnerability Types
|
|
209
|
+
|
|
210
|
+
| Type | Detection | Automatic Fix |
|
|
211
|
+
|------|-----------|---|
|
|
212
|
+
| **Hardcoded Secrets** | API keys, passwords, tokens | ✅ Replace with `process.env` |
|
|
213
|
+
| **Command Injection** | Unescaped shell commands | ✅ Add proper escaping |
|
|
214
|
+
| **SQL Injection** | Dynamic SQL queries | ⚠️ Suggest parameterized queries |
|
|
215
|
+
| **XSS** | innerHTML, dangerouslySetInnerHTML | ✅ Use textContent |
|
|
216
|
+
| **Insecure Random** | Math.random() for security | ✅ Use crypto.randomBytes() |
|
|
217
|
+
| **Path Traversal** | Unvalidated file paths | ⚠️ Suggest validation |
|
|
218
|
+
| **Insecure Eval** | eval(), Function() usage | ⚠️ Suggest alternatives |
|
|
219
|
+
|
|
220
|
+
## ⚙️ Configuration
|
|
221
|
+
|
|
222
|
+
### Config File
|
|
223
|
+
```
|
|
224
|
+
~/.codeprobe/config.json
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### API Keys (Encrypted)
|
|
228
|
+
```json
|
|
229
|
+
{
|
|
230
|
+
"kimi_api_key": "sk-...",
|
|
231
|
+
"github_token": "ghp_...",
|
|
232
|
+
"bright_data_api_key": "...",
|
|
233
|
+
"daytona_api_key": "..."
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
All secrets are encrypted using AES-256-GCM.
|
|
238
|
+
|
|
239
|
+
### Environment Variables (Override Config)
|
|
240
|
+
```bash
|
|
241
|
+
export KIMI_API_KEY=sk-...
|
|
242
|
+
export GITHUB_TOKEN=ghp_...
|
|
243
|
+
export BRIGHT_DATA_API_KEY=...
|
|
244
|
+
export DAYTONA_API_KEY=...
|
|
106
245
|
```
|
|
107
246
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
-
|
|
247
|
+
## 🔒 Security
|
|
248
|
+
|
|
249
|
+
### Built-In Security Features
|
|
250
|
+
- ✅ **Encrypted Config** — API keys encrypted in `~/.codeprobe/config.json`
|
|
251
|
+
- ✅ **No Hardcoded Secrets** — Detects and fixes credentials in code
|
|
252
|
+
- ✅ **Command Injection Prevention** — Proper shell escaping
|
|
253
|
+
- ✅ **Secure Random** — Uses `crypto.randomBytes()`
|
|
254
|
+
- ✅ **Full SAST Analysis** — Comprehensive source code scanning
|
|
255
|
+
- ✅ **Zero Vulnerabilities** — See [SECURITY_AUDIT.md](./SECURITY_AUDIT.md)
|
|
256
|
+
|
|
257
|
+
### Privacy
|
|
258
|
+
- Scans run locally on your machine
|
|
259
|
+
- Reports saved to `~/.codeprobe/scans/` (private)
|
|
260
|
+
- Kimi only called for patch generation (configurable)
|
|
111
261
|
|
|
112
|
-
##
|
|
262
|
+
## 📁 Output Files
|
|
113
263
|
|
|
114
|
-
|
|
264
|
+
### Scan Reports
|
|
265
|
+
```
|
|
266
|
+
~/.codeprobe/scans/
|
|
267
|
+
├── scan_<timestamp>.json # Individual scans
|
|
268
|
+
└── latest.json # Latest scan
|
|
269
|
+
```
|
|
115
270
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
271
|
+
### Fixed Code
|
|
272
|
+
```
|
|
273
|
+
.proofs/
|
|
274
|
+
├── CVE-2022-29078_timestamp.json
|
|
275
|
+
└── ...
|
|
276
|
+
```
|
|
120
277
|
|
|
121
|
-
|
|
278
|
+
## 🚀 Advanced Usage
|
|
122
279
|
|
|
123
|
-
|
|
280
|
+
### Monorepo Scanning
|
|
281
|
+
```bash
|
|
282
|
+
codeprobe scan /path/to/monorepo
|
|
283
|
+
# Automatically finds and scans all package.json files
|
|
284
|
+
```
|
|
124
285
|
|
|
125
|
-
|
|
286
|
+
### JSON Export
|
|
287
|
+
```bash
|
|
288
|
+
codeprobe scan . --json > report.json
|
|
289
|
+
```
|
|
126
290
|
|
|
127
|
-
|
|
128
|
-
|
|
291
|
+
### Verbose Output
|
|
292
|
+
```bash
|
|
293
|
+
codeprobe scan . --verbose
|
|
129
294
|
```
|
|
130
295
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
| `GET /api/auth/github` | GET | GitHub OAuth callback |
|
|
137
|
-
| `GET /api/auth/logout` | GET | Logout |
|
|
296
|
+
### Undo Previous Changes
|
|
297
|
+
```bash
|
|
298
|
+
# Revert all AI-made fixes from the last scan
|
|
299
|
+
codeprobe scan . --undo
|
|
300
|
+
```
|
|
138
301
|
|
|
139
|
-
|
|
302
|
+
### Combined Options
|
|
303
|
+
```bash
|
|
304
|
+
codeprobe scan . --fix --verbose --json
|
|
305
|
+
```
|
|
140
306
|
|
|
141
|
-
##
|
|
307
|
+
## 🐛 Troubleshooting
|
|
142
308
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
309
|
+
### "No Kimi API key configured"
|
|
310
|
+
```bash
|
|
311
|
+
codeprobe config set kimi_api_key sk-YOUR_KEY
|
|
146
312
|
```
|
|
147
313
|
|
|
148
|
-
|
|
314
|
+
### "No package.json files found"
|
|
315
|
+
Make sure your project has a `package.json` file.
|
|
149
316
|
|
|
150
|
-
|
|
317
|
+
### "Uncommitted changes detected"
|
|
318
|
+
After `--fix`, commit the changes:
|
|
319
|
+
```bash
|
|
320
|
+
git add -A
|
|
321
|
+
git commit -m "Security fixes: patch vulnerabilities"
|
|
322
|
+
```
|
|
151
323
|
|
|
324
|
+
## 📊 Performance
|
|
325
|
+
|
|
326
|
+
| Task | Time |
|
|
327
|
+
|------|------|
|
|
328
|
+
| Dependency scanning | 1-3s |
|
|
329
|
+
| Source code analysis | <1s per 100 files |
|
|
330
|
+
| Exploit verification | 2-10s |
|
|
331
|
+
| Patch generation | 5-15s |
|
|
332
|
+
| **Total** | **1-30s** |
|
|
333
|
+
|
|
334
|
+
## 🏗️ Project Structure
|
|
335
|
+
|
|
336
|
+
```
|
|
337
|
+
src/
|
|
338
|
+
├── cli/ # CLI commands and interface
|
|
339
|
+
├── engine/ # Core scanner modules
|
|
340
|
+
│ ├── parser.ts # Package parsing
|
|
341
|
+
│ ├── scraper.ts # CVE database queries
|
|
342
|
+
│ ├── sast.ts # Source code analysis
|
|
343
|
+
│ ├── code-fixer.ts # Automatic code fixing
|
|
344
|
+
│ ├── patcher.ts # Patch generation (Kimi)
|
|
345
|
+
│ └── sandbox.ts # Exploit verification
|
|
346
|
+
├── shared/ # Types and utilities
|
|
347
|
+
├── api/ # REST API (optional)
|
|
348
|
+
└── integrations/ # Daytona, VideoDB, etc.
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
## 📚 Examples
|
|
352
|
+
|
|
353
|
+
### Scan Your Project
|
|
354
|
+
```bash
|
|
355
|
+
codeprobe scan .
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### Fix All Vulnerabilities
|
|
359
|
+
```bash
|
|
360
|
+
codeprobe scan . --fix
|
|
361
|
+
git add -A && git commit -m "Security fixes"
|
|
362
|
+
git push
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
### Scan Monorepo
|
|
366
|
+
```bash
|
|
367
|
+
codeprobe scan ./monorepo
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### Export as JSON
|
|
371
|
+
```bash
|
|
372
|
+
codeprobe scan . --json | jq '.summary'
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
## 🔗 Integration
|
|
376
|
+
|
|
377
|
+
### GitHub Actions
|
|
152
378
|
```yaml
|
|
153
|
-
# .github/workflows/codeprobe-scan.yml
|
|
154
379
|
name: Security Scan
|
|
155
380
|
on: [push, pull_request]
|
|
156
381
|
jobs:
|
|
@@ -158,52 +383,63 @@ jobs:
|
|
|
158
383
|
runs-on: ubuntu-latest
|
|
159
384
|
steps:
|
|
160
385
|
- uses: actions/checkout@v3
|
|
161
|
-
- run: npx codeprobe-scanner scan --json
|
|
162
|
-
- uses: actions/upload-artifact@v3
|
|
163
|
-
with:
|
|
164
|
-
name: security-report
|
|
165
|
-
path: report.json
|
|
386
|
+
- run: npx codeprobe-scanner scan --json
|
|
166
387
|
```
|
|
167
388
|
|
|
168
|
-
|
|
169
|
-
|
|
389
|
+
### Pre-commit Hook
|
|
390
|
+
```bash
|
|
391
|
+
#!/bin/sh
|
|
392
|
+
codeprobe scan . || exit 1
|
|
170
393
|
```
|
|
171
|
-
╔══════════════════════════════════════════╗
|
|
172
|
-
║ CodeProbe Scanner ║
|
|
173
|
-
╚══════════════════════════════════════════╝
|
|
174
394
|
|
|
175
|
-
|
|
176
|
-
Risk Score: 🔴 HIGH (43)
|
|
177
|
-
Confirmed Exploitable: 2 | Theoretical Risk: 5
|
|
178
|
-
Patches Available: 3
|
|
179
|
-
Duration: 8.3s
|
|
395
|
+
## 📄 License
|
|
180
396
|
|
|
181
|
-
|
|
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
|
|
397
|
+
MIT License - See LICENSE file
|
|
186
398
|
|
|
187
|
-
|
|
188
|
-
CRITICAL lodash - Prototype Pollution
|
|
189
|
-
HIGH axios - SSRF via redirect
|
|
190
|
-
```
|
|
399
|
+
## 🙏 Contributing
|
|
191
400
|
|
|
192
|
-
|
|
401
|
+
Contributions welcome! Please:
|
|
402
|
+
1. Fork the repository
|
|
403
|
+
2. Create a feature branch
|
|
404
|
+
3. Submit a pull request
|
|
193
405
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
406
|
+
## 📞 Support
|
|
407
|
+
|
|
408
|
+
- 🐛 [Issue Tracker](https://github.com/NachikethReddyY/codeprobe/issues)
|
|
409
|
+
- 💬 [Discussions](https://github.com/NachikethReddyY/codeprobe/discussions)
|
|
410
|
+
- 📖 [Full Documentation](./SECURITY_AUDIT.md)
|
|
411
|
+
|
|
412
|
+
## 📝 Changelog
|
|
413
|
+
|
|
414
|
+
### v1.0.20
|
|
415
|
+
- ✨ Integrated SAST code vulnerability scanning
|
|
416
|
+
- ✨ Automatic source code fixing
|
|
417
|
+
- 🔒 Fixed code fixer to actually apply fixes
|
|
418
|
+
- 🔒 Kimi as primary patch generator
|
|
419
|
+
|
|
420
|
+
### v1.0.19
|
|
421
|
+
- ✨ Full codebase scanning
|
|
422
|
+
- ✨ Automatic code fixing
|
|
423
|
+
|
|
424
|
+
### v1.0.18
|
|
425
|
+
- ✨ Security audit (0 vulnerabilities found)
|
|
426
|
+
|
|
427
|
+
### v1.0.17
|
|
428
|
+
- ✨ Kimi patch generation enabled
|
|
429
|
+
- 🔧 Fixed patches_available reporting
|
|
430
|
+
|
|
431
|
+
### v1.0.16
|
|
432
|
+
- ✨ SAST scanner implementation
|
|
433
|
+
- 🔒 Fixed security vulnerabilities
|
|
434
|
+
|
|
435
|
+
### v1.0.15
|
|
436
|
+
- ✨ Recursive package.json scanning
|
|
437
|
+
|
|
438
|
+
### v1.0.14
|
|
439
|
+
- 🔒 Fixed VideoDB proof recording
|
|
440
|
+
|
|
441
|
+
---
|
|
206
442
|
|
|
207
|
-
|
|
443
|
+
**CodeProbe: Security, Simplified** 🚀
|
|
208
444
|
|
|
209
|
-
|
|
445
|
+
[GitHub](https://github.com/NachikethReddyY/codeprobe) | [npm](https://npmjs.com/package/codeprobe-scanner) | [Issues](https://github.com/NachikethReddyY/codeprobe/issues)
|
package/package.json
CHANGED
package/src/cli/commands/scan.ts
CHANGED
|
@@ -12,6 +12,7 @@ import { createScraper } from '../../engine/scraper.js';
|
|
|
12
12
|
|
|
13
13
|
interface ScanOptions {
|
|
14
14
|
fix: boolean;
|
|
15
|
+
undo: boolean;
|
|
15
16
|
json: boolean;
|
|
16
17
|
verbose: boolean;
|
|
17
18
|
}
|
|
@@ -19,6 +20,7 @@ interface ScanOptions {
|
|
|
19
20
|
function parseArgs(args: string[]): { repoPath: string; options: ScanOptions } {
|
|
20
21
|
const options: ScanOptions = {
|
|
21
22
|
fix: false,
|
|
23
|
+
undo: false,
|
|
22
24
|
json: false,
|
|
23
25
|
verbose: false,
|
|
24
26
|
};
|
|
@@ -29,6 +31,8 @@ function parseArgs(args: string[]): { repoPath: string; options: ScanOptions } {
|
|
|
29
31
|
const arg = args[i];
|
|
30
32
|
if (arg === '--fix') {
|
|
31
33
|
options.fix = true;
|
|
34
|
+
} else if (arg === '--undo') {
|
|
35
|
+
options.undo = true;
|
|
32
36
|
} else if (arg === '--json') {
|
|
33
37
|
options.json = true;
|
|
34
38
|
} else if (arg === '--verbose') {
|
|
@@ -114,10 +118,68 @@ function displayReport(report: Report, json: boolean, durationMs: number): void
|
|
|
114
118
|
logger.printSeparator();
|
|
115
119
|
}
|
|
116
120
|
|
|
121
|
+
async function undoLastChanges(): Promise<void> {
|
|
122
|
+
console.log("↩️ Reverting AI-made changes...\n");
|
|
123
|
+
|
|
124
|
+
try {
|
|
125
|
+
// Load last scan report
|
|
126
|
+
const latestPath = path.join(PATHS.SCANS_DIR, 'latest.json');
|
|
127
|
+
if (!existsSync(latestPath)) {
|
|
128
|
+
console.log(chalk.yellow("⚠️ No previous scan found to undo."));
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const latestReport = JSON.parse(await Bun.file(latestPath).text());
|
|
133
|
+
|
|
134
|
+
// Revert package.json if it was modified
|
|
135
|
+
if (latestReport.scan.cves && latestReport.scan.cves.length > 0) {
|
|
136
|
+
console.log("📦 Reverting package.json updates...");
|
|
137
|
+
try {
|
|
138
|
+
// Use git to revert
|
|
139
|
+
const result = await Bun.$`git checkout package.json 2>&1`.nothrow();
|
|
140
|
+
if (result.exitCode === 0) {
|
|
141
|
+
console.log(chalk.green(" ✓ package.json reverted"));
|
|
142
|
+
} else {
|
|
143
|
+
console.log(chalk.yellow(" ⚠️ Could not auto-revert package.json. Run: git checkout package.json"));
|
|
144
|
+
}
|
|
145
|
+
} catch {
|
|
146
|
+
console.log(chalk.yellow(" ⚠️ Could not auto-revert package.json. Run: git checkout package.json"));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Revert code fixes if any were made
|
|
151
|
+
if ((latestReport as any).code_vulnerabilities && (latestReport as any).code_vulnerabilities.length > 0) {
|
|
152
|
+
console.log("🔧 Reverting source code fixes...");
|
|
153
|
+
try {
|
|
154
|
+
// Use git to revert all changes
|
|
155
|
+
const result = await Bun.$`git checkout -- . 2>&1`.nothrow();
|
|
156
|
+
if (result.exitCode === 0) {
|
|
157
|
+
console.log(chalk.green(" ✓ All code changes reverted"));
|
|
158
|
+
} else {
|
|
159
|
+
console.log(chalk.yellow(" ⚠️ Could not auto-revert code. Run: git checkout -- ."));
|
|
160
|
+
}
|
|
161
|
+
} catch {
|
|
162
|
+
console.log(chalk.yellow(" ⚠️ Could not auto-revert code. Run: git checkout -- ."));
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
console.log(chalk.green("\n✓ Undo complete! Review changes with: git status"));
|
|
167
|
+
} catch (error) {
|
|
168
|
+
console.error(chalk.red(`✗ Undo failed: ${error instanceof Error ? error.message : String(error)}`));
|
|
169
|
+
process.exit(EXIT_CODES.FAILURE);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
117
173
|
export async function scanCommand(args: string[]): Promise<void> {
|
|
118
174
|
const { repoPath, options } = parseArgs(args);
|
|
119
175
|
const logger = new ProgressLogger(options.verbose);
|
|
120
176
|
|
|
177
|
+
// Handle --undo flag
|
|
178
|
+
if (options.undo) {
|
|
179
|
+
await undoLastChanges();
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
|
|
121
183
|
logger.printHeader();
|
|
122
184
|
|
|
123
185
|
const startTime = Date.now();
|
package/src/engine/code-fixer.ts
CHANGED
|
@@ -12,24 +12,50 @@ export interface CodeFix {
|
|
|
12
12
|
export class CodeFixer {
|
|
13
13
|
async fixVulnerabilities(vulnerabilities: CodeVulnerability[]): Promise<CodeFix[]> {
|
|
14
14
|
const fixes: CodeFix[] = [];
|
|
15
|
+
const fileCache = new Map<string, { original: string; lines: string[] }>();
|
|
15
16
|
|
|
17
|
+
// Group vulnerabilities by file
|
|
18
|
+
const vulnsByFile = new Map<string, CodeVulnerability[]>();
|
|
16
19
|
for (const vuln of vulnerabilities) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
if (!vulnsByFile.has(vuln.file)) {
|
|
21
|
+
vulnsByFile.set(vuln.file, []);
|
|
22
|
+
}
|
|
23
|
+
vulnsByFile.get(vuln.file)!.push(vuln);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Process each file
|
|
27
|
+
for (const [filePath, fileVulns] of vulnsByFile) {
|
|
28
|
+
try {
|
|
29
|
+
const content = await readFile(filePath, "utf-8");
|
|
30
|
+
const lines = content.split("\n");
|
|
31
|
+
let modified = false;
|
|
32
|
+
|
|
33
|
+
for (const vuln of fileVulns) {
|
|
34
|
+
const fix = this.generateFixForVulnerability(vuln, lines);
|
|
35
|
+
if (fix) {
|
|
36
|
+
lines[vuln.line - 1] = fix.fixed;
|
|
37
|
+
fixes.push({ file: filePath, line: vuln.line, original: fix.original, fixed: fix.fixed, type: vuln.type });
|
|
38
|
+
modified = true;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Write back if modified
|
|
43
|
+
if (modified) {
|
|
44
|
+
const updatedContent = lines.join("\n");
|
|
45
|
+
await writeFile(filePath, updatedContent, "utf-8");
|
|
46
|
+
console.log(` ✓ Fixed ${fileVulns.length} issues in ${filePath}`);
|
|
47
|
+
}
|
|
48
|
+
} catch (error) {
|
|
49
|
+
console.warn(` ⚠️ Failed to fix ${filePath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
21
50
|
}
|
|
22
51
|
}
|
|
23
52
|
|
|
24
53
|
return fixes;
|
|
25
54
|
}
|
|
26
55
|
|
|
27
|
-
private
|
|
56
|
+
private generateFixForVulnerability(vuln: CodeVulnerability, lines: string[]): { original: string; fixed: string } | null {
|
|
28
57
|
try {
|
|
29
|
-
const file = await readFile(vuln.file, "utf-8");
|
|
30
|
-
const lines = file.split("\n");
|
|
31
58
|
const lineIndex = vuln.line - 1;
|
|
32
|
-
|
|
33
59
|
if (lineIndex < 0 || lineIndex >= lines.length) {
|
|
34
60
|
return null;
|
|
35
61
|
}
|
|
@@ -51,16 +77,10 @@ export class CodeFixer {
|
|
|
51
77
|
}
|
|
52
78
|
|
|
53
79
|
if (fixed !== original) {
|
|
54
|
-
return {
|
|
55
|
-
file: vuln.file,
|
|
56
|
-
line: vuln.line,
|
|
57
|
-
original,
|
|
58
|
-
fixed,
|
|
59
|
-
type: vuln.type,
|
|
60
|
-
};
|
|
80
|
+
return { original, fixed };
|
|
61
81
|
}
|
|
62
82
|
} catch (error) {
|
|
63
|
-
|
|
83
|
+
// Silent fail for individual fixes
|
|
64
84
|
}
|
|
65
85
|
|
|
66
86
|
return null;
|
|
@@ -71,22 +91,32 @@ export class CodeFixer {
|
|
|
71
91
|
let fixed = line;
|
|
72
92
|
|
|
73
93
|
// Replace apiKey/api_key patterns
|
|
74
|
-
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
94
|
+
if (/api_?key\s*[:=]\s*["']/i.test(fixed)) {
|
|
95
|
+
const varName = fixed.match(/(\w+)\s*[:=]/)?.[1] || "apiKey";
|
|
96
|
+
fixed = fixed.replace(/api_?key\s*[:=]\s*["'][^"']*["']/i,
|
|
97
|
+
`${varName} = process.env.API_KEY || ""`);
|
|
98
|
+
}
|
|
78
99
|
|
|
79
100
|
// Replace password patterns
|
|
80
|
-
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
101
|
+
if (/password\s*[:=]\s*["']/i.test(fixed)) {
|
|
102
|
+
const varName = fixed.match(/(\w+)\s*[:=]/)?.[1] || "password";
|
|
103
|
+
fixed = fixed.replace(/password\s*[:=]\s*["'][^"']*["']/i,
|
|
104
|
+
`${varName} = process.env.PASSWORD || ""`);
|
|
105
|
+
}
|
|
84
106
|
|
|
85
107
|
// Replace token patterns
|
|
86
|
-
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
108
|
+
if (/token\s*[:=]\s*["']/i.test(fixed)) {
|
|
109
|
+
const varName = fixed.match(/(\w+)\s*[:=]/)?.[1] || "token";
|
|
110
|
+
fixed = fixed.replace(/token\s*[:=]\s*["'][^"']*["']/i,
|
|
111
|
+
`${varName} = process.env.TOKEN || ""`);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Replace secret patterns
|
|
115
|
+
if (/secret\s*[:=]\s*["']/i.test(fixed)) {
|
|
116
|
+
const varName = fixed.match(/(\w+)\s*[:=]/)?.[1] || "secret";
|
|
117
|
+
fixed = fixed.replace(/secret\s*[:=]\s*["'][^"']*["']/i,
|
|
118
|
+
`${varName} = process.env.SECRET || ""`);
|
|
119
|
+
}
|
|
90
120
|
|
|
91
121
|
return fixed;
|
|
92
122
|
}
|
|
@@ -134,17 +164,6 @@ export class CodeFixer {
|
|
|
134
164
|
return line;
|
|
135
165
|
}
|
|
136
166
|
|
|
137
|
-
private async applyFix(fix: CodeFix): Promise<void> {
|
|
138
|
-
try {
|
|
139
|
-
const file = await readFile(fix.file, "utf-8");
|
|
140
|
-
const lines = file.split("\n");
|
|
141
|
-
lines[fix.line - 1] = fix.fixed;
|
|
142
|
-
const updated = lines.join("\n");
|
|
143
|
-
await writeFile(fix.file, updated, "utf-8");
|
|
144
|
-
} catch (error) {
|
|
145
|
-
console.warn(`Failed to apply fix to ${fix.file}:${fix.line}`);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
167
|
}
|
|
149
168
|
|
|
150
169
|
export const createCodeFixer = () => new CodeFixer();
|
package/src/engine/index.ts
CHANGED
|
@@ -132,7 +132,7 @@ export class CodeProbeEngine {
|
|
|
132
132
|
}
|
|
133
133
|
|
|
134
134
|
// Step 7: Generate patches for exploitable CVEs + any HIGH/CRITICAL with a known fix version
|
|
135
|
-
console.log("\x1b[33m[
|
|
135
|
+
console.log("\x1b[33m[Kimi]\x1b[0m 🔧 Generating patches with Kimi LLM...");
|
|
136
136
|
await this.patcher.loadPrebakedPatches();
|
|
137
137
|
const patchCandidates = matchedCves.filter((c) =>
|
|
138
138
|
c.exploitable || ((c.severity === "CRITICAL" || c.severity === "HIGH") && c.version_fixed)
|
package/src/engine/patcher.ts
CHANGED
|
@@ -67,38 +67,35 @@ export class PatchGenerator {
|
|
|
67
67
|
async generatePatch(cve: ScanCVE): Promise<string | null> {
|
|
68
68
|
await this.resolveKeys();
|
|
69
69
|
|
|
70
|
+
// First, check for prebaked patches (highest priority)
|
|
70
71
|
const prebakedPatch = this.patches.get(cve.id);
|
|
71
72
|
if (prebakedPatch) {
|
|
72
73
|
cve.patch_diff = prebakedPatch.diff;
|
|
73
74
|
return prebakedPatch.diff;
|
|
74
75
|
}
|
|
75
76
|
|
|
76
|
-
//
|
|
77
|
+
// Use Kimi LLM for patch generation (primary method)
|
|
77
78
|
if (this.kimiApiKey) {
|
|
78
79
|
try {
|
|
79
|
-
console.log(`[Kimi] Generating patch for ${cve.id}...`);
|
|
80
|
+
console.log(`[Kimi] 🔧 Generating patch for ${cve.id}...`);
|
|
80
81
|
const patch = await this.generatePatchWithKimi(cve);
|
|
81
82
|
if (patch) {
|
|
82
83
|
cve.patch_diff = patch;
|
|
84
|
+
console.log(`[Kimi] ✓ Patch generated for ${cve.id}`);
|
|
83
85
|
return patch;
|
|
84
86
|
}
|
|
85
87
|
} catch (error) {
|
|
86
|
-
console.warn(
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
if (this.nosanaApiKey) {
|
|
92
|
-
try {
|
|
93
|
-
console.log(`[Kimi] Generating patch for ${cve.id}...`);
|
|
94
|
-
const patch = await this.generatePatchWithKimi(cve);
|
|
95
|
-
if (patch) {
|
|
96
|
-
cve.patch_diff = patch;
|
|
97
|
-
return patch;
|
|
98
|
-
}
|
|
99
|
-
} catch (error) {
|
|
100
|
-
console.warn(`[Kimi] Failed to generate patch: ${error instanceof Error ? error.message : String(error)}`);
|
|
88
|
+
console.warn(
|
|
89
|
+
`[Kimi] ⚠️ Failed to generate patch for ${cve.id}: ${
|
|
90
|
+
error instanceof Error ? error.message : String(error)
|
|
91
|
+
}`
|
|
92
|
+
);
|
|
101
93
|
}
|
|
94
|
+
} else {
|
|
95
|
+
console.warn(
|
|
96
|
+
`[Kimi] ⚠️ No Kimi API key configured. Set KIMI_API_KEY or run:\n` +
|
|
97
|
+
` codeprobe config set kimi_api_key <your-key>`
|
|
98
|
+
);
|
|
102
99
|
}
|
|
103
100
|
|
|
104
101
|
return null;
|