ValtersIT Open-Source CVE Scanner Suite: Linux, Docker, WordPress and Windows Setup Guide
Most vulnerability scanners are either paid SaaS with an agent you can’t audit, or open-source tools that require a local database the size of a small appliance. The ValtersIT scanner suite is neither: five small scripts — two to four files each, no pip install, standard-library Python or a single PowerShell file — that send your installed component list to the ValtersIT CVE API and return the CVEs that match.
This guide covers every scanner in the suite: installation, a first run, scheduling, and what to do with the output.
What the suite does
Section titled “What the suite does”Each scanner detects what is actually installed on the machine you run it on, then hands that inventory to the ValtersIT CVE API for matching. The result is a ranked list of CVEs that affect your specific versions — not a generic advisory feed, not a cloud agent phoning home with your traffic.
| Tool | What it scans | Language | Size |
|---|---|---|---|
| Linux Scanner | dpkg / rpm / apk / pacman packages + service versions | Python 3.7+ | ~350 lines |
| Docker Scanner | Docker Engine version + images used by running/stopped containers | Python 3.7+ | ~350 lines |
| WordPress Scanner | WP core + all themes + all plugins (+ WP-CLI status if present) | Python 3.7+ | ~450 lines |
| Windows Scanner | All installed software (registry Uninstall keys, 64-bit + 32-bit) | PowerShell 5.1+ | ~350 lines |
| Threat-IP Blocklist | Pulls the ValtersIT IP threat feed → nftables / ipset / fail2ban / pfSense / MikroTik | Python 3.7+ | ~300 lines |
All five are Apache-2.0. All are small enough to read in a few minutes — that is deliberate.
Privacy model: what leaves your machine
Section titled “Privacy model: what leaves your machine”Every scanner follows the same data-minimisation rule:
- Sent to the API: component name + version only (e.g.
openssl 3.0.13,woocommerce 9.4.1,nginx alpine). A locally-generated random identifier (32 hex chars, stored in~/.valtersit/fingerprint) lets the API recognise repeat scans of the same system — it is never derived from your IP address, hostname, MAC address, or any other stable machine identifier. - Never sent: IP address, hostname, MAC address, encryption keys, passwords, database contents, file contents. The Linux scanner reads
dpkg-query/rpm -qa/apk info/pacman -Qoutput only. The WordPress scanner reads plugin header comments and, optionally, WP-CLI output — it never openswp-config.phpor touches MySQL. The Docker scanner issues only read-onlydocker info/docker version/docker ps -acommands — it refuses to run against a remoteDOCKER_HOST. The Windows scanner reads onlyHKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*registry keys, the same data Control Panel reads. - Threat-IP Blocklist is the mirror image: it sends nothing about your system — it only pulls threat data down from the feed endpoint.
Every tool is open source. The privacy claims above are falsifiable: clone the repo and read the two-file source before you run it.
Requirements
Section titled “Requirements”- Python 3.7 or later with no additional packages (all tools use the standard library only). Present by default on every major Linux distribution and macOS.
- Windows Scanner: Windows PowerShell 5.1 (built into every supported Windows version) or PowerShell 7+. No modules to install.
- Docker Scanner: a working
dockerCLI with access to the local daemon (user must be in thedockergroup, or run withsudo). - WordPress Scanner: optional WP-CLI for active/inactive plugin status — degrades gracefully to filesystem-only detection without it.
- An API key from valtersit.com/cve/pricing. Set it as
VALTERSIT_API_KEYin your environment.
Getting an API key
Section titled “Getting an API key”- Go to valtersit.com/cve/pricing and pick a scan plan (or a Standard/Pro API plan that includes scanner slots).
- After signup you receive a key that looks like
vit_v1_xxxxxxxxxxxxxxxxxxxxxxxx. - Set it once — either method works:
# Method 1: environment variable (recommended for cron / CI)export VALTERSIT_API_KEY="vit_v1_your_key_here"
# Method 2: edit one line in valtersit_client.py# API_KEY = "vit_v1_your_key_here"# Windows — Method 1: environment variable$env:VALTERSIT_API_KEY = "vit_v1_your_key_here"
# Windows — Method 2: edit one line in ValtersIT-Scan.ps1# $ApiKey = "vit_v1_your_key_here"Linux Scanner
Section titled “Linux Scanner”Detects every installed OS package across the four major package managers — dpkg (Debian/Ubuntu), rpm (RHEL/Fedora/openSUSE), apk (Alpine), and pacman (Arch) — whichever is present on the machine you run it on.
Install
Section titled “Install”# Clone from GitLabgit clone https://gitlab.com/valtersit/linux-cve-scannercd linux-cve-scanner
# Or one-liner (no git required)mkdir -p linux-cve-scanner && cd linux-cve-scannercurl -fsSLO https://gitlab.com/valtersit/linux-cve-scanner/-/raw/main/valtersit-linux-scan.pycurl -fsSLO https://gitlab.com/valtersit/linux-cve-scanner/-/raw/main/valtersit_client.pyexport VALTERSIT_API_KEY="vit_v1_your_key_here"python3 valtersit-linux-scan.pyOn first run the tool requires you to type YES at an authorised-use confirmation prompt. After that, use --yes to skip the prompt in cron:
python3 valtersit-linux-scan.py --yesSample output
Section titled “Sample output”ValtersIT Linux Package Scanner - target: Ubuntu 24.04.4 LTS (dpkg)
============================================================================== INSTALLED PACKAGES (1203 total, showing 60)==============================================================================Package Version------------------------------------------------------------openssl 3.0.13-0ubuntu3.4nginx-common 1.24.0-2ubuntu7.4...
60 item(s) detected. No IP address, hostname, MAC address, file contents, or credentials were read or transmitted by this scan.==============================================================================
[+] Scan submitted. 1203 component(s) sent for matching.{ "matched_cves": 1, "results": [ {"slug": "openssl", "version": "3.0.13-0ubuntu3.4", "cve_id": "CVE-2026-11023", "cvss": 7.5, "patched_in": "3.0.13-0ubuntu3.6"} ]}For every matched CVE, visit https://www.valtersit.com/cve/CVE-XXXX-XXXXX/ for the full write-up: CVSS vector, EPSS probability, exploit availability, patch guidance, and Shodan dorks where applicable.
Schedule with cron
Section titled “Schedule with cron”# Daily at 03:00 — confirm authorised use interactively once first0 3 * * * cd /opt/linux-cve-scanner && \ VALTERSIT_API_KEY=vit_v1_xxx /usr/bin/python3 valtersit-linux-scan.py --yes \ >> /var/log/valtersit-linux-scan.log 2>&1The tool reads your package manager’s own metadata — dpkg-query, rpm -qa, apk info, or pacman -Q. It never installs, removes, or upgrades anything.
Docker Scanner
Section titled “Docker Scanner”Detects the Docker Engine version and every image used by a running or stopped container on the local host (deduplicated repository + tag/digest). It only ever talks to the local Docker daemon: if DOCKER_HOST points at a remote endpoint, the scanner refuses to run.
Install
Section titled “Install”# Clone from GitLabgit clone https://gitlab.com/valtersit/docker-cve-scannercd docker-cve-scanner
# Or one-linermkdir -p docker-cve-scanner && cd docker-cve-scannercurl -fsSLO https://gitlab.com/valtersit/docker-cve-scanner/-/raw/main/valtersit-docker-scan.pycurl -fsSLO https://gitlab.com/valtersit/docker-cve-scanner/-/raw/main/valtersit_client.pyexport VALTERSIT_API_KEY="vit_v1_your_key_here"python3 valtersit-docker-scan.pyIf you’re not in the docker group: sudo python3 valtersit-docker-scan.py.
Sample output
Section titled “Sample output”ValtersIT Docker Scanner - Engine 29.4.3
============================================================================== DOCKER ENGINE==============================================================================Component Version-------------------------------------docker-engine 29.4.3
============================================================================== IMAGES IN USE BY CONTAINERS (5)==============================================================================Repository Tag / Digest---------------------------------------------------------------nginx alpineredis 7-alpinepostgres 15directus/directus latestminio/minio latest
5 item(s) detected. No IP address, hostname, MAC address, file contents, or credentials were read or transmitted by this scan.==============================================================================
[+] Scan submitted. 6 component(s) sent for matching.{ "matched_cves": 1, "results": [ {"slug": "redis", "version": "7-alpine", "cve_id": "CVE-2026-44017", "cvss": 6.8, "patched_in": "7.4.2-alpine"} ]}Schedule with cron
Section titled “Schedule with cron”# Daily at 05:000 5 * * * cd /opt/docker-cve-scanner && \ VALTERSIT_API_KEY=vit_v1_xxx /usr/bin/python3 valtersit-docker-scan.py --yes \ >> /var/log/valtersit-docker-scan.log 2>&1The scanner issues only docker info, docker version, and docker ps -a — it never starts, stops, or modifies any container or image.
WordPress Scanner
Section titled “WordPress Scanner”Detects WordPress core version, every installed theme (with version and active/inactive status), and every installed plugin (version + status). If WP-CLI is available it reports active vs. inactive states; otherwise it lists everything it finds on disk. It only scans a WordPress installation physically present on the local filesystem — pass it a URL and it refuses to run.
Install
Section titled “Install”# Clone from GitLabgit clone https://gitlab.com/valtersit/wordpress-cve-scannercd wordpress-cve-scanner
# Or one-linermkdir -p wordpress-cve-scanner && cd wordpress-cve-scannercurl -fsSLO https://gitlab.com/valtersit/wordpress-cve-scanner/-/raw/main/valtersit-wp-scan.pycurl -fsSLO https://gitlab.com/valtersit/wordpress-cve-scanner/-/raw/main/valtersit_client.pyexport VALTERSIT_API_KEY="vit_v1_your_key_here"python3 valtersit-wp-scan.py --path /var/www/htmlIf run from inside the WordPress root, --path can be omitted. WP-CLI is picked up automatically if it’s in PATH.
Sample output
Section titled “Sample output”ValtersIT WordPress Scanner - target: /var/www/htmlDetection method: WP-CLI (active/inactive known)
============================================================================== WORDPRESS CORE==============================================================================Component Version-------------------------------------wordpress-core 6.7.1
============================================================================== ACTIVE / INSTALLED THEMES (2)==============================================================================Slug Version Status--------------------------------------------------------twentytwentyfour 1.2 activetwentytwentythree 1.4 inactive
============================================================================== INSTALLED PLUGINS (14)==============================================================================Slug Version Status------------------------------------------------------------akismet 5.3.3 activewoocommerce 9.4.1 active...
[+] Scan submitted. 17 component(s) sent for matching.{ "matched_cves": 2, "results": [ {"slug": "woocommerce", "version": "9.4.1", "cve_id": "CVE-2026-31842", "cvss": 8.1, "patched_in": "9.4.3"}, {"slug": "akismet", "version": "5.3.3", "cve_id": "CVE-2025-90210", "cvss": 5.4, "patched_in": "5.3.4"} ]}Anything with a patched_in version newer than what’s installed is your priority list. Prioritise by CVSS score, then check EPSS on the full CVE page — a high-CVSS CVE with a low EPSS score is less likely to be actively exploited than a medium-CVSS one with high EPSS.
The scanner never opens wp-config.php, never connects to MySQL, never writes to wp-content. It needs only read access to the WordPress directory — a low-privilege user is sufficient.
Schedule with cron
Section titled “Schedule with cron”# Daily at 04:000 4 * * * cd /opt/wordpress-cve-scanner && \ VALTERSIT_API_KEY=vit_v1_xxx /usr/bin/python3 valtersit-wp-scan.py \ --path /var/www/html --yes >> /var/log/valtersit-wp-scan.log 2>&1Windows Scanner
Section titled “Windows Scanner”Reads every installed program from the standard HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\* registry keys — the same read-only data Control Panel uses — across both 64-bit and 32-bit entries, plus per-user installs.
Install
Section titled “Install”# Clone from GitLabgit clone https://gitlab.com/valtersit/windows-cve-scannercd windows-cve-scanner
# Or download the single script directlyInvoke-WebRequest ` -Uri "https://gitlab.com/valtersit/windows-cve-scanner/-/raw/main/ValtersIT-Scan.ps1" ` -OutFile "ValtersIT-Scan.ps1"$env:VALTERSIT_API_KEY = "vit_v1_your_key_here".\ValtersIT-Scan.ps1If script execution is blocked by policy:
powershell -ExecutionPolicy Bypass -File .\ValtersIT-Scan.ps1Works on Windows PowerShell 5.1 (built into Windows 10/11/Server) and PowerShell 7+. No modules to install.
Sample output
Section titled “Sample output”ValtersIT Windows Scanner - DESKTOP-AB12CD3
============================================================================== INSTALLED SOFTWARE (87)==============================================================================Name Version Publisher---- ------- ---------7-Zip 23.01 23.01 Igor PavlovMozilla Firefox 129.0.2 MozillaNotepad++ (64-bit x64) 8.6.9 Notepad++ Team...
87 item(s) detected. No IP address, hostname, MAC address, file contents, or credentials were read or transmitted by this scan.==============================================================================
[+] Scan submitted. 87 component(s) sent for matching.{ "matched_cves": 1, "results": [ {"slug": "mozilla-firefox", "version": "129.0.2", "cve_id": "CVE-2026-27310", "cvss": 4.3, "patched_in": "130.0.1"} ]}Schedule with Task Scheduler
Section titled “Schedule with Task Scheduler”Run once interactively first (to clear the authorised-use confirmation), then register the scheduled task:
$action = New-ScheduledTaskAction ` -Execute "powershell.exe" ` -Argument '-ExecutionPolicy Bypass -File "C:\ValtersIT\ValtersIT-Scan.ps1" -Yes'$trigger = New-ScheduledTaskTrigger -Daily -At 4amRegister-ScheduledTask ` -TaskName "ValtersIT Windows Scan" ` -Action $action -Trigger $trigger -RunLevel HighestThe scanner does not require Administrator privileges to read the Uninstall registry keys.
Threat-IP Blocklist Importer
Section titled “Threat-IP Blocklist Importer”Pulls the ValtersIT threat-IP feed (GET /api/v1/ip/feed, Standard plan and above) and renders it into the firewall format you need: nftables, ipset, fail2ban, pfSense (URL Table alias), or MikroTik RouterOS. For nftables and ipset it can apply the result directly with --apply.
This is the mirror image of the scanners: it sends nothing about your system — it only pulls threat data down.
Requires a Standard or Pro API plan. See API pricing →
Install
Section titled “Install”# Clone from GitLabgit clone https://gitlab.com/valtersit/threat-ip-blocklistcd threat-ip-blocklist
# Or one-linermkdir -p threat-ip-blocklist && cd threat-ip-blocklistcurl -fsSLO https://gitlab.com/valtersit/threat-ip-blocklist/-/raw/main/valtersit-blocklist.pycurl -fsSLO https://gitlab.com/valtersit/threat-ip-blocklist/-/raw/main/valtersit_client.pyRun — pick a format
Section titled “Run — pick a format”export VALTERSIT_API_KEY="vit_v1_your_key_here"
# First run: verify the feed response shapepython3 valtersit-blocklist.py --format nftables --debug
# Write output to a filepython3 valtersit-blocklist.py --format nftables --output blocklist.nft
# Apply directly to this host's nftablespython3 valtersit-blocklist.py --format nftables --apply --yes
# ipsetpython3 valtersit-blocklist.py --format ipset --apply --yes
# fail2ban (ban IPs into a named jail — the jail must already exist)python3 valtersit-blocklist.py --format fail2ban --jail valtersit-threat
# pfSense — writes a plain IP list, host this file and point a URL Table alias at itpython3 valtersit-blocklist.py --format pfsense --output /srv/blocklist/valtersit.txt
# MikroTik RouterOS — generates a .rsc script to importpython3 valtersit-blocklist.py --format mikrotik --output blocklist.rscSample nftables output
Section titled “Sample nftables output”#!/usr/sbin/nft -f# ValtersIT threat-IP blocklist - generated 2026-09-25T15:00:00Z# Load with: nft -f <this file> (or pipe it in: nft -f -)
table inet valtersit_threat_ip { set blocklist_v4 { type ipv4_addr flags interval elements = { 203.0.113.5, 203.0.113.6 } } chain input { type filter hook input priority 0; policy accept; ip saddr @blocklist_v4 counter drop }}The generated table fully replaces itself each run — stale entries are dropped automatically. It only ever touches the single table/set named valtersit_threat_ip (override with --list-name); it does not modify, flush, or reorder any of your existing rules.
Schedule with cron — nftables, every 6 hours
Section titled “Schedule with cron — nftables, every 6 hours”0 */6 * * * cd /opt/threat-ip-blocklist && \ VALTERSIT_API_KEY=vit_v1_xxx /usr/bin/python3 valtersit-blocklist.py \ --format nftables --apply --yes >> /var/log/valtersit-blocklist.log 2>&1For pfSense: host the generated file behind a small web server and point a Firewall > Aliases > URL Table (IPs) alias at that URL. pfSense fetches and applies it on its own refresh schedule.
For MikroTik: schedule /tool fetch to pull the regenerated .rsc file and /import it via /system scheduler.
Interpreting results
Section titled “Interpreting results”All five scanners return the same shape: matched_cves (count) and a results array with cve_id, cvss, and patched_in. For each matched CVE:
- Open
https://www.valtersit.com/cve/{cve-id}/— the full record includes CVSS vector, EPSS score (probability of exploitation in the next 30 days), exploit availability, CISA KEV status, Nuclei template if one exists, and patch guidance. - Sort your fix list by CVSS descending, then by EPSS descending. A CVSS 9.8 with EPSS 0.0001 is theoretically severe but rarely exploited; a CVSS 6.5 with EPSS 0.85 is being actively used in the wild.
- Anything in CISA KEV —
cisa_kev: true— has a known exploitation record. Treat it as P1 regardless of CVSS. - For
has_exploit: truerecords, the Nuclei template or PoC link is on the CVE page. Run it against your own system before patching to confirm exploitability.
Authorised use
Section titled “Authorised use”Every scanner requires you to type YES at a consent prompt on first run. The prompt text:
------------------------------------------------------------------------------ ValtersIT Scanner — Authorised Use Confirmation------------------------------------------------------------------------------ Run this tool ONLY against systems you own, or for which you have explicit written authorisation to assess.
This scan sends only component name + version (plus a random local identifier) to the ValtersIT API — no IP address, hostname, or file contents. See the Privacy Policy: https://www.valtersit.com/privacy
Type YES to confirm you are authorised to scan this system and continue. Anything else aborts without scanning.------------------------------------------------------------------------------After confirming once interactively, use --yes (or -Yes on Windows) for non-interactive runs in cron or CI. The Docker scanner additionally refuses to run if DOCKER_HOST points at a remote endpoint. The WordPress scanner refuses to accept a URL as a target — --path must be a local filesystem path.
Scanner plan pricing
Section titled “Scanner plan pricing”| Plan | Founding | Regular | System slots | Scans |
|---|---|---|---|---|
| Solo | €8/mo | €12/mo | 1 | Unlimited |
| Team | €29/mo | €44/mo | 5 | Unlimited |
| Agency | €89/mo | €135/mo | 25 | Unlimited |
Founding price locked for life while the subscription stays active. Offer ends 31 Dec 2026. Standard and Pro API plans (€19/mo and €65/mo founding) include 1 and 5 scanner slots respectively — no separate scan plan needed if you already have an API subscription.
Do the scanners need root?
The Linux scanner does not — it runs the same package-manager read commands an unprivileged user can run. The Docker scanner needs docker group membership or sudo. The WordPress scanner needs read access to the WordPress directory (no need for www-data or root). The Windows scanner reads registry keys without Administrator rights.
Can I scan a remote server?
No. Every scanner is designed to run on the machine it scans. The Docker scanner actively refuses to run against a remote DOCKER_HOST. The WordPress scanner only accepts a local filesystem path. This is a deliberate design choice — scanning third-party systems you don’t own requires explicit authorisation.
What if a CVE ID appears but I can’t reproduce the exploit?
CVSS measures potential severity, not active exploitation. Check the EPSS score and has_exploit flag on the CVE page. If EPSS is low and no public PoC exists, monitor and patch in your normal cycle. If has_exploit: true, prioritise.
I installed a fix — how do I confirm the scanner sees it?
Run the scanner again with --yes. If patched_in appears in the result, the match was on the old version; update the package/plugin/software and re-scan to confirm the CVE no longer appears.
Do the scripts need internet access beyond the API call?
No. The only outbound connection is the one HTTPS call to api.valtersit.com. No CDN, no telemetry, no update checks.