{"id":50607692,"url":"https://github.com/trcyberoptic/openvas-tracker","last_synced_at":"2026-06-06T00:30:53.342Z","repository":{"id":346046636,"uuid":"1187224438","full_name":"trcyberoptic/openvas-tracker","owner":"trcyberoptic","description":"Vulnerability management dashboard for OpenVAS/Greenbone — automated ticketing, scan comparison, LDAP auth, risk acceptance rules. Single Go binary with embedded React UI.","archived":false,"fork":false,"pushed_at":"2026-04-20T13:18:09.000Z","size":1057,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-04-20T13:45:05.704Z","etag":null,"topics":["active-directory","cve","cybersecurity","dashboard","devsecops","go","golang","greenbone","gvm","infosec","ldap","nist","openvas","react","security","ticket-management","vulnerability-assessment","vulnerability-management","vulnerability-scanner","vulnerability-tracking"],"latest_commit_sha":null,"homepage":"https://github.com/trcyberoptic/openvas-tracker","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/trcyberoptic.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-20T13:35:58.000Z","updated_at":"2026-04-20T13:18:01.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/trcyberoptic/openvas-tracker","commit_stats":null,"previous_names":["trcyberoptic/openvas-tracker"],"tags_count":25,"template":false,"template_full_name":null,"purl":"pkg:github/trcyberoptic/openvas-tracker","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trcyberoptic%2Fopenvas-tracker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trcyberoptic%2Fopenvas-tracker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trcyberoptic%2Fopenvas-tracker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trcyberoptic%2Fopenvas-tracker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/trcyberoptic","download_url":"https://codeload.github.com/trcyberoptic/openvas-tracker/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trcyberoptic%2Fopenvas-tracker/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33965591,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-05T02:00:06.157Z","response_time":120,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["active-directory","cve","cybersecurity","dashboard","devsecops","go","golang","greenbone","gvm","infosec","ldap","nist","openvas","react","security","ticket-management","vulnerability-assessment","vulnerability-management","vulnerability-scanner","vulnerability-tracking"],"created_at":"2026-06-06T00:30:52.870Z","updated_at":"2026-06-06T00:30:53.327Z","avatar_url":"https://github.com/trcyberoptic.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# OpenVAS-Tracker\n\nVulnerability management dashboard that imports OpenVAS and OWASP ZAP scan results and tracks remediation through automated ticketing.\n\n## Screenshots\n\n| Dashboard | Tickets | Ticket Detail |\n|-----------|---------|---------------|\n| ![Dashboard](docs/screenshots/dashboard.png) | ![Tickets](docs/screenshots/tickets.png) | ![Ticket Detail](docs/screenshots/ticket-detail.png) |\n\n## Features\n\n- **OpenVAS Import**: Webhook endpoint receives scan results automatically when scans complete, with original scan timestamps preserved from GMP reports\n- **OWASP ZAP Import**: Webhook endpoint for ZAP Traditional JSON Reports — URL-granular ticketing for web application findings\n- **Multi-Scanner Architecture**: Pluggable parser interface supports multiple scanner types with scan-type-scoped auto-resolve\n- **Automatic Ticketing**: New findings create tickets, missing findings auto-resolve, recurring findings reopen\n- **Flapping Protection**: Configurable threshold (default 3) of consecutive scan misses before auto-resolve — prevents noisy ticket churn from intermittent scan results, with visible `pending_resolution` intermediate status\n- **Scope-aware Auto-resolve**: Importing a scan only auto-resolves tickets for hosts that were in that scan's scope — other subnets are unaffected\n- **Ticket Lifecycle**: open → pending_resolution → fixed / risk_accepted / false_positive, with full activity audit trail\n- **Risk Acceptance with Expiry**: Risk-accepted tickets auto-reopen after expiry date\n- **Auto-Accept Rules**: Define rules (by CVE or title, per host or globally) to automatically accept known risks on future imports — configurable from any ticket\n- **Scan Comparison**: Side-by-side diff of two scans — new, fixed, unchanged findings\n- **Bulk Actions**: Select multiple tickets for batch status change or assignment\n- **Dashboard**: Open ticket counts by priority, scan source distribution pie chart (OpenVAS vs ZAP), 30-day trend chart, \"My Tickets\" and \"Unassigned\" quick filters\n- **CVE \u0026 CWE References**: NVD, MITRE, and Google links on tickets with CVE; CWE links for ZAP findings; title-based search for tickets without\n- **Also Affected**: See which other hosts have the same vulnerability — click any affected host to filter tickets by that host\n- **DNS Hostname Resolution**: Automatic PTR lookup with 48h cache and 3s per-lookup timeout, normalized (UPPERCASE.domain.lowercase), runs async after import so a misbehaving DNS can never stall an import\n- **LDAP / Active Directory**: Optional AD authentication with group-based access control\n- **Admin + LDAP Auth**: Built-in admin user plus optional LDAP for team access, login by username\n- **Settings UI**: Edit all configuration (.env file) from the browser, test LDAP connection\n- **Filterable \u0026 Sortable Tables**: Column sorting, multi-filter (priority, status, host, scan source), full-text search across all columns, searchable host filter with hostname autocomplete, default filter on open tickets\n- **Report Generation**: HTML, PDF, Excel, Markdown — technical, executive, compliance, comparison, and trend report types\n- **Teams \u0026 Collaboration** (API only): Create teams with member roles (owner, admin, member), invite users, assign tickets to teams\n- **Assets Management** (API only): Automatic asset inventory — hostname, IP, MAC, OS, open ports, services, risk score\n- **Targets Management**: Define and manage scan targets/scopes\n- **Notifications**: In-app notification system with unread counts and WebSocket real-time push\n- **Audit Logging**: Full audit trail of all user actions\n- **Global Search**: Search across tickets, vulnerabilities, and hosts\n- **Embedded React SPA**: Single binary, no separate frontend deploy\n\n## Architecture\n\n```mermaid\nsequenceDiagram\n    participant OV as OpenVAS (GVM)\n    participant ZAP as OWASP ZAP\n    participant TR as OpenVAS-Tracker\n    participant AD as Active Directory\n    participant DB as MariaDB\n    participant UI as React Dashboard\n\n    Note over OV: Network scan completes\n    OV-\u003e\u003eTR: HTTP GET /api/import/openvas?api_key=...\n    TR-\u003e\u003eOV: GMP Socket: fetch latest report\n    OV--\u003e\u003eTR: XML report\n    TR-\u003e\u003eDB: Create scan + vulnerabilities + tickets\n\n    Note over ZAP: Web app scan completes\n    ZAP-\u003e\u003eTR: POST /api/import/zap (JSON report)\n    TR-\u003e\u003eDB: Create scan + vulnerabilities + tickets\n\n    TR-\u003e\u003eDB: Check risk accept rules → auto-accept matches\n    TR-\u003e\u003eDB: Auto-fix/reopen tickets (scoped by scanner type)\n    TR-\u003e\u003eDB: Commit\n    TR-\u003e\u003eUI: WebSocket push\n\n    Note over UI: User logs in\n    UI-\u003e\u003eTR: POST /api/auth/login (username + password)\n    alt Admin user\n        TR-\u003e\u003eTR: Check OT_ADMIN_PASSWORD\n    else LDAP user\n        TR-\u003e\u003eAD: Bind + group check\n    end\n    TR--\u003e\u003eUI: JWT token\n```\n\n## Quick Start with Docker\n\n```bash\ncp .env.example .env    # edit: set OT_JWT_SECRET, OT_ADMIN_PASSWORD, OT_IMPORT_APIKEY\ndocker compose up -d\n```\n\nThe UI is at http://localhost:8080. Login: username `admin`, password from `OT_ADMIN_PASSWORD`.\n\n## Quick Start without Docker\n\n```bash\n# 1. Create database\nmysql -e \"CREATE DATABASE \\`openvas-tracker\\` CHARACTER SET utf8mb4;\"\n\n# 2. Run migrations\nmake migrate-up\n\n# 3. Configure\ncat \u003e .env \u003c\u003c EOF\nOT_DATABASE_DSN=root@tcp(localhost:3306)/openvas-tracker?parseTime=true\nOT_JWT_SECRET=$(openssl rand -hex 32)\nOT_IMPORT_APIKEY=$(openssl rand -hex 32)\nOT_ADMIN_PASSWORD=your-admin-password\nEOF\n\n# 4. Build and run\nmake build \u0026\u0026 ./bin/openvas-tracker\n```\n\n## Configuration\n\nAll config via `.env` file. Editable from the Settings page in the UI.\n\n| Variable | Default | Purpose |\n|----------|---------|---------|\n| `OT_SERVER_PORT` | 8080 | HTTP listen port |\n| `OT_DATABASE_DSN` | `...@tcp(localhost:3306)/openvas-tracker?parseTime=true` | MariaDB DSN |\n| `OT_JWT_SECRET` | (none — **required**) | JWT signing key (min 32 chars) |\n| `OT_IMPORT_APIKEY` | (empty) | API key for import webhook (min 32 chars) |\n| `OT_ADMIN_PASSWORD` | (empty) | Admin user password |\n| `OT_GMP_USER` | `admin` | Greenbone user used by the fetch script when `GET /api/import/openvas` is triggered |\n| `OT_GMP_PASSWORD` | (empty) | Greenbone password for the fetch script |\n| `OT_AUTORESOLVE_THRESHOLD` | `3` | Consecutive scans without finding before auto-resolve |\n| `OT_LDAP_URL` | (empty) | LDAP server URL |\n| `OT_LDAP_BASE_DN` | (empty) | LDAP search base DN |\n| `OT_LDAP_BIND_DN` | (empty) | LDAP service account DN |\n| `OT_LDAP_BIND_PASSWORD` | (empty) | LDAP service account password |\n| `OT_LDAP_GROUP_DN` | (empty) | Required AD group for access |\n| `OT_LDAP_USER_FILTER` | `(sAMAccountName=%s)` | LDAP user search filter |\n\n## Authentication\n\n1. **Admin**: Username `admin` + `OT_ADMIN_PASSWORD` → always available\n2. **LDAP**: Bind against Active Directory, verify group membership → if configured\n3. **DB fallback**: Existing database users → for backwards compatibility\n\nNo self-registration. LDAP users auto-created in DB on first login and also when the user list is loaded (Settings → Users), so they can be assigned to tickets before their first login.\n\n## OpenVAS Setup\n\n1. Set `OT_IMPORT_APIKEY`, `OT_GMP_USER`, and `OT_GMP_PASSWORD` in `.env`\n2. In GSA: **Configuration → Alerts → New Alert** → HTTP Get → `http://\u003chost\u003e:8080/api/import/openvas?api_key=\u003ckey\u003e`\n3. Attach alert to scan task\n\nWhen the alert fires, the tracker runs `sudo /usr/local/bin/openvas-tracker-fetch-latest`, which speaks GMP directly to the local Greenbone Unix socket, downloads the newest report and POSTs it back to itself. The script and its sudoers rule are installed by `deploy/install.sh`. The script needs read access to the gvmd socket — by default it expects the Greenbone CE Docker volume path; override with `OT_GMP_SOCKET` if your install puts it elsewhere.\n\n## ZAP Setup\n\nZAP scans are run externally — the tracker receives results via webhook. The same `OT_IMPORT_APIKEY` is used for both OpenVAS and ZAP imports.\n\n### Manual (ZAP Desktop)\n\n1. Run your scan in ZAP (Spider + Active Scan)\n2. Export report: **Report → Generate Report → Traditional JSON**\n3. Send to tracker:\n\n```bash\ncurl -X POST https://your-server:8080/api/import/zap \\\n  -H \"X-API-Key: your-api-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d @zap-report.json\n```\n\n### Automated (ZAP Docker)\n\n```bash\n# Full scan (spider + active scan)\ndocker run --rm -v $(pwd):/zap/wrk ghcr.io/zaproxy/zaproxy:stable \\\n  zap-full-scan.py -t https://target-app.example.com -J zap-report.json\n\n# Send results to tracker\ncurl -X POST https://your-server:8080/api/import/zap \\\n  -H \"X-API-Key: your-api-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d @zap-report.json\n```\n\nZAP Docker scan modes:\n- `zap-baseline.py` — Passive checks only (fast, safe for production)\n- `zap-full-scan.py` — Spider + active scan (thorough, sends attack payloads)\n- `zap-api-scan.py` — API scan against OpenAPI/Swagger definitions\n\n### Cron Example\n\n```bash\n#!/bin/bash\n# /usr/local/bin/zap-scan-and-import.sh\nTARGET=\"https://internal-app.example.com\"\nAPIKEY=\"your-32-char-api-key\"\nREPORT=\"/tmp/zap-report.json\"\n\ndocker run --rm --network host \\\n  -v /tmp:/zap/wrk ghcr.io/zaproxy/zaproxy:stable \\\n  zap-full-scan.py -t \"$TARGET\" -J zap-report.json\n\ncurl -s -X POST http://localhost:8080/api/import/zap \\\n  -H \"X-API-Key: $APIKEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d @\"$REPORT\"\n\nrm -f \"$REPORT\"\n```\n\n### How ZAP Findings Become Tickets\n\n- **Parameter-specific findings** (XSS, SQLi): one ticket per URL + parameter combination. Fingerprint: `cwe:\u003cID\u003e:url:\u003cpath\u003e:param:\u003cname\u003e`\n- **Server-wide findings** (missing headers, CSP): one ticket per host, regardless of how many URLs are affected. Fingerprint: `cwe:\u003cID\u003e`. All affected URLs listed in ticket detail\n- CVE always takes priority as fingerprint if present\n- Severity mapping: ZAP riskcode 3→high (CVSS 7.0), 2→medium (4.0), 1→low (2.0), 0→info (skipped)\n- Auto-resolve is scoped by scanner type — ZAP scans only affect ZAP tickets, never OpenVAS tickets\n\n## Ticket Lifecycle\n\n```\nImport finds new vulnerability     →  Ticket created (open)\nImport matches risk accept rule    →  Ticket created (risk_accepted)\nImport finds same vulnerability    →  Ticket updated (last_seen_at)\nImport missing old vulnerability   →  Ticket pending_resolution (miss counter +1)\nConsecutive misses reach threshold →  Ticket auto-fixed\nFinding reappears while pending    →  Counter reset, ticket back to open\nImport re-finds fixed vuln        →  Ticket reopened (open)\nImport re-finds false_positive     →  Skipped (never reopened)\nRisk acceptance expires            →  Ticket auto-reopened\n```\n\n## Auto-Accept Rules\n\nRules automatically set matching tickets to `risk_accepted` during import. Created from any ticket's detail page with scope \"this host only\" or \"all hosts\". Managed via the Auto-Accept Rules page.\n\nMatching by: CVE ID (if available) or vulnerability title. Optional expiry date.\n\n## API\n\n| Method | Path | Description |\n|--------|------|-------------|\n| POST | /api/auth/login | Login (username + password) |\n| POST | /api/import/openvas | Import OpenVAS XML (API-Key) |\n| GET | /api/import/openvas | Trigger GMP fetch (API-Key) |\n| POST | /api/import/zap | Import ZAP JSON report (API-Key) |\n| GET | /api/hosts/:host/vulnerabilities | Vulnerabilities for a host |\n| GET | /api/scans | List scans |\n| GET | /api/scans/diff?old=X\u0026new=Y | Compare two scans |\n| GET | /api/scans/:id | Scan detail |\n| GET | /api/tickets | List all tickets |\n| POST | /api/tickets/bulk | Bulk status/assign |\n| GET | /api/tickets/:id | Ticket detail |\n| PATCH | /api/tickets/:id/status | Change status |\n| PATCH | /api/tickets/:id/assign | Assign to user |\n| POST | /api/tickets/:id/risk-rule | Create auto-accept rule from ticket |\n| POST/GET | /api/tickets/:id/comments | Notes |\n| GET | /api/tickets/:id/activity | Activity log |\n| GET | /api/tickets/:id/also-affected | Other affected hosts |\n| GET | /api/dashboard | Priority counts + ticket stats |\n| GET | /api/dashboard/trend | 30-day open ticket trend |\n| GET | /api/settings/setup | Setup guide |\n| GET | /api/settings/users | User list (local + LDAP) |\n| GET/PUT | /api/settings/env | Read/write .env config |\n| POST | /api/settings/ldap/test | Test LDAP connection |\n| GET | /api/settings/risk-rules | List auto-accept rules |\n| POST | /api/settings/risk-rules/apply | Re-apply rules to existing open tickets |\n| DELETE | /api/settings/risk-rules/:id | Delete rule |\n| GET | /api/vulnerabilities | List vulnerabilities |\n| GET | /api/vulnerabilities/:id | Vulnerability detail |\n| PATCH | /api/vulnerabilities/:id/status | Update vulnerability status |\n| POST | /api/tickets | Create ticket manually |\n| GET | /api/search?q= | Global search |\n| GET | /api/assets | List assets |\n| GET | /api/assets/:id | Asset detail |\n| GET | /api/targets | List targets |\n| POST | /api/targets | Create target |\n| GET | /api/teams | List teams |\n| POST | /api/teams | Create team |\n| GET | /api/notifications | List notifications |\n| PUT | /api/notifications/read-all | Mark all read |\n| GET | /api/audit | Audit log |\n| POST | /api/reports | Generate report |\n| GET | /api/reports/:id | Download report |\n| PUT | /api/settings/env/batch | Batch update config |\n| GET | /api/health | Health check |\n\n## Tech Stack\n\n- **Backend**: Go 1.26, Echo v4, MariaDB, golang-jwt, bcrypt, godotenv, go-ldap\n- **Frontend**: React 19, Vite, Tailwind CSS, TanStack Query, Recharts, Zustand\n- **Deploy**: Docker Compose or systemd (Debian). Database migrations auto-applied on startup\n\n## Donate\n\nIf you find this project useful, consider supporting development:\n\n**XMR (Monero):**\n```\n89fMD41wm8n88tgVj836qf3m16odqRjBhLti8dmVbvgsYAuEpTGfHBL7zNW8hingxQJNLWXfP3c2tgyyUMxYBiqHVYWR2rU\n```\n\n## License\n\nGPL v3\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrcyberoptic%2Fopenvas-tracker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftrcyberoptic%2Fopenvas-tracker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrcyberoptic%2Fopenvas-tracker/lists"}