codeprobe-scanner 1.0.4 → 1.0.5

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.
Files changed (71) hide show
  1. package/package.json +1 -1
  2. package/.claude/settings.local.json +0 -19
  3. package/.dockerignore +0 -17
  4. package/.env.development +0 -8
  5. package/.env.setup +0 -214
  6. package/.github/workflows/codeprobe-scan.yml +0 -137
  7. package/.github/workflows/codeprobe.yml +0 -84
  8. package/.github/workflows/scan-schedule.yml +0 -28
  9. package/ANALYSIS_SUMMARY.md +0 -365
  10. package/API_INTEGRATIONS.md +0 -469
  11. package/BUILD_PLAYBOOK.md +0 -349
  12. package/CLAUDE.md +0 -106
  13. package/DEPLOY.md +0 -452
  14. package/DEPLOYMENT_STATUS.md +0 -240
  15. package/DEPLOY_CHECKLIST.md +0 -316
  16. package/Dockerfile +0 -24
  17. package/EXECUTION_PLAN.html +0 -1086
  18. package/IMPLEMENTATION_COMPLETE.md +0 -288
  19. package/IMPLEMENTATION_SUMMARY.md +0 -443
  20. package/INTERACTIVE_FIX_FLOW.md +0 -308
  21. package/MIGRATION_COMPLETE.md +0 -327
  22. package/ORCHESTRATOR_SYNTHESIS.json +0 -80
  23. package/PENDING_WORK.md +0 -308
  24. package/PREFLIGHT_PLAN.md +0 -182
  25. package/QUICKSTART.md +0 -305
  26. package/STAGE_1_SETUP_ENGINE.md +0 -245
  27. package/STAGE_2_ARCHITECTURE.md +0 -714
  28. package/STAGE_2_CLI_VERIFICATION.md +0 -269
  29. package/STAGE_2_COMPLETE.md +0 -332
  30. package/STAGE_2_IMPLEMENTATION_PLAN.md +0 -679
  31. package/STAGE_3_COMPLETE.md +0 -246
  32. package/STAGE_3_DASHBOARD_POLISH.md +0 -371
  33. package/STAGE_3_SETUP.md +0 -155
  34. package/VIDEODB_INTEGRATION.md +0 -237
  35. package/archived/DASHBOARD_UI_WALKTHROUGH.md +0 -392
  36. package/archived/FRONTEND_SETUP.md +0 -236
  37. package/archived/auth.ts +0 -40
  38. package/archived/dashboard/components/BusinessImpactCard.tsx +0 -48
  39. package/archived/dashboard/components/CVETable.tsx +0 -104
  40. package/archived/dashboard/components/ErrorBoundary.tsx +0 -48
  41. package/archived/dashboard/components/PatchDiffViewer.tsx +0 -43
  42. package/archived/dashboard/components/RiskGauge.tsx +0 -64
  43. package/archived/dashboard/frontend.tsx +0 -104
  44. package/archived/dashboard/hooks/useAuth.ts +0 -32
  45. package/archived/dashboard/hooks/useScan.ts +0 -65
  46. package/archived/dashboard/index.html +0 -15
  47. package/archived/dashboard/pages/LoginPage.tsx +0 -28
  48. package/archived/dashboard/pages/ScanDetailPage.tsx +0 -143
  49. package/archived/dashboard/pages/ScansListPage.tsx +0 -160
  50. package/bun.lock +0 -603
  51. package/codeprobe-prd.md +0 -674
  52. package/cve-cache.json +0 -25
  53. package/demo-vulnerable-app/.github/workflows/codeprobe.yml +0 -32
  54. package/demo-vulnerable-app/README.md +0 -70
  55. package/demo-vulnerable-app/package-lock.json +0 -27
  56. package/demo-vulnerable-app/package.json +0 -15
  57. package/demo-vulnerable-app/server.js +0 -34
  58. package/demo.sh +0 -45
  59. package/index.ts +0 -19
  60. package/patches.json +0 -12
  61. package/serve-dashboard.ts +0 -23
  62. package/src/cli/index.ts +0 -137
  63. package/src/engine/index.ts +0 -90
  64. package/src/test/cli.test.ts +0 -211
  65. package/src/test/dashboard.test.ts +0 -38
  66. package/src/test/demo-scan.json +0 -32
  67. package/src/test/engine.test.ts +0 -157
  68. package/tailwind.config.js +0 -11
  69. package/tsconfig.json +0 -30
  70. package/verify-dashboard.ts +0 -87
  71. package/verify-env.sh +0 -98
