Files
spectre-meltdown-checker/doc/batch_json.md
github-actions[bot] a2823830a6 chore: create doc/ in -build branch
built from commit 2b1389e5c667a3c10c8e47fca7cb14d81695165c
 dated 2026-04-08 21:57:03 +0200
 by Stéphane Lesimple (speed47_github@speed47.net)
2026-04-08 20:10:38 +00:00

17 KiB

JSON Output Format

--batch json emits a single, self-contained JSON object that describes the scan environment and the result of every CVE check. You can feed it to your monitoring system, to a SIEM, to a time-series database, you name it.

sudo ./spectre-meltdown-checker.sh --batch json | jq .

Top-level schema

{
  "meta":          { ... },   // Run metadata and flags
  "system":        { ... },   // Kernel and host context
  "cpu":           { ... },   // CPU hardware identification
  "cpu_microcode": { ... },   // Microcode version and status
  "vulnerabilities": [ ... ]  // One object per checked CVE
}

format_version in meta is an integer that will be incremented on backward-incompatible schema changes. The current value is 1.

Section reference

meta

Run metadata. Always present.

Field Type Values Meaning
script_version string e.g. "25.30.0250400123" Script version
format_version integer 1 JSON schema version; incremented on breaking changes
timestamp string ISO 8601 UTC, e.g. "2025-04-07T12:00:00Z" When the scan started
os string e.g. "Linux", "FreeBSD" Output of uname -s
mode string "live" / "no-runtime" / "no-hw" / "hw-only" Operating mode (see modes)
run_as_root boolean Whether the script ran as root. Non-root scans skip MSR reads and may miss mitigations
reduced_accuracy boolean Kernel image, config, or System.map was missing; some checks fall back to weaker heuristics
paranoid boolean --paranoid mode: stricter criteria (e.g. requires SMT disabled, IBPB always-on)
sysfs_only boolean --sysfs-only: only the kernel's own sysfs report was used, not independent detection
no_hw boolean --no-hw: hardware checks (MSR, CPUID) were skipped
extra boolean --extra: additional experimental checks were enabled
mocked boolean One or more CPU values were overridden for testing. Results do not reflect the real system

Example:

"meta": {
  "script_version": "25.30.025040123",
  "format_version": 1,
  "timestamp": "2026-04-06T12:22:14Z",
  "os": "Linux",
  "mode": "live",
  "run_as_root": true,
  "reduced_accuracy": false,
  "paranoid": false,
  "sysfs_only": false,
  "no_hw": false,
  "extra": false,
  "mocked": false
}

Important flags for fleet operators:

  • run_as_root: false means the scan was incomplete. Treat results as lower confidence. Alert separately: results may be missing or wrong.
  • sysfs_only: true means the script trusted the kernel's self-report without independent verification. Some older kernels misreport their mitigation status. Do not use --sysfs-only for production fleet monitoring.
  • paranoid: true raises the bar: only compare vulnerable counts across hosts with the same paranoid value.
  • mocked: true must never appear on a production host. If it does, every downstream result is fabricated.

system

Kernel and host environment. Always present.

Field Type Values Meaning
kernel_release string | null e.g. "6.1.0-21-amd64" Output of uname -r (null in no-runtime, no-hw, and hw-only modes)
kernel_version string | null e.g. "#1 SMP Debian …" Output of uname -v (null in no-runtime, no-hw, and hw-only modes)
kernel_arch string | null e.g. "x86_64" Output of uname -m (null in no-runtime, no-hw, and hw-only modes)
kernel_image string | null e.g. "/boot/vmlinuz-6.1.0-21-amd64" Path passed via --kernel, or null if not specified
kernel_config string | null Path passed via --config, or null
kernel_version_string string | null Kernel version banner extracted from the image
kernel_cmdline string | null Kernel command line from /proc/cmdline (live mode) or the image
cpu_count integer | null Number of logical CPUs detected
smt_enabled boolean | null Whether SMT (HyperThreading) is currently active; null if undeterminable
hypervisor_host boolean | null Whether this machine is detected as a VM host (running KVM, Xen, VMware, etc.)
hypervisor_host_reason string | null Human-readable explanation of why hypervisor_host was set

