A self-hosted server that watches public CVE feeds for vulnerabilities you actually care about. You keep a watchlist of vendors, products, or keywords, it polls the public CVE sources on a schedule, and it emails you when something on your watchlist lands. Built for MSP technicians and small IT teams who need to know about the CVEs relevant to their stack without babysitting a feed all day.
- Keyword and vendor:product watchlist matching, with an optional CVSS threshold
- CISA KEV (Known Exploited Vulnerabilities) flagging
- NVD CVSS and FIRST.org EPSS enrichment
- Coalesced email alerts with a retry queue for failed sends
- Web dashboard showing sync health for every data source
- SQLite storage, no external database to run or manage
- All data stays local: no telemetry, no third-party analytics
docker compose up -dOpen http://localhost:8080. On first run the app downloads about 90 days of
CVE history; this takes a few minutes and progress is shown in the UI. Data
persists in a named Docker volume, so it survives container rebuilds.
The first run needs about 2 GB of free disk space temporarily for the download; ongoing usage afterward is under 100 MB.
Requires Python 3.11+.
pip install -r requirements.txt
python -m simple_cve_tracker serveBy default the server binds to 127.0.0.1:8080. Pass --host 0.0.0.0 to
expose it beyond localhost, and --port to change the port.
This installs the app under a dedicated service account so it runs
independent of any user login. Extract the release tarball, cd into it,
then run the install script as root:
tar xzf simple-cve-tracker-vX.Y.Z.tar.gz
cd simple-cve-tracker-vX.Y.Z
sudo ./deploy/install.shThe script probes ports 8080 through 8090 and uses the first one that is
free. Pass --port N to force a specific port instead, for example if you
already know 8080 is taken:
sudo ./deploy/install.sh --port 8091If your chosen port is already in use by another service (Pi-hole's web UI uses 8080, for example), pick a different one. The app now refuses to start with a clear error instead of failing oddly if the port turns out to be unavailable.
The installation keeps application code, persistent data, and the Python environment separate:
/opt/simple-cve-tracker/appcontains the active release./opt/simple-cve-tracker/datacontains the database and downloaded source data./opt/simple-cve-tracker/venvcontains the Python virtual environment.
To update, extract the new release tarball and run the same install command
from that extracted directory. The installer stages and replaces app,
rebuilds venv, and preserves data. On the first update from an older
installation that stored release files directly in
/opt/simple-cve-tracker, it removes only known legacy release files after the
replacement service has started successfully. Other files are left alone.
Manual install: the script above just automates these steps, which you can also run by hand if you want more control:
sudo useradd --system --create-home --home-dir /opt/simple-cve-tracker sct
sudo install -d -o sct -g sct /opt/simple-cve-tracker/{app,data,venv}
# From the extracted release root, copy the release into app/:
sudo cp -a . /opt/simple-cve-tracker/app/
sudo chown -R sct:sct /opt/simple-cve-tracker/app
sudo -u sct python3 -m venv /opt/simple-cve-tracker/venv
sudo -u sct /opt/simple-cve-tracker/venv/bin/pip install -r /opt/simple-cve-tracker/app/requirements.txt
sudo cp /opt/simple-cve-tracker/app/deploy/simple-cve-tracker.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now simple-cve-trackerEverything is configured in the web UI settings page: poll intervals, retention, SMTP, and the optional NVD API key.
The data directory and two secrets can be set by environment variables:
| Variable | Purpose |
|---|---|
SCT_DATA_DIR |
Data directory location |
SCT_SMTP_PASSWORD |
SMTP password; overrides and locks the UI field |
SCT_NVD_API_KEY |
NVD API key; overrides and locks the UI field |
For SMTP, use an app password rather than your account password. Email alerts are optional; the app works with alerts turned off.
Docker: pull or rebuild the image and run docker compose up -d again.
The named volume keeps your data.
From source / systemd: extract the new release tarball, then rerun
sudo ./deploy/install.sh from that extracted directory. The installer
replaces the application directory and rebuilds its virtual environment while
the data directory remains in place.
Releases are packed on GitHub-hosted runners with signed build provenance.
gh attestation verify simple-cve-tracker-vX.Y.Z.tar.gz \
--repo JDE-Projects/Simple-CVE-Tracker \
--signer-repo JDE-Projects/Build-Tools
sha256sum -c simple-cve-tracker-vX.Y.Z.tar.gz.sha256The --signer-repo flag is required because the release workflow lives in a
separate repository.
- CISA Known Exploited Vulnerabilities (KEV) catalog
- CVEProject cvelistV5 (the CVE Program)
- NVD (this product uses the NVD API but is not endorsed or certified by the NVD)
- FIRST.org EPSS (scores provided by FIRST)
Released under the PolyForm Internal Use License 1.0.0: free to use and modify within your own organization. See THIRD-PARTY-LICENSES.txt for notices on bundled fonts and runtime dependencies.