All notable changes to quantumvalidator are documented in this file.
Format follows Keep a Changelog. Version numbers follow Semantic Versioning.
0.5.2 — 2026-05-15
info groupssub-command — lists all quantum-safe TLS and SSH key exchange groups with their IANA codepoint and governing standard.pytest-mock>=3.12added to dev extras.
assessor.assess(): parameters aftertargetare now keyword-only (enforced by*,);timeouttype corrected frominttofloat(default10.0), consistent with all other platform modules.- All
Optional[X]type hints replaced withX | None(PEP 604) throughoutassessor.py,cli.py,models.py, andtls_utils.py. cli:--versionshort flag changed from-vto-V(uppercase), consistent with all other platform modules.reporter:print_report()renamed toprint_full_report();save_report()now raisesValueErrorfor unsupported file extensions instead of silently falling back to plain text.
reporter.print_reportdeprecated alias removed; useprint_full_reportdirectly.
0.5.1 — 2026-05-15
pyproject.toml: correctedauthorsfield tot0kubetsu(consistent with all other platform modules).reporter: exposes a publicconsolealias (Console(record=True)) and asave_report(path)function supporting.txt,.svg, and.htmlextensions (unknown extensions fall back to plain text).- CLI migrated to use
reporter.console;print_report()now renders to the module-level console sosave_report()captures the output correctly. The private_save_report()helper incli.pyhas been removed.
0.5.0 — 2026-05-05
_probe_ftpgreeting/response reads are now loop-safe — replaced singlesock.recv(1024)calls with chunk-accumulation loops that read until\nor 1024 bytes, guarding against TCP segmentation on slow links._probe_ftpusesdataclasses.replace()instead of post-construction field mutation when stampingdetected_starttls="ftp"onto the openssl result.- Empty AUTH TLS response now reports
"(no response)"in the error message instead of a trailing bare colon. _fingerprint_bannerdocstring documents the FTP keyword-detection limitation (FileZilla) and the NNTP200/201heuristic caveat.
- FTP probe no longer hangs on servers that reject AUTH TLS —
openssl s_client -starttls ftpdoes not exit cleanly when the server replies with e.g.500 AUTH not understood; it hangs until the subprocess timeout fires. A new_probe_ftpfunction now sendsAUTH TLSover a raw socket first; if the server responds with anything other than234, the error is returned immediately without invokingopenssl.
- Extended STARTTLS protocol detection —
_fingerprint_bannernow auto-detects FTP (220 … FTP …), LMTP (220 … LMTP …), NNTP (200/201), and ManageSieve ("IMPLEMENTATION"/"SIEVE"/"STARTTLS"capability lines) from server banners, dispatching to the correctopenssl -starttlsmode automatically. Protocols that send no opening banner (XMPP, LDAP, MySQL, PostgreSQL) remain unsupported in auto-detect mode by design, keeping the probe protocol-agnostic.
0.4.0 — 2026-04-29
- SSH PQC probe — auto-detects
SSH-2.0-banner via banner-first socket read and probes the server's RFC 4253 KEXINIT in pure Python (noopensslrequired). Checks whether the server advertises an ML-KEM hybrid KEX algorithm (mlkem768nistp256-sha256,mlkem1024nistp384-sha384,mlkem768x25519-sha256). - SSH constants —
SSH_PQC_GROUPSandSSH_SAFE_GROUPSinconstants.pycovering the three ML-KEM hybrid KEX algorithms per NIST FIPS 203 / CNSA 2.0 / BSI TR-02102-4.sntrup761x25519-sha512@openssh.com(NTRU) intentionally excluded — not NIST-selected. - SSH verdict logic —
determine_verdict("SSHv2", ...)and_build_ssh_checks()inverdict.py; producesssh_version+kex_algorithmchecks per NIST SP 800-209 and NIST FIPS 203. - SSH report mode — terminal header shows
[SSH]; verdict panel shows SSH-specific remediation text ("Upgrade to OpenSSH ≥ 9.9 …") and references BSI TR-02102-4 for SAFE results. GroupInfo.iana_codepoint: str | None— field is now optional; SSH algorithms set it toNone(no IANA codepoint assigned).
- README: intro, PQC Groups Detected, Standards, and Verdict sections updated to cover SSH alongside TLS. Standards table gains NIST FIPS 203, BSI TR-02102-4, and NIST SP 800-209.
0.3.0 — 2026-04-29
-pshort flag for--port:quantumvalidator check host -p 587.- Banner-first probe — plain TCP socket reads the server's opening bytes
before the TLS probe. Reduces connections for STARTTLS services from 3 to 2
and fixes STARTTLS detection (
openssl -briefsuppresses plaintext banners). - "Security Verdict" label in terminal report panel (was "Verdict").
probe_tls()starttls_smtpparameter — deprecated backward-compat kwarg removed. Callprobe_tls(host, port)directly.- Standard column from the checks table in the terminal report.
TLSProbeResult.raw_outputfield — no longer needed since banner detection uses a direct socket read.
assess(port=0)no longer silently uses port 443; raisesRuntimeErrorinstead.openssl versionparse failure now logged at DEBUG instead of silently ignored.
0.2.0 — 2026-04-28
- Protocol-agnostic probing —
quantumvalidator check host --port Nauto-detects STARTTLS mode (SMTP/IMAP/POP3) via server banner fingerprinting. No protocol flag needed. QuantumReport.detected_starttls: str | None— surfaces the auto-detected STARTTLS mode ("smtp"/"imap"/"pop3"), orNonefor raw TLS.- Report header — displays detected probe mode:
[TLS],[SMTP/STARTTLS], etc.
assess()protocol=parameter — useport=directly.QuantumReport.protocolfield — replaced bydetected_starttls.check_https()/check_smtp()fromchecker.py— usecheck_tls(host, port).--protocol/-pCLI flag — pass--portinstead.DEFAULT_PORT_SMTPconstant fromconstants.py.
check_tls(host, port)is now the single probe entry point inchecker.py, replacing the formercheck_https/check_smtpsplit.
0.1.0 — 2026-04-28
- Initial release of quantumvalidator.
- HTTPS and SMTP/STARTTLS probing with explicit
--protocolflag. - Post-quantum key-exchange detection: ML-KEM-768 / X25519MLKEM768 / hybrid
groups flagged as
SAFE; classical-only KEX flagged asUNSAFE. - TLS 1.3 requirement check — TLS ≤ 1.2 always yields
UNSAFEverdict. - CLI:
quantumvalidator check <target>with--port,--timeout,--json,--output,--versionflags. - Exit codes:
0SAFE,1UNSAFE,2error. - Report export to
.txt,.svg,.html. - 100% test coverage via pytest.