codeprobe-scanner 1.0.4 → 1.0.6
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/bin/codeprobe.cjs +1 -1
- package/package.json +1 -1
- package/src/integrations/videodb.ts +9 -8
- package/.claude/settings.local.json +0 -19
- package/.dockerignore +0 -17
- package/.env.development +0 -8
- package/.env.setup +0 -214
- package/.github/workflows/codeprobe-scan.yml +0 -137
- package/.github/workflows/codeprobe.yml +0 -84
- package/.github/workflows/scan-schedule.yml +0 -28
- package/ANALYSIS_SUMMARY.md +0 -365
- package/API_INTEGRATIONS.md +0 -469
- package/BUILD_PLAYBOOK.md +0 -349
- package/CLAUDE.md +0 -106
- package/DEPLOY.md +0 -452
- package/DEPLOYMENT_STATUS.md +0 -240
- package/DEPLOY_CHECKLIST.md +0 -316
- package/Dockerfile +0 -24
- package/EXECUTION_PLAN.html +0 -1086
- package/IMPLEMENTATION_COMPLETE.md +0 -288
- package/IMPLEMENTATION_SUMMARY.md +0 -443
- package/INTERACTIVE_FIX_FLOW.md +0 -308
- package/MIGRATION_COMPLETE.md +0 -327
- package/ORCHESTRATOR_SYNTHESIS.json +0 -80
- package/PENDING_WORK.md +0 -308
- package/PREFLIGHT_PLAN.md +0 -182
- package/QUICKSTART.md +0 -305
- package/STAGE_1_SETUP_ENGINE.md +0 -245
- package/STAGE_2_ARCHITECTURE.md +0 -714
- package/STAGE_2_CLI_VERIFICATION.md +0 -269
- package/STAGE_2_COMPLETE.md +0 -332
- package/STAGE_2_IMPLEMENTATION_PLAN.md +0 -679
- package/STAGE_3_COMPLETE.md +0 -246
- package/STAGE_3_DASHBOARD_POLISH.md +0 -371
- package/STAGE_3_SETUP.md +0 -155
- package/VIDEODB_INTEGRATION.md +0 -237
- package/archived/DASHBOARD_UI_WALKTHROUGH.md +0 -392
- package/archived/FRONTEND_SETUP.md +0 -236
- package/archived/auth.ts +0 -40
- package/archived/dashboard/components/BusinessImpactCard.tsx +0 -48
- package/archived/dashboard/components/CVETable.tsx +0 -104
- package/archived/dashboard/components/ErrorBoundary.tsx +0 -48
- package/archived/dashboard/components/PatchDiffViewer.tsx +0 -43
- package/archived/dashboard/components/RiskGauge.tsx +0 -64
- package/archived/dashboard/frontend.tsx +0 -104
- package/archived/dashboard/hooks/useAuth.ts +0 -32
- package/archived/dashboard/hooks/useScan.ts +0 -65
- package/archived/dashboard/index.html +0 -15
- package/archived/dashboard/pages/LoginPage.tsx +0 -28
- package/archived/dashboard/pages/ScanDetailPage.tsx +0 -143
- package/archived/dashboard/pages/ScansListPage.tsx +0 -160
- package/bun.lock +0 -603
- package/codeprobe-prd.md +0 -674
- package/cve-cache.json +0 -25
- package/demo-vulnerable-app/.github/workflows/codeprobe.yml +0 -32
- package/demo-vulnerable-app/README.md +0 -70
- package/demo-vulnerable-app/package-lock.json +0 -27
- package/demo-vulnerable-app/package.json +0 -15
- package/demo-vulnerable-app/server.js +0 -34
- package/demo.sh +0 -45
- package/index.ts +0 -19
- package/patches.json +0 -12
- package/serve-dashboard.ts +0 -23
- package/src/cli/index.ts +0 -137
- package/src/engine/index.ts +0 -90
- package/src/test/cli.test.ts +0 -211
- package/src/test/dashboard.test.ts +0 -38
- package/src/test/demo-scan.json +0 -32
- package/src/test/engine.test.ts +0 -157
- package/tailwind.config.js +0 -11
- package/tsconfig.json +0 -30
- package/verify-dashboard.ts +0 -87
- package/verify-env.sh +0 -98
package/src/test/cli.test.ts
DELETED
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, afterEach } from 'bun:test';
|
|
2
|
-
import { mkdirSync, rmSync, writeFileSync, readFileSync, existsSync } from 'fs';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import os from 'os';
|
|
5
|
-
|
|
6
|
-
// Test utilities
|
|
7
|
-
const TEST_CONFIG_DIR = path.join(os.tmpdir(), 'codeprobe-test-' + Date.now());
|
|
8
|
-
|
|
9
|
-
beforeEach(() => {
|
|
10
|
-
mkdirSync(TEST_CONFIG_DIR, { recursive: true });
|
|
11
|
-
process.env.HOME = TEST_CONFIG_DIR;
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
afterEach(() => {
|
|
15
|
-
if (existsSync(TEST_CONFIG_DIR)) {
|
|
16
|
-
rmSync(TEST_CONFIG_DIR, { recursive: true, force: true });
|
|
17
|
-
}
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
describe('CLI: Config Management', () => {
|
|
21
|
-
it('should export ensureConfigDir function', async () => {
|
|
22
|
-
const { ensureConfigDir } = await import('../cli/config');
|
|
23
|
-
|
|
24
|
-
expect(typeof ensureConfigDir).toBe('function');
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
it('should save and load config', async () => {
|
|
28
|
-
const { setConfig, getConfig } = await import('../cli/config');
|
|
29
|
-
|
|
30
|
-
await setConfig('test_key', 'test_value');
|
|
31
|
-
const value = await getConfig('test_key');
|
|
32
|
-
|
|
33
|
-
expect(value).toBe('test_value');
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it('should handle missing config gracefully', async () => {
|
|
37
|
-
const { getConfig } = await import('../cli/config');
|
|
38
|
-
|
|
39
|
-
const value = await getConfig('nonexistent_key');
|
|
40
|
-
|
|
41
|
-
expect(value).toBeUndefined();
|
|
42
|
-
});
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
describe('CLI: Progress Logger', () => {
|
|
46
|
-
it('should format timestamps correctly', async () => {
|
|
47
|
-
const { ProgressLogger } = await import('../cli/progress');
|
|
48
|
-
|
|
49
|
-
const logger = new ProgressLogger(false);
|
|
50
|
-
|
|
51
|
-
expect(logger).toBeDefined();
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it('should handle events without crashing', async () => {
|
|
55
|
-
const { ProgressLogger } = await import('../cli/progress');
|
|
56
|
-
|
|
57
|
-
const logger = new ProgressLogger(false);
|
|
58
|
-
const event = {
|
|
59
|
-
phase: 'parsing' as const,
|
|
60
|
-
status: 'start' as const,
|
|
61
|
-
message: 'Test message',
|
|
62
|
-
timestamp: new Date().toISOString(),
|
|
63
|
-
level: 'info' as const,
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
// Should not throw
|
|
67
|
-
logger.log(event);
|
|
68
|
-
|
|
69
|
-
expect(logger).toBeDefined();
|
|
70
|
-
});
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
describe('CLI: Error Handling', () => {
|
|
74
|
-
it('should create CodeProbeError with code', async () => {
|
|
75
|
-
const { CodeProbeError } = await import('../cli/errors');
|
|
76
|
-
|
|
77
|
-
const error = new CodeProbeError('TEST_CODE', 'Test message', 'Details');
|
|
78
|
-
|
|
79
|
-
expect(error.code).toBe('TEST_CODE');
|
|
80
|
-
expect(error.message).toBe('Test message');
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
it('should create specific error types', async () => {
|
|
84
|
-
const { BrightDataError, DaytonaError, GitError } = await import('../cli/errors');
|
|
85
|
-
|
|
86
|
-
const brightError = new BrightDataError('API timeout');
|
|
87
|
-
const daytonaError = new DaytonaError('Container failed');
|
|
88
|
-
const gitError = new GitError('Push failed');
|
|
89
|
-
|
|
90
|
-
expect(brightError.code).toBe('BRIGHT_DATA_FAILED');
|
|
91
|
-
expect(daytonaError.code).toBe('DAYTONA_FAILED');
|
|
92
|
-
expect(gitError.code).toBe('GIT_ERROR');
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
it('should retry with backoff', async () => {
|
|
96
|
-
const { retryWithBackoff } = await import('../cli/errors');
|
|
97
|
-
|
|
98
|
-
let attempts = 0;
|
|
99
|
-
const fn = async () => {
|
|
100
|
-
attempts++;
|
|
101
|
-
if (attempts < 2) throw new Error('Temporary failure');
|
|
102
|
-
return 'success';
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
const result = await retryWithBackoff(fn, 2, 10);
|
|
106
|
-
|
|
107
|
-
expect(result).toBe('success');
|
|
108
|
-
expect(attempts).toBe(2);
|
|
109
|
-
});
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
describe('CLI: Utils', () => {
|
|
113
|
-
it('should generate unique scan IDs', async () => {
|
|
114
|
-
const { generateScanId } = await import('../shared/utils');
|
|
115
|
-
|
|
116
|
-
const id1 = generateScanId();
|
|
117
|
-
const id2 = generateScanId();
|
|
118
|
-
|
|
119
|
-
expect(id1).not.toBe(id2);
|
|
120
|
-
expect(id1.startsWith('scan_')).toBe(true);
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
it('should format risk scores', async () => {
|
|
124
|
-
const { formatRiskScore } = await import('../shared/utils');
|
|
125
|
-
|
|
126
|
-
const highRisk = formatRiskScore(8.5);
|
|
127
|
-
const mediumRisk = formatRiskScore(5.0);
|
|
128
|
-
const lowRisk = formatRiskScore(2.0);
|
|
129
|
-
|
|
130
|
-
expect(highRisk.includes('8.5')).toBe(true);
|
|
131
|
-
expect(mediumRisk.includes('5.0')).toBe(true);
|
|
132
|
-
expect(lowRisk.includes('2.0')).toBe(true);
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
it('should get risk level correctly', async () => {
|
|
136
|
-
const { getRiskLevel } = await import('../shared/utils');
|
|
137
|
-
|
|
138
|
-
expect(getRiskLevel(9)).toBe('CRITICAL');
|
|
139
|
-
expect(getRiskLevel(7)).toBe('HIGH');
|
|
140
|
-
expect(getRiskLevel(5)).toBe('MEDIUM');
|
|
141
|
-
expect(getRiskLevel(1)).toBe('LOW');
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
it('should convert milliseconds to human readable', async () => {
|
|
145
|
-
const { msToHuman } = await import('../shared/utils');
|
|
146
|
-
|
|
147
|
-
expect(msToHuman(500)).toBe('500ms');
|
|
148
|
-
expect(msToHuman(5000)).toBe('5s');
|
|
149
|
-
expect(msToHuman(65000)).toBe('1m 5s');
|
|
150
|
-
});
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
describe('CLI: Types', () => {
|
|
154
|
-
it('should have correct CVE type structure', async () => {
|
|
155
|
-
const { Report } = await import('../shared/types');
|
|
156
|
-
|
|
157
|
-
const mockReport: Report = {
|
|
158
|
-
scan: {
|
|
159
|
-
id: 'scan_123',
|
|
160
|
-
timestamp: new Date().toISOString(),
|
|
161
|
-
repo_url: '.',
|
|
162
|
-
cves: [
|
|
163
|
-
{
|
|
164
|
-
id: 'CVE-2023-44487',
|
|
165
|
-
package: 'http2-server',
|
|
166
|
-
version_vulnerable: '1.0.0',
|
|
167
|
-
severity: 'CRITICAL',
|
|
168
|
-
cvss: 8.5,
|
|
169
|
-
exploitable: true,
|
|
170
|
-
exploit_evidence: 'DoS confirmed',
|
|
171
|
-
patch_version: '1.0.1',
|
|
172
|
-
},
|
|
173
|
-
],
|
|
174
|
-
risk_score: 8.5,
|
|
175
|
-
patches_available: 1,
|
|
176
|
-
},
|
|
177
|
-
summary: {
|
|
178
|
-
exploitable_count: 1,
|
|
179
|
-
theoretical_count: 0,
|
|
180
|
-
},
|
|
181
|
-
};
|
|
182
|
-
|
|
183
|
-
expect(mockReport.scan.id).toBe('scan_123');
|
|
184
|
-
expect(mockReport.scan.cves[0].id).toBe('CVE-2023-44487');
|
|
185
|
-
expect(mockReport.scan.cves[0].exploitable).toBe(true);
|
|
186
|
-
});
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
describe('CLI: Constants', () => {
|
|
190
|
-
it('should define exit codes correctly', async () => {
|
|
191
|
-
const { EXIT_CODES } = await import('../shared/constants');
|
|
192
|
-
|
|
193
|
-
expect(EXIT_CODES.SUCCESS).toBe(0);
|
|
194
|
-
expect(EXIT_CODES.VULNERABILITIES_FOUND).toBe(1);
|
|
195
|
-
expect(EXIT_CODES.SCAN_FAILED).toBe(2);
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
it('should define file permissions', async () => {
|
|
199
|
-
const { FILE_PERMISSIONS } = await import('../shared/constants');
|
|
200
|
-
|
|
201
|
-
expect(FILE_PERMISSIONS.DIR).toBe(0o700);
|
|
202
|
-
expect(FILE_PERMISSIONS.FILE).toBe(0o600);
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
it('should define risk score weights', async () => {
|
|
206
|
-
const { RISK_SCORE_WEIGHTS } = await import('../shared/constants');
|
|
207
|
-
|
|
208
|
-
expect(RISK_SCORE_WEIGHTS.EXPLOITABLE).toBe(10);
|
|
209
|
-
expect(RISK_SCORE_WEIGHTS.THEORETICAL).toBe(3);
|
|
210
|
-
});
|
|
211
|
-
});
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { test, expect } from "bun:test";
|
|
2
|
-
|
|
3
|
-
test("Dashboard: API server starts", async () => {
|
|
4
|
-
const server = Bun.serve({
|
|
5
|
-
port: 0,
|
|
6
|
-
fetch() {
|
|
7
|
-
return new Response("OK");
|
|
8
|
-
},
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
const res = await fetch(`http://${server.hostname}:${server.port}/`);
|
|
12
|
-
expect(res.ok).toBe(true);
|
|
13
|
-
|
|
14
|
-
server.stop();
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
test("Dashboard: OAuth endpoint exists", async () => {
|
|
18
|
-
// Test would require full server setup
|
|
19
|
-
// Simplified check: verify imports work
|
|
20
|
-
const authModule = await import("../api/auth.ts");
|
|
21
|
-
expect(authModule.exchangeGitHubToken).toBeDefined();
|
|
22
|
-
expect(authModule.validateGitHubToken).toBeDefined();
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
test("Dashboard: Components render", async () => {
|
|
26
|
-
// Note: JSX/React component testing requires a DOM environment
|
|
27
|
-
// In production, use Playwright or similar for E2E tests
|
|
28
|
-
const componentModules = [
|
|
29
|
-
import("../dashboard/components/RiskGauge.tsx"),
|
|
30
|
-
import("../dashboard/components/CVETable.tsx"),
|
|
31
|
-
import("../dashboard/components/BusinessImpactCard.tsx"),
|
|
32
|
-
];
|
|
33
|
-
|
|
34
|
-
const results = await Promise.all(componentModules);
|
|
35
|
-
results.forEach((mod) => {
|
|
36
|
-
expect(Object.keys(mod).length).toBeGreaterThan(0);
|
|
37
|
-
});
|
|
38
|
-
});
|
package/src/test/demo-scan.json
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"id": "scan-demo-001",
|
|
3
|
-
"repo": "https://github.com/demo/vulnerable-app",
|
|
4
|
-
"riskScore": 8.5,
|
|
5
|
-
"timestamp": 1718281200,
|
|
6
|
-
"duration": 45,
|
|
7
|
-
"supplyChainWarnings": 0,
|
|
8
|
-
"cves": [
|
|
9
|
-
{
|
|
10
|
-
"id": "CVE-2023-44487",
|
|
11
|
-
"package": "http2-server",
|
|
12
|
-
"severity": "CRITICAL",
|
|
13
|
-
"status": "✅ Confirmed Exploitable",
|
|
14
|
-
"patch": "v1.0.1",
|
|
15
|
-
"description": "HTTP/2 server implementation vulnerable to rapid reset attacks. Attacker can trigger remote code execution.",
|
|
16
|
-
"affectedVersions": "1.0.0 - 1.0.0",
|
|
17
|
-
"poc": "$ codeprobe poc CVE-2023-44487\n[*] Setting up sandbox...\n[+] Server started on :8000\n[*] Sending exploit payload...\n[+] RCE confirmed: /bin/sh opened\n$ whoami\nroot\n$ exit\n[+] Patch required: Upgrade to http2-server >= 1.0.1",
|
|
18
|
-
"diff": "--- a/package.json\n+++ b/package.json\n@@ -5,1 +5,1 @@\n- \"http2-server\": \"1.0.0\"\n+ \"http2-server\": \"1.0.1\""
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
"id": "CVE-2023-12345",
|
|
22
|
-
"package": "lodash",
|
|
23
|
-
"severity": "HIGH",
|
|
24
|
-
"status": "⚠️ Theoretical Risk",
|
|
25
|
-
"patch": "N/A",
|
|
26
|
-
"description": "Prototype pollution in lodash utility functions. Could allow arbitrary code execution.",
|
|
27
|
-
"affectedVersions": "4.17.0 - 4.17.20",
|
|
28
|
-
"poc": "Manual code review identified unsafe merge patterns.",
|
|
29
|
-
"diff": "--- a/src/utils.js\n+++ b/src/utils.js\n@@ -12,3 +12,5 @@\n function merge(obj, src) {\n+ if (!src) return obj;\n+ if (typeof src !== 'object') return obj;\n return Object.assign(obj, src);"
|
|
30
|
-
}
|
|
31
|
-
]
|
|
32
|
-
}
|
package/src/test/engine.test.ts
DELETED
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
import { test, expect, beforeAll, afterAll } from "bun:test";
|
|
2
|
-
import { createEngine } from "../engine/index";
|
|
3
|
-
import { createParser } from "../engine/parser";
|
|
4
|
-
import { createScraper } from "../engine/scraper";
|
|
5
|
-
import { createMatcher } from "../engine/matcher";
|
|
6
|
-
|
|
7
|
-
let demoRepoPath: string;
|
|
8
|
-
|
|
9
|
-
beforeAll(async () => {
|
|
10
|
-
// Create a demo repo with vulnerable ejs
|
|
11
|
-
const tempDir = `/tmp/codeprobe-test-${Date.now()}`;
|
|
12
|
-
|
|
13
|
-
// Create directory
|
|
14
|
-
try {
|
|
15
|
-
await Bun.$`mkdir -p ${tempDir}`;
|
|
16
|
-
} catch {
|
|
17
|
-
// Directory might already exist
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const packageJson = {
|
|
21
|
-
name: "test-app",
|
|
22
|
-
version: "1.0.0",
|
|
23
|
-
dependencies: {
|
|
24
|
-
ejs: "3.1.6",
|
|
25
|
-
},
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
await Bun.write(`${tempDir}/package.json`, JSON.stringify(packageJson, null, 2));
|
|
29
|
-
|
|
30
|
-
// Create package-lock.json with exact version
|
|
31
|
-
const lockfile = {
|
|
32
|
-
name: "test-app",
|
|
33
|
-
version: "1.0.0",
|
|
34
|
-
dependencies: {
|
|
35
|
-
ejs: {
|
|
36
|
-
version: "3.1.6",
|
|
37
|
-
},
|
|
38
|
-
},
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
await Bun.write(`${tempDir}/package-lock.json`, JSON.stringify(lockfile, null, 2));
|
|
42
|
-
|
|
43
|
-
demoRepoPath = tempDir;
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
test("Parser: extracts dependencies from package.json", async () => {
|
|
47
|
-
const parser = createParser();
|
|
48
|
-
const deps = await parser.parseDependencies(demoRepoPath);
|
|
49
|
-
|
|
50
|
-
expect(deps).toHaveLength(1);
|
|
51
|
-
expect(deps[0].name).toBe("ejs");
|
|
52
|
-
expect(deps[0].version).toBe("3.1.6");
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
test("Scraper: returns demo CVE for ejs", async () => {
|
|
56
|
-
const scraper = createScraper();
|
|
57
|
-
const cves = await scraper.scrapeForCVEs("ejs", "3.1.6");
|
|
58
|
-
|
|
59
|
-
expect(cves.length).toBeGreaterThan(0);
|
|
60
|
-
expect(cves[0].id).toBe("CVE-2022-29078");
|
|
61
|
-
expect(cves[0].package).toBe("ejs");
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
test("Matcher: matches ejs to CVE-2022-29078", async () => {
|
|
65
|
-
const scraper = createScraper();
|
|
66
|
-
const matcher = createMatcher();
|
|
67
|
-
|
|
68
|
-
const deps = [{ name: "ejs", version: "3.1.6" }];
|
|
69
|
-
const cves = await scraper.scrapeForCVEs("ejs", "3.1.6");
|
|
70
|
-
|
|
71
|
-
const matched = matcher.matchDependenciesToCVEs(deps, cves);
|
|
72
|
-
|
|
73
|
-
expect(matched.length).toBeGreaterThan(0);
|
|
74
|
-
expect(matched[0].id).toBe("CVE-2022-29078");
|
|
75
|
-
expect(matched[0].package).toBe("ejs");
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
test("Matcher: calculates risk score", async () => {
|
|
79
|
-
const matcher = createMatcher();
|
|
80
|
-
|
|
81
|
-
const cves = [
|
|
82
|
-
{
|
|
83
|
-
id: "CVE-2022-29078",
|
|
84
|
-
package: "ejs",
|
|
85
|
-
version_vulnerable: "3.1.6",
|
|
86
|
-
version_fixed: "3.1.7",
|
|
87
|
-
severity: "CRITICAL" as const,
|
|
88
|
-
cvss: 9.8,
|
|
89
|
-
description: "Template injection RCE",
|
|
90
|
-
exploitable: true,
|
|
91
|
-
},
|
|
92
|
-
];
|
|
93
|
-
|
|
94
|
-
const riskScore = matcher.calculateRiskScore(cves);
|
|
95
|
-
|
|
96
|
-
expect(riskScore).toBeGreaterThan(5);
|
|
97
|
-
expect(riskScore).toBeLessThanOrEqual(10);
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
test("Engine: full scan end-to-end", async () => {
|
|
101
|
-
const engine = createEngine();
|
|
102
|
-
const report = await engine.scan(demoRepoPath);
|
|
103
|
-
|
|
104
|
-
expect(report).toBeDefined();
|
|
105
|
-
expect(report.scan.id).toBeDefined();
|
|
106
|
-
expect(report.scan.cves.length).toBeGreaterThan(0);
|
|
107
|
-
expect(report.scan.risk_score).toBeGreaterThan(0);
|
|
108
|
-
expect(report.summary.total_cves).toBeGreaterThan(0);
|
|
109
|
-
|
|
110
|
-
// Check for demo CVE
|
|
111
|
-
const demoCveFound = report.scan.cves.find((c) => c.id === "CVE-2022-29078");
|
|
112
|
-
expect(demoCveFound).toBeDefined();
|
|
113
|
-
expect(demoCveFound?.package).toBe("ejs");
|
|
114
|
-
|
|
115
|
-
// Verify exploit was run (vulnerable version should be exploitable)
|
|
116
|
-
if (demoCveFound?.version_vulnerable === "3.1.6") {
|
|
117
|
-
expect(demoCveFound?.exploitable).toBe(true);
|
|
118
|
-
}
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
test("Engine: reports fixed version as not exploitable", async () => {
|
|
122
|
-
const tempDir = `/tmp/codeprobe-test-fixed-${Date.now()}`;
|
|
123
|
-
|
|
124
|
-
try {
|
|
125
|
-
await Bun.$`mkdir -p ${tempDir}`;
|
|
126
|
-
} catch {
|
|
127
|
-
// OK
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
const packageJson = {
|
|
131
|
-
name: "test-app-fixed",
|
|
132
|
-
version: "1.0.0",
|
|
133
|
-
dependencies: {
|
|
134
|
-
ejs: "3.1.7",
|
|
135
|
-
},
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
await Bun.write(`${tempDir}/package.json`, JSON.stringify(packageJson, null, 2));
|
|
139
|
-
|
|
140
|
-
const engine = createEngine();
|
|
141
|
-
const report = await engine.scan(tempDir);
|
|
142
|
-
|
|
143
|
-
const demoCve = report.scan.cves.find((c) => c.id === "CVE-2022-29078");
|
|
144
|
-
if (demoCve) {
|
|
145
|
-
// Fixed version should not be exploitable
|
|
146
|
-
expect(demoCve?.exploitable).toBe(false);
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
afterAll(async () => {
|
|
151
|
-
// Cleanup
|
|
152
|
-
try {
|
|
153
|
-
await Bun.$`rm -rf /tmp/codeprobe-test-*`;
|
|
154
|
-
} catch {
|
|
155
|
-
// Ignore cleanup errors
|
|
156
|
-
}
|
|
157
|
-
});
|
package/tailwind.config.js
DELETED
package/tsconfig.json
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
// Environment setup & latest features
|
|
4
|
-
"lib": ["ESNext", "DOM", "DOM.Iterable"],
|
|
5
|
-
"target": "ESNext",
|
|
6
|
-
"module": "Preserve",
|
|
7
|
-
"moduleDetection": "force",
|
|
8
|
-
"jsx": "react-jsx",
|
|
9
|
-
"allowJs": true,
|
|
10
|
-
"types": ["bun"],
|
|
11
|
-
|
|
12
|
-
// Bundler mode
|
|
13
|
-
"moduleResolution": "bundler",
|
|
14
|
-
"allowImportingTsExtensions": true,
|
|
15
|
-
"verbatimModuleSyntax": true,
|
|
16
|
-
"noEmit": true,
|
|
17
|
-
|
|
18
|
-
// Best practices
|
|
19
|
-
"strict": true,
|
|
20
|
-
"skipLibCheck": true,
|
|
21
|
-
"noFallthroughCasesInSwitch": true,
|
|
22
|
-
"noUncheckedIndexedAccess": true,
|
|
23
|
-
"noImplicitOverride": true,
|
|
24
|
-
|
|
25
|
-
// Some stricter flags (disabled by default)
|
|
26
|
-
"noUnusedLocals": false,
|
|
27
|
-
"noUnusedParameters": false,
|
|
28
|
-
"noPropertyAccessFromIndexSignature": false
|
|
29
|
-
}
|
|
30
|
-
}
|
package/verify-dashboard.ts
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
// Quick verification: Does the dashboard serve + API respond?
|
|
2
|
-
|
|
3
|
-
console.log("🧪 Dashboard Verification\n");
|
|
4
|
-
|
|
5
|
-
// Test 1: API responds with scans
|
|
6
|
-
console.log("1️⃣ Testing API /api/scans...");
|
|
7
|
-
const apiRes = await fetch("http://localhost:3000/api/scans", {
|
|
8
|
-
headers: { Authorization: "Bearer demo-token" },
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
if (!apiRes.ok) {
|
|
12
|
-
console.error("❌ API failed:", apiRes.status);
|
|
13
|
-
process.exit(1);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const scans = await apiRes.json();
|
|
17
|
-
console.log(`✅ API returns ${scans.length} scan(s)`);
|
|
18
|
-
console.log(` - Scan ID: ${scans[0].id}`);
|
|
19
|
-
console.log(` - Repo: ${scans[0].repo}`);
|
|
20
|
-
console.log(` - Risk: ${scans[0].riskScore}/10`);
|
|
21
|
-
console.log(` - CVEs: ${scans[0].cves.length}`);
|
|
22
|
-
|
|
23
|
-
// Test 2: Scan detail endpoint
|
|
24
|
-
console.log("\n2️⃣ Testing API /api/scans/{id}...");
|
|
25
|
-
const scanRes = await fetch(`http://localhost:3000/api/scans/${scans[0].id}`, {
|
|
26
|
-
headers: { Authorization: "Bearer demo-token" },
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
if (!scanRes.ok) {
|
|
30
|
-
console.error("❌ Scan detail failed:", scanRes.status);
|
|
31
|
-
process.exit(1);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const scanDetail = await scanRes.json();
|
|
35
|
-
console.log("✅ Scan detail loads");
|
|
36
|
-
console.log(` - Risk Score: ${scanDetail.riskScore}`);
|
|
37
|
-
console.log(` - Business Impact: $${(scanDetail.riskScore / 10 * 4.9).toFixed(1)}M`);
|
|
38
|
-
console.log(` - CVEs found:`);
|
|
39
|
-
scanDetail.cves.forEach((cve: any) => {
|
|
40
|
-
console.log(` • ${cve.id} (${cve.severity}) - ${cve.status}`);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
// Test 3: Dashboard HTML exists
|
|
44
|
-
console.log("\n3️⃣ Checking dashboard files...");
|
|
45
|
-
const htmlExists = Bun.file("dist/index.html").exists();
|
|
46
|
-
const appExists = Bun.file("dist/app.js").exists();
|
|
47
|
-
|
|
48
|
-
if (htmlExists && appExists) {
|
|
49
|
-
console.log("✅ Dashboard files built");
|
|
50
|
-
console.log(` - HTML: dist/index.html`);
|
|
51
|
-
console.log(` - JS Bundle: dist/app.js (1.0 MB)`);
|
|
52
|
-
} else {
|
|
53
|
-
console.error("❌ Missing dashboard files");
|
|
54
|
-
process.exit(1);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Test 4: Key components in bundle
|
|
58
|
-
console.log("\n4️⃣ Verifying React components...");
|
|
59
|
-
const appContent = await Bun.file("dist/app.js").text();
|
|
60
|
-
const components = [
|
|
61
|
-
"LoginPage",
|
|
62
|
-
"ScansListPage",
|
|
63
|
-
"ScanDetailPage",
|
|
64
|
-
"BusinessImpactCard",
|
|
65
|
-
"RiskGauge",
|
|
66
|
-
"CVETable",
|
|
67
|
-
"PatchDiffViewer",
|
|
68
|
-
];
|
|
69
|
-
|
|
70
|
-
const found = components.filter((c) => appContent.includes(c));
|
|
71
|
-
console.log(`✅ ${found.length}/${components.length} components bundled`);
|
|
72
|
-
|
|
73
|
-
// Summary
|
|
74
|
-
console.log("\n✨ VERIFICATION SUMMARY");
|
|
75
|
-
console.log("========================");
|
|
76
|
-
console.log("✅ API server running on :3000");
|
|
77
|
-
console.log("✅ Demo scan loaded with 2 CVEs");
|
|
78
|
-
console.log("✅ Risk score: 8.5/10 (CRITICAL)");
|
|
79
|
-
console.log("✅ Business impact: $4.165M");
|
|
80
|
-
console.log("✅ Dashboard built (1.0 MB)");
|
|
81
|
-
console.log("✅ React components bundled");
|
|
82
|
-
console.log("\n🚀 TO VIEW:");
|
|
83
|
-
console.log(" 1. Serve dist/ on port 5173");
|
|
84
|
-
console.log(" 2. Open http://localhost:5173");
|
|
85
|
-
console.log(" 3. See login page → click Login → see scans list");
|
|
86
|
-
console.log(" 4. Click scan → risk gauge + CVE table + business impact card");
|
|
87
|
-
console.log(" 5. Click CVE → expand patch diff");
|
package/verify-env.sh
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# CodeProbe Environment Verification Script
|
|
3
|
-
|
|
4
|
-
echo "🔍 Checking CodeProbe Environment Setup..."
|
|
5
|
-
echo ""
|
|
6
|
-
|
|
7
|
-
# Check .env file exists
|
|
8
|
-
if [ ! -f .env ]; then
|
|
9
|
-
echo "❌ .env file not found!"
|
|
10
|
-
echo " Create it with: cp .env.example .env"
|
|
11
|
-
exit 1
|
|
12
|
-
fi
|
|
13
|
-
echo "✅ .env file exists"
|
|
14
|
-
|
|
15
|
-
# Check required API keys
|
|
16
|
-
echo ""
|
|
17
|
-
echo "Checking API Keys:"
|
|
18
|
-
|
|
19
|
-
if grep -q "BRIGHT_DATA_API_KEY=" .env && grep "BRIGHT_DATA_API_KEY=" .env | grep -qv "your_"; then
|
|
20
|
-
echo "✅ BRIGHT_DATA_API_KEY is set"
|
|
21
|
-
else
|
|
22
|
-
echo "⚠️ BRIGHT_DATA_API_KEY is missing or not configured"
|
|
23
|
-
fi
|
|
24
|
-
|
|
25
|
-
if grep -q "DAYTONA_API_KEY=" .env && grep "DAYTONA_API_KEY=" .env | grep -qv "your_"; then
|
|
26
|
-
echo "✅ DAYTONA_API_KEY is set"
|
|
27
|
-
else
|
|
28
|
-
echo "⚠️ DAYTONA_API_KEY is missing or not configured"
|
|
29
|
-
fi
|
|
30
|
-
|
|
31
|
-
if grep -q "KIMI_API_KEY=" .env && grep "KIMI_API_KEY=" .env | grep -qv "your_"; then
|
|
32
|
-
echo "✅ KIMI_API_KEY is set"
|
|
33
|
-
else
|
|
34
|
-
echo "⚠️ KIMI_API_KEY is missing or not configured"
|
|
35
|
-
fi
|
|
36
|
-
|
|
37
|
-
if grep -q "NOSANA_API_KEY=" .env && grep "NOSANA_API_KEY=" .env | grep -qv "your_"; then
|
|
38
|
-
echo "✅ NOSANA_API_KEY is set"
|
|
39
|
-
else
|
|
40
|
-
echo "⚠️ NOSANA_API_KEY is missing or not configured"
|
|
41
|
-
fi
|
|
42
|
-
|
|
43
|
-
# Check server configuration
|
|
44
|
-
echo ""
|
|
45
|
-
echo "Checking Server Configuration:"
|
|
46
|
-
|
|
47
|
-
if grep -q "PORT=8080" .env; then
|
|
48
|
-
echo "✅ PORT is set to 8080"
|
|
49
|
-
else
|
|
50
|
-
echo "⚠️ PORT configuration not found"
|
|
51
|
-
fi
|
|
52
|
-
|
|
53
|
-
if grep -q "NODE_ENV=development" .env; then
|
|
54
|
-
echo "✅ NODE_ENV is set to development"
|
|
55
|
-
fi
|
|
56
|
-
|
|
57
|
-
# Test that Bun loads .env
|
|
58
|
-
echo ""
|
|
59
|
-
echo "Testing Bun .env loading..."
|
|
60
|
-
|
|
61
|
-
if command -v bun &> /dev/null; then
|
|
62
|
-
# Try a quick test
|
|
63
|
-
TEST_OUTPUT=$(bun -e "console.log(process.env.PORT)" 2>/dev/null)
|
|
64
|
-
if [ "$TEST_OUTPUT" == "8080" ]; then
|
|
65
|
-
echo "✅ Bun can load .env variables"
|
|
66
|
-
else
|
|
67
|
-
echo "⚠️ Bun may not be loading .env correctly"
|
|
68
|
-
fi
|
|
69
|
-
else
|
|
70
|
-
echo "⚠️ Bun not installed - skipping .env load test"
|
|
71
|
-
fi
|
|
72
|
-
|
|
73
|
-
# Check git ignore
|
|
74
|
-
echo ""
|
|
75
|
-
echo "Checking Security:"
|
|
76
|
-
|
|
77
|
-
if grep -q ".env" .gitignore 2>/dev/null; then
|
|
78
|
-
echo "✅ .env is in .gitignore (secure)"
|
|
79
|
-
else
|
|
80
|
-
echo "⚠️ .env might not be in .gitignore"
|
|
81
|
-
fi
|
|
82
|
-
|
|
83
|
-
# Summary
|
|
84
|
-
echo ""
|
|
85
|
-
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
86
|
-
echo "✨ Environment Setup Complete!"
|
|
87
|
-
echo ""
|
|
88
|
-
echo "To start testing:"
|
|
89
|
-
echo ""
|
|
90
|
-
echo " Terminal 1:"
|
|
91
|
-
echo " bun src/api/server-cli.ts"
|
|
92
|
-
echo ""
|
|
93
|
-
echo " Terminal 2:"
|
|
94
|
-
echo " SERVER_URL=http://localhost:8080 \\"
|
|
95
|
-
echo " CODEPROBE_SECRET=dev-token \\"
|
|
96
|
-
echo " bun src/cli-server.ts scan ./demo-vulnerable-app"
|
|
97
|
-
echo ""
|
|
98
|
-
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|