Reports
kartis-scan turns a consolidated scan document — the JSON produced by
scripts/full-scan.sh (see Scanning) — into a
customer-facing Markdown report. There is no report viewer in Kartis itself;
the Markdown is meant to be read directly, converted with another tool, or
consumed by Eon Center, Eon Aethis, or Eon Insights.
Generating a report
kartis-scan report [file] [flags]
--lang <nl|en> report language (default "nl")
-o, --out <path> output file (default: stdout)
--anonymize anonymize the input before renderingThe input is a file argument, or stdin when no argument (or -) is given:
kartis-scan report scan.json # Dutch report to stdout
kartis-scan report --lang en scan.json # English report
scripts/full-scan.sh qgf.io | kartis-scan report -o report.mdWhat’s in the rendered document
internal/report renders, in order:
- Header — domain, scan window, duration, host/service/finding counts.
- Summary — an overall risk verdict plus a per-severity tally, and a “top actions” list of up to five items: the highest-severity findings (one action per finding source, to avoid repetition), plus a post-quantum key-exchange recommendation appended whenever no service offers hybrid PQ key exchange.
- Post-quantum readiness — whether hybrid PQ key exchange (for example
X25519MLKEM768) is present anywhere, and a per-TLS-service table of key exchange group, weakest certificate link, and PQC classification. - Findings — grouped by severity, each with its description, evidence,
any associated CVE IDs, and a risk/mitigation block. Mitigation text comes
from
internal/report/mitigations.go, keyed by finding source. - Appendix — a table of every discovered service (host, port, protocol, service, product/version), and for each TLS service, its certificate chain: subject, issuer, signature algorithm, key details, PQC classification, expiry, and SANs.
- Methodology — a fixed disclosure paragraph: the scan is an authorized external perimeter scan, the scanner identifies itself honestly and performs no evasion, and certificate parsing relies on the TLS 1.2 cleartext handshake (a TLS 1.3-only host reports protocol/key-exchange posture without parsed certificates).
The document renders in Dutch (nl, the default) or English (en); all
section headers, labels, and the methodology text are localized
(internal/report/i18n.go).
Output format
kartis-scan report only produces GitHub-flavored Markdown — there is no
built-in DOCX or PDF export. Converting the Markdown to another format (for
example with pandoc, or by opening it in a word processor) is a manual
step outside the CLI.
Anonymizing scan data
kartis-scan anonymize [file] [flags]
-o, --out <path> output file (default: stdout)Reads a consolidated scan JSON document (file argument or stdin) and writes an anonymized copy:
- hostnames matching the literal
qgf.iodomain (and the bareqgftoken, including its dash form used by Microsoft 365 routing hosts) becomeacme.comsubdomains - IP addresses become RFC 5737 documentation addresses
- certificate identifiers (serial numbers, fingerprints, key IDs, raw DER/PEM) are replaced with random values
Every distinct real value maps to one stable anonymized value, so the anonymized document stays internally consistent (the same real hostname always becomes the same fake one, throughout the document).
Limitation: the domain match is hardcoded to qgf.io (internal/ anonymize/anonymize.go) — there is no domain parameter. Anonymizing a scan
of any other domain will not scrub that domain’s hostnames; they pass
through unchanged into the “anonymized” output, while IPs and certificate
fields are still scrubbed. Today this command is effectively limited to
producing sample documents from qgf.io (the standing own-infra reference
target), not to anonymizing arbitrary customer scans.
Pipe it into report to produce an anonymized, shareable sample document:
kartis-scan anonymize scan.json | kartis-scan report -o sample.mdor use report’s own --anonymize flag to do both in one step:
kartis-scan report --anonymize -o sample.md scan.json