A vulnerability management system for tracking and triaging security vulnerabilities across your Ubuntu Linux infrastructure using agent-based scanning, OVAL definitions, and Ubuntu VEX data.
VulTrack was developed entirely with AI. There might be dragons. 🐉
The VulTrack Agent can be found in this repository.
- Dashboard: Overview of your vulnerability landscape with key metrics and charts
- Server Management: View all monitored servers and their vulnerability status
- Findings Browser: Search and filter vulnerability findings across all servers
- Triage Queue: Efficiently assess and categorize high-severity vulnerabilities
- Statistics: Trend analysis and detailed reports
- Agent Management: Manage agents and enrollment keys
- OVAL Integration: Automatic vulnerability detection using OVAL definitions (Ubuntu and others)
- NVD Enrichment: CVE details enriched with CVSS scores, CWE IDs, and descriptions
- ExploitDB Integration: Identify vulnerabilities with known exploits
- Ubuntu VEX Integration: Automatic enrichment of findings with Canonical's VEX (Vulnerability Exploitability eXchange) data — surfaces
Not Affected,Will Not Fix, andUnder Investigationassessments from Ubuntu Security directly in your findings and triage queue - Scheduled Reports: Automated PDF reports delivered by email (weekly / monthly)
- Server Groups: Organize servers into groups for targeted reporting and filtering
- Jira Integration: Automatically create Jira tickets for relevant findings
- OIDC Authentication: Optional single sign-on via any OpenID Connect identity provider
┌────────────────┐
│ PostgreSQL │
│ Port: 5432 │
└───────▲────────┘
│
┌─────────────────┐ │
┌───────▶│ Frontend │ │
│ │ (React) │ │
│ │ Port: 8080 │ │
┌───────────┐ ┌─────────┴─────┐ └─────────────────┘ │
│ │ │ │ │
│ Browser │─────▶│ Reverse │ ┌─────────────────┐ │
│ │ │ Proxy │─▶│ Backend │──────┘
│ │ │ │ │ (Go/Fiber) │
└───────────┘ │ Port: 443 │ │ Port: 8080 │
│ │ └─────────────────┘
┌───────────┐ │ /* → FE │ ▲
│ │ │ /api/* → BE │ │
│ Agents │─────▶│ │───────────┘
│ │ │ │
└───────────┘ └───────────────┘
Components:
- Frontend: React SPA served by Nginx (static files only)
- Backend: Go/Fiber REST API
- PostgreSQL: Database for all application data
- Reverse Proxy: Routes requests to Frontend or Backend (not included, bring your own)
- Agents: Lightweight agents on monitored servers that report package information
If you don't enable OIDC (see below) VulTrack can be used without any authentication.
- Docker and Docker Compose
- A reverse proxy (e.g., Caddy, Traefik, Nginx)
- PostgreSQL database
# Build backend image
docker build -t vultrack-backend ./backend
# Build frontend image
docker build -t vultrack-frontend ./frontendBelow is an example using Caddy as a reverse proxy. Adjust according to your infrastructure.
docker-compose.yml:
services:
caddy:
image: caddy:2-alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
depends_on:
- frontend
- backend
restart: unless-stopped
frontend:
image: vultrack-frontend:latest
restart: unless-stopped
backend:
image: vultrack-backend:latest
environment:
- POSTGRES_HOST=postgres
- POSTGRES_PORT=5432
- POSTGRES_USER=vultrack
- POSTGRES_PASSWORD=changeme
- POSTGRES_DB=vultrack
- LOG_LEVEL=info
depends_on:
- postgres
restart: unless-stopped
postgres:
image: postgres:16-alpine
environment:
- POSTGRES_USER=vultrack
- POSTGRES_PASSWORD=changeme
- POSTGRES_DB=vultrack
volumes:
- postgres_data:/var/lib/postgresql/data
restart: unless-stopped
volumes:
caddy_data:
postgres_data:Caddyfile:
vultrack.example.com {
# Frontend (static files)
handle {
reverse_proxy frontend:8080
}
# Backend API
handle /api/* {
reverse_proxy backend:8080
}
}
- Start the services:
docker compose up -d - Access the web interface at
https://vultrack.example.com - Create an enrollment key in Admin → Enrollment Keys
- Deploy agents on your servers using the enrollment key
All configuration is done via environment variables.
| Variable | Description | Default |
|---|---|---|
POSTGRES_HOST |
PostgreSQL hostname | localhost |
POSTGRES_PORT |
PostgreSQL port | 5432 |
POSTGRES_USER |
PostgreSQL username | vultrack |
POSTGRES_PASSWORD |
PostgreSQL password | vultrack |
POSTGRES_DB |
PostgreSQL database name | vultrack |
BACKEND_PORT |
Port the backend listens on | 8080 |
LOG_LEVEL |
Log level (debug, info, warn, error) | info |
TRIAGE_CVSS_THRESHOLD |
Minimum CVSS score for triage queue | 7.0 |
CORS_ORIGINS |
Comma-separated origins for CORS (required when using OIDC) | (empty) |
VulTrack automatically downloads and syncs Canonical's VEX data (vex-all.tar.xz) to enrich findings with Ubuntu's own exploitability assessments. The sync runs on a configurable schedule.
| Variable | Description | Default |
|---|---|---|
VEX_SYNC_INTERVAL_HOURS |
How often the VEX data is refreshed (hours) | 24 |
| Variable | Description | Default |
|---|---|---|
SCAN_WORKERS |
Number of concurrent scan workers | 5 |
SCAN_TIMEOUT |
Timeout per scan in seconds | 600 |
SCAN_MAX_RETRIES |
Maximum retry attempts for failed scans | 3 |
SCAN_QUEUE_SIZE |
Maximum scan queue depth | 500 |
When SMTP_ENABLED=true, VulTrack sends email reports via SMTP.
| Variable | Description | Default |
|---|---|---|
SMTP_ENABLED |
Enable email sending | false |
SMTP_HOST |
SMTP server hostname | (empty) |
SMTP_PORT |
SMTP server port | 587 |
SMTP_USER |
SMTP username (leave empty for unauthenticated relay) | (empty) |
SMTP_PASSWORD |
SMTP password | (empty) |
SMTP_FROM |
Sender address (e.g. VulTrack <vultrack@example.com>) |
(empty) |
SMTP_TLS |
TLS mode: starttls (port 587), tls (port 465), none (port 25) |
starttls |
SMTP_HELO_HOST |
EHLO hostname sent to the relay. Many relays reject localhost; set to your server's FQDN if needed |
(OS hostname) |
When JIRA_ENABLED=true, a Jira ticket is automatically created whenever a finding is assessed as Relevant.
| Variable | Description | Default |
|---|---|---|
JIRA_ENABLED |
Enable Jira integration | false |
JIRA_BASE_URL |
Jira instance URL (e.g. https://your-org.atlassian.net) |
(empty) |
JIRA_USER_EMAIL |
Jira user email for API authentication | (empty) |
JIRA_API_TOKEN |
Jira API token | (empty) |
JIRA_PROJECT_KEY |
Jira project key (e.g. SEC) |
(empty) |
JIRA_ISSUE_TYPE |
Issue type for created tickets | Task |
| Variable | Description | Default |
|---|---|---|
VITE_API_URL |
Backend API base URL used during the frontend build | http://localhost:8080/api/v1 |
When OIDC_ENABLED=true, the web UI requires users to sign in via an OpenID Connect identity provider (e.g. Keycloak, Auth0, Okta). When disabled, no login is required.
| Variable | Description | Default |
|---|---|---|
OIDC_ENABLED |
Enable OIDC login for the web UI | false |
OIDC_ISSUER |
IdP issuer URL (e.g. https://idp.example.com/realms/vultrack) |
(empty) |
OIDC_CLIENT_ID |
OAuth2 client ID | (empty) |
OIDC_CLIENT_SECRET |
OAuth2 client secret | (empty) |
OIDC_REDIRECT_URL |
Backend callback URL (e.g. https://vultrack.example.com/api/v1/auth/callback) |
(empty) |
OIDC_FRONTEND_URL |
Frontend URL for redirect after login (e.g. https://vultrack.example.com) |
/ |
OIDC_SCOPES |
OAuth2 scopes (space or comma separated) | openid profile email |
Setup:
- Create an OAuth2/OIDC client in your IdP with redirect URI =
OIDC_REDIRECT_URL. - Set
CORS_ORIGINSto your frontend origin(s) so session cookies work (e.g.http://localhost:3000orhttps://vultrack.example.com). - The first user to sign in when no admin exists becomes an admin. Further admins can be assigned in Admin → Users.
The agent API (/api/v1/agent/*) is unchanged and uses enrollment keys and agent tokens, not OIDC.
cd backend
go mod download
go run ./cmd/vultrackcd frontend
npm install
npm run devFor development, you can start just the database:
docker compose up -d postgresGET /api/v1/auth/login- Redirect to OIDC identity providerGET /api/v1/auth/callback- OIDC callback (handles token exchange and session creation)POST /api/v1/auth/logout- Invalidate current sessionGET /api/v1/auth/me- Current user info (returnsauthEnabled: falsewhen OIDC is disabled)
GET /api/v1/dashboard- Dashboard statistics
GET /api/v1/servers- List all serversGET /api/v1/servers/:id- Get server detailsGET /api/v1/servers/:id/findings- Get server findingsGET /api/v1/servers/:id/packages- Get server packagesGET /api/v1/servers/:id/groups- Get groups for a serverPUT /api/v1/servers/:id/groups- Set groups for a serverPOST /api/v1/servers/:id/scan- Trigger a vulnerability scanDELETE /api/v1/admin/servers/:id- Delete server
GET /api/v1/findings- List findings with filters (supportsvexStatusquery param:not_affected,will_not_fix,under_investigation)GET /api/v1/findings/triage- Get triage queue (supportshideVexNotAffected=falseto include not-affected findings; default istrue)GET /api/v1/findings/:id- Get finding details
GET /api/v1/cves/:id- Get CVE detailsGET /api/v1/cves/:id/servers- Get servers affected by CVE
GET /api/v1/assessments- List all assessmentsPOST /api/v1/assessments- Create assessmentPUT /api/v1/assessments/:cveId- Update assessmentDELETE /api/v1/assessments/:cveId- Delete assessment
GET /api/v1/reason-templates- List reason templatesPOST /api/v1/reason-templates- Create reason templatePUT /api/v1/reason-templates/:id- Update reason templateDELETE /api/v1/reason-templates/:id- Delete reason template
GET /api/v1/stats/severity- Severity breakdownGET /api/v1/stats/trend- Finding trends over timeGET /api/v1/stats/top-servers- Most affected serversGET /api/v1/stats/top-cves- Most widespread CVEsGET /api/v1/stats/assessments-by-severity- Assessments grouped by severity
POST /api/v1/reports/generate- Generate a PDF report on demandGET /api/v1/report-schedules- List report schedulesPOST /api/v1/report-schedules- Create report scheduleGET /api/v1/report-schedules/:id- Get report schedulePUT /api/v1/report-schedules/:id- Update report scheduleDELETE /api/v1/report-schedules/:id- Delete report schedulePOST /api/v1/report-schedules/:id/toggle- Enable or disable a schedulePOST /api/v1/report-schedules/:id/run-now- Run a schedule immediately
GET /api/v1/scans- List scan jobsGET /api/v1/scans/stats- Scan queue statisticsPOST /api/v1/scans/:id/cancel- Cancel a queued scanPOST /api/v1/scans/:id/retry- Retry a failed scan
POST /api/v1/agent/enroll- Register a new agent (requiresX-Enrollment-Keyheader)POST /api/v1/agent/report- Submit agent report (requiresX-Agent-Tokenheader)
GET /api/v1/admin/settings- Get application settingsPUT /api/v1/admin/settings- Update application settings
GET /api/v1/admin/users- List users (requires OIDC)
GET /api/v1/admin/server-groups- List server groupsPOST /api/v1/admin/server-groups- Create server groupGET /api/v1/admin/server-groups/:id- Get server groupPUT /api/v1/admin/server-groups/:id- Update server groupDELETE /api/v1/admin/server-groups/:id- Delete server groupGET /api/v1/admin/server-groups/:id/members- List group membersPOST /api/v1/admin/server-groups/:id/members- Add member to groupDELETE /api/v1/admin/server-groups/:id/members/:serverId- Remove member from group
GET /api/v1/admin/enrollment-keys- List enrollment keysPOST /api/v1/admin/enrollment-keys- Create enrollment keyPUT /api/v1/admin/enrollment-keys/:id- Update enrollment keyDELETE /api/v1/admin/enrollment-keys/:id- Delete enrollment key
GET /api/v1/admin/agents- List registered agentsPUT /api/v1/admin/agents/:id/approve- Approve pending agentPUT /api/v1/admin/agents/:id/revoke- Revoke agent accessDELETE /api/v1/admin/agents/:id- Delete agent
GET /api/v1/admin/oval/distributions- List available distributionsGET /api/v1/admin/oval/sources- List enabled OVAL sourcesPOST /api/v1/admin/oval/sources- Enable OVAL sourcePUT /api/v1/admin/oval/sources/:id/disable- Disable an OVAL sourceDELETE /api/v1/admin/oval/sources/:id- Remove an OVAL sourcePOST /api/v1/admin/oval/sources/:id/sync- Trigger sync for a specific sourcePOST /api/v1/admin/oval/sync-all- Trigger sync for all enabled sources
POST /api/v1/admin/nvd/sync- Trigger NVD CVE syncGET /api/v1/admin/nvd/status- NVD sync statusPOST /api/v1/admin/exploitdb/sync- Trigger ExploitDB syncGET /api/v1/admin/exploitdb/status- ExploitDB sync statusGET /api/v1/admin/sync/status- Combined sync statusPOST /api/v1/admin/vex/sync- Trigger Ubuntu VEX syncGET /api/v1/admin/vex/status- VEX sync status and statement count
POST /api/v1/admin/system/reset- Reset all application data
Agents are lightweight scripts or binaries that run on monitored servers. They:
- Enroll with VulTrack using an enrollment key
- Periodically report system information and installed packages
- VulTrack matches packages against OVAL definitions to detect vulnerabilities
See docs/AGENT_API.md for the complete agent API specification.
For a deeper OIDC setup guide including IdP-specific instructions, see docs/OIDC_SETUP.md.
- Support for more Linux distributions (Debian, RHEL, ...)
- REST API for report export (CSV)
- Multi-tenancy / team workspaces
MIT License