@@ -1,48 +0,0 @@
1
- import React from "react";
2
-
3
- interface BusinessImpactCardProps {
4
- riskScore: number;
5
- cveCount: number;
6
- }
7
-
8
- export function BusinessImpactCard({ riskScore, cveCount }: BusinessImpactCardProps) {
9
- const breachCostM = 4.9;
10
- const estimatedRisk = (riskScore / 10) * breachCostM;
11
-
12
- return (
13
- <div className="bg-red-900 border-4 border-red-600 rounded-lg p-8 mb-8">
14
- <div className="flex items-start gap-4 mb-6">
15
- <span className="text-4xl">⚠️</span>
16
- <h2 className="text-3xl font-bold text-white">BUSINESS IMPACT</h2>
17
- </div>
18
-
19
- <p className="text-white text-lg mb-4">
20
- This codebase contains <strong>{cveCount}</strong> confirmed vulnerabilities.
21
- </p>
22
-
23
- <div className="bg-red-800 rounded p-4 mb-6">
24
- <p className="text-white font-semibold mb-2">If exploited → attacker can:</p>
25
- <ul className="text-white space-y-2">
26
- <li>• Execute arbitrary code on your server</li>
27
- <li>• Steal sensitive customer data</li>
28
- <li>• Hold your service ransom</li>
29
- </ul>
30
- </div>
31
-
32
- <div className="grid grid-cols-2 gap-4 mb-6">
33
- <div className="bg-red-800 rounded p-4">
34
- <p className="text-gray-200 text-sm">Average breach cost</p>
35
- <p className="text-2xl font-bold text-white">${breachCostM.toFixed(1)}M</p>
36
- </div>
37
- <div className="bg-red-800 rounded p-4">
38
- <p className="text-gray-200 text-sm">Your estimated risk</p>
39
- <p className="text-2xl font-bold text-white">${estimatedRisk.toFixed(1)}M</p>
40
- </div>
41
- </div>
42
-
43
- <p className="text-white font-semibold bg-red-800 rounded p-3">
44
- Recommended: Patch within 24 hours
45
- </p>
46
- </div>
47
- );
48
- }
@@ -1,104 +0,0 @@
1
- import React, { useState } from "react";
2
-
3
- interface CVE {
4
- id: string;
5
- package: string;
6
- severity: string;
7
- status: string;
8
- patch?: string;
9
- description?: string;
10
- affectedVersions?: string;
11
- poc?: string;
12
- }
13
-
14
- interface CVETableProps {
15
- cves: CVE[];
16
- onExpandCVE?: (cve: CVE) => void;
17
- }
18
-
19
- export function CVETable({ cves, onExpandCVE }: CVETableProps) {
20
- const [expanded, setExpanded] = useState<string | null>(null);
21
-
22
- const getSeverityColor = (severity: string) => {
23
- if (severity === "CRITICAL" || severity === "HIGH") return "text-red-400";
24
- if (severity === "MEDIUM") return "text-yellow-400";
25
- return "text-green-400";
26
- };
27
-
28
- const getStatusIcon = (status: string) => {
29
- if (status.includes("Confirmed")) return "✅";
30
- if (status.includes("Theoretical")) return "⚠️";
31
- return "❓";
32
- };
33
-
34
- if (!cves || cves.length === 0) {
35
- return <div className="text-gray-400 text-center py-8">No CVEs found</div>;
36
- }
37
-
38
- return (
39
- <div className="overflow-x-auto">
40
- <table className="w-full text-sm">
41
- <thead>
42
- <tr className="border-b border-gray-700">
43
- <th className="text-left py-3 px-4 font-semibold text-gray-300">CVE ID</th>
44
- <th className="text-left py-3 px-4 font-semibold text-gray-300">Package</th>
45
- <th className="text-left py-3 px-4 font-semibold text-gray-300">Severity</th>
46
- <th className="text-left py-3 px-4 font-semibold text-gray-300">Status</th>
47
- <th className="text-left py-3 px-4 font-semibold text-gray-300">Patch</th>
48
- </tr>
49
- </thead>
50
- <tbody>
51
- {cves.map((cve) => (
52
- <React.Fragment key={cve.id}>
53
- <tr
54
- className="border-b border-gray-800 hover:bg-gray-800 cursor-pointer transition"
55
- onClick={() => {
56
- setExpanded(expanded === cve.id ? null : cve.id);
57
- onExpandCVE?.(cve);
58
- }}
59
- >
60
- <td className="py-4 px-4 font-mono text-blue-400">{cve.id}</td>
61
- <td className="py-4 px-4 text-gray-300">{cve.package}</td>
62
- <td className={`py-4 px-4 font-semibold ${getSeverityColor(cve.severity)}`}>
63
- {cve.severity}
64
- </td>
65
- <td className="py-4 px-4 text-gray-300">
66
- {getStatusIcon(cve.status)} {cve.status}
67
- </td>
68
- <td className="py-4 px-4 text-gray-400">{cve.patch || "N/A"}</td>
69
- </tr>
70
- {expanded === cve.id && (
71
- <tr className="bg-gray-800 border-b border-gray-700">
72
- <td colSpan={5} className="py-4 px-4">
73
- <div className="space-y-3">
74
- {cve.description && (
75
- <div>
76
- <p className="text-xs font-semibold text-gray-400 mb-1">Description</p>
77
- <p className="text-gray-300">{cve.description}</p>
78
- </div>
79
- )}
80
- {cve.affectedVersions && (
81
- <div>
82
- <p className="text-xs font-semibold text-gray-400 mb-1">Affected Versions</p>
83
- <p className="text-gray-300 font-mono text-sm">{cve.affectedVersions}</p>
84
- </div>
85
- )}
86
- {cve.poc && (
87
- <div>
88
- <p className="text-xs font-semibold text-gray-400 mb-1">Exploit Evidence</p>
89
- <pre className="bg-gray-900 p-2 rounded text-xs text-gray-300 overflow-auto max-h-32">
90
- {cve.poc}
91
- </pre>
92
- </div>
93
- )}
94
- </div>
95
- </td>
96
- </tr>
97
- )}
98
- </React.Fragment>
99
- ))}
100
- </tbody>
101
- </table>
102
- </div>
103
- );
104
- }
@@ -1,48 +0,0 @@
1
- import React from "react";
2
-
3
- interface ErrorBoundaryProps {
4
- children: React.ReactNode;
5
- }
6
-
7
- interface ErrorBoundaryState {
8
- hasError: boolean;
9
- error: Error | null;
10
- }
11
-
12
- export class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {
13
- constructor(props: ErrorBoundaryProps) {
14
- super(props);
15
- this.state = { hasError: false, error: null };
16
- }
17
-
18
- static getDerivedStateFromError(error: Error) {
19
- return { hasError: true, error };
20
- }
21
-
22
- render() {
23
- if (this.state.hasError) {
24
- return (
25
- <div className="flex items-center justify-center min-h-screen bg-gray-900">
26
- <div className="text-center max-w-md">
27
- <div className="text-6xl mb-4">😱</div>
28
- <h1 className="text-3xl font-bold mb-4">Something went wrong</h1>
29
- <p className="text-gray-400 mb-4">
30
- An unexpected error occurred. Please refresh the page or contact support.
31
- </p>
32
- <p className="text-gray-600 text-sm font-mono break-all">
33
- {this.state.error?.message}
34
- </p>
35
- <button
36
- onClick={() => window.location.reload()}
37
- className="mt-6 bg-blue-600 hover:bg-blue-700 px-6 py-2 rounded font-semibold transition"
38
- >
39
- Refresh Page
40
- </button>
41
- </div>
42
- </div>
43
- );
44
- }
45
-
46
- return this.props.children;
47
- }
48
- }
@@ -1,43 +0,0 @@
1
- import React from "react";
2
-
3
- interface PatchDiffViewerProps {
4
- diff: string;
5
- }
6
-
7
- export function PatchDiffViewer({ diff }: PatchDiffViewerProps) {
8
- const copyToPaste = () => {
9
- navigator.clipboard.writeText(diff);
10
- };
11
-
12
- const downloadPatch = () => {
13
- const element = document.createElement("a");
14
- element.setAttribute("href", "data:text/plain;charset=utf-8," + encodeURIComponent(diff));
15
- element.setAttribute("download", "patch.diff");
16
- element.style.display = "none";
17
- document.body.appendChild(element);
18
- element.click();
19
- document.body.removeChild(element);
20
- };
21
-
22
- return (
23
- <div className="space-y-3">
24
- <div className="flex gap-2">
25
- <button
26
- onClick={copyToPaste}
27
- className="px-3 py-2 bg-blue-600 hover:bg-blue-700 rounded text-sm font-semibold transition"
28
- >
29
- Copy to Clipboard
30
- </button>
31
- <button
32
- onClick={downloadPatch}
33
- className="px-3 py-2 bg-gray-700 hover:bg-gray-600 rounded text-sm font-semibold transition"
34
- >
35
- Download .patch
36
- </button>
37
- </div>
38
- <pre className="bg-gray-900 border border-gray-700 rounded p-4 overflow-auto max-h-96 text-xs text-gray-300 font-mono whitespace-pre-wrap break-words">
39
- {diff}
40
- </pre>
41
- </div>
42
- );
43
- }
@@ -1,64 +0,0 @@
1
- import React from "react";
2
-
3
- interface RiskGaugeProps {
4
- score: number;
5
- }
6
-
7
- export function RiskGauge({ score }: RiskGaugeProps) {
8
- const percentage = (score / 10) * 100;
9
- let colorClass = "bg-green-500";
10
- let labelColor = "text-green-400";
11
-
12
- if (score >= 8) {
13
- colorClass = "bg-red-500";
14
- labelColor = "text-red-400";
15
- } else if (score >= 6) {
16
- colorClass = "bg-orange-500";
17
- labelColor = "text-orange-400";
18
- } else if (score >= 4) {
19
- colorClass = "bg-yellow-500";
20
- labelColor = "text-yellow-400";
21
- }
22
-
23
- return (
24
- <div className="flex items-center gap-6">
25
- <div className="flex-shrink-0">
26
- <div className="relative w-32 h-32">
27
- <svg className="w-32 h-32 transform -rotate-90" viewBox="0 0 100 100">
28
- <circle
29
- cx="50"
30
- cy="50"
31
- r="45"
32
- fill="none"
33
- stroke="currentColor"
34
- strokeWidth="8"
35
- className="text-gray-700"
36
- />
37
- <circle
38
- cx="50"
39
- cy="50"
40
- r="45"
41
- fill="none"
42
- stroke="currentColor"
43
- strokeWidth="8"
44
- strokeDasharray={`${(percentage / 100) * 282.7} 282.7`}
45
- className={`text-blue-500 transition-all duration-500`}
46
- />
47
- </svg>
48
- <div className="absolute inset-0 flex items-center justify-center">
49
- <div className="text-center">
50
- <div className={`text-3xl font-bold ${labelColor}`}>{score.toFixed(1)}</div>
51
- <div className="text-xs text-gray-400">/10</div>
52
- </div>
53
- </div>
54
- </div>
55
- </div>
56
- <div>
57
- <h3 className="text-sm font-semibold text-gray-300 mb-2">Risk Level</h3>
58
- <p className={`text-lg font-bold ${labelColor}`}>
59
- {score >= 8 ? "CRITICAL" : score >= 6 ? "HIGH" : score >= 4 ? "MEDIUM" : "LOW"}
60
- </p>
61
- </div>
62
- </div>
63
- );
64
- }
@@ -1,104 +0,0 @@
1
- import React, { useEffect, useState } from "react";
2
- import { createRoot } from "react-dom/client";
3
- import { useAuth } from "./hooks/useAuth.ts";
4
- import { LoginPage } from "./pages/LoginPage.tsx";
5
- import { ScansListPage } from "./pages/ScansListPage.tsx";
6
- import { ScanDetailPage } from "./pages/ScanDetailPage.tsx";
7
- import { ErrorBoundary } from "./components/ErrorBoundary.tsx";
8
-
9
- type Page = "login" | "list" | "detail";
10
-
11
- function Dashboard() {
12
- const { token, loading, login, logout, setAndStoreToken } = useAuth();
13
- const [page, setPage] = useState<Page>("login");
14
- const [selectedScanId, setSelectedScanId] = useState<string | null>(null);
15
-
16
- // Handle OAuth callback
17
- useEffect(() => {
18
- const params = new URLSearchParams(window.location.search);
19
- const code = params.get("code");
20
-
21
- if (code && !token) {
22
- const apiBase = window.location.origin;
23
- fetch(`${apiBase}/api/auth/github?code=${code}`)
24
- .then((res) => res.json())
25
- .then((data) => {
26
- if (data.token) {
27
- setAndStoreToken(data.token);
28
- setPage("list");
29
- window.history.replaceState({}, document.title, window.location.pathname);
30
- } else {
31
- alert("Authentication failed. Try again.");
32
- }
33
- })
34
- .catch((e) => {
35
- console.error("OAuth error:", e);
36
- alert("Authentication failed. Try again.");
37
- });
38
- }
39
- }, [token, setAndStoreToken]);
40
-
41
- // Auto-login if token exists
42
- useEffect(() => {
43
- if (token && !loading) {
44
- setPage("list");
45
- }
46
- }, [token, loading]);
47
-
48
- if (loading) {
49
- return (
50
- <div className="flex items-center justify-center min-h-screen bg-gray-900">
51
- <p className="text-gray-400">Loading...</p>
52
- </div>
53
- );
54
- }
55
-
56
- return (
57
- <div className="min-h-screen bg-gray-900 text-white">
58
- {token && (
59
- <nav className="border-b border-gray-800 bg-gray-800">
60
- <div className="max-w-7xl mx-auto px-4 py-4 flex justify-between items-center">
61
- <h1 className="text-xl font-bold cursor-pointer" onClick={() => setPage("list")}>
62
- 🔍 CodeProbe
63
- </h1>
64
- <button
65
- onClick={() => {
66
- logout();
67
- setPage("login");
68
- }}
69
- className="px-4 py-2 bg-red-600 hover:bg-red-700 rounded text-sm font-semibold transition"
70
- >
71
- Logout
72
- </button>
73
- </div>
74
- </nav>
75
- )}
76
-
77
- <main className="max-w-7xl mx-auto px-4 py-8">
78
- <ErrorBoundary>
79
- {page === "login" && !token && <LoginPage onLogin={login} />}
80
- {page === "list" && token && (
81
- <ScansListPage token={token} onSelectScan={(id) => {
82
- setSelectedScanId(id);
83
- setPage("detail");
84
- }} />
85
- )}
86
- {page === "detail" && token && selectedScanId && (
87
- <ScanDetailPage
88
- scanId={selectedScanId}
89
- token={token}
90
- onBack={() => setPage("list")}
91
- />
92
- )}
93
- </ErrorBoundary>
94
- </main>
95
-
96
- <footer className="border-t border-gray-800 bg-gray-800 mt-8 py-4 text-center text-gray-400 text-sm">
97
- <p>Powered by <span className="font-semibold text-white">Daytona</span> | <span className="font-semibold text-white">Bright Data</span> | <span className="font-semibold text-white">Nosana</span></p>
98
- </footer>
99
- </div>
100
- );
101
- }
102
-
103
- const root = createRoot(document.getElementById("root")!);
104
- root.render(<Dashboard />);
@@ -1,32 +0,0 @@
1
- import { useState, useEffect } from "react";
2
-
3
- export function useAuth() {
4
- const [token, setToken] = useState<string | null>(null);
5
- const [loading, setLoading] = useState(true);
6
-
7
- useEffect(() => {
8
- const stored = localStorage.getItem("codeprobe_token");
9
- setToken(stored);
10
- setLoading(false);
11
- }, []);
12
-
13
- function login() {
14
- const clientId = "Ov23liN8SBt9rcom1Msm";
15
- const redirectUri = "http://localhost:3000/api/auth/github";
16
- const scope = "user:email";
17
- const url = `https://github.com/login/oauth/authorize?client_id=${clientId}&redirect_uri=${redirectUri}&scope=${scope}`;
18
- window.location.href = url;
19
- }
20
-
21
- function logout() {
22
- localStorage.removeItem("codeprobe_token");
23
- setToken(null);
24
- }
25
-
26
- function setAndStoreToken(t: string) {
27
- localStorage.setItem("codeprobe_token", t);
28
- setToken(t);
29
- }
30
-
31
- return { token, loading, login, logout, setAndStoreToken };
32
- }
@@ -1,65 +0,0 @@
1
- import { useState, useEffect } from "react";
2
-
3
- export function useScan(scanId: string | null, token: string | null) {
4
- const [scan, setScan] = useState(null);
5
- const [loading, setLoading] = useState(false);
6
- const [error, setError] = useState<string | null>(null);
7
-
8
- useEffect(() => {
9
- if (!scanId || !token) return;
10
-
11
- async function fetchScan() {
12
- setLoading(true);
13
- setError(null);
14
- try {
15
- const apiBase = window.location.origin;
16
- const res = await fetch(`${apiBase}/api/scans/${scanId}`, {
17
- headers: { Authorization: `Bearer ${token}` },
18
- });
19
- if (!res.ok) throw new Error("Failed to fetch scan");
20
- const data = await res.json();
21
- setScan(data);
22
- } catch (e) {
23
- setError(e instanceof Error ? e.message : "Unknown error");
24
- } finally {
25
- setLoading(false);
26
- }
27
- }
28
-
29
- fetchScan();
30
- }, [scanId, token]);
31
-
32
- return { scan, loading, error };
33
- }
34
-
35
- export function useScans(token: string | null) {
36
- const [scans, setScans] = useState([]);
37
- const [loading, setLoading] = useState(false);
38
- const [error, setError] = useState<string | null>(null);
39
-
40
- useEffect(() => {
41
- if (!token) return;
42
-
43
- async function fetchScans() {
44
- setLoading(true);
45
- setError(null);
46
- try {
47
- const apiBase = window.location.origin;
48
- const res = await fetch(`${apiBase}/api/scans`, {
49
- headers: { Authorization: `Bearer ${token}` },
50
- });
51
- if (!res.ok) throw new Error("Failed to fetch scans");
52
- const data = await res.json();
53
- setScans(data);
54
- } catch (e) {
55
- setError(e instanceof Error ? e.message : "Unknown error");
56
- } finally {
57
- setLoading(false);
58
- }
59
- }
60
-
61
- fetchScans();
62
- }, [token]);
63
-
64
- return { scans, loading, error };
65
- }
@@ -1,15 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>CodeProbe Dashboard</title>
7
- <script src="https://cdn.tailwindcss.com"></script>
8
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/prism.min.css" />
9
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism-tomorrow.min.css" />
10
- </head>
11
- <body class="bg-gray-900 text-white">
12
- <div id="root"></div>
13
- <script src="./frontend.tsx" type="module"></script>
14
- </body>
15
- </html>
@@ -1,28 +0,0 @@
1
- import React from "react";
2
-
3
- interface LoginPageProps {
4
- onLogin: () => void;
5
- }
6
-
7
- export function LoginPage({ onLogin }: LoginPageProps) {
8
- return (
9
- <div className="flex items-center justify-center min-h-screen bg-gradient-to-br from-gray-900 to-gray-800">
10
- <div className="text-center max-w-md">
11
- <div className="text-5xl mb-6">🔒</div>
12
- <h1 className="text-4xl font-bold mb-4">CodeProbe Dashboard</h1>
13
- <p className="text-gray-300 mb-8">
14
- Log in with GitHub to view your scan results and security insights.
15
- </p>
16
- <button
17
- onClick={onLogin}
18
- className="w-full bg-white text-black font-semibold py-3 px-6 rounded-lg hover:bg-gray-100 transition"
19
- >
20
- Login with GitHub
21
- </button>
22
- <p className="text-gray-500 text-sm mt-6">
23
- We'll only access your public profile data.
24
- </p>
25
- </div>
26
- </div>
27
- );
28
- }