hypervisor_host materially changes the risk profile of several CVEs. L1TF (CVE-2018-3646) and MDS (CVE-2018-12126/12130/12127) are significantly more severe on hypervisor hosts because they can be exploited across VM boundaries by a malicious guest. Prioritise remediation where hypervisor_host: true.


cpu

CPU hardware identification. null when --no-hw is active.

Field Type Values Meaning
vendor string | null e.g. "Intel", "AuthenticAMD" CPU vendor string
friendly_name string | null e.g. "Intel(R) Core(TM) i7-9700K CPU @ 3.60GHz" Human-readable CPU model
family integer | null CPU family number
model integer | null CPU model number
stepping integer | null CPU stepping number
cpuid string | null hex, e.g. "0x000906ed" Full CPUID leaf 1 EAX value
platform_id integer | null Intel platform ID (from MSR 0x17); null on AMD and ARM
hybrid boolean | null Whether this is a hybrid CPU (P-cores + E-cores, e.g. Alder Lake)
codename string | null e.g. "Coffee Lake" Intel CPU codename; null on AMD and ARM
arm_part_list string | null Space-separated list of ARM part numbers detected across cores
arm_arch_list string | null Space-separated list of ARM architecture levels detected across cores
capabilities object CPU feature flags detected via CPUID and MSR reads (see below)

cpu.capabilities

Each capability is a tri-state: true (present), false (absent), or null (not applicable or could not be read, e.g. when not root or on AMD for Intel-specific features).

Capability Meaning
spec_ctrl SPEC_CTRL MSR (Intel: ibrs + ibpb via WRMSR; required for many mitigations)
ibrs Indirect Branch Restricted Speculation
ibpb Indirect Branch Prediction Barrier
ibpb_ret IBPB on return (enhanced form)
stibp Single Thread Indirect Branch Predictors
ssbd Speculative Store Bypass Disable
l1d_flush L1D cache flush instruction
md_clear VERW clears CPU buffers (MDS mitigation)
arch_capabilities IA32_ARCH_CAPABILITIES MSR is present
rdcl_no Not susceptible to RDCL (Meltdown-like attacks)
ibrs_all Enhanced IBRS always-on mode supported
rsba RSB may use return predictions from outside the RSB
l1dflush_no Not susceptible to L1D flush side-channel
ssb_no Not susceptible to Speculative Store Bypass
mds_no Not susceptible to MDS
taa_no Not susceptible to TSX Asynchronous Abort
pschange_msc_no Page-size-change MSC not susceptible
tsx_ctrl_msr TSX_CTRL MSR is present
tsx_ctrl_rtm_disable RTM disabled via TSX_CTRL
tsx_ctrl_cpuid_clear CPUID HLE/RTM bits cleared via TSX_CTRL
gds_ctrl GDS_CTRL MSR present (GDS mitigation control)
gds_no Not susceptible to Gather Data Sampling
gds_mitg_dis GDS mitigation disabled
gds_mitg_lock GDS mitigation locked
rfds_no Not susceptible to Register File Data Sampling
rfds_clear VERW clears register file stale data
its_no Not susceptible to Indirect Target Selection
sbdr_ssdp_no Not susceptible to SBDR/SSDP
fbsdp_no Not susceptible to FBSDP
psdp_no Not susceptible to PSDP
fb_clear Fill buffer cleared on idle/C6
rtm Restricted Transactional Memory (TSX RTM) present
tsx_force_abort TSX_FORCE_ABORT MSR present
tsx_force_abort_rtm_disable RTM disabled via TSX_FORCE_ABORT
tsx_force_abort_cpuid_clear CPUID RTM cleared via TSX_FORCE_ABORT
sgx Software Guard Extensions present
srbds SRBDS affected
srbds_on SRBDS mitigation active
amd_ssb_no AMD: not susceptible to Speculative Store Bypass
hygon_ssb_no Hygon: not susceptible to Speculative Store Bypass
ipred Indirect Predictor Barrier support
rrsba Restricted RSB Alternate (Intel Retbleed mitigation)
bhi Branch History Injection mitigation support
tsa_sq_no Not susceptible to TSA-SQ
tsa_l1_no Not susceptible to TSA-L1
verw_clear VERW clears CPU buffers
autoibrs AMD AutoIBRS (equivalent to enhanced IBRS on Intel)
sbpb Selective Branch Predictor Barrier (AMD Inception mitigation)
avx2 AVX2 supported (relevant to Downfall / GDS)
avx512 AVX-512 supported (relevant to Downfall / GDS)

