Phase one of the federal PQC mandate is inventory — and that is what this does
On June 22, 2026 the White House signed Executive Order 14412, “Securing the Nation Against Advanced Cryptographic Attacks”, turning post-quantum migration from guidance into mandate. OMB's binding execution memo, M-26-15, followed two days later: every agency owes a PQC Migration Plan within 120 days — roughly October 22, 2026 — and the memo names its first phase (2026–2027) explicitly as inventorying cryptographic systems. You cannot write that plan, or the two migration schedules under it, without first knowing what cryptography you actually have. That inventory is the gap this product fills.
The deadline is administrative; the risk is not. Harvest now, decrypt later means traffic captured today is decrypted the day a cryptographically relevant quantum computer arrives, so the exposure window opened years before any deadline and closes only when the affected key exchange is replaced. Anything protecting data with a lifetime past 2030 is already exposed, which is why the mandate starts with inventory: you cannot prioritise what you have not found.
Not a government-only deadline. The order directs the first proposed contractor FAR rule within 180 days, so anyone selling to the federal government inherits the requirement through procurement — and passes it to their own suppliers. That is the usual path: federal cryptographic deadlines have generally become the commercial baseline once they reach contracts and audits, the way NIST's deprecation dates for SHA-1 and RSA-1024 ended up enforced for everyone by CAs, browsers and auditors rather than by statute. Whether or not you sell to an agency, the schedule your customers, insurers and auditors will use is being set now — and it starts with an inventory.
The order's other clocks sit around that: agency PQC migration leads within 30 days; the first proposed contractor FAR rule within 180 days; NIST revising the Cryptographic Module Validation Program within 180 days to accelerate PQC module validations; and — the part aimed squarely at tooling — CISA/NIST guidance within 270 days defining the minimum elements of a Cryptographic Bill of Materials, which must "enable the automated assessment of the cryptographic assets utilized by a hardware or software element." Scope is federal high-value assets and high-impact systems, with contractors required to meet post-quantum FIPS by the end of 2030. Section 6 goes further still, directing OMB, the Department of War, NASA and GSA to establish "shared procurement of PQC tools" — the order does not merely permit agencies to buy cryptographic discovery tooling, it organizes how they will buy it.
Requirement by requirement
The Discovery Agent and its CBOM export were built for exactly that shape of obligation: discover the estate, classify what's quantum-vulnerable and who can fix it, and emit the evidence in a format a machine — not just an auditor — can assess.
| Executive order requirement | How this product answers it |
|---|---|
| Cryptographic system inventory — phase one (2026–2027) of OMB memo M-26-15 (June 24, 2026), feeding the PQC Migration Plan every agency owes OMB by ~October 22, 2026 | Eight-source discovery — filesystem certs/keys, the native OS certificate store (Windows CryptoAPI / macOS Keychain), SSH, live TLS, database columns, F5/NetScaler stores, keystores, source code — with hosting-device attribution, so every asset maps to the system it actually serves. This is the phase agencies are in right now. |
| CBOM minimum elements enabling automated assessment (CISA/NIST guidance, 270 days) | CycloneDX 1.6 export validating with zero errors against the official schema. The quantum verdict is machine-reachable through spec-standard fields alone: the dependencies graph links every certificate and key to a shared algorithm component carrying primitive and nistQuantumSecurityLevel. No vendor-specific knowledge needed to assess it. |
| Post-quantum key establishment by Dec 31, 2030 | Quantum-vulnerable assets in the pke / key-agree / kem primitive classes enumerate this workload directly from the exported document. |
| Post-quantum digital signatures by Dec 31, 2031 | The same query on the signature primitive class yields the second workload — the EO's two deadlines fall out of the CBOM mechanically. |
| Contractor post-quantum FIPS compliance evidence (FAR rule, 180 days) | A filter-scoped CBOM with a stable serial number and incrementing version per scope is the handover artifact; remediation-ownership classification separates what a contractor can act on from what waits on a CA, OS, or hardware vendor. |
| "Shared procurement of PQC tools" (Sec. 6: OMB, Department of War, NASA, GSA) with CMVP validation acceleration (NIST, 180 days) | This is the order inviting exactly this product category. The discovery inventory and machine-assessable CBOM are the evidence stream a shared-procurement vehicle evaluates, and because every asset is classified by algorithm and primitive, the inventory shows precisely which assets each newly CMVP-validated PQC module replaces as accelerated validations land. |
Stated plainly, because credible alignment includes its bounds: the CISA/NIST minimum-element guidance itself is not yet published (due ~March 2027), so conformance today targets CycloneDX 1.6 — the only widely adopted CBOM format and the one that guidance is expected to reference. Anything the final guidance names beyond the spec's fields is already carried in the export's namespaced properties and can be promoted without a schema change. And ECC assets are classified as key-agreement, so ECDSA signing certificates land in the 2030 rather than the 2031 bucket — both classes are equally quantum-vulnerable, so migration urgency is unaffected.
Three Products in One
"Discovery agent" undersells it. One binary, one scan, three genuinely distinct capabilities — most vendors sell these as separate products.
Cryptographic Asset Discovery
Finds the certificates, keys, and keystores across every discovery surface you configure and the agent can reach: filesystem, SSH, live TLS endpoints, database columns, native OS certificate stores, and F5/NetScaler appliances. Each run reports which of those surfaces it assessed and any location it was refused, so the inventory arrives with its own scope attached — the part most vendors call the whole product.
Cryptographic Bill of Materials (CBOM)
Scans your own application source across 20+ languages for calls into deprecated crypto (MD5, SHA-1, DES, RC4, ECB, undersized RSA) — the class of finding a certificate inventory can never see, because it's not a file at rest, it's a line of code.
Post-Quantum Migration Manager
Classifies every asset by real NIST OIDs, assigns remediation ownership (yours to fix vs. waiting on a vendor), tracks expiration and issue-date lifecycle, and surfaces exactly what's actionable right now — turning an inventory into an actual migration plan.
Quick Start
Real, working downloads — no account or API key required to get the binary. For the full walkthrough — every run mode, the complete configuration reference, appliance scanning, offline mode, and troubleshooting — see the Complete Guide →
curl -sSL https://api.pqcrypta.com/stream/downloads/discovery-agent/install.sh | bash
๐ Not blind curl | bash. The installer fails closed: it verifies the binary's Ed25519 signature (key pinned in the script) and SHA-256 checksum before making it executable. Every release is hybrid-signed — classical Ed25519 and post-quantum ML-DSA-65 (NIST FIPS 204), both over a signed SHA256SUMS manifest and verifiable entirely offline (no CA). We sign our own supply chain with the same hybrid transition we recommend to you. Full verification steps: Verify Your Download →
# Linux x86_64 (~30.2 MB)
curl -o pqcrypta-discovery https://api.pqcrypta.com/stream/downloads/discovery-agent/linux
# Windows x86_64 (~18.0 MB)
# https://api.pqcrypta.com/stream/downloads/discovery-agent/windows
# macOS Apple Silicon / arm64 (~18.9 MB)
curl -o pqcrypta-discovery https://api.pqcrypta.com/stream/downloads/discovery-agent/macos
# macOS Intel / x86_64 (~19.9 MB)
# curl -o pqcrypta-discovery https://api.pqcrypta.com/stream/downloads/discovery-agent/macos-intel
chmod +x pqcrypta-discovery
./pqcrypta-discovery \
--api-url https://api.pqcrypta.com \
--api-key YOUR_API_KEY \
--deep-scan
What It Captures
Certificates & Keys
X.509 certificates (PEM, DER, CRT, CER) and private/public keys (RSA, ECC, Ed25519), including full certificate chains and bundles.
Full X.509 Parsing Depth
Not just algorithm and expiry — Subject Alternative Names, key usage/extended key usage, CRL distribution points, OCSP URLs, policy OIDs, authority/subject key identifiers, and certificate hierarchy (root/intermediate/leaf, CA flag, self-signed detection). The reported algorithm, key size and curve come from the certificate's SubjectPublicKeyInfo — the key the subject actually holds — not from its signature algorithm, which describes the issuer: an ECDSA P-384 intermediate signed by an RSA root is P-384, not RSA. Fingerprints are SHA-256 over the complete DER certificate, so they match openssl x509 -fingerprint -sha256, your browser's certificate viewer, and Certificate Transparency exactly.
SSH Keys
Host and user keys in the openssh-key-v1 binary format, plus authorized_keys and known_hosts — detected even without a matching file extension.
Live Network TLS
A real TLS handshake against any configured host:port, inspecting whatever certificate is actually being served right now — not just what's sitting in a file. Each endpoint is then attributed to the device that actually hosts it (not the machine that ran the scan) by two signals: the endpoint's DNS records matched against every known device's IPs, and — when DNS can't decide, as with a VIP or TLS passthrough — the unique device holding the byte-identical certificate on disk by SHA-256 fingerprint. When the hosting device has been filesystem-scanned, the same fingerprint join goes one step further and reports the certificate's exact on-disk file path(s) on that device: "served by pqcrypta.com" becomes "lives in /etc/pqcrypta/certs/fated.org.crt".
Database Columns
Samples real values from columns matching cert/key/pem naming patterns and parses them — structural metadata only, the raw value is never stored.
F5 & NetScaler
Queries F5 BIG-IP's iControl REST and Citrix NetScaler's NITRO API directly, surfacing the full appliance certificate store — including certs not currently bound to a live VIP.
CBOM: Weak Crypto in Code
Scans application source across 20+ languages — Rust, PHP, Python, JS/TS, Go, Java, Ruby, C/C++, the .NET family (C#/VB.NET/F#/PowerShell), JVM family (Kotlin/Scala/Groovy), Apple family (Swift/Objective-C), Perl, Shell, Dart, SQL, Elixir, Erlang, Clojure — for calls into MD5, SHA-1, DES/3DES, RC4, AES-ECB, and undersized RSA key generation, using each ecosystem's real idioms, not just its file extension.
Keystore Analysis
Detects JKS, JCEKS, PKCS#12, BKS/UBER, Oracle Wallet, and NSS databases (cert9.db, key4.db) by magic bytes/extension — plus two specializations: a PKCS#12 file named .pfx is labeled Windows PFX, and a JKS/BKS under a .android directory or named debug.keystore/release.keystore is labeled Android KeyStore. Containers are opened and parsed: JKS/JCEKS certificate chains read without a password (the store password only protects private-key bytes and the integrity digest); NSS cert9.db certificates are read directly from its SQLite schema (they're stored in the clear — only key4.db's private keys are encrypted); and PKCS#12/PFX are tried with the well-known defaults (empty / changeit / password). Every certificate inside becomes its own inventory asset at store-path#alias, pointing back to the keystore that holds it. For containers protected by a non-default password, you can supply your own password list — inline in the config, from a separate secrets file, an env var, or the stdout of a command you specify (e.g. vault kv get, aws secretsmanager get-secret-value, op read) so any secrets manager works with no bespoke integration. Passwords are tried locally, first-match-wins with no need to map them to specific stores (a local keystore has no lockout), and never leave the machine — only the certificate metadata inside is reported. BKS/UBER entry formats aren't parsed yet.
Crypto Libraries Inside Binaries
Reads the version banner a crypto library compiles into itself, so the TLS stack inside a closed-source vendor binary is identified with no source, no symbols and no package manager — statically linked or not. Recognises OpenSSL, LibreSSL, BoringSSL, GnuTLS, Libgcrypt, mbedTLS, wolfSSL, NSS and libsodium across ELF, PE and Mach-O. This is a question the host cannot answer about itself: openssl version reports the command-line tool, routinely not the library your applications load, and ldconfig proves only that a library exists somewhere — no version, no link to the binary using it. Findings are graded on post-quantum capability rather than scored as algorithms: OpenSSL 3.5+ ships ML-KEM/ML-DSA/SLH-DSA and is compliant, 3.0–3.4 is supported but cannot negotiate PQC, and the out-of-support 1.1.1 series is critical. Detection is by embedded banner, so a stripped, renamed or packed binary can still hide one — a finding is evidence of presence, never proof of absence.
PQC Readiness
Classifies every asset against real NIST OIDs for ML-KEM, ML-DSA, SLH-DSA, and HQC, alongside legacy RSA/ECC and forbidden broken primitives.
OS & Security Metadata
TPM presence, Secure Boot state, CPU crypto extensions (AES-NI/AVX2/SHA-NI), virtualization/container detection, and network interfaces — per host.
Platform Support
- x86_64 prebuilt binary, ready to download
- OS trust stores, systemd services, containers
- /proc-based CPU/memory/virtualization detection
- SELinux, AppArmor, and firewall status
- x86_64 prebuilt binary, ready to download
- IIS, Exchange, MSSQL, AD CS/ADFS filesystem locations (see Scan Coverage below)
- Native Windows Certificate Store scanning via CryptoAPI (MY/Root/CA/TrustedPublisher, LocalMachine + CurrentUser)
- Native admin/elevation detection
- Apple Silicon (arm64) prebuilt binary, built on real Apple hardware via CI
- Intel Mac (x86_64) prebuilt binary, also built on real Apple hardware via CI
- Native macOS Keychain scanning via Keychain Services (System + login keychain)
- FreeBSD, OpenBSD, NetBSD: build from source (no prebuilt binary)
- Dedicated default path set — Heimdal Kerberos, ports-tree OpenSSL layout, BSD mail/VPN conventions
Comprehensive Scan Coverage
The built-in per-OS defaults (used when you run with no --config) cover these categories out of the box — each a real, tested path pattern, not aspirational. Every one of these paths lives in the downloadable reference-{linux,windows,macos}.toml config, so you can trim this list down or extend it: run with --config and your file's scan_paths are exactly what gets scanned.
Private keys that are not TLS certificates, and so are missed entirely by a scan that looks only for certs. Added 2026-08-16 after auditing the catalog against a taxonomy of where crypto material actually lives.
- DNSSEC zone signing: /etc/bind/, /var/lib/bind/, /etc/unbound/, /etc/knot/, /etc/nsd/, /etc/powerdns/ — rotation is a KSK/ZSK rollover, not a reissue
- DKIM message signing: /etc/opendkim/, /etc/dkimkeys/, /etc/rspamd/, /var/lib/rspamd/dkim/ — rspamd keeps its own set, separate from opendkim, and a mail server can run either
- Internal CAs: FreeIPA (/etc/ipa/), Dogtag (/var/lib/pki/), certmonger, step-ca, cfssl, easy-rsa, /etc/pki/CA/ — a CA's own key bounds what every certificate it ever issued can be
- Cluster PKI: k3s (/var/lib/rancher/k3s/server/tls/), microk8s, etcd, calico, cilium, and corosync's authkey
- Virtualisation: libvirt, Proxmox (/etc/pve/), Ceph, GlusterFS, DRBD, Xen
- Directory & 802.1X: SSSD, Samba AD (/var/lib/samba/private/), FreeRADIUS, hostapd, wpa_supplicant
- Overlay networks: Tailscale, ZeroTier, Nebula, NetBird, tinc, SoftEther node identities
- Platform credentials: systemd's credential store (/etc/credstore/, /etc/credstore.encrypted/) and cloud guest agents (waagent, AWS SSM, cloud-init — inventoried, but classified as vendor-rotated, not as work for you)
- SSO signing: Keycloak, Shibboleth, SimpleSAMLphp — a SAML signing key authenticates every assertion the IdP issues
- Also added: Caddy (which obtains real ACME certs into a data directory nobody configured), squid, stunnel, Cassandra, ClickHouse, Neo4j, NATS, Pulsar, Mosquitto, EMQX, Bacula/Bareos, Zabbix, Icinga, Wazuh, Beats, Telegraf, Vector
- Debian/Ubuntu: /etc/ssl/, /usr/share/ca-certificates/
- RHEL/CentOS/Fedora/SUSE: /etc/pki/
- Reverse proxy ACME certs: /etc/letsencrypt/archive/ (real bytes; live/ is symlinks only, and the walker doesn't follow symlinks)
- Windows: AD CS enrollment paths, ADFS config, Group Policy distributed roots,
ProgramData\Microsoft\Crypto\and per-user crypto directories, Symantec/McAfee trust stores - macOS: system root/CA Keychains, login Keychain, CloudKit Keychain (read as files on disk)
Everything above is filesystem-path scanning — it only sees what's sitting in a loose file on disk. That misses certificates installed via MMC, Group Policy, or an app that calls the store API directly with no backing file. These two scans query the real, structured store instead, and feed whatever they find through the same certificate parser used for on-disk files (subject, issuer, algorithm, SANs, key usage, CRL/OCSP, everything).
- Windows Certificate Store: queries CryptoAPI directly (
CertOpenStore/CertEnumCertificatesInStore) across theMY,Root,CA, andTrustedPublisherstores, in bothLocalMachineandCurrentUser— the same stores you'd browse incertmgr.msc. Runs automatically on Windows, no configuration needed. - macOS Keychain: reads the System keychain and the current user's login keychain via
security find-certificate(Apple's own Keychain Services front-end). Runs automatically on macOS, no configuration needed.
- Apache: /etc/apache2/ssl/, /etc/httpd/ssl/
- Nginx: /etc/nginx/ssl/, /etc/nginx/certs/
- HAProxy: /etc/haproxy/certs/, /etc/haproxy/ssl/
- Traefik: /etc/traefik/certs/
- Envoy: /etc/envoy/certs/
- IIS (Windows):
C:\inetpub\ssl\, IIS Express dev config, config history/backups
- OpenSSH host keys: /etc/ssh/ (openssh-key-v1 format, always cleartext public key section even when the private key is passphrase-protected)
- OpenSSH user keys: ~/.ssh/ — scanned regardless of file extension when the parent directory is named .ssh or ssh
- authorized_keys / known_hosts: each valid line becomes its own asset
- WireGuard: /etc/wireguard/
- OpenVPN / StrongSwan / IPsec: /etc/openvpn/, /etc/ipsec.d/, /etc/strongswan/
- Windows: Remote Desktop Gateway / Network Policy Server certificate directories
- Postfix: /etc/postfix/
- Dovecot: /etc/dovecot/
- Exim: /etc/exim4/
- Exchange Server (Windows):
Program Files\Microsoft\Exchange Server\, includingV15\ClientAccess\ - Mail.app (macOS): per-user Mail library directory
- PostgreSQL: /etc/postgresql/, /var/lib/postgresql/ (TLS config files) — plus optional live column scanning via
database_connections - MySQL/MariaDB: /etc/mysql/, /var/lib/mysql/
- Redis: /etc/redis/
- SQL Server (Windows):
Program Files\Microsoft SQL Server\,ProgramData\Microsoft\Microsoft SQL Server\ - Also attempted: Oracle Wallet, CouchDB, IBM DB2
- Column scanning samples up to 25 rows per matching column and at most 64 KB of any single value, parses real values, and discards the raw value before submission — only structural metadata (algorithm, key size, expiry) is kept.
- Metrics/observability: Prometheus, Grafana, Elasticsearch, Kibana, Logstash
- Containers: Docker, Podman, LXD registry/certs.d directories
- Kubernetes: /etc/kubernetes/pki/, kubelet PKI, mounted service-account secrets (
/var/run/secrets/) - Service mesh: Istio sidecar certs, Linkerd identity/TLS directories
- Service discovery: etcd, ZooKeeper TLS
- Vault: /opt/vault/tls/, /etc/vault.d/certs/
- Consul / Nomad: /etc/consul.d/certs/, /etc/nomad.d/certs/
- PKCS#11 / HSM: SoftHSM, generic /usr/lib/pkcs11/, vendor HSM libraries
- GnuPG: system and per-user keyrings
- Messaging: RabbitMQ, Kafka, ActiveMQ, ZeroMQ
- Directory/auth: OpenLDAP, 389 Directory Server, MIT Kerberos, Heimdal Kerberos
- ERP/CRM: SAP PSE files, Oracle Fusion Middleware, PeopleSoft
- CI/CD: Jenkins, GitLab Runner
- Config management: Puppet, Chef, SaltStack; Windows Intune, SCCM/Configuration Manager, WSUS
- Cert automation: generic ACME clients, Lego, Kubernetes cert-manager
- Virtualization: libvirt/KVM, Hyper-V & Failover Clustering
- MDM (macOS): configuration profiles, device management certificates
- Xcode (macOS): provisioning profiles, Safari dev certs
- Cloud/dev CLI credentials (same directories on Linux, macOS, and Windows): AWS, Azure, Google Cloud, Kubernetes, Docker, NuGet, plus ASP.NET/Visual Studio dev certs on Windows
F5 and NetScaler have real, verified management-API integrations (see below). Other appliances — pfSense/OpenWRT, Juniper SRX, Cisco ASA/Firepower, Aruba/HP, Check Point, A10 Networks — only get best-effort filesystem path attempts (in case the agent ever runs on a device with a compatible filesystem, or against a cached config export); there's no verified API integration for those yet.
F5 BIG-IP and Citrix NetScaler are closed appliances — the agent can't run on them the way it does on a Linux or Windows host. Instead it queries each device's own management API remotely:
- F5 BIG-IP: iControl REST —
GET /mgmt/tm/sys/file/ssl-cert(name, subject, issuer, expiration, serial, key size, key type, fingerprint), HTTP Basic Auth - Citrix NetScaler / ADC: NITRO API —
GET /nitro/v1/config/sslcertkey(certkey, subject, issuer, serial, public key size, signature algorithm, days to expiration), HTTP Basic Auth - Configured via
appliance_targetsin the config file with the device's management URL and read-only credentials (F5 Auditor / NetScaler read-only roles are sufficient) - Surfaces the entire certificate store, including spare/staged certs not currently bound to a live virtual server — something live network scanning of the VIP can't see
- Cert bindings, resolved: for every certificate the agent records which virtual servers actually serve it (F5 client-ssl/server-ssl profiles → virtuals; NetScaler SSL vserver bindings), or flags it as an unbound spare — so you can tell a live cert from a forgotten one at a glance, and filter or export by it
- Device facts too, not just certs: software version (
sys/version/nsversion), platform and Virtual-Edition detection, CPU/memory, management IP, traffic self-IPs, and interfaces with MAC addresses — so each appliance appears as its own first-class device in the Compliance Dashboard, with its own device filter, system-details view, and per-appliance drill-down - Factory certificates the vendor ships on the device (F5's ca-bundle/f5-irule/default, NetScaler's ns-server-certificate) are automatically classified as hardware vendor remediation; certificates your organization installed classify as internal — yours to rotate
Measured Performance
Real numbers from real machines, not estimates. Every figure below was measured on v1.0.45 — the same binary published on this page — using /usr/bin/time -v on Linux and polled process counters on Windows. Linux rows are the median of three runs; Windows is a single run of each mode. Your numbers will differ with disk speed and how much of the filesystem your scan_paths cover, so treat these as the shape of the cost rather than a guarantee.
Cost on the scanned host
| Host | Cores / RAM | Assets | Mode | Wall clock | CPU time | Peak memory |
|---|---|---|---|---|---|---|
| Mail server (Ubuntu 26.04) | 2 / 1 GB | 339 | online | 3.5 s | 0.7 s | 32 MB |
| 339 | offline bundle | 1.4 s | 0.7 s | 35 MB | ||
| Web server (Ubuntu 26.04) | 12 / 23 GB | 864 | online | 10.9 s | 5.1 s | 107 MB |
| 864 | offline bundle | 5.8 s | 5.2 s | 109 MB | ||
| Home server (Ubuntu 25.10) | 8 / 12 GB | 584 | online | 12.1 s | 6.9 s | 134 MB |
| 584 | offline bundle | 8.6 s | 6.7 s | 134 MB | ||
| Web server (Ubuntu 24.04) | 4 / 7 GB | 2,047 | online | 58.3 s | 15.3 s | 81 MB |
| 2,047 | offline bundle | 43.5 s | 13.9 s | 108 MB | ||
| Desktop (Windows 11 Pro 24H2) | 12 / 32 GB | 6,479 | online | 12 min 29 s | 7 min 33 s | 129 MB |
| 6,479 | offline bundle | 12 min 9 s | 7 min 54 s | 165 MB |
- It fits on a 1 GB VM. Peak memory tracks the largest single artifact parsed, not the number of assets — the 339-asset mail server used 32 MB, and the 6,479-asset desktop used 129 MB.
- Most of the wall clock is I/O, not CPU. The 2,047-asset scan spent 58 s wall for 15 s of CPU: about a quarter of one core on a 4-core box, with the rest waiting on the filesystem.
- The offline bundle is not slower. It does strictly more work — compliance scoring, CycloneDX CBOM, a self-contained HTML report — yet finishes sooner, because it never waits on API round trips.
- Windows costs far more per asset — roughly 70 ms of CPU each against 7 ms on Linux. It walks the native CryptoAPI stores, a deep
Program Filestree and thousands of DLLs for the compiled-in crypto library surface. Budget minutes on Windows, seconds on a Linux server.
Cost on an agentless appliance
Agentless means nothing is installed on the device — not that the device does no work. It still authenticates, enumerates its certificate store and serialises the reply, so both sides are measured: the scanning host, and the appliance itself. Appliance CPU and memory were sampled every 0.5 s while idle and again throughout the scan; without the idle baseline a percentage means nothing.
| Appliance | Certs | On the appliance | On the scanning host | |||
|---|---|---|---|---|---|---|
| CPU (idle → scan) | Memory | Wall | CPU | Peak RSS | ||
| F5 BIG-IP 17.5.1 (iControl REST) | 9 | 12.0% → 14.4% avg, 18.0% peak | 88 MB, unchanged | 2.6 s | 0.13 s | 17 MB |
| Citrix NetScaler 14.1 (NITRO) | 7 | 1.0% → 1.5% avg and peak | 320 MB, unchanged | 1.4 s | 0.11 s | 17 MB |
| Both in one run | 16 | — | 2.9 s | 0.13 s | 17 MB | |
- The F5 saw about +2.4% average CPU for three seconds and no measurable memory change. The NetScaler stayed inside its own noise floor.
- The scanning host spends 0.13 s of CPU and 17 MB to inventory both devices, so appliance discovery can run from any host without deploying anything to the appliances.
- Honest caveat: these are lab appliances holding 9 and 7 certificates, and a scan short enough that only a handful of samples land inside it. A production device with hundreds of certificates does more work enumerating its store — the store walk is the part that scales, not the connection.
Air-Gap / Offline Mode
The agent runs a complete assessment entirely on-host, with zero network access โ no API key, no callback, nothing leaves the machine. One flag produces a self-contained bundle you carry out on removable media:
--offline-report ./assessment— scan, classify, and report locally in one step- report.html — a single self-contained compliance report (all styling inlined, no external requests) safe to open on an isolated host: post-quantum readiness, risk breakdown, remediation ownership, and the full inventory
- cbom.json — a CycloneDX 1.6 Cryptographic Bill of Materials
- inventory.json — every asset with full detail and its assessment
Post-quantum scoring, risk rating, remediation-ownership classification, and CBOM assembly are all computed on the agent — the same logic the platform runs server-side — so an air-gapped report is identical to an online one. There is no SaaS tether: the same single binary that scans a cloud host also runs unattended inside a classified enclave and hands back a complete, standards-based assessment. Verified by running under a network namespace with no interfaces at all.
Self-Hosted / On-Premises Platform
Three ways to run PQCrypta, so the deployment fits your data-sovereignty posture — not the other way around:
- Hosted (SaaS): agents submit to our dashboard with
--api-url. Nothing to operate. - Offline / air-gap: one binary, one flag, a complete on-host assessment — the mode above.
- Self-hosted platform: run the entire platform — API, PostgreSQL, and the Compliance Dashboard — inside your own network. Agents point at your API; no inventory, CBOM, or telemetry ever leaves your environment.
The self-hosted tier ships as a docker compose stack (database + API + dashboard) with a
connected installer and a fully air-gapped bundle — container images, schema, and
signed agent artifacts staged into a single tarball that installs on a disconnected host with zero
registry pulls. Point agents at it with nothing more than
--api-url http://your-host:3003; the dashboard, its CSP, and every download link follow the
same local base URL.
It runs behind a license that is post-quantum signed with ML-DSA (Dilithium3, NIST FIPS 204) and verified entirely offline at startup — no phone-home, so it works in classified enclaves. A tampered license fails closed; an expired one keeps you running in grace mode. It's the same hybrid post-quantum transition we sign our own supply chain with, applied to entitlement.
Appliance Lab Validation
The F5/NetScaler integration isn't tested against mocks — it's validated against a live, licensed F5 BIG-IP Virtual Edition 17.5 (TMOS) running on KVM, scanned exactly the way a customer would run it: agentlessly, from a separate jump host, over iControl REST, using a least-privilege Auditor-role account.
- Deliberate certificate matrix: RSA-2048, RSA-4096, ECDSA P-256, an already-expired certificate, and a spare certificate never bound to any virtual server — every one discovered with correct algorithm, key size, subject, and expiry
- The unbound-certificate claim, proven: the spare cert is invisible to live TLS scanning of the appliance's endpoints (nothing serves it), but the management-API inventory surfaces it — the core reason this scan mode exists
- Factory-vs-customer split verified: TMOS's shipped certificates (ca-bundle, f5-irule, default) classify as hardware-vendor remediation; every certificate we installed classifies as internal — yours to rotate
- Device facts cross-checked: the reported TMOS version, Virtual Edition platform, CPU/memory, management IP, and interface MACs all matched the known VM configuration exactly
- Operationally honest: re-scans are idempotent (no duplicate assets), one unreachable appliance never aborts the rest of the scan, and read-only credentials are sufficient end-to-end — including the TMOS quirk that newly created accounts start password-expired, which is documented in the setup guidance
- End-to-end, not endpoint-deep: the validated path runs appliance → agent → API → inventory → Compliance Dashboard → CycloneDX 1.6 CBOM export
The Citrix NetScaler/ADC integration is validated the same way, against live
NetScaler 14.1 firmware (NetScaler CPX) over the NITRO API: the same
certificate matrix, correct handling of NITRO's expired-certificate semantics (the true
not-after date is preserved even when daystoexpiration has hit zero), factory
certificates (ns-server-certificate, ns-sftrust-certificate)
classified as hardware-vendor remediation, and device facts — build version, platform,
management IP, interfaces — collected from the device's own
nsversion/nshardware/nsip endpoints.
CBOM: Weak Cryptography in Source Code
Every other scan type finds crypto material at rest — a cert file, a live TLS
endpoint, a database column. CBOM (Cryptographic Bill of Materials) is different in kind: it
looks for calls into known-weak cryptographic primitives inside your own application
source code. A codebase can have a spotless certificate inventory and still call
hashlib.md5() for something security-sensitive — nothing else in this tool
can see that.
Scope, stated plainly: this is known-weak call-site detection via pattern matching against real per-ecosystem API idioms — not full static analysis. It does not follow data flow, so a weak primitive reached through a wrapper function or a variable-selected cipher name is out of scope by design. That trade keeps findings high-confidence: what it flags is a literal call into a broken primitive at a specific file and line.
# Off by default. Point it at your source trees:
code_scan_paths = ["/opt/myapp/src", "/opt/myapp/internal"]
OS & Security Metadata Collection
Collected once per scan and attached to every submission — this is what powers the Discovered Systems page in the dashboard (security score, TPM/Secure Boot indicators, hardware).
Command Line Options
| Option | Description | Example |
|---|---|---|
-c, --config | Path to configuration file. When it exists, its scan_paths are authoritative; when absent, the built-in per-OS default set is used. Pair it with --with-defaults to scan both. | --config linux.toml |
--with-defaults | Scan the built-in per-OS catalog in addition to the paths in --config, de-duplicated. Without it a config file replaces the catalog outright — correct when the config is the scope, and a trap when it is a handful of site-specific paths, because adding three paths silently drops the other 256. The built-in exclusions and source-code paths merge too, so widening the walk does not send it through /proc and WinSxS. | --config mine.toml --with-defaults |
--api-url | API endpoint URL (env: PQCRYPTA_API_URL) | --api-url https://api.pqcrypta.com |
--api-key | API authentication key (env: PQCRYPTA_API_KEY) | --api-key YOUR_API_KEY |
-t, --targets | Scan targets: filesystem paths, database DSNs, or network hosts (repeatable). Overrides both config scan_paths and the built-in defaults. | -t /etc/ssl -t db.host:5432 |
--deep-scan | Enable deep scanning (raises directory recursion depth from 10 to 20 levels within the configured paths — it does not widen the path set) | --deep-scan |
--no-binary-scan | Skip the binary surface for this run — do not read executables and shared objects for the crypto library compiled into them. It is the only surface whose cost scales with how much software is installed rather than how much cryptography is deployed. Skipping is reported as a gap in coverage, never as a clean result. | --no-binary-scan |
--full-disk-scan | Whole-disk sweep: adds the filesystem root (C:\ on Windows, / elsewhere) to the scan targets on top of your config/default paths. Slow, but the built-in exclusions (/proc, /sys, /dev, temp dirs; WinSxS and Temp on Windows) still apply — if your config sets excluded_paths it replaces that list, so keep them in it. | --full-disk-scan |
--algorithms | Filter for specific algorithms (comma-separated) | --algorithms RSA,ECDSA |
-o, --output | Write results to a JSON file instead of submitting to the API | --output results.json |
--offline-report | Air-gap mode: produce a complete self-contained assessment in this directory (report.html + cbom.json + inventory.json) with zero network access — compliance/risk scoring, remediation ownership, and the CycloneDX 1.6 CBOM are all computed locally. No API key or URL required. | --offline-report ./assessment |
-v, --verbose | Verbose (debug-level) logging | --verbose |
Exactly one output mode is required per run: --api-url (submit to the dashboard), --output (raw JSON file), or --offline-report (air-gap bundle). Running with none of the three exits with Specify one of --api-url, --output, or --offline-report.
Configuration File
The agent is fully config-driven — there is no hidden hardcoded path list. Run it with --config yourfile.toml and that file's scan_paths are authoritative: the agent scans exactly what you list and nothing else. Run it with no --config and it falls back to a built-in per-OS default set — which is literally the same reference-{linux,windows,macos}.toml file you can download and edit (256 paths on Linux, 67 on Windows, 64 on macOS). There are three modes, not two: config alone replaces the catalog, no config uses the catalog, and --config … --with-defaults scans both. Keystores (.jks/.p12/.pfx/โฆ) are opened and their certificates inventoried wherever scan_paths point, so widening keystore coverage just means adding a path. Every field below is real and currently supported. Start from a ready-made preset in the dashboard's Download Discovery Agent section (role presets, or full per-OS catalogs with every path active) — all at /stream/downloads/discovery-agent/config/<name>.toml.
# API endpoint configuration
api_url = "https://api.pqcrypta.com"
api_key = "your-api-key-here"
# Filesystem paths to scan for certificates, keys, SSH keys, and keystores
# (.jks/.p12/.pfx found here are opened and their certs inventoried too).
# When this file is passed via --config, these paths are AUTHORITATIVE โ the
# agent scans exactly this list. ~, $VAR, ${VAR} and %VAR% are expanded.
# For the complete built-in set, start from reference-linux.toml (or the
# Windows/macOS catalogs) instead.
scan_paths = [
"/etc/ssl/certs",
"/etc/pki",
"/root/.ssh",
"/opt/tomcat/conf", # e.g. keystore.jks โ parsed into individual certs
]
# Enable deep scanning (slower but more thorough)
deep_scan = false
# Filter for specific algorithms (comma-separated). Leave empty/commented to scan
# for all algorithms.
# algorithms_filter = ["RSA", "ECC"]
# Read executables and shared objects for the crypto library compiled into them.
# On by default; the only surface that sees inside a closed-source vendor binary,
# and the only one whose cost scales with installed software rather than deployed
# cryptography. Set false where that budget does not exist โ coverage then reports
# it as not configured rather than clean.
binary_scan = true
# Paths to exclude from scanning. Your config is authoritative: listing this key
# replaces the built-in exclusions rather than adding to them, so keep the
# pseudo-filesystems if you override it. With NO config at all, the built-in
# catalog for the platform already excludes /proc, /sys, /dev, /run and the temp
# dirs (WinSxS, Temp and the recycle bin on Windows).
excluded_paths = ["/proc", "/sys", "/dev", "/run", "/tmp", "/var/tmp"]
# Source-code trees to scan for weak-crypto API calls (CBOM). Off by default.
code_scan_paths = []
# Keystore passwords for locked PKCS#12/PFX/JKS containers. The built-in defaults
# (empty / changeit / password) are always tried first; these are added after.
# There is no lockout on a local keystore, so the list is tried first-match-wins
# with no need to map a password to a specific store. Used LOCALLY only โ never
# submitted, never logged. Four sources, merged in order (all opt-in):
# keystore_passwords = ["s3cret", "corp-export-pw"] # inline
# keystore_passwords_file = "/etc/pqcrypta/keystore-pw.txt" # newline-separated file
# (env) PQCRYPTA_KEYSTORE_PASSWORDS="pw1\npw2" # environment variable
# keystore_passwords_command = "vault kv get -field=pw secret/keystores" # any secrets
# manager via its CLI โ aws secretsmanager get-secret-value, op read, gpg -d, etc.
# Database connections to scan (optional). Reads real column values matching
# %cert%/%key%/%pem% and parses them; never stores the raw value. Dispatch is by
# DSN scheme (postgres/mysql/sqlite/mssql/oracle all functional). Oracle needs
# Instant Client installed on the scanning host itself โ skipped gracefully if not.
# [[database_connections]]
# name = "Production PostgreSQL"
# db_type = "postgres"
# dsn = "postgres://user:password@localhost/dbname"
# [[database_connections]]
# name = "Legacy SQL Server"
# db_type = "mssql"
# dsn = "mssql://user:password@localhost:1433/dbname"
# [[database_connections]]
# name = "Oracle Prod"
# db_type = "oracle"
# dsn = "oracle://user:password@host:1521/ORCL"
database_connections = []
# Live network/TLS endpoints to inspect — reflects what's actually being
# served right now, not just files sitting in a cert store. STARTTLS ports
# (SMTP 25/587, IMAP 143, POP3 110) are upgraded automatically; implicit-TLS
# ports (443/465/993/995) handshake directly.
[[network_targets]]
host = "example.com"
port = 443
# F5 BIG-IP / Citrix NetScaler certificate stores, via management API.
# [[appliance_targets]]
# name = "F5 Prod LB"
# appliance_type = "f5" # or "netscaler"
# mgmt_url = "https://your-f5-mgmt-host"
# username = "readonly-api-user"
# password = "..."
# verify_tls = true
API Integration
/crypto-assets/scan/results
Submits discovered assets in batches, along with OS metadata (attached to the first batch only) and scan errors.
{
"scan_id": "550e8400-e29b-41d4-a716-446655440000",
"agent_hostname": "server-01.example.com",
"agent_version": "1.0.38",
"agent_platform": "linux",
"os_metadata": {
"os_name": "Ubuntu", "os_version": "24.04",
"tpm_available": true, "secure_boot_enabled": false,
"cpu_model": "AMD EPYC-Milan Processor", "cpu_cores": 4
},
"assets": [
{
"location": "/etc/ssl/certs/server.crt",
"location_type": "filesystem",
"asset_type": "certificate",
"algorithm": "RSA",
"key_size": 2048,
"subject_cn": "server.example.com",
"issuer_cn": "Let's Encrypt Authority X3",
"not_after": "2026-06-01T00:00:00Z",
"sha256_fingerprint": "..."
}
],
"scan_duration_ms": 45320,
"errors": [],
"batch_number": 1,
"total_batches": 12
}
batch_number/total_batches let the server run end-of-scan work — retiring assets this host no longer has — once the full inventory has arrived rather than against a half-submitted one. Both are optional; omit them and that sweep runs on every batch, which is still correct because re-reporting an asset reactivates it.
{
"success": true,
"message": "Stored 10 of 10 assets",
"assets_processed": 10,
"assets_compliant": 1,
"assets_legacy": 9,
"violations": [ /* one per non-compliant asset */ ]
}
assets_processed is the number of rows that actually landed in the inventory, not the number you submitted, and success is false when those differ. A rejected asset (a constraint violation, an oversized field) is reported back in message and recorded on the scan's error_message, so a partially-stored batch can never read as a clean success. Treat assets_processed < assets.len() as a gap in the inventory, not a warning.
/crypto-assets/report
Granular report/export of the asset inventory — the same endpoint the dashboard's Reports tab uses. Accepts the identical filter set as /crypto-assets/inventory (shared query builder, so a filter combination always selects the same rows in both), with no pagination: format=csv streams a spreadsheet-ready download, format=json returns {columns, assets, summary}. The summary block (assets, distinct hosting systems, internally-actionable vs. vendor-dependent split, PQC-compliant count, readiness %) is aggregated over the full filtered match with the same WHERE clause — it describes your selection, not the whole estate.
GET /crypto-assets/report
?remediation_owner=internal # any inventory filter: compliance_status,
&expires_after=2026-07-06T00:00:00Z # risk_level, asset_type, environment,
&discovered_by_hostname=web-01 # application, search, date bounds, device
&columns=device,location,hosted_on_hostname,hosted_at_locations,algorithm,valid_until,compliance_status
&group_by=device # orders rows by hosting device for sectioned output
&format=csv # csv | json (default csv)
&limit=10000 # row cap, max 50000 (json summary still counts the full match)
columns= selects any subset of the 33-column catalog (unknown names are rejected with the valid list) — including hosted_on_hostname, hosted_at_locations, and binding_targets (which virtual servers actually serve an appliance certificate, or "unbound spare"), so a live-TLS finding exports with the device that serves it and the certificate's on-disk path(s) there. The device filter and grouping attribute network assets to their DNS-correlated hosting device, never the scanner.
/stream/downloads/discovery-agent/{linux,windows,macos,install.sh})
— no API key required to get the tool, same reasoning as the public health-check endpoint.
Submitting scan results and generating reports do require a valid API key.
Compliance Assessment
Classification is based on the actual NIST-registered OIDs for post-quantum algorithms, not string matching.
Post-quantum, hybrid, or symmetric cryptography (symmetric ciphers are already post-quantum secure at sufficient key size — Grover's algorithm only halves their effective strength, unlike Shor's algorithm which fully breaks RSA/ECC/DH).
Classical algorithms, not yet broken but quantum-vulnerable.
Quantum-resistant, but predating the NIST standard it was superseded by. Round-3 CRYSTALS-Dilithium keys on the pre-FIPS OID arcs are not interoperable with FIPS 204 ML-DSA and are not CNSA 2.0 acceptable, so they still carry migration work — counting them as compliant would report an unfinished migration as done.
Broken or deprecated primitives — critical/high risk regardless of quantum threat.
A weak signature hash is judged separately from a weak key. MD2/MD5/SHA-1 in a certificate's signatureAlgorithm is Forbidden where the signature is actually verified during chain building — that is, on any certificate that is not self-signed. On a self-signed root it is recorded but not flagged: trust in a root comes from its presence in a trust store, never from verifying its own signature, which is why NIST SP 800-131A Rev. 2 and the CA/Browser Forum Baseline Requirements both scope the SHA-1 prohibition to verified signatures, and why several hundred SHA-1 self-signed roots legitimately ship in every OS trust store. Flagging those would bury the certificates where a weak signature genuinely is a finding.
Remediation Ownership
A flat inventory tells you what's wrong. Ownership classification tells you who can actually fix it — the difference between an inventory and a to-do list. Classification is layered: operator-defined location rules match first (first match by priority wins, editable without a deploy), then a semantic classifier reasons from what the asset is — holding a private key means the key material is yours; a certificate whose CN/SAN matches one of your own scanned domains is yours (or your public CA's, if one issued it); a locally-minted self-signed certificate is yours; a code-signing or timestamping certificate belongs to the software vendor that shipped it; and any other CA certificate is a trust anchor owned by the issuing CA. A final content-aware pass then corrects for what location alone cannot see: a copy of a public CA certificate is still the CA's wherever it sits on disk, so roots are matched by SHA-256 against the known trust anchors and intermediates by whether they chain to one. That pass only ever moves work off your list — it never marks something actionable that the earlier layers did not. Only what survives every layer lands in Unknown for human review.
You control the algorithm end-to-end — actionable now. Your own certs, internal CAs, mail/web server configs.
Renewal cadence is yours, but the signing algorithm depends on the CA (e.g. Let's Encrypt) offering PQC.
Bundled OS trust store (e.g. Ubuntu's ca-certificates package). Wait for a package update.
Bundled by a package manager — pip's certifi, Composer's ca-bundle, WordPress core. Update the package.
Firmware update authority CA. Wait for the device/firmware vendor.
Survived both the rule and semantic layers unclassified — e.g. personal certificate-store entries. Needs manual review.
Technical Stack
Use Cases
Post-Quantum Migration Planning
Find every legacy RSA/ECC asset, ranked by risk and grouped by who owns fixing it.
Load Balancer & ADC Audits
Inventory F5/NetScaler certificate stores without SSH/console access — management API only.
Application Security Review
Catch hardcoded MD5/DES/RC4 calls in your own codebase before an audit does.
Certificate Lifecycle Management
Track expirations across every host and appliance from one Urgent Migrations view.
Compliance Reporting
Compliant/Legacy/Forbidden breakdown, exportable, for auditors and stakeholders.
Multi-Host Fleet Visibility
Run the same agent across servers and workstations; filter the whole dashboard down to one device.
Using the Compliance Dashboard
Every scan submission lands here. The Compliance Dashboard is one page with everything scoped consistently — pick a device once, and every table on the page narrows to it.
Migration Status (Executive Summary)
One dynamic paragraph at the top of the page, computed fresh from live totals on every load — asset count, device count, how many are actionable by your org vs. dependent on a vendor, how many are already compliant, and the overall readiness percentage. Never hardcoded.
Device Filter
One dropdown at the top scopes the summary cards, breakdowns, Urgent Migrations, Asset Inventory, and Certificate Bundles to a single host. The redundant Device column disappears from every table while one is selected.
Summary Cards
Total Assets, Total Devices, Compliant, Legacy, Deprecated, Forbidden, Quantum Readiness (with a qualitative Early Stage/In Progress/Strong label, not just a bare percentage), Organization Controlled and Vendor Controlled (each broken down further into Completed/Progress vs. Already Compliant/Waiting on Ecosystem), Last Scan Duration, and a Discovery Coverage checklist. Most cards are clickable and jump to a pre-filtered Asset Inventory view.
Discovery Coverage
What the fleet's scans have found evidence of, unioned across every device in view — all nine discovery surfaces, not a subset. Filesystem, Live TLS, SSH and Keystores report found vs. not; Binaries, Database, Source Code (CBOM), Appliances (F5/NetScaler) and OS Trust Stores are multi-state: found real findings, scanned and genuinely clean, never configured, or not applicable on any platform in view (an OS trust store on an all-Linux fleet is not a gap you can close). A clean codebase and an unconfigured scan look identical if you only check "did we find anything," so this distinguishes them explicitly. The Last Scan Duration tile names the device it describes and covers the discovery phase (enumeration/parsing, not upload) — a Windows cert-store walk legitimately takes seconds while a Linux filesystem crawl takes minutes.
Certificate Lifecycle
Two breakdown tables — By Expiration (Expired, Next 30/90 Days, Next Year, Beyond) and By Age/Issued (under 1 year, 1–3, 3–5, 5+ years) — with every row clickable, jumping straight to Asset Inventory filtered to exactly that date range.
Honest Color Coding
Vendor-blocked assets render in neutral gray, not the same alarm red/orange used for assets your organization can actually act on right now — so a large vendor-blocked count (waiting on an OS vendor or public CA) doesn't read as an equally large number of active fires.
By Remediation Owner / By Algorithm
Aggregate breakdowns answering "what's actionable" and "what algorithms are we actually running," each with a plain-language what-to-do note.
Urgent Migrations
Critical/high-risk actionable assets and anything expiring within 90 days — vendor-blocked assets are excluded regardless of risk level, since there's nothing to action until the vendor ships an update. Filterable by algorithm and risk level, sortable, with the device that actually hosts each finding — a live-TLS cert points at the box serving it, never at whichever agent happened to scan the URL.
Asset Inventory
The full list, searchable across location, hostname, owner, application, algorithm, and subject/issuer fields in one box — plus dropdown filters for asset type, algorithm, compliance status, risk, ownership, and expiration status (Expired / Active / Expiring in 30 or 90 Days). Certificates show both Created and Expires columns, sortable. Live-TLS rows expand into a Hosted On section: the hosting device plus the certificate's exact on-disk file path(s) there — and when attribution isn't possible yet, an actionable prompt saying what to scan: run the agent on the hosting machine, or register an F5/NetScaler/proxy TLS terminator as an appliance_targets entry so its certificate store can be inventoried and matched.
Certificate Bundles
Groups CA bundle files (composer's ca-bundle.pem, pip's certifi, WordPress's ca-bundle.crt) by path and device, so a 148-certificate bundle shows as one row, not 148.
Report Builder (Reports Tab)
A dedicated Reports tab generates exports on exactly the data you need — combine any filters (device, compliance status, risk, remediation owner, expiration presets including "not expired", asset type, free-text search), pick any of 30+ columns per row (including Hosted On and the on-disk locations of live-TLS certificates), and output flat or grouped by device. Three formats: a print-ready PDF report (letterhead, applied-criteria table, on-screen collapsible device groups that auto-expand when printing so nothing is missing from the saved file), CSV for spreadsheets, and JSON for automation. The optional executive summary is include/excludable and computed with the same WHERE clause as the report rows — filter to internal-owner-only and the narrative describes that slice (assets, systems, actionable vs. vendor-dependent split, readiness %), not the whole estate. Filters share the exact query semantics of the Asset Inventory, so identical criteria always select identical assets in both views.
CBOM Export (CycloneDX 1.6)
One click on the Reports tab exports the inventory as a standards-conformant Cryptographic Bill of Materials in CycloneDX 1.6 JSON — the format CISA/NIST guidance and the June 2026 Executive Order "Securing the Nation Against Advanced Cryptographic Attacks" point to, whose CBOM minimum-element guidance requires enabling automated assessment of cryptographic assets. "Standards-conformant" is not a slogan here: full-scale exports (9,000+ real assets) validate with zero errors against the official CycloneDX 1.6 JSON schema. Every discovered asset becomes a cryptographic-asset component: certificates carry certificateProperties (subject, issuer, validity window — the X.509 serial rides as a namespaced property, the 1.6 schema has no field for it), keys become relatedCryptoMaterialProperties with an algorithmRef and key size, and each distinct algorithm + parameter set is a shared algorithm component (kem / signature / pke / key-agree / hash) that certificates and keys link to through the BOM's dependencies graph. Algorithm components carry a real nistQuantumSecurityLevel — 0 for quantum-vulnerable (RSA, ECC, DSA, finite-field DH), the NIST PQC category (1–5) for recognized post-quantum parameter sets. Because primitives are classified, the EO's two migration workloads fall out mechanically: key establishment (pke / key-agree / kem, deadline 2030) and digital signatures (deadline 2031). PQCrypta-specific context (location, hosting device, remediation owner, risk, compliance) rides along as namespaced properties so nothing from the inventory is lost. Re-exporting the same scope keeps the same BOM serialNumber with an incrementing version — quarterly re-attestations diff as revisions of one document, not unrelated files — and an export that hits the 50,000-asset cap says so explicitly (metadata property + dashboard warning) rather than silently dropping rows. Honors the same report filters, so you can emit a CBOM scoped to one device, one asset type, or your whole estate — ready to hand to an auditor or ingest into a downstream toolchain.
Discovered Systems
Per-host OS/security metadata — TPM, Secure Boot, disk encryption, CPU, memory. The Security Score isn't a bare number: hover it (or any per-system score in the table) for a full point-by-point breakdown. All platforms: TPM +20, Secure Boot +20, Disk Encryption +15 (BitLocker/LUKS/FileVault), active firewall +10, AES-NI +5, AVX2 +5. Linux adds SELinux enforcing +20/permissive +10 and AppArmor +20; Windows adds real-time antivirus +10 and UAC +5; macOS adds SIP +10 and Gatekeeper +5. Each score displays against its platform's own applicable max (Linux 115, Windows/macOS 90), and checks an older agent never assessed are excluded from that system's max rather than counted as failed. Plus the agent download page, ready-made config presets, and full per-OS option references.
Three ways to run it, and none of them are mandatory
“We cannot send our cryptographic inventory to a third party” is a reasonable position, and it is not one you have to argue us out of. Pick the row that matches your constraint — the agent and the assessment are identical in all three.
| Model | Where findings go | What it suits |
|---|---|---|
| Hosted | Agent → our API → your dashboard | Estates that are happy with a SaaS collector and want history, trending and estate-wide CBOM with nothing to operate. |
| Offline | Agent → three files on the host. Nothing else, ever. | Air gaps, classified and CUI environments, OT networks, data residency, vendor-risk work, anywhere a credential must not be left behind. The air-gap guide. |
| Self-hosted | Agents → your API → your PostgreSQL → your dashboard | You want the whole platform — history, trending, estate-wide view — with no data leaving your network. Ships as an air-gap installable bundle; the licence verifies offline and never calls home. |
Security Characteristics
Read-Only Operation
The agent never modifies or deletes files, database rows, or appliance configuration. Pure discovery, safe for production.
No Raw Secrets From Databases
Database column values are parsed for structural metadata, then discarded — the raw value is never submitted or stored.
Secure Communication
HTTPS/TLS for all API communication and appliance management-API calls; API key authentication for scan submission.
Memory Safety
Written in Rust, eliminating broad classes of memory-safety defects — use-after-free, buffer overflows, data races — in safe Rust code. It is not a claim that the agent has no vulnerabilities.
Database Safety Profile
Column scanning is the one capability a DBA is entitled to interrogate before allowing it near a production instance, so here is the whole of it. Every row below is a property of the code, not an intention.
| Property | Guarantee |
|---|---|
| Statements issued | SELECT only. There is no INSERT,
UPDATE, DELETE, CREATE,
ALTER, DROP or TRUNCATE
anywhere in the scanner — the only write statements in the
source are inside the test module, against throwaway fixtures. |
| Schema changes | None. No temporary tables, no stored procedures, no session state beyond the statement timeout it sets on itself. |
| Discovery scope | Reads the catalog (information_schema, or
all_tab_columns on Oracle) for columns whose
name matches cert/key/PEM patterns. Capped at 100
columns per connection (200 tables on SQLite). Every schema the
connecting role can see is in scope, not only its default one
— sample queries name the schema explicitly, so a
certificate in an application schema is found when the agent
connects as an administrator. Narrow it with
excluded_tables, or with a read-only role that
can only see the schemas you intend to scan. |
| Sampling | At most 25 rows per matching column, via
LIMIT / TOP / ROWNUM
depending on engine, and at most 64 KB from any
single value (4 KB on Oracle, where
SUBSTR in a SQL statement returns
VARCHAR2). The truncation is done by the database,
in LEFT / SUBSTRING /
SUBSTR, so the rest of a large value is never sent
over the connection at all. A certificate or key is far smaller
than either bound; a multi-megabyte blob that happens to sit in
a column called cert_data is cut off and simply
does not parse. |
| Column types read | Text and binary types only, by name and type:
text/varchar/char everywhere, plus
bytea (PostgreSQL), blob/longblob
(MySQL), varbinary (SQL Server),
CLOB/NCLOB/RAW/LONG (Oracle). Numeric, date and
unmatched columns are never selected. |
| Query timeout | query_timeout_secs, default 30,
0 disables, and it now covers every engine.
PostgreSQL, MySQL and MariaDB are capped twice — client-side
on each query and server-side via statement_timeout,
max_execution_time and
max_statement_time respectively. SQL Server has no
server-side equivalent to set from a session, so the client-side
cap is the whole control there. Oracle is capped on the connection
with call_timeout, because ODPI-C is a blocking
library and abandoning the caller would leave the query running on
your instance. The budget is per query, not per scan. |
| Raw values | Parsed in memory and discarded. Only structural metadata leaves the parser — algorithm, key size, expiry, fingerprint. The value itself is never stored, never submitted, and never written to the offline bundle. |
| Permissions required | Catalog read plus SELECT on the candidate tables. A
dedicated read-only role is sufficient and is what we recommend;
nothing needs DDL or an owner role. Oracle's own dictionary schemas
(SYS, SYSTEM, XDB and the
rest) are excluded from discovery outright, so a certificate stored
in one of those is deliberately not inventoried. |
| Encrypted columns | Read exactly as the connecting role sees them. Where the engine decrypts transparently for that role, the agent sees plaintext and parses it like any other value; where it does not, the ciphertext simply fails to parse and no asset is recorded. |
| Excludable | excluded_tables and excluded_columns
per connection, applied before any sample query runs.
A table entry may be bare (secrets, excluded in
every schema) or schema-qualified
(app.secrets, excluding only that copy);
column entries are bare names and match wherever that column
appears. All matching is case-insensitive. |
The honest caveat about load
The sample query is
SELECT LEFT(col, 65536) FROM schema.tbl WHERE col IS NOT NULL LIMIT
25. That is bounded in rows returned and in bytes
returned, but not in work done: on a large
table whose matching column is mostly NULL and unindexed, the engine may
scan a long way before it finds 25 rows. The query timeout is the control
for exactly this, which is why it defaults to on and is enforced on the
server as well as the client — a client that merely stops waiting has
still left the work running on your instance.
If that is unacceptable on a particular instance, exclude it. Column scanning is opt-in per connection, and everything else the agent does is unaffected.
Frequently Asked Questions
Eight distinct sources: filesystem certificates and keys, the native OS certificate store (Windows CryptoAPI / macOS Keychain, scanned automatically), SSH host/user keys, live network TLS endpoints, database columns, F5/NetScaler certificate stores via management API, keystores, and application source code for deprecated crypto calls (CBOM).
Not by running on the appliance — that's not possible on closed devices. It queries each device's own management API remotely: F5's iControl REST and NetScaler's NITRO API, over HTTPS with admin credentials you provide. This surfaces the full store, including certs not currently bound to a live virtual server.
A codebase can have a spotless certificate inventory and still call a broken hash function internally — that's a different kind of finding than a file at rest. CBOM (Cryptographic Bill of Materials) flags MD5, SHA-1, DES/3DES, RC4, AES-ECB, and undersized RSA key generation in your own source by matching each ecosystem's real API idioms at the call site — high-confidence detection, not full data-flow static analysis.
For certificates on disk: the public certificate PEM, never a private key's secret material. For database columns: no — the raw value is parsed for metadata and then discarded, since it may be a per-tenant or per-user secret.
Linux x86_64 and Windows x86_64 have prebuilt binaries available now. macOS has native Apple Silicon (arm64) and Intel (x86_64) builds. All are real, tested downloads — the download page links work.
Every asset is classified by who can fix it: internal, public_ca, os_vendor, language_ecosystem, hardware_vendor, or unknown. This turns a flat inventory into a to-do list — the dashboard's Actionable Now / Vendor-Blocked split is built on this.
Classification is not purely by location. A copy of a public CA certificate is still the CA's wherever it sits on disk, so a final pass checks the certificate itself: roots are matched by SHA-256 against the known trust anchors, and intermediates by whether they chain to one. That pass only ever moves work off your list — it never marks something actionable that the location rules did not.
The order ("Securing the Nation Against Advanced Cryptographic Attacks", June 22, 2026) requires agencies to review cryptographic inventories, migrate key establishment to post-quantum by end of 2030 and digital signatures by end of 2031, and directs CISA/NIST to define CBOM minimum elements that enable automated assessment of cryptographic assets. This product supplies each piece: nine-source discovery builds the inventory, the CycloneDX 1.6 export (zero errors against the official schema) is the machine-assessable CBOM, and its primitive classification splits the estate into exactly the order's two deadline workloads — key establishment vs. signatures. The mandate card at the top of this page maps it requirement by requirement.
🚀 Start Your PQC Migration Pilot
Planning a post-quantum migration? Tell us about your environment and we’ll help you scope a discovery pilot — agent rollout, asset inventory, and a prioritized remediation report for your organization.