Files
cve-dashboard/README.md
jramos f2e6069c08 docs: overhaul documentation for fork readiness
- Rewrite README from scratch: accurate stack versions, correct setup
  sequence, verified feature list, full API reference, architecture
  overview, and security model — all sourced directly from the codebase
- Remove internal/stale docs: COLOR_SCHEME_MODERNIZATION.md, plan.md,
  frontend/README.md (CRA boilerplate)
- Clean up DESIGN_SYSTEM.md: remove emoji headers and version footer
- Fix WEEKLY_REPORT_FEATURE.md: replace hardcoded absolute paths with
  relative paths
- Clean up test_cases_auth.md: remove stale branch and date references

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 14:30:17 -07:00

516 lines
18 KiB
Markdown

# CVE Dashboard
A self-hosted vulnerability management dashboard for tracking CVE remediation status, maintaining vendor documentation, and managing risk acceptance workflows.
---
## Table of Contents
- [Overview](#overview)
- [Tech Stack](#tech-stack)
- [Prerequisites](#prerequisites)
- [Installation](#installation)
- [Configuration](#configuration)
- [Running the Application](#running-the-application)
- [Features](#features)
- [API Reference](#api-reference)
- [Architecture](#architecture)
- [Database Schema](#database-schema)
- [Security Model](#security-model)
- [Migrations](#migrations)
---
## Overview
The CVE Dashboard answers a common problem in vulnerability management: before requesting false positive designations, you need to know whether a CVE has already been addressed, and whether the supporting vendor documentation exists. This application provides:
- A searchable, filterable CVE list with per-vendor tracking
- Document storage attached to each CVE/vendor pair (advisories, emails, screenshots, patches)
- NVD API integration to auto-populate CVE metadata
- Archer risk acceptance ticket tracking (EXC numbers)
- Weekly vulnerability report upload and processing
- A knowledge base for internal documentation and policies
- Role-based access control with a full audit trail
---
## Tech Stack
| Layer | Technology |
|---|---|
| Backend | Node.js, Express 5 |
| Database | SQLite3 |
| File uploads | Multer 2 |
| Auth | bcryptjs, cookie-based sessions |
| Frontend | React 19, lucide-react, react-markdown |
| Report processing | Python 3 (pandas, openpyxl) |
---
## Prerequisites
- Node.js 18 or later
- npm
- Python 3 with pip (required only for weekly report processing)
---
## Installation
### 1. Clone the repository
```bash
git clone <repo-url>
cd cve-dashboard
```
### 2. Install backend dependencies
```bash
cd backend
npm install
```
The root `package.json` lists the backend dependencies. Install them from the `backend/` directory where `server.js` lives.
### 3. Install frontend dependencies
```bash
cd frontend
npm install
```
### 4. Install Python dependencies (for weekly report upload feature)
```bash
cd backend/scripts
pip install -r requirements.txt
```
Required packages: `pandas>=2.0.0`, `openpyxl>=3.0.0`
### 5. Initialize the database
Run this once from the `backend/` directory to create the SQLite database, all tables, indexes, the uploads directory, and a default admin user:
```bash
cd backend
node setup.js
```
This creates `backend/cve_database.db` and a default admin account:
- Username: `admin`
- Password: `admin123`
**Change the admin password immediately after first login.**
### 6. Run database migrations
After the initial setup, apply the feature migrations in order:
```bash
cd backend
node migrations/add_weekly_reports_table.js
node migrations/add_knowledge_base_table.js
node migrations/add_archer_tickets_table.js
```
---
## Configuration
The application is configured via `.env` files. These files are gitignored and must be created manually per environment.
### Backend: `backend/.env`
```
PORT=3001
API_HOST=localhost
CORS_ORIGINS=http://YOUR_IP:3000
SESSION_SECRET=change-this-to-a-random-secret
NODE_ENV=development
# Optional: NVD API key for higher rate limits
# Register at https://nvd.nist.gov/developers/request-an-api-key
NVD_API_KEY=your-key-here
```
### Frontend: `frontend/.env`
```
REACT_APP_API_BASE=http://YOUR_IP:3001/api
REACT_APP_API_HOST=http://YOUR_IP:3001
```
Replace `YOUR_IP` with the machine's IP address or `localhost` for local development.
**Important:** React caches environment variables at build/start time. After changing `frontend/.env`, you must fully restart the frontend process. A page refresh alone is not sufficient.
---
## Running the Application
### Using the helper scripts (recommended)
From the project root:
```bash
./start-servers.sh # Starts backend and frontend in the background
./stop-servers.sh # Stops all servers
```
The start script saves PIDs to `backend.pid` and `frontend.pid`. Logs are written to `backend/backend.log` and `frontend/frontend.log`.
### Running manually
```bash
# Terminal 1 - backend
cd backend
node server.js
# Terminal 2 - frontend
cd frontend
npm start
```
### Default ports
- Frontend: http://localhost:3000
- Backend API: http://localhost:3001
---
## Features
### Authentication and User Roles
All routes require authentication. Three roles are supported:
| Role | Permissions |
|---|---|
| `viewer` | Read-only access to CVEs, documents, weekly reports, knowledge base, Archer tickets |
| `editor` | All viewer permissions plus: create/update CVEs, upload documents, upload weekly reports, manage knowledge base articles, manage Archer tickets |
| `admin` | All editor permissions plus: delete documents, delete weekly reports, manage users, view audit logs |
Sessions expire after 24 hours. Session tokens are stored in `httpOnly` cookies.
### CVE Management
- Add CVEs with full metadata: CVE ID, vendor, severity (Critical/High/Medium/Low), description, published date, and status (Open/In Progress/Addressed/Resolved)
- The same CVE ID can be tracked across multiple vendors independently
- Filter the CVE list by search term, vendor, severity, and status
- Edit any field on an existing CVE entry; file paths are updated automatically when CVE ID or vendor changes
- Delete a single vendor entry or all vendor entries for a CVE ID
- Paginated list view to prevent performance issues with large datasets
- Quick Check: look up a CVE ID and see all vendors tracking it with their current status
### NVD Integration
- Auto-fill CVE description, severity, and published date from the NIST NVD API 2.0 when adding a new CVE
- Bulk NVD Sync: fetch updated metadata for all CVEs in the database in one operation (editor/admin)
- CVSS severity mapping cascades: v3.1 preferred, then v3.0, then v2.0
- NVD API key support via `NVD_API_KEY` environment variable for higher rate limits
### Document Management
Documents are attached to a CVE/vendor pair and stored on disk under `backend/uploads/<CVE-ID>/<vendor>/`.
Supported document types: `advisory`, `email`, `screenshot`, `patch`, `other`
Allowed file extensions: PDF, images (PNG, JPG, GIF, BMP, TIFF), Office documents (DOC, DOCX, XLS, XLSX, PPT, PPTX), text files (TXT, MD, CSV, LOG), email files (MSG, EML), and others (RTF, HTML, XML, JSON, YAML, ODF variants).
File size limit: 10 MB per upload.
### Weekly Reports
Editors and admins can upload weekly vulnerability reports as `.xlsx` files. The report is processed by a Python script (`backend/scripts/split_cve_report.py`) that:
1. Reads the `Vulnerabilities` sheet
2. Splits rows where multiple CVE IDs are comma-separated in the `CVE ID` column into individual rows
3. Saves the processed file alongside the original
Both the original and processed files can be downloaded from the weekly reports list. Only the most recently uploaded report is marked as current. Admins can delete old report records and their associated files.
### Archer Risk Acceptance Tickets
Track Archer exception tickets (EXC numbers) linked to specific CVE/vendor pairs.
- EXC number format: `EXC-NNNNN`
- Statuses: `Draft`, `Open`, `Under Review`, `Accepted`
- Optional Archer URL field for deep-linking to the Archer record
- Filter tickets by CVE ID, vendor, or status
- EXC numbers are unique across the system
### Knowledge Base
A document library for internal reference material such as policies, runbooks, and vendor advisories.
- Upload documents with a title, optional description, and category
- View documents inline in the browser (PDFs render in an iframe; markdown files are rendered as HTML)
- Download any document
- Filter and browse by category
- Editors and admins can upload and delete; all authenticated users can view
Allowed file types: PDF, Markdown, TXT, Office documents, HTML, JSON, YAML, and images.
### User Management (Admin)
Admins can create, update, and delete user accounts from the UI. Supported operations:
- Create users with a role assignment
- Change username, email, password, role, or active status
- Deactivating a user immediately invalidates all their active sessions
- Admins cannot demote themselves or deactivate their own account
### Audit Log (Admin)
Every state-changing action is recorded with the user identity, IP address, action type, target entity, and a before/after details payload. Admins can view the audit log with filtering by user, action type, entity type, and date range. Results are paginated.
---
## API Reference
All endpoints are prefixed with `/api`. All endpoints except `/api/auth/login` and `/api/auth/logout` require a valid session cookie.
### Auth
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | `/api/auth/login` | Public | Log in, receive session cookie |
| POST | `/api/auth/logout` | Public | Invalidate session |
| GET | `/api/auth/me` | Session | Get current user info |
| POST | `/api/auth/cleanup-sessions` | Session | Delete expired sessions |
### CVEs
| Method | Path | Role | Description |
|---|---|---|---|
| GET | `/api/cves` | viewer+ | List CVEs with optional filters: `search`, `vendor`, `severity`, `status` |
| POST | `/api/cves` | editor+ | Create a new CVE entry |
| PUT | `/api/cves/:id` | editor+ | Update a CVE entry by row ID |
| PATCH | `/api/cves/:cveId/status` | editor+ | Update status for all vendor rows matching a CVE ID |
| DELETE | `/api/cves/:id` | editor+ | Delete a single CVE vendor entry |
| DELETE | `/api/cves/by-cve-id/:cveId` | editor+ | Delete all vendor entries for a CVE ID |
| GET | `/api/cves/check/:cveId` | viewer+ | Quick check: does this CVE exist and what is its status? |
| GET | `/api/cves/distinct-ids` | viewer+ | List all distinct CVE IDs (used by NVD sync) |
| GET | `/api/cves/:cveId/vendors` | viewer+ | List all vendor entries for a specific CVE ID |
### Documents
| Method | Path | Role | Description |
|---|---|---|---|
| GET | `/api/cves/:cveId/documents` | viewer+ | List documents for a CVE, optionally filtered by `?vendor=` |
| POST | `/api/cves/:cveId/documents` | editor+ | Upload a document for a CVE/vendor pair |
| DELETE | `/api/documents/:id` | admin | Delete a document and its file from disk |
### NVD
| Method | Path | Role | Description |
|---|---|---|---|
| GET | `/api/nvd/lookup/:cveId` | viewer+ | Look up a single CVE in the NVD API |
| POST | `/api/cves/nvd-sync` | editor+ | Bulk update CVE metadata from NVD |
### Weekly Reports
| Method | Path | Role | Description |
|---|---|---|---|
| POST | `/api/weekly-reports/upload` | editor+ | Upload and process a `.xlsx` vulnerability report |
| GET | `/api/weekly-reports` | viewer+ | List all uploaded reports |
| GET | `/api/weekly-reports/:id/download/:type` | viewer+ | Download `original` or `processed` file |
| DELETE | `/api/weekly-reports/:id` | admin | Delete a report record and its files |
### Knowledge Base
| Method | Path | Role | Description |
|---|---|---|---|
| POST | `/api/knowledge-base/upload` | editor+ | Upload a new knowledge base document |
| GET | `/api/knowledge-base` | viewer+ | List all articles |
| GET | `/api/knowledge-base/:id` | viewer+ | Get article metadata |
| GET | `/api/knowledge-base/:id/content` | viewer+ | Get file content for inline display |
| GET | `/api/knowledge-base/:id/download` | viewer+ | Download the file |
| DELETE | `/api/knowledge-base/:id` | editor+ | Delete article and file |
### Archer Tickets
| Method | Path | Role | Description |
|---|---|---|---|
| GET | `/api/archer-tickets` | viewer+ | List tickets, optional filters: `cve_id`, `vendor`, `status` |
| POST | `/api/archer-tickets` | editor+ | Create a new Archer ticket |
| PUT | `/api/archer-tickets/:id` | editor+ | Update an Archer ticket |
| DELETE | `/api/archer-tickets/:id` | editor+ | Delete an Archer ticket |
### Users (Admin only)
| Method | Path | Role | Description |
|---|---|---|---|
| GET | `/api/users` | admin | List all users |
| GET | `/api/users/:id` | admin | Get a single user |
| POST | `/api/users` | admin | Create a user |
| PATCH | `/api/users/:id` | admin | Update a user |
| DELETE | `/api/users/:id` | admin | Delete a user |
### Audit Logs (Admin only)
| Method | Path | Role | Description |
|---|---|---|---|
| GET | `/api/audit-logs` | admin | Paginated audit log with filters |
| GET | `/api/audit-logs/actions` | admin | List distinct action types |
### Utility
| Method | Path | Role | Description |
|---|---|---|---|
| GET | `/api/vendors` | viewer+ | List all distinct vendor names |
| GET | `/api/stats` | viewer+ | Dashboard statistics (total CVEs, critical count, addressed count, document count) |
---
## Architecture
```
cve-dashboard/
├── start-servers.sh # Start backend + frontend in background
├── stop-servers.sh # Stop all servers
├── backend/
│ ├── server.js # Express app, CVE/document endpoints, middleware
│ ├── setup.js # One-time DB initialization and default admin creation
│ ├── cve_database.db # SQLite database (gitignored)
│ ├── uploads/ # File storage (gitignored)
│ │ ├── <CVE-ID>/
│ │ │ └── <vendor>/ # CVE documents stored here
│ │ ├── weekly_reports/ # Uploaded vulnerability reports
│ │ ├── knowledge_base/ # Knowledge base documents
│ │ └── temp/ # Temporary upload staging directory
│ ├── routes/
│ │ ├── auth.js # Login, logout, session check
│ │ ├── users.js # User CRUD (admin)
│ │ ├── auditLog.js # Audit log viewer (admin)
│ │ ├── nvdLookup.js # NVD API proxy
│ │ ├── weeklyReports.js # Weekly report upload and management
│ │ ├── knowledgeBase.js # Knowledge base document management
│ │ └── archerTickets.js # Archer EXC ticket CRUD
│ ├── middleware/
│ │ └── auth.js # requireAuth and requireRole middleware
│ ├── helpers/
│ │ ├── auditLog.js # logAudit helper
│ │ └── excelProcessor.js # Calls Python script for report processing
│ ├── migrations/
│ │ ├── add_weekly_reports_table.js
│ │ ├── add_knowledge_base_table.js
│ │ └── add_archer_tickets_table.js
│ └── scripts/
│ ├── split_cve_report.py # Python: splits multi-CVE rows in Excel reports
│ └── requirements.txt # pandas, openpyxl
└── frontend/
└── src/
├── App.js # Main application, CVE list, filters, modals
├── App.css # Global styles
├── contexts/
│ └── AuthContext.js # Auth state provider
└── components/
├── LoginForm.js # Login page
├── UserMenu.js # User dropdown in header
├── UserManagement.js # Admin user management panel
├── AuditLog.js # Admin audit log viewer
├── NvdSyncModal.js # Bulk NVD sync dialog
├── WeeklyReportModal.js # Weekly report upload dialog
├── KnowledgeBaseModal.js # Knowledge base upload/list
└── KnowledgeBaseViewer.js # Inline document viewer
```
---
## Database Schema
### Core tables
**`cves`** - One row per CVE/vendor pair. `UNIQUE(cve_id, vendor)`.
**`documents`** - Files attached to a CVE/vendor pair. Foreign key to `cves(cve_id)`.
**`required_documents`** - Vendor-specific document requirements (advisory, screenshot, etc.).
**`users`** - Accounts with roles: `admin`, `editor`, `viewer`.
**`sessions`** - Active sessions. Expire after 24 hours.
**`audit_logs`** - Append-only log of all state-changing actions.
### Feature tables (added by migrations)
**`weekly_reports`** - Metadata for uploaded vulnerability reports. Tracks original and processed file paths, row counts, uploader, and a `is_current` flag.
**`knowledge_base`** - Document library entries with title, slug, category, description, and file metadata.
**`archer_tickets`** - Archer EXC exception tickets linked to CVE/vendor pairs. `UNIQUE(exc_number)`.
### View
**`cve_document_status`** - Aggregates document counts per CVE/vendor and derives a `compliance_status` (`Complete` when an advisory is present, otherwise `Missing Required Docs`).
---
## Security Model
### File upload security
- Extension allowlist enforced by Multer; executables (`.exe`, `.js`, `.sh`, `.py`, `.bat`, etc.) are blocked
- MIME type prefix validation in addition to extension checking
- 10 MB per-file size limit
- Filenames are sanitized: path separators, `..` sequences, null bytes, and non-alphanumeric characters are removed
### Path traversal prevention
- `sanitizePathSegment()` strips `/`, `\`, `..`, and null bytes from any value used in `path.join()`
- `isPathWithinUploads()` verifies resolved paths stay within the uploads root before any file operation
### Input validation
- CVE ID must match `/^CVE-\d{4}-\d{4,}$/`
- Severity must be one of: `Critical`, `High`, `Medium`, `Low`
- Status must be one of: `Open`, `Addressed`, `In Progress`, `Resolved`
- Archer EXC numbers must match `/^EXC-\d+$/`
- All database operations use prepared statements
### Error handling
- 500 responses never leak internal error messages to the client
- Full errors are logged server-side only
- Descriptive 400/409 responses are safe because they contain only validation messages written by the application
### Security headers
Applied to all responses:
- `X-Content-Type-Options: nosniff`
- `X-Frame-Options: SAMEORIGIN`
- `X-XSS-Protection: 1; mode=block`
- `Referrer-Policy: strict-origin-when-cross-origin`
- `Permissions-Policy: camera=(), microphone=(), geolocation=()`
### Session cookies
`httpOnly: true`, `sameSite: lax`, `secure: true` in production.
---
## Migrations
Migrations are standalone Node.js scripts that alter the database directly. Run them in the order listed. They use `CREATE TABLE IF NOT EXISTS`, so they are safe to run again if needed.
```bash
cd backend
node migrations/add_weekly_reports_table.js
node migrations/add_knowledge_base_table.js
node migrations/add_archer_tickets_table.js
```
For an existing deployment upgrading from an earlier schema, also check the legacy migration scripts in `backend/`:
- `migrate_multivendor.js` - Adds multi-vendor support to an older single-vendor schema
- `migrate-audit-log.js` - Adds the audit_logs table to pre-auth deployments
- `migrate-to-1.1.js` - General 1.0 to 1.1 schema update