cpu_microcode

Microcode version and status. null under the same conditions as cpu.

Field Type Values Meaning
installed_version string | null hex, e.g. "0xf4" Currently running microcode revision
latest_version string | null hex Latest known-good version in the firmware database; null if CPU is not in the database
microcode_up_to_date boolean | null Whether installed_version == latest_version; null if either is unavailable
is_blacklisted boolean Whether the installed microcode is known to cause instability and must be rolled back
message string | null Human-readable note from the firmware database (e.g. changelog excerpt)
db_source string | null Which database was used (e.g. "Intel-SA", "MCExtractor")
db_info string | null Database revision or date

is_blacklisted: true means the installed microcode is known to cause system instability or incorrect behaviour. Treat this as a P1 incident: roll back to the previous microcode immediately.

microcode_up_to_date: false means a newer microcode is available. This does not necessarily mean the system is vulnerable (the current microcode may still include all required mitigations), but warrants investigation.


vulnerabilities

Array of CVE check results. One object per checked CVE, in check order. Empty array ([]) if no CVEs were checked (unusual; would require --cve with an unknown CVE ID).

Field Type Values Meaning
cve string e.g. "CVE-2017-5753" CVE identifier
name string e.g. "SPECTRE VARIANT 1" Short key name used in batch formats
aliases string | null e.g. "Spectre Variant 1, bounds check bypass" Full name including all known aliases
cpu_affected boolean Whether this CPU's hardware design is affected by this CVE
status string "OK" / "VULN" / "UNK" Check outcome (see below)
vulnerable boolean | null false / true / null false=OK, true=VULN, null=UNK
info string Human-readable description of the specific mitigation state or reason
sysfs_status string | null "OK" / "VULN" / "UNK" / null Status as reported by the kernel via /sys/devices/system/cpu/vulnerabilities/; null if sysfs was not consulted for this CVE
sysfs_message string | null Raw text from the sysfs file (e.g. "Mitigation: PTI"); null if sysfs was not consulted

Status values

status vulnerable Meaning
"OK" false CPU is unaffected by design, or all required mitigations are in place
"VULN" true CPU is affected and mitigations are missing or insufficient
"UNK" null The script could not determine the status (missing kernel info, insufficient privileges, or no detection logic for this platform)

cpu_affected explained

cpu_affected: false with status: "OK" means the CPU hardware is architecturally immune — no patch was ever needed.

cpu_affected: true with status: "OK" means the hardware has the weakness but all required mitigations (kernel, microcode, or both) are in place.

This distinction matters for fleet auditing: filter on cpu_affected: true to see only systems where mitigation effort was actually required and confirmed.

sysfs_status vs status

