EUVD CLI
Query the ENISA EU Vulnerability Database (EUVD) from the command line and from Python
Overview
EUVD CLI is both a command-line tool and a Python library that fetches vulnerabilities, advisories, and KEV entries from the ENISA EU Vulnerability Database, validates the responses with Pydantic, and emits JSON or SARIF 2.1 output. The same client and validation rules apply when used as a library.
Current feature set
| Area | Capabilities |
|---|---|
| Endpoints | latest, critical, exploited, ENISA ID lookup, advisory lookup, search, KEV dump |
| Search filters | --text, --vendor, --product, --assigner, --from-score/--to-score (0-10), --from-epss/--to-epss (0-100), --from-date/--to-date (YYYY-MM-DD), --exploited/--not-exploited, --size (1-100), --page |
| Output | JSON (default), JSONL, CSV, TOON, and SARIF 2.1, written to stdout cleanly for piping |
| Save to file | --output <path> and --save (timestamped filename) for kev-dump, with overwrite warning |
| Validation | CVSS/EPSS bounds, strict ISO date format, from_X <= to_X cross-pair, page-size cap enforced via Pydantic before the request |
| Streams | banner/status/errors on stderr, machine-readable data on stdout, no ANSI escapes in JSON output |
| Errors | typed exceptions (API_ERRORS, SARIFConversionError, OSError) handled with a single-line user message; SIGINT exits 130, SIGPIPE exits cleanly |
| Library API | from euvd_python import EUVDAPIClient, SearchFilters, to_sarif_json, ... (32 public symbols) |
| Resilience | client-side rate limiter (1 request / 6 s) and 30-second HTTP timeout (calibrated for slow /search?text= queries) |
| Self-test | 39-check regression suite against the live API (euvd-cli selftest) |
Supported endpoints
| Path | Subcommand |
|---|---|
/lastvulnerabilities |
latest |
/criticalvulnerabilities |
critical |
/exploitedvulnerabilities |
exploited |
/enisaid?id= |
search-enisa |
/advisory?id= |
search-advisory |
/search |
search |
/kev/dump |
kev-dump |
Base URL: https://euvdservices.enisa.europa.eu/api.
Installation
From PyPI
pip install euvd-python-cli
From source
git clone https://github.com/seifreed/euvd-cli.git
cd euvd-cli
python3 -m venv venv
source venv/bin/activate
pip install -e .
Development
pip install -e ".[dev]"
Quick start
euvd-cli latest
euvd-cli critical
euvd-cli exploited
euvd-cli search-enisa EUVD-2025-4893
euvd-cli search-advisory oxas-adv-2024-0002
euvd-cli search --text "OpenSSL" --from-score 7.0 --size 20
euvd-cli stats
euvd-cli kev-dump --save
euvd-cli --format sarif latest > latest.sarif.json
CLI usage
Inputs
euvd-cli latest
euvd-cli critical
euvd-cli exploited
euvd-cli search-enisa EUVD-2025-4893
euvd-cli search-advisory oxas-adv-2024-0002
euvd-cli kev-dump
Search
euvd-cli search --text "Windows" --size 10
euvd-cli search --exploited --size 5
euvd-cli search --from-score 9.0 --to-score 10.0
euvd-cli search --from-date 2024-01-01 --to-date 2024-12-31
euvd-cli search --from-epss 50 --to-epss 100
Output formats
The --format flag is on the group, before the subcommand. Supported: json (default, indented), jsonl (one JSON object per line), csv, toon (Token-Oriented Object Notation, requires pip install "euvd-python-cli[toon]" --pre), sarif (SARIF 2.1).
euvd-cli --format json latest
euvd-cli --format jsonl latest
euvd-cli --format csv latest
euvd-cli --format toon latest
euvd-cli --format sarif search-advisory oxas-adv-2024-0002
For search, the jsonl and csv formats emit only the items (the total wrapper is dropped because flat formats can't represent it).
Save to file
euvd-cli kev-dump -o kev.json
euvd-cli kev-dump --save # kev_dump_YYYYMMDD_HHMMSS.json
euvd-cli --format sarif kev-dump -o kev.sarif.json
Statistics and self-test
euvd-cli stats
euvd-cli selftest
Common options
| Option | Meaning |
|---|---|
-v, --verbose |
Enable DEBUG logging (rate-limiter timing) |
--format json|sarif |
Output format. Group-level flag, before the subcommand |
-h, --help |
Help. Works on the group and on every subcommand |
-o, --output <path> |
Save destination for kev-dump |
--save |
Save with auto-generated timestamped filename |
Python library
from euvd_python import EUVDAPIClient, SearchFilters, to_sarif_json
with EUVDAPIClient() as client:
latest = client.get_latest_vulnerabilities()
advisory = client.get_advisory_by_id("oxas-adv-2024-0002")
results = client.search_vulnerabilities(
SearchFilters(text="OpenSSL", from_score=7.0, size=20)
)
sarif_json = to_sarif_json(latest)
The same validation rules apply: SearchFilters rejects out-of-range CVSS/EPSS, non-ISO dates, inverted ranges, and out-of-bounds size before the request is made.
Public API
from euvd_python import (
EUVDAPIClient,
RateLimiter,
APIResponseError,
API_ERRORS,
SearchFilters,
LatestVulnerability,
CriticalVulnerability,
ExploitedVulnerability,
SearchResultVulnerability,
ENISAVulnerabilityByID,
VulnerabilityByID,
AdvisoryByID,
AdvisorySource,
KevEntry,
VulnerabilityQueryResponse,
to_sarif_json,
SARIFConversionError,
CVSS_CRITICAL_THRESHOLD,
CVSS_HIGH_THRESHOLD,
CVSS_MEDIUM_THRESHOLD,
)
Importing euvd_python does not load Click, does not load rich.console, and does not install signal handlers. Those are only loaded by euvd_python.cli and euvd_python.main, which library users have no reason to import.
Output notes
- JSON: pretty-printed with
indent=2, written viasys.stdout.writeso the output is pipe-safe and free of ANSI escapes. - SARIF: SARIF 2.1 with stable rule deduplication, EPSS mapped to
rankon the API's native 0-100 scale, severity derived from CVSS thresholds. - Diagnostics (banner, "Fetching...", "Saved to...", error messages) all go to stderr so stdout stays parseable.
- Models preserve unknown wire fields via Pydantic
extra="allow", so future EUVD additions show up in JSON output without a code change.
Validation
SearchFilters enforces all input invariants in one place:
| Field | Rule |
|---|---|
from_score, to_score |
float in [0, 10] |
from_epss, to_epss |
float in [0, 100] |
from_date, to_date |
string matching ^\d{4}-\d{2}-\d{2}$, valid calendar date |
from_X, to_X |
from_X <= to_X |
size |
int in [1, 100] |
page |
int >= 0 |
Invalid input prints Invalid input: --<flag>: <reason> to stderr and exits 1, before any HTTP request.
Testing
euvd-cli selftest
The self-test hits the live EUVD API. There are no mocks — a passing self-test means real usage works against the real endpoints. CVSS/EPSS bounds, ISO date parsing, SARIF correctness, stream routing, signal handling, and library re-exports are all locked by synthetic checks within the same suite.
Quality gates run with default rules and zero suppressions:
black --check euvd_python/
ruff check euvd_python/
mypy euvd_python/
bandit -r euvd_python/
pip-audit -r requirements.txt
License
MIT — see LICENSE.
Author: Marc Rivero Lopez · mriverolopez@gmail.com
Metadata
Release files for euvd-python-cli 1.0.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| euvd_python_cli-1.0.2.tar.gz | 24.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| euvd_python_cli-1.0.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 47.4 kB
Release files / euvd_python_cli-1.0.2.tar.gz
| Download URL | euvd_python_cli-1.0.2.tar.gz |
|---|---|
| Size | 24.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
141f0cb547e0cb9b388d9dfeeef4f8de2c84d124dbb35da7544d2832db62d7ef
|
|
BLAKE2b-256 checksum How to use checksums |
3cabdb431964a58c4309db092f037943cc5621edc2452a2782b57b6cb0631f48
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 9, 2026.
Transparency logRelease files / euvd_python_cli-1.0.2-py3-none-any.whl
| Download URL | euvd_python_cli-1.0.2-py3-none-any.whl |
|---|---|
| Size | 23.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
25cf1a495180addfeb7090cddf3536e58bf777516fa1e134fca030d5381130d0
|
|
BLAKE2b-256 checksum How to use checksums |
48d1481c7da4512f61f47e13f6ba5a1d221d10d95da9a91ae1e06ae58c2a0146
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 9, 2026.
Transparency log