Skip to content

Scripting with JSON

Two inputs:

Terminal window
pqdoctor github.com --json > report.json # one host, one object
pqdoctor scan hosts.txt --json --quiet > results.jsonl # one object per line

The PowerShell examples were run against real pqdoctor output.

Terminal window
Get-Content results.jsonl | ConvertFrom-Json | Group-Object verdict | Select-Object Name, Count
Name Count
---- -----
noTls13 1
pq 1
notPq 1

List the hosts that aren’t post-quantum, with why

Section titled “List the hosts that aren’t post-quantum, with why”
Terminal window
Get-Content results.jsonl | ConvertFrom-Json |
Where-Object { $_.verdict -notin 'pq', 'pqWithWarning' } |
Select-Object host, cause, stack
host cause stack
---- ----- -----
nginx.org tls12-only nginx
github.com no-mlkem

Post-quantum share of the hosts that answered

Section titled “Post-quantum share of the hosts that answered”
Terminal window
$r = @(Get-Content results.jsonl | ConvertFrom-Json |
Where-Object { $_.verdict -notin 'unreachable', 'error', 'skipped', 'resolved' })
$pq = @($r | Where-Object { $_.verdict -in 'pq', 'pqWithWarning' }).Count
'{0} of {1} post-quantum ({2:P1})' -f $pq, $r.Count, ($pq / $r.Count)
1 of 3 post-quantum (33.3%)

@(…) keeps a single match countable in Windows PowerShell 5.1.

That’s the same “answered TLS” denominator the scan summary uses.

Terminal window
(Get-Content report.json -Raw | ConvertFrom-Json).fixes[0].snippet
# Go
cfg.CurvePreferences = nil // Go 1.24+ default includes X25519MLKEM768
# OpenSSL-based
Groups = X25519MLKEM768:X25519:prime256v1
Terminal window
(Get-Content report.json -Raw | ConvertFrom-Json).probes | Select-Object id, summary
id summary
-- -------
tls13Classical TLS 1.3: picked X25519
pqOnly TLS 1.3: asked to retry with X25519
pqPreference TLS 1.3: picked X25519
kyberDraft TLS 1.3: asked to retry with X25519
pqSplit TLS 1.3: asked to retry with X25519
bigClassicalSplit TLS 1.3: picked X25519
nistOnly TLS 1.3: picked P-256
Terminal window
Get-Content results.jsonl | ConvertFrom-Json | Export-Csv results.csv -NoTypeInformation

Which hosts changed between last week’s scan and today’s:

Terminal window
$old = @{}; Get-Content last-week.jsonl | ConvertFrom-Json | ForEach-Object { $old["$($_.host):$($_.port)"] = $_.cause }
Get-Content today.jsonl | ConvertFrom-Json | ForEach-Object {
$k = "$($_.host):$($_.port)"
if ($old.ContainsKey($k) -and $old[$k] -ne $_.cause) { "$k $($old[$k]) -> $($_.cause)" }
}

Flarebox does this for you per origin, with fixed and regressed notes and alerts.