sysfs_status is the raw kernel self-report. status is the script's independent assessment, which may differ:

  • The script may upgrade a sysfs "VULN" to "OK" when it detects a silent backport that the kernel doesn't know about.
  • The script may downgrade a sysfs "OK" to "VULN" when it detects an incomplete mitigation the kernel doesn't flag (e.g. L1TF on a hypervisor host with SMT still enabled, or TSA in user mode on a VMM host).
  • sysfs_status is null when the kernel has no sysfs entry for this CVE (older kernels, or CVEs not yet tracked by the kernel).

Always use status / vulnerable for alerting. Use sysfs_status for diagnostics and audit trails.

Example:

{
  "cve": "CVE-2017-5715",
  "name": "SPECTRE VARIANT 2",
  "aliases": "Spectre Variant 2, branch target injection",
  "cpu_affected": true,
  "status": "OK",
  "vulnerable": false,
  "info": "Full generic retpoline is mitigating the vulnerability",
  "sysfs_status": "OK",
  "sysfs_message": "Mitigation: Retpolines; IBPB: conditional; IBRS_FW; STIBP: conditional; RSB filling; PBRSB-eIBRS: Not affected; BHI: Not affected"
}

Exit codes

The script exits with:

Code Meaning
0 All checked CVEs are OK
2 At least one CVE is VULN
3 No CVEs are VULN, but at least one is UNK

These exit codes are the same in all batch modes and in interactive mode. Use them in combination with the JSON body for reliable alerting.


Caveats and edge cases

No-runtime mode (--no-runtime) system.kernel_release, kernel_version, and kernel_arch are null (those come from uname, which reports the running kernel, not the inspected one). meta.mode: "no-runtime" signals this. system.kernel_image and system.kernel_version_string carry the inspected image path and banner instead.

No-hardware mode (--no-hw) cpu and cpu_microcode are null. CVE checks that rely on hardware capability detection (cap_* flags, MSR reads) will report status: "UNK". cpu_affected will be false for all CVEs (cannot determine affection without hardware info). meta.mode: "no-hw" signals this.

Hardware-only mode (--hw-only) Only CPU information and per-CVE affectedness are reported. No kernel inspection is performed, so vulnerability mitigations are not checked. meta.mode: "hw-only" signals this.

--sysfs-only The script trusts the kernel's sysfs report without running independent detection. meta.sysfs_only: true flags this. Some older kernels misreport their status. Do not use for production fleet monitoring.

--paranoid Enables defense-in-depth checks beyond the security community consensus. A status: "OK" under paranoid: true means a higher bar was met. Do not compare results across hosts with different paranoid values.

reduced_accuracy Set when the kernel image, config file, or System.map could not be read. Some checks fall back to weaker heuristics and may report "UNK" for CVEs that are actually mitigated.

Non-x86 architectures (ARM, ARM64) cpu.codename and cpu.platform_id are always null. cpu.arm_part_list and cpu.arm_arch_list carry the relevant identifiers instead. Most cpu.capabilities fields are null (those flags are Intel/AMD-specific).

mocked: true Must never appear on a production host. If it does, the results are fabricated and every downstream alert is unreliable.


Schema stability

meta.format_version is incremented on backward-incompatible changes (field removal or type change). Additive changes (new fields) do not increment the version; consumers must tolerate unknown fields.

Recommended practice: check format_version == 1 at parse time and reject or alert on any other value until you have tested compatibility with the new version.


Migration from json-terse

The legacy --batch json-terse format emits a flat array of objects:

[
  {"NAME": "SPECTRE VARIANT 1", "CVE": "CVE-2017-5753", "VULNERABLE": false, "INFOS": "..."},
  ...
]

It carries no system, CPU, or microcode context. It has no sysfs data. It uses uppercase field names.

To migrate:

  1. Replace --batch json-terse with --batch json.
  2. The equivalent of the old VULNERABLE field is vulnerabilities[].vulnerable.
  3. The equivalent of the old INFOS field is vulnerabilities[].info.
  4. The equivalent of the old NAME field is vulnerabilities[].name.
  5. The old format is still available as --batch json-terse for transition periods.