7 Commits

Author SHA1 Message Date
Stéphane Lesimple
8a6f9d5d63 Implement ITS/VMScape/BTI and misc enhancements (#539)
7a7408d fix: add rebleet to --variant
cccb3c0 enh: add known fixed ucode versions for CVE-2023-23583 (Reptar) and CVE-2024-45332 (BPI)
090f109 doc: add CVE-2023-31315 (SinkClose) to the unsupported list, add categories
5dc9c3c chore: reorder CVE list in README.md
a00fab1 feat: implement CVE-2025-40300 (VMScape) and CVE-2024-45332 (BTI)
e0b818f chore: stalebot: disable dryrun by default
4af1155 feat: implement CVE-2024-28956 (ITS, Indirect Target Selection) vulnerability and mitigation detection
dfed6f3 doc: add note about more unsupported CVEs
1652977 add a generated version of src/libs/003_intel_models.sh
a089ae8 fix: sys_interface_check() must set the caller's $msg var (closes #533)
cc6bbaa chore: don't include src/ generated files in build
2717b0a doc: CVE-2020-12965 unsupported (#478)
2026-04-04 18:38:49 +02:00
Stéphane Lesimple
f2d871acff fix: spurious local keyword broke sysfs based detection (#533) (#534)
The $msg var assigned in sys_interface_check() must not be
local to the func, but must capture and modify the callers'
own local $msg var
2026-04-03 01:31:58 +02:00
Stéphane Lesimple
83ebe2f75f chore: update workflows (#531)
* chore: add stalebot in dryrun

 built from commit afadf53f7f
 dated 2026-04-02 13:13:19 +0200
 by Stéphane Lesimple (speed47_github@speed47.net)

* Merge branch 'test' into source

 built from commit 952fe6a87f
 dated 2026-04-02 18:40:05 +0200
 by Stéphane Lesimple (speed47_github@speed47.net)

* Merge pull request #530 from speed47/test

 built from commit d3c0f1a24d
 dated 2026-04-02 16:49:41 +0000
 by Stéphane Lesimple (speed47_github@speed47.net)

 chore: workflows revamp

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-04-02 18:53:44 +02:00
github-actions[bot]
a05f8aab34 chore: add stalebot in dryrun
built from commit afadf53f7f
 dated 2026-04-02 13:13:19 +0200
 by Stéphane Lesimple (speed47_github@speed47.net)
2026-04-02 11:34:30 +00:00
github-actions[bot]
f9c3d19f72 enh: CVE-2017-5715; check for unprivileged eBPF for paranoid mode
built from commit e5c6d2d905
 dated 2026-04-01 20:37:54 +0000
 by Stéphane Lesimple (speed47_github@speed47.net)
2026-04-01 21:30:51 +00:00
github-actions[bot]
8389d9593c chore: prepare for dev-build renaming to test-build
built from commit 9497abbee2
 dated 2026-03-31 19:34:52 +0200
 by Stéphane Lesimple (speed47_github@speed47.net)
2026-04-01 21:30:51 +00:00
Stéphane Lesimple
3a822fdcf2 chore: master: remove obsolete workflow 2026-03-31 19:53:57 +02:00
10 changed files with 389 additions and 4442 deletions

View File

@@ -25,81 +25,21 @@ jobs:
mv spectre-meltdown-checker.sh dist/
- name: check direct execution
run: |
set -x
expected=$(cat .github/workflows/expected_cve_count)
cd dist
json=$(sudo ./spectre-meltdown-checker.sh --batch json || true)
# Validate JSON is well-formed (and show it if not)
echo "$json" | jq . >/dev/null || {
echo "Invalid JSON produced by spectre-meltdown-checker.sh"
echo "$json"
exit 1
}
# Validate required keys exist
for key in meta system cpu cpu_microcode vulnerabilities; do
echo "$json" | jq -e ".$key" >/dev/null || {
echo "Missing top-level key: $key"
echo "$json" | jq .
exit 1
}
done
# Use -r to get raw scalars (no quotes)
fmtver=$(echo "$json" | jq -r '.meta.format_version // empty')
if [ "$fmtver" != "1" ]; then
echo "Unexpected format_version: $fmtver"
echo "$json" | jq .
exit 1
fi
run_as_root=$(echo "$json" | jq -r '.meta.run_as_root // empty')
if [ "$run_as_root" != "true" ]; then
echo "Expected run_as_root=true, got: $run_as_root"
echo "$json" | jq .
exit 1
fi
mocked=$(echo "$json" | jq -r '.meta.mocked // "false"')
if [ "$mocked" = "true" ]; then
echo "mocked=true must never appear in production"
echo "$json" | jq .
exit 1
fi
# Count CVEs robustly (as a number)
nb=$(echo "$json" | jq -r '[.vulnerabilities[].cve] | length')
nb=$(sudo ./spectre-meltdown-checker.sh --batch json | jq '.[]|.CVE' | wc -l)
if [ "$nb" -ne "$expected" ]; then
echo "Invalid number of CVEs reported: $nb instead of $expected"
echo "$json" | jq '.vulnerabilities[].cve'
exit 1
else
echo "OK $nb CVEs reported"
fi
# Validate json-terse backward compatibility
nb_terse=$(sudo ./spectre-meltdown-checker.sh --batch json-terse | jq -r 'map(.CVE) | length')
if [ "$nb_terse" -ne "$expected" ]; then
echo "json-terse backward compat broken: $nb_terse CVEs instead of $expected"
exit 1
else
echo "OK json-terse backward compat: $nb_terse CVEs"
fi
- name: check docker compose run execution
run: |
expected=$(cat .github/workflows/expected_cve_count)
cd dist
docker compose build
json=$(docker compose run --rm spectre-meltdown-checker --batch json || true)
echo "$json" | jq . > /dev/null
fmtver=$(echo "$json" | jq '.meta.format_version')
if [ "$fmtver" != "1" ]; then
echo "Unexpected format_version: $fmtver"
exit 1
fi
nb=$(echo "$json" | jq '.vulnerabilities[].cve' | wc -l)
nb=$(docker compose run --rm spectre-meltdown-checker --batch json | jq '.[]|.CVE' | wc -l)
if [ "$nb" -ne "$expected" ]; then
echo "Invalid number of CVEs reported: $nb instead of $expected"
exit 1
@@ -111,14 +51,7 @@ jobs:
expected=$(cat .github/workflows/expected_cve_count)
cd dist
docker build -t spectre-meltdown-checker .
json=$(docker run --rm --privileged -v /boot:/boot:ro -v /dev/cpu:/dev/cpu:ro -v /lib/modules:/lib/modules:ro spectre-meltdown-checker --batch json || true)
echo "$json" | jq . > /dev/null
fmtver=$(echo "$json" | jq '.meta.format_version')
if [ "$fmtver" != "1" ]; then
echo "Unexpected format_version: $fmtver"
exit 1
fi
nb=$(echo "$json" | jq '.vulnerabilities[].cve' | wc -l)
nb=$(docker run --rm --privileged -v /boot:/boot:ro -v /dev/cpu:/dev/cpu:ro -v /lib/modules:/lib/modules:ro spectre-meltdown-checker --batch json | jq '.[]|.CVE' | wc -l)
if [ "$nb" -ne "$expected" ]; then
echo "Invalid number of CVEs reported: $nb instead of $expected"
exit 1
@@ -159,19 +92,15 @@ jobs:
fi
- name: create a pull request to ${{ github.ref_name }}-build
run: |
# all the files in dist/* and .github/* must be moved as is to the -build branch root, move them out for now:
tmpdir=$(mktemp -d)
mv ./dist/* .github $tmpdir/
rm -rf ./dist
git fetch origin ${{ github.ref_name }}-build
git checkout -f ${{ github.ref_name }}-build
rm -rf doc/
mv $tmpdir/* .
rm -rf src/ scripts/ img/
rm -rf src/
mkdir -p .github
rsync -vaP --delete $tmpdir/.github/ .github/
git add --all
echo =#=#= DIFF CACHED
git diff --cached

View File

@@ -1 +1 @@
31
26

View File

@@ -85,7 +85,7 @@ However I see a few reasons why this script might still be useful to you, and th
- The script can be pointed at a kernel image, and will deep dive into it, telling you if this kernel will mitigate vulnerabilities that might be present on your system. This is a good way to verify before booting a new kernel, that it'll mitigate the vulnerabilities you expect it to, especially if you modified a few config options around these topics.
- The script will also work regardless of the custom patches that might be integrated in the kernel you're running (or you're pointing it to, in no-runtime mode), and completely ignores the advertised kernel version, to tell whether a given kernel mitigates vulnerabilities. This is especially useful for non-vanilla kernel, where patches might be backported, sometimes silently (this has already happened, too).
- The script will also work regardless of the custom patches that might be integrated in the kernel you're running (or you're pointing it to, in offline mode), and completely ignores the advertised kernel version, to tell whether a given kernel mitigates vulnerabilities. This is especially useful for non-vanilla kernel, where patches might be backported, sometimes silently (this has already happened, too).
- Educational purposes: the script gives interesting insights about a vulnerability, and how the different parts of the system work together to mitigate it.

View File

@@ -22,17 +22,12 @@ CVE | Name | Aliases
[CVE-2019-11091](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-11091) | Microarchitectural Data Sampling Uncacheable Memory | MDSUM, RIDL
[CVE-2019-11135](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-11135) | TSX Asynchronous Abort | TAA, ZombieLoad V2
[CVE-2020-0543](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-0543) | Special Register Buffer Data Sampling | SRBDS, CROSSTalk
[CVE-2022-21123](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-21123) | Shared Buffers Data Read | SBDR, MMIO Stale Data
[CVE-2022-21125](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-21125) | Shared Buffers Data Sampling | SBDS, MMIO Stale Data
[CVE-2022-21166](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-21166) | Device Register Partial Write | DRPW, MMIO Stale Data
[CVE-2022-29900](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-29900) | Arbitrary Speculative Code Execution with Return Instructions | Retbleed (AMD)
[CVE-2022-29901](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-29901) | Arbitrary Speculative Code Execution with Return Instructions | Retbleed (Intel), RSBA
[CVE-2022-40982](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-40982) | Gather Data Sampling | Downfall, GDS
[CVE-2023-20569](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-20569) | Return Address Security | Inception, SRSO
[CVE-2023-20588](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-20588) | AMD Division by Zero Speculative Data Leak | DIV0
[CVE-2023-20593](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-20593) | Cross-Process Information Leak | Zenbleed
[CVE-2023-23583](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-23583) | Redundant Prefix Issue | Reptar
[CVE-2023-28746](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-28746) | Register File Data Sampling | RFDS
[CVE-2024-28956](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-28956) | Indirect Target Selection | ITS
[CVE-2024-36350](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-36350) | Transient Scheduler Attack, Store Queue | TSA-SQ
[CVE-2024-36357](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-36357) | Transient Scheduler Attack, L1 | TSA-L1
@@ -61,17 +56,12 @@ CVE-2018-12207 (iTLB Multihit, No eXcuses) | ✅ | ✅ | ☠️ | ✅ | Hypervis
CVE-2019-11091 (MDSUM, RIDL) | 💥 | 💥 (1) | 💥 | 💥 (1) | Microcode + kernel update
CVE-2019-11135 (TAA, ZombieLoad V2) | 💥 | 💥 (1) | 💥 | 💥 (1) | Microcode + kernel update
CVE-2020-0543 (SRBDS, CROSSTalk) | 💥 (2) | 💥 (2) | 💥 (2) | 💥 (2) | Microcode + kernel update
CVE-2022-21123 (SBDR, MMIO Stale Data) | 💥 | 💥 (1) | 💥 | 💥 (1) | Microcode + kernel update
CVE-2022-21125 (SBDS, MMIO Stale Data) | 💥 | 💥 (1) | 💥 | 💥 (1) | Microcode + kernel update
CVE-2022-21166 (DRPW, MMIO Stale Data) | 💥 | 💥 (1) | 💥 | 💥 (1) | Microcode + kernel update
CVE-2022-29900 (Retbleed AMD) | 💥 | ✅ | 💥 | ✅ | Kernel update (+ microcode for IBPB)
CVE-2022-29901 (Retbleed Intel, RSBA) | 💥 | ✅ | 💥 | ✅ | Microcode + kernel update (eIBRS or IBRS)
CVE-2022-40982 (Downfall, GDS) | 💥 | 💥 | 💥 | 💥 | Microcode update (or disable AVX)
CVE-2023-20569 (Inception, SRSO) | 💥 | ✅ | 💥 | ✅ | Microcode + kernel update
CVE-2023-20588 (DIV0) | 💥 | 💥 (1) | 💥 | 💥 (1) | Kernel update (+ disable SMT)
CVE-2023-20593 (Zenbleed) | 💥 | 💥 | 💥 | 💥 | Microcode update (or kernel workaround)
CVE-2023-23583 (Reptar) | ☠️ | ☠️ | ☠️ | ☠️ | Microcode update
CVE-2023-28746 (RFDS) | 💥 | ✅ | 💥 | ✅ | Microcode + kernel update
CVE-2024-28956 (ITS) | 💥 | ✅ | 💥 (4) | ✅ | Microcode + kernel update
CVE-2024-36350 (TSA-SQ) | 💥 | 💥 (1) | 💥 | 💥 (1) | Microcode + kernel update
CVE-2024-36357 (TSA-L1) | 💥 | 💥 (1) | 💥 | 💥 (1) | Microcode + kernel update
@@ -151,10 +141,6 @@ On CPUs with Intel TSX, a transactional abort can leave data from the line fill
Certain special CPU instructions (RDRAND, RDSEED, EGETKEY) read data through a shared staging buffer that is accessible across all cores via speculative execution. An attacker running code on any core can observe the output of these instructions from a victim on a different core, including extracting cryptographic keys from SGX enclaves (a complete ECDSA key was demonstrated). This is notable as one of the first cross-core speculative execution attacks. Mitigation requires a microcode update that serializes access to the staging buffer, plus a kernel update to manage the mitigation. Performance impact is low, mainly affecting workloads that heavily use RDRAND/RDSEED.
**CVE-2022-21123, CVE-2022-21125, CVE-2022-21166 — Processor MMIO Stale Data (SBDR, SBDS, DRPW)**
A class of MMIO (Memory-Mapped I/O) vulnerabilities where stale data from CPU internal fill buffers can be inferred through side-channel attacks during MMIO operations. Three sub-vulnerabilities are covered: Shared Buffers Data Read (SBDR, CVE-2022-21123), Shared Buffers Data Sampling (SBDS, CVE-2022-21125), and Device Register Partial Write (DRPW, CVE-2022-21166). Affected Intel CPUs include Haswell through Rocket Lake server and client processors, plus Tremont Atom cores. Mitigation requires a microcode update providing the FB_CLEAR capability (VERW instruction clears fill buffers) plus a kernel update (Linux 5.19+) that invokes VERW at kernel/user transitions and VM entry/exit. When SMT is enabled, sibling threads can still exploit the vulnerability even with mitigations active. Performance impact is low, as the VERW mechanism is shared with the existing MDS mitigation.
**CVE-2022-29900 — Arbitrary Speculative Code Execution with Return Instructions (Retbleed AMD)**
On AMD processors from families 0x15 through 0x17 (Bulldozer through Zen 2) and Hygon family 0x18, an attacker can exploit return instructions to redirect speculative execution and leak kernel memory, bypassing retpoline mitigations that were effective against Spectre V2. Unlike Spectre V2 which targets indirect jumps and calls, Retbleed specifically targets return instructions, which were previously considered safe. Mitigation requires a kernel update providing either the untrained return thunk (safe RET) or IBPB-on-entry mechanism, plus a microcode update providing IBPB support on Zen 1/2. On Zen 1/2, SMT should be disabled for full protection when using IBPB-based mitigation. Performance impact is medium.
@@ -171,10 +157,6 @@ The AVX GATHER instructions can leak data from previously used vector registers
On AMD Zen 1 through Zen 4 processors, an attacker can manipulate the return address predictor to redirect speculative execution on return instructions, leaking kernel memory. Mitigation requires both a kernel update (providing SRSO safe-return sequences or IBPB-on-entry) and a microcode update (providing SBPB on Zen 3/4, or IBPB support on Zen 1/2 — which additionally requires SMT to be disabled). Performance impact ranges from low to significant depending on the chosen mitigation and CPU generation.
**CVE-2023-20588 — AMD Division by Zero Speculative Data Leak (DIV0)**
On AMD Zen 1 processors, a #DE (divide-by-zero) exception can leave stale quotient data from a previous division in the divider unit, observable by a subsequent division via speculative side channels. This can leak data across any privilege boundary, including between SMT sibling threads sharing the same physical core. Mitigation requires a kernel update (Linux 6.5+) that adds a dummy division (`amd_clear_divider()`) on every exit to userspace and before VMRUN, preventing stale data from persisting. No microcode update is needed. Disabling SMT provides additional protection because the kernel mitigation does not cover cross-SMT-thread leaks. Performance impact is negligible.
**CVE-2023-20593 — Cross-Process Information Leak (Zenbleed)**
A bug in AMD Zen 2 processors causes the VZEROUPPER instruction to incorrectly zero register files during speculative execution, leaving stale data from other processes observable in vector registers. This can leak data across any privilege boundary, including from the kernel and other processes, at rates up to 30 KB/s per core. Mitigation is available either through a microcode update that fixes the bug, or through a kernel workaround that sets the FP_BACKUP_FIX bit (bit 9) in the DE_CFG MSR, disabling the faulty optimization. Either approach alone is sufficient. Performance impact is negligible.
@@ -183,10 +165,6 @@ A bug in AMD Zen 2 processors causes the VZEROUPPER instruction to incorrectly z
A bug in Intel processors causes unexpected behavior when executing instructions with specific redundant REX prefixes. Depending on the circumstances, this can result in a system crash (MCE), unpredictable behavior, or potentially privilege escalation. Any software running on an affected CPU can trigger the bug. Mitigation requires a microcode update. Performance impact is low.
**CVE-2023-28746 — Register File Data Sampling (RFDS)**
On certain Intel Atom and hybrid processors (Goldmont, Goldmont Plus, Tremont, Gracemont, and the Atom cores of Alder Lake and Raptor Lake), the register file can retain stale data from previous operations that is accessible via speculative execution, allowing an attacker to infer data across privilege boundaries. Mitigation requires both a microcode update (providing the RFDS_CLEAR capability) and a kernel update (CONFIG_MITIGATION_RFDS, Linux 6.9+) that uses the VERW instruction to clear the register file on privilege transitions. CPUs with the RFDS_NO capability bit are not affected. Performance impact is low.
**CVE-2024-28956 — Indirect Target Selection (ITS)**
On certain Intel processors (Skylake-X stepping 6+, Kaby Lake, Comet Lake, Ice Lake, Tiger Lake, Rocket Lake), an attacker can train the indirect branch predictor to speculatively execute a targeted gadget in the kernel, bypassing eIBRS protections. The Branch Target Buffer (BTB) uses only partial address bits to index indirect branch targets, allowing user-space code to influence kernel-space speculative execution. Some affected CPUs (Ice Lake, Tiger Lake, Rocket Lake) are only vulnerable to native user-to-kernel attacks, not guest-to-host (VMX) attacks. Mitigation requires both a microcode update (IPU 2025.1 / microcode-20250512+, which fixes IBPB to fully flush indirect branch predictions) and a kernel update (CONFIG_MITIGATION_ITS, Linux 6.15+) that aligns branch/return thunks or uses RSB stuffing. Performance impact is low.
@@ -214,17 +192,17 @@ A race condition in the branch predictor update mechanism of Intel processors (C
Several transient execution CVEs are not covered by this tool, for various reasons (duplicates, only
affecting non-supported hardware or OS, theoretical with no known exploitation, etc.).
The complete list along with the reason for each exclusion is available in the
[UNSUPPORTED_CVE_LIST.md](doc/UNSUPPORTED_CVE_LIST.md) file.
[UNSUPPORTED_CVE_LIST.md](https://github.com/speed47/spectre-meltdown-checker/blob/source/UNSUPPORTED_CVE_LIST.md) file.
## Scope
Supported operating systems:
- Linux (all versions, flavors and distros)
- FreeBSD, NetBSD, DragonFlyBSD and derivatives (others BSDs are [not supported](doc/FAQ.md#which-bsd-oses-are-supported))
- FreeBSD, NetBSD, DragonFlyBSD and derivatives (others BSDs are [not supported](FAQ.md#which-bsd-oses-are-supported))
For Linux systems, the tool will detect mitigations, including backported non-vanilla patches, regardless of the advertised kernel version number and the distribution (such as Debian, Ubuntu, CentOS, RHEL, Fedora, openSUSE, Arch, ...), it also works if you've compiled your own kernel. More information [here](doc/FAQ.md#how-does-this-script-work).
For Linux systems, the tool will detect mitigations, including backported non-vanilla patches, regardless of the advertised kernel version number and the distribution (such as Debian, Ubuntu, CentOS, RHEL, Fedora, openSUSE, Arch, ...), it also works if you've compiled your own kernel. More information [here](FAQ.md#how-does-this-script-work).
Other operating systems such as MacOS, Windows, ESXi, etc. [will never be supported](doc/FAQ.md#why-is-my-os-not-supported).
Other operating systems such as MacOS, Windows, ESXi, etc. [will never be supported](FAQ.md#why-is-my-os-not-supported).
Supported architectures:
- `x86` (32 bits)
@@ -236,29 +214,7 @@ Supported architectures:
What is the purpose of this tool? Why was it written? How can it be useful to me? How does it work? What can I expect from it?
All these questions (and more) have detailed answers in the [FAQ](doc/FAQ.md), please have a look!
## Operating modes
The script supports four operating modes, depending on whether you want to inspect the running kernel, a kernel image, the CPU hardware, or a combination.
| Mode | Flag | CPU hardware | Running kernel | Kernel image | Use case |
|------|------|:---:|:---:|:---:|----------|
| **Live** *(default)* | *(none)* | Yes | Yes | auto-detect | Day-to-day auditing of the current system |
| **No-runtime** | `--no-runtime` | Yes | No | required | Check a different kernel against this CPU (e.g. pre-deployment) |
| **No-hardware** | `--no-hw` | No | No | required | Pure static analysis of a kernel image for another system or architecture |
| **Hardware-only** | `--hw-only` | Yes | No | No | Quickly check CPU affectedness without inspecting any kernel |
In **Live** mode (the default), the script inspects both the CPU and the running kernel.
You can optionally pass `--kernel`, `--config`, or `--map` to point the script at files it couldn't auto-detect.
In **No-runtime** mode, the script still reads the local CPU (CPUID, MSRs, microcode) but skips all running-kernel artifacts (`/sys`, `/proc`, `dmesg`).
Use this when you have a kernel image from another system but want to evaluate it against the current CPU.
In **No-hardware** mode, both CPU inspection and running-kernel artifacts are skipped entirely.
This is useful for cross-architecture analysis, for example inspecting an ARM kernel image on an x86 workstation.
In **Hardware-only** mode, the script only reports CPU information and per-CVE hardware affectedness, without inspecting any kernel.
All these questions (and more) have detailed answers in the [FAQ](FAQ.md), please have a look!
## Running the script
@@ -310,6 +266,15 @@ docker run --rm --privileged -v /boot:/boot:ro -v /dev/cpu:/dev/cpu:ro -v /lib/m
## Example of script output
- AMD EPYC-Milan running under Debian Trixie
- Intel Haswell CPU running under Ubuntu 16.04 LTS
![haswell](https://user-images.githubusercontent.com/218502/108764885-6dcfc380-7553-11eb-81ac-4d19060a3acf.png)
- AMD Ryzen running under OpenSUSE Tumbleweed
![ryzen](https://user-images.githubusercontent.com/218502/108764896-70321d80-7553-11eb-9dd2-fad2a0a1a737.png)
- Batch mode (JSON flavor)
![batch](https://user-images.githubusercontent.com/218502/108764902-71634a80-7553-11eb-9678-fd304995fa64.png)
![alt text](https://raw.githubusercontent.com/speed47/spectre-meltdown-checker/refs/heads/test/img/smc_amd_epyc_milan.jpg)

View File

@@ -1,298 +0,0 @@
# Unsupported CVEs
This document lists transient execution CVEs that have been evaluated and determined to be **out of scope** for this tool. See the [Which rules are governing the support of a CVE in this tool?](dist/FAQ.md#which-rules-are-governing-the-support-of-a-cve-in-this-tool) section in the FAQ for the general policy.
CVEs are grouped by reason for exclusion:
- [Already covered by an existing CVE check](#already-covered-by-an-existing-cve-check) — subvariants or subsets whose mitigations are already detected under a parent CVE.
- [No kernel or microcode mitigations to check](#no-kernel-or-microcode-mitigations-to-check) — no fix has been issued, or the mitigation is not detectable by this tool.
- [Not a transient/speculative execution vulnerability](#not-a-transientspeculative-execution-vulnerability) — wrong vulnerability class entirely.
---
# Already covered by an existing CVE check
These CVEs are subvariants or subsets of vulnerabilities already implemented in the tool. Their mitigations are detected as part of the parent CVE's checks.
## CVE-2018-3693 — Bounds Check Bypass Store (Spectre v1.1)
- **Issue:** [#236](https://github.com/speed47/spectre-meltdown-checker/issues/236)
- **Red Hat advisory:** [Speculative Store Bypass / Bounds Check Bypass (CVE-2018-3693)](https://access.redhat.com/solutions/3523601)
- **CVSS:** 5.6 (Medium)
- **Covered by:** CVE-2017-5753 (Spectre V1)
A subvariant of Spectre V1 where speculative store operations can write beyond validated buffer boundaries before the bounds check resolves, allowing an attacker to alter cache state and leak information via side channels.
**Why out of scope:** The mitigations are identical to CVE-2017-5753 (Spectre V1): `lfence` instructions after bounds checks and `array_index_nospec()` barriers in kernel code. There is no separate sysfs entry, no new CPU feature flag, and no distinct microcode change. This tool's existing CVE-2017-5753 checks already detect these mitigations (`__user pointer sanitization`, `usercopy/swapgs barriers`), so CVE-2018-3693 is fully covered as part of Spectre V1.
## CVE-2018-15572 — SpectreRSB (Return Stack Buffer)
- **Issue:** [#224](https://github.com/speed47/spectre-meltdown-checker/issues/224)
- **Research paper:** [Spectre Returns! Speculation Attacks using the Return Stack Buffer (WOOT'18)](https://arxiv.org/abs/1807.07940)
- **Kernel fix:** [commit fdf82a7856b3](https://github.com/torvalds/linux/commit/fdf82a7856b32d905c39afc85e34364491e46346) (Linux 4.18.1)
- **CVSS:** 6.5 (Medium)
- **Covered by:** CVE-2017-5715 (Spectre V2)
The `spectre_v2_select_mitigation` function in the Linux kernel before 4.18.1 did not always fill the RSB upon a context switch, allowing userspace-to-userspace SpectreRSB attacks on Skylake+ CPUs where an empty RSB falls back to the BTB.
**Why out of scope:** This CVE is a Spectre V2 mitigation gap (missing RSB filling on context switch), not a distinct hardware vulnerability. It is already fully covered by this tool's CVE-2017-5715 (Spectre V2) checks, which detect whether the kernel performs RSB filling on CPUs vulnerable to RSB underflow (Skylake+ and RSBA-capable CPUs). A missing RSB fill is flagged as a caveat ("RSB filling missing on Skylake+") in the Spectre V2 verdict.
## CVE-2019-1125 — Spectre SWAPGS gadget
- **Issue:** [#301](https://github.com/speed47/spectre-meltdown-checker/issues/301)
- **Kernel fix:** [commit 18ec54fdd6d1](https://github.com/torvalds/linux/commit/18ec54fdd6d18d92025af097cd042a75cf0ea24c) (Linux 5.3)
- **CVSS:** 5.6 (Medium)
- **Covered by:** CVE-2017-5753 (Spectre V1)
A Spectre V1 subvariant where the `SWAPGS` instruction can be speculatively executed on x86 CPUs, allowing an attacker to leak kernel memory via a side channel on the GS segment base value.
**Why out of scope:** This is a Spectre V1 subvariant whose mitigation (SWAPGS barriers) shares the same sysfs entry as CVE-2017-5753. This tool's existing CVE-2017-5753 checks already detect SWAPGS barriers: a mitigated kernel reports `"Mitigation: usercopy/swapgs barriers and __user pointer sanitization"`, while a kernel lacking the fix reports `"Vulnerable: __user pointer sanitization and usercopy barriers only; no swapgs barriers"`. CVE-2019-1125 is therefore fully covered as part of Spectre V1.
## CVE-2021-26341 — AMD Straight-Line Speculation (direct branches)
- **Bulletin:** [AMD-SB-1026](https://www.amd.com/en/resources/product-security/bulletin/amd-sb-1026.html)
- **Affected CPUs:** AMD Zen 1, Zen 2
- **CVSS:** 6.5 (Medium)
- **Covered by:** CVE-0000-0001 (SLS supplementary check)
AMD Zen 1/Zen 2 CPUs may transiently execute instructions beyond unconditional direct branches (JMP, CALL), potentially allowing information disclosure via side channels.
**Why out of scope:** This is the AMD-specific direct-branch subset of the broader Straight-Line Speculation (SLS) class. The kernel mitigates it via `CONFIG_MITIGATION_SLS` (formerly `CONFIG_SLS`), which enables the GCC flag `-mharden-sls=all` to insert INT3 after unconditional control flow instructions. Since this is a compile-time-only mitigation with no sysfs interface, no MSR, and no per-CVE CPU feature flag, it cannot be checked using the standard CVE framework. A supplementary SLS check is available via `--extra` mode, which covers this CVE's mitigation as well.
## CVE-2020-13844 — ARM Straight-Line Speculation
- **Advisory:** [ARM Developer Security Update (June 2020)](https://developer.arm.com/Arm%20Security%20Center/Speculative%20Processor%20Vulnerability)
- **Affected CPUs:** Cortex-A32, A34, A35, A53, A57, A72, A73, and broadly all speculative Armv8-A cores
- **CVSS:** 5.5 (Medium)
- **Covered by:** CVE-0000-0001 (SLS supplementary check)
ARM processors may speculatively execute instructions past unconditional control flow changes (RET, BR, BLR). GCC and Clang support `-mharden-sls=all` for aarch64, but the Linux kernel never merged the patches to enable it: a `CONFIG_HARDEN_SLS_ALL` series was submitted in 2021 but rejected upstream.
**Why out of scope:** This is the ARM-specific subset of the broader Straight-Line Speculation (SLS) class. The supplementary SLS check available via `--extra` mode detects affected ARM CPU models and reports that no kernel mitigation is currently available.
## CVE-2024-2201 — Native BHI (Branch History Injection without eBPF)
- **Issue:** [#491](https://github.com/speed47/spectre-meltdown-checker/issues/491)
- **Research:** [InSpectre Gadget / Native BHI (VUSec)](https://www.vusec.net/projects/native-bhi/)
- **Intel advisory:** [Branch History Injection (Intel)](https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/technical-documentation/branch-history-injection.html)
- **Affected CPUs:** Intel CPUs with eIBRS (Ice Lake+, 10th gen+, and virtualized Intel guests)
- **CVSS:** 4.7 (Medium)
- **Covered by:** CVE-2017-5715 (Spectre V2)
VUSec researchers demonstrated that the original BHI mitigation (disabling unprivileged eBPF) was insufficient: 1,511 native kernel gadgets exist that allow exploiting Branch History Injection without eBPF, leaking arbitrary kernel memory at ~3.5 kB/sec on Intel CPUs.
**Why out of scope:** CVE-2024-2201 is not a new hardware vulnerability — it is the same BHI hardware bug as CVE-2022-0002, but proves that eBPF restriction alone was never sufficient. The required mitigations are identical: `BHI_DIS_S` hardware control (MSR `IA32_SPEC_CTRL` bit 10), software BHB clearing loop at syscall entry and VM exit, or retpoline with RRSBA disabled. These are all already detected by this tool's CVE-2017-5715 (Spectre V2) checks, which parse the `BHI:` suffix from `/sys/devices/system/cpu/vulnerabilities/spectre_v2` and check for `CONFIG_MITIGATION_SPECTRE_BHI` in no-runtime mode. No new sysfs entry, MSR, kernel config option, or boot parameter was introduced for this CVE.
## CVE-2020-0549 — L1D Eviction Sampling (CacheOut)
- **Issue:** [#341](https://github.com/speed47/spectre-meltdown-checker/issues/341)
- **Advisory:** [INTEL-SA-00329](https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/advisory-guidance/l1d-eviction-sampling.html)
- **Affected CPUs:** Intel Skylake through 10th gen (Tiger Lake+ not affected)
- **CVSS:** 6.5 (Medium)
- **Covered by:** CVE-2018-12126 / CVE-2018-12127 / CVE-2018-12130 / CVE-2019-11091 (MDS) and CVE-2018-3646 (L1TF)
An Intel-specific data leakage vulnerability where L1 data cache evictions can be exploited in combination with MDS or TAA side channels to leak data across security boundaries.
**Why out of scope:** The June 2020 microcode update that addresses this CVE does not introduce any new MSR bits or CPUID flags — it reuses the existing MD_CLEAR (`CPUID.7.0:EDX[10]`) and L1D_FLUSH (`MSR_IA32_FLUSH_CMD`, 0x10B) infrastructure already deployed for MDS and L1TF. The Linux kernel has no dedicated sysfs entry in `/sys/devices/system/cpu/vulnerabilities/` for this CVE; instead, it provides an opt-in per-task L1D flush via `prctl(PR_SPEC_L1D_FLUSH)` and the `l1d_flush=on` boot parameter, which piggyback on the same L1D flush mechanism checked by the existing L1TF and MDS vulnerability modules. In practice, a system with up-to-date microcode and MDS/L1TF mitigations in place is already protected against L1D Eviction Sampling.
## CVE-2025-20623 — Shared Microarchitectural Predictor State (10th Gen Intel)
- **Advisory:** [INTEL-SA-01247](https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-01247.html)
- **Affected CPUs:** Intel 10th Generation Core Processors only
- **CVSS:** 5.6 (Medium)
- **Covered by:** CVE-2024-45332 (BPI)
Shared microarchitectural predictor state on 10th generation Intel CPUs may allow information disclosure.
**Why out of scope:** Very narrow scope (single CPU generation). Mitigated by the same microcode update as CVE-2024-45332 (BPI) and handled through the existing Spectre V2 framework. No dedicated sysfs entry or kernel mitigation beyond what BPI already provides.
## CVE-2025-24495 — Lion Cove BPU Initialization
- **Advisory:** [INTEL-SA-01322](https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-01322.html)
- **Research:** [Training Solo (VUSec)](https://www.vusec.net/projects/training-solo/)
- **Affected CPUs:** Intel Core Ultra with Lion Cove core only (Lunar Lake, Arrow Lake)
- **CVSS:** 6.8 (Medium, CVSS v4)
- **Covered by:** CVE-2024-28956 (ITS)
A branch predictor initialization issue specific to Intel's Lion Cove microarchitecture, discovered as part of the "Training Solo" research.
**Why out of scope:** This is a subset of the ITS (Indirect Target Selection) vulnerability (CVE-2024-28956). It shares the same sysfs entry (`/sys/devices/system/cpu/vulnerabilities/indirect_target_selection`) and kernel mitigation framework. Since ITS (CVE-2024-28956) is implemented in this tool, Lion Cove BPU is already covered automatically.
---
# No kernel or microcode mitigations to check
These CVEs are real vulnerabilities, but no kernel or microcode fix has been issued, the mitigation is delegated to individual software, or the fix is not detectable by this tool.
## CVE-2018-9056 — BranchScope
- **Issue:** [#169](https://github.com/speed47/spectre-meltdown-checker/issues/169)
- **Research paper:** [BranchScope (ASPLOS 2018)](http://www.cs.ucr.edu/~nael/pubs/asplos18.pdf)
- **Red Hat bug:** [#1561794](https://bugzilla.redhat.com/show_bug.cgi?id=1561794)
- **CVSS:** 5.6 (Medium)
A speculative execution attack exploiting the directional branch predictor, allowing an attacker to infer data by manipulating the shared branch prediction state (pattern history table). Initially demonstrated on Intel processors.
**Why out of scope:** No kernel or microcode mitigations have been issued. Red Hat closed their tracking bug as "CLOSED CANTFIX", concluding that "this is a hardware processor issue, not a Linux kernel flaw" and that "it is specific to a target software which uses sensitive information in branching expressions." The mitigation responsibility falls on individual software to avoid using sensitive data in conditional branches, which is out of the scope of this tool.
## CVE-2019-15902 — Spectre V1 backport regression
- **Issue:** [#304](https://github.com/speed47/spectre-meltdown-checker/issues/304)
- **CVSS:** 5.6 (Medium)
A backporting mistake in Linux stable/longterm kernel versions (4.4.x through 4.4.190, 4.9.x through 4.9.190, 4.14.x through 4.14.141, 4.19.x through 4.19.69, and 5.2.x through 5.2.11) swapped two code lines in `ptrace_get_debugreg()`, placing the `array_index_nospec()` call after the array access instead of before, reintroducing a Spectre V1 vulnerability.
**Why out of scope:** This is a kernel bug (bad backport), not a hardware vulnerability. The flawed code is not detectable on a running kernel without hardcoding kernel version ranges, which is against this tool's design principles. As the tool author noted: "it's going to be almost impossible to detect it on a running kernel."
## CVE-2020-12965 — Transient Execution of Non-Canonical Accesses (SLAM)
- **Issue:** [#478](https://github.com/speed47/spectre-meltdown-checker/issues/478)
- **Bulletin:** [AMD-SB-1010](https://www.amd.com/en/corporate/product-security/bulletin/amd-sb-1010)
- **Research paper:** [SLAM (VUSec)](https://www.vusec.net/projects/slam/)
- **CVSS:** 7.5 (High)
AMD CPUs may transiently execute non-canonical loads and stores using only the lower 48 address bits, potentially resulting in data leakage. The SLAM research (2023) demonstrated that this could be exploited on existing AMD Zen+/Zen2 CPUs and could also affect future CPUs with Intel LAM, AMD UAI, or ARM TBI features.
**Why out of scope:** AMD's mitigation guidance is for software vendors to "analyze their code for any potential vulnerabilities" and insert LFENCE or use existing speculation mitigation techniques in their own code. No microcode or kernel-level mitigations have been issued. The responsibility falls on individual software, not on the kernel or firmware, leaving nothing for this script to check.
## CVE-2020-24511 — Domain-Type Confusion (IBRS Scope)
- **Issue:** [#409](https://github.com/speed47/spectre-meltdown-checker/issues/409)
- **Advisory:** [INTEL-SA-00464](https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00464.html)
- **Affected CPUs:** Intel Skylake through Comet Lake (different steppings; see advisory for details)
- **CVSS:** 6.5 (Medium)
Improper isolation of shared resources in some Intel processors allows an authenticated user to potentially enable information disclosure via local access. Specifically, the Indirect Branch Restricted Speculation (IBRS) mitigation may not be fully applied after certain privilege-level transitions, allowing residual branch predictions to cross security boundaries.
**Why out of scope:** The mitigation is exclusively a microcode update (released June 2021) with no corresponding Linux kernel sysfs entry in `/sys/devices/system/cpu/vulnerabilities/`, no new CPUID bit, no new MSR, and no kernel configuration option. The only way to detect the fix would be to maintain a per-CPU-stepping minimum microcode version lookup table, which is brittle and high-maintenance. Additionally, Intel dropped microcode support for Sandy Bridge and Ivy Bridge in the same timeframe, leaving those generations permanently unpatched with no mitigation path available.
## CVE-2020-24512 — Observable Timing Discrepancy (Trivial Data Value)
- **Issue:** [#409](https://github.com/speed47/spectre-meltdown-checker/issues/409)
- **Advisory:** [INTEL-SA-00464](https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00464.html)
- **Affected CPUs:** Intel Skylake through Tiger Lake (broad scope; see advisory for details)
- **CVSS:** 2.8 (Low)
Observable timing discrepancy in some Intel processors allows an authenticated user to potentially enable information disclosure via local access. Certain cache optimizations treat "trivial data value" cache lines (e.g., all-zero lines) differently from non-trivial lines, creating a timing side channel that can distinguish memory content patterns.
**Why out of scope:** Like CVE-2020-24511, this is a microcode-only fix with no Linux kernel sysfs entry, no CPUID bit, no MSR, and no kernel configuration option. Detection would require a per-CPU-stepping microcode version lookup table. The vulnerability has low severity (CVSS 2.8) and practical exploitation is limited. Intel dropped microcode support for Sandy Bridge and Ivy Bridge, leaving those generations permanently vulnerable.
## CVE-2021-26318 — AMD Prefetch Attacks through Power and Time
- **Issue:** [#412](https://github.com/speed47/spectre-meltdown-checker/issues/412)
- **Bulletin:** [AMD-SB-1017](https://www.amd.com/en/resources/product-security/bulletin/amd-sb-1017.html)
- **Research paper:** [AMD Prefetch Attacks through Power and Time (USENIX Security '22)](https://www.usenix.org/conference/usenixsecurity22/presentation/lipp)
- **CVSS:** 5.5 (Medium)
The x86 PREFETCH instruction on AMD CPUs leaks timing and power information, enabling a microarchitectural KASLR bypass from unprivileged userspace. The researchers demonstrated kernel address space layout recovery and kernel memory leakage at ~52 B/s using Spectre gadgets.
**Why out of scope:** AMD acknowledged the research but explicitly stated they are "not recommending any mitigations at this time," as the attack leaks kernel address layout information (KASLR bypass) but does not directly leak kernel data across address space boundaries. KPTI was never enabled on AMD by default in the Linux kernel as a result. No microcode, kernel, or sysfs mitigations have been issued, leaving nothing for this script to check.
## CVE-2024-7881 — ARM Prefetcher Privilege Escalation
- **Affected CPUs:** Specific ARM cores only
- **CVSS:** 5.1 (Medium)
The prefetch engine on certain ARM cores can fetch data from privileged memory locations. Mitigation is disabling the affected prefetcher via the `CPUACTLR6_EL1[41]` register bit.
**Why out of scope:** ARM-specific with very narrow scope and no Linux sysfs integration. The mitigation is a per-core register tweak, not a kernel or microcode update detectable by this tool.
## CVE-2024-36348 — AMD Transient Scheduler Attack (UMIP bypass)
- **Bulletin:** [AMD-SB-7029](https://www.amd.com/en/resources/product-security/bulletin/amd-sb-7029.html)
- **CVSS:** 3.8 (Low)
A transient execution vulnerability in some AMD processors may allow a user process to speculatively infer CPU configuration registers even when UMIP is enabled.
**Why out of scope:** AMD has determined that "leakage of CPU Configuration does not result in leakage of sensitive information" and has marked this CVE as "No fix planned" across all affected product lines. No microcode or kernel mitigations have been issued, leaving nothing for this script to check.
## CVE-2024-36349 — AMD Transient Scheduler Attack (TSC_AUX leak)
- **Bulletin:** [AMD-SB-7029](https://www.amd.com/en/resources/product-security/bulletin/amd-sb-7029.html)
- **CVSS:** 3.8 (Low)
A transient execution vulnerability in some AMD processors may allow a user process to infer TSC_AUX even when such a read is disabled.
**Why out of scope:** AMD has determined that "leakage of TSC_AUX does not result in leakage of sensitive information" and has marked this CVE as "No fix planned" across all affected product lines. No microcode or kernel mitigations have been issued, leaving nothing for this script to check.
## No CVE — BlindSide (Speculative Probing)
- **Issue:** [#374](https://github.com/speed47/spectre-meltdown-checker/issues/374)
- **Research paper:** [Speculative Probing: Hacking Blind in the Spectre Era (VUSec, ACM CCS 2020)](https://www.vusec.net/projects/blindside/)
- **Red Hat advisory:** [Article 5394291](https://access.redhat.com/articles/5394291)
- **Affected CPUs:** All CPUs vulnerable to Spectre V2 (BTB-based speculative execution)
An attack technique that combines a pre-existing kernel memory corruption bug (e.g., a heap buffer overflow) with speculative execution to perform "Speculative BROP" (Blind Return-Oriented Programming). Instead of crashing the system when probing invalid addresses, BlindSide performs the probing speculatively: faults are suppressed in the speculative domain, and information is leaked via cache timing side channels. This allows an attacker to silently derandomize kernel memory layout and bypass KASLR/FGKASLR without triggering any fault.
**Why out of scope:** BlindSide is an exploitation technique, not a discrete hardware vulnerability: no CVE was assigned. Red Hat explicitly states it is "not a new flaw, but a new attack." It requires a pre-existing kernel memory corruption bug as a prerequisite, and the speculative execution aspect leverages the same BTB behavior as Spectre V2 (CVE-2017-5715). No dedicated microcode update, kernel config, MSR, CPUID bit, or sysfs entry exists for BlindSide. The closest hardware mitigations (IBPB, IBRS, STIBP, Retpoline) are already covered by this tool's Spectre V2 checks.
## No CVE — TLBleed (TLB side-channel)
- **Issue:** [#231](https://github.com/speed47/spectre-meltdown-checker/issues/231)
- **Research paper:** [Defeating Cache Side-channel Protections with TLB Attacks (VUSec, USENIX Security '18)](https://www.vusec.net/projects/tlbleed/)
- **Red Hat blog:** [Temporal side-channels and you: Understanding TLBleed](https://www.redhat.com/en/blog/temporal-side-channels-and-you-understanding-tlbleed)
- **Affected CPUs:** Intel CPUs with Hyper-Threading (demonstrated on Skylake, Coffee Lake, Broadwell Xeon)
A timing side-channel attack exploiting the shared Translation Lookaside Buffer (TLB) on Intel hyperthreaded CPUs. By using machine learning to analyze TLB hit/miss timing patterns, an attacker co-located on the same physical core can extract cryptographic keys (demonstrated with 99.8% success rate on a 256-bit EdDSA key). OpenBSD disabled Hyper-Threading by default in response.
**Why out of scope:** No CVE was ever assigned — Intel explicitly declined to request one. Intel stated the attack is "not related to Spectre or Meltdown" and has no plans to issue a microcode fix, pointing to existing constant-time coding practices in cryptographic software as the appropriate defense. No Linux kernel mitigation was ever merged. Red Hat's guidance was limited to operational advice (disable SMT, use CPU pinning) rather than a software fix. The only OS-level response was OpenBSD disabling Hyper-Threading by default. With no CVE, no microcode update, and no kernel mitigation, there is nothing for this script to check.
---
# Not a transient/speculative execution vulnerability
These are hardware flaws but not side-channel or speculative execution issues. They fall outside the vulnerability class this tool is designed to detect.
## CVE-2019-11157 — Plundervolt (VoltJockey)
- **Issue:** [#335](https://github.com/speed47/spectre-meltdown-checker/issues/335)
- **Advisory:** [INTEL-SA-00289](https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00289.html)
- **Research:** [Plundervolt (plundervolt.com)](https://plundervolt.com/)
- **Affected CPUs:** Intel Core 6th10th gen (Skylake through Comet Lake) with SGX
- **CVSS:** 7.1 (High)
A voltage fault injection attack where a privileged attacker (ring 0) uses the software-accessible voltage scaling interface to undervolt the CPU during SGX enclave computations, inducing predictable bit flips that compromise enclave integrity and confidentiality. Intel's microcode fix locks down the voltage/frequency scaling MSRs to prevent software-initiated undervolting.
**Why out of scope:** Not a transient or speculative execution vulnerability — this is a fault injection attack exploiting voltage manipulation, with no side-channel or speculative execution component. It requires ring 0 access and targets SGX enclaves specifically. While Intel issued a microcode update that locks voltage controls, there is no Linux kernel sysfs entry, no CPUID flag, and no kernel-side mitigation to detect. The fix is purely a microcode-level lockdown of voltage scaling registers, which is not exposed in any standard interface this tool can query.
## CVE-2020-8694 / CVE-2020-8695 — Platypus (RAPL Power Side Channel)
- **Issue:** [#384](https://github.com/speed47/spectre-meltdown-checker/issues/384)
- **Advisory:** [INTEL-SA-00389](https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00389.html)
- **Research:** [PLATYPUS (platypusattack.com)](https://platypusattack.com/)
- **Affected CPUs:** Intel Core (Sandy Bridge+), Intel Xeon (Sandy Bridge-EP+)
- **CVSS:** 5.6 (Medium) / 6.5 (Medium)
A software-based power side-channel attack exploiting Intel's Running Average Power Limit (RAPL) interface. By monitoring energy consumption reported through the `powercap` sysfs interface or the `MSR_RAPL_POWER_UNIT` / `MSR_PKG_ENERGY_STATUS` MSRs, an unprivileged attacker can statistically distinguish instructions and operands, recover AES-NI keys from SGX enclaves, and break kernel ASLR.
**Why out of scope:** Not a transient or speculative execution vulnerability — this is a power analysis side-channel attack with no speculative execution component. The mitigations (microcode update restricting RAPL energy reporting to privileged access, and kernel restricting the `powercap` sysfs interface) are not exposed via `/sys/devices/system/cpu/vulnerabilities/`. There is no dedicated sysfs vulnerability entry, no CPUID flag, and no kernel configuration option for this tool to check.
## CVE-2023-31315 — SinkClose (AMD SMM Lock Bypass)
- **Issue:** [#499](https://github.com/speed47/spectre-meltdown-checker/issues/499)
- **Bulletin:** [AMD-SB-7014](https://www.amd.com/en/resources/product-security/bulletin/amd-sb-7014.html)
- **Research:** [AMD SinkClose (IOActive, DEF CON 32)](https://www.ioactive.com/resources/amd-sinkclose-universal-ring-2-privilege-escalation)
- **Affected CPUs:** AMD Zen 15 (EPYC, Ryzen, Threadripper, Embedded)
- **CVSS:** 7.5 (High)
Improper validation in a model-specific register (MSR) allows a program with ring 0 (kernel) access to modify System Management Mode (SMM) configuration while SMI lock is enabled, escalating privileges from ring 0 to ring -2 (SMM). AMD provides two mitigation paths: BIOS/AGESA firmware updates (all product lines) and hot-loadable microcode updates (EPYC server processors only).
**Why out of scope:** Not a transient or speculative execution vulnerability — this is a privilege escalation via MSR manipulation, with no side-channel component. It requires ring 0 access as a prerequisite, fundamentally different from Spectre/Meltdown-class attacks where unprivileged code can leak data across privilege boundaries. There is no Linux kernel sysfs entry and no kernel-side mitigation. Although AMD provides hot-loadable microcode for some EPYC processors, the client and embedded product lines are mitigated only through BIOS firmware updates, which this tool cannot detect.
## CVE-2024-56161 — EntrySign (AMD Microcode Signature Bypass)
- **Affected CPUs:** AMD Zen 1-5
- **CVSS:** 7.2 (High)
A weakness in AMD's microcode signature verification (AES-CMAC hash) allows loading arbitrary unsigned microcode with administrator privileges.
**Why out of scope:** This is a microcode integrity/authentication issue, not a speculative execution vulnerability. It does not involve transient execution side channels and is outside the scope of this tool.
## CVE-2025-29943 — StackWarp (AMD SEV-SNP)
- **Affected CPUs:** AMD Zen 1-5
- **CVSS:** Low
Exploits a synchronization failure in the AMD stack engine via an undocumented MSR bit, targeting AMD SEV-SNP confidential VMs. Requires hypervisor-level (ring 0) access.
**Why out of scope:** Not a transient/speculative execution side channel. This is an architectural attack on AMD SEV-SNP confidential computing that requires hypervisor access, which is outside the threat model of this tool.

View File

@@ -1,391 +0,0 @@
# 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.
```sh
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](README.md#operating-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 |
| `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:**
```json
"meta": {
"script_version": "25.30.025040123",
"format_version": 1,
"timestamp": "2025-04-07T12:00:00Z",
"os": "Linux",
"mode": "live",
"run_as_root": true,
"reduced_accuracy": false,
"paranoid": false,
"sysfs_only": 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.
The object uses `arch` as a discriminator: `"x86"` for Intel/AMD/Hygon CPUs,
`"arm"` for ARM/Cavium/Phytium. Arch-specific fields live under a matching
sub-object (`cpu.x86` or `cpu.arm`), so consumers never see irrelevant null
fields from the other architecture.
#### Common fields
| Field | Type | Values | Meaning |
|---|---|---|---|
| `arch` | string | `"x86"` / `"arm"` | CPU architecture family; determines which sub-object is present |
| `vendor` | string \| null | e.g. `"GenuineIntel"`, `"ARM"` | CPU vendor string |
| `friendly_name` | string \| null | e.g. `"Intel(R) Core(TM) i7-9700K CPU @ 3.60GHz"` | Human-readable CPU model |
#### `cpu.x86` (present when `arch == "x86"`)
| Field | Type | Values | Meaning |
|---|---|---|---|
| `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 |
| `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 |
| `capabilities` | object | | CPU feature flags (see below) |
#### `cpu.arm` (present when `arch == "arm"`)
| Field | Type | Values | Meaning |
|---|---|---|---|
| `part_list` | string \| null | e.g. `"0xd0b 0xd05"` | Space-separated ARM part numbers across cores (big.LITTLE may have several) |
| `arch_list` | string \| null | e.g. `"8 8"` | Space-separated ARM architecture levels across cores |
| `capabilities` | object | | ARM-specific capability flags (currently empty; reserved for future use) |
#### `cpu.x86.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:**
```json
{
"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)**
On ARM, `cpu.arch` is `"arm"` and the `cpu.arm` sub-object carries `part_list`
and `arch_list`. The x86-specific sub-object is absent (no null noise).
`cpu.arm.capabilities` is currently empty; ARM-specific flags will be added
there as needed.
**`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:
```json
[
{"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.

View File

@@ -1,382 +0,0 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://github.com/speed47/spectre-meltdown-checker/dist/batch_json.schema.json",
"title": "spectre-meltdown-checker --batch json output",
"description": "Schema for the comprehensive JSON output produced by spectre-meltdown-checker.sh --batch json. format_version 1.",
"type": "object",
"required": ["meta", "system", "cpu", "cpu_microcode", "vulnerabilities"],
"additionalProperties": false,
"properties": {
"meta": {
"description": "Run metadata and option flags.",
"type": "object",
"required": [
"script_version", "format_version", "timestamp", "os", "mode",
"run_as_root", "reduced_accuracy", "paranoid", "sysfs_only",
"extra", "mocked"
],
"additionalProperties": false,
"properties": {
"script_version": {
"description": "Script version string, e.g. '25.30.0250400123'.",
"type": ["string", "null"]
},
"format_version": {
"description": "JSON schema version. Incremented on backward-incompatible changes. Current value: 1.",
"type": "integer",
"const": 1
},
"timestamp": {
"description": "ISO 8601 UTC timestamp of when the scan started, e.g. '2025-04-07T12:00:00Z'.",
"type": ["string", "null"]
},
"os": {
"description": "Operating system name from uname -s, e.g. 'Linux', 'FreeBSD'.",
"type": ["string", "null"]
},
"mode": {
"description": "Operating mode: 'live' (default), 'no-runtime' (--no-runtime), 'no-hw' (--no-hw), or 'hw-only' (--hw-only).",
"type": "string",
"enum": ["live", "no-runtime", "no-hw", "hw-only"]
},
"run_as_root": {
"description": "Whether the script ran as root. Non-root scans skip MSR reads and may produce incomplete or inaccurate results.",
"type": "boolean"
},
"reduced_accuracy": {
"description": "True when the kernel image, config, or System.map was missing. Some checks fall back to weaker heuristics.",
"type": ["boolean", "null"]
},
"paranoid": {
"description": "True when --paranoid was set: stricter criteria (e.g. requires SMT disabled, IBPB always-on).",
"type": "boolean"
},
"sysfs_only": {
"description": "True when --sysfs-only was set: the script trusted the kernel's own sysfs report without independent detection.",
"type": "boolean"
},
"extra": {
"description": "True when --extra was set: additional experimental checks were enabled.",
"type": "boolean"
},
"mocked": {
"description": "True when one or more CPU values were overridden for testing. Results do NOT reflect the real system.",
"type": ["boolean", "null"]
}
}
},
"system": {
"description": "Kernel and host environment context.",
"type": ["object", "null"],
"required": [
"kernel_release", "kernel_version", "kernel_arch",
"kernel_image", "kernel_config", "kernel_version_string",
"kernel_cmdline", "cpu_count", "smt_enabled",
"hypervisor_host", "hypervisor_host_reason"
],
"additionalProperties": false,
"properties": {
"kernel_release": {
"description": "Output of uname -r (live mode only), e.g. '6.1.0-21-amd64'. Null in other modes.",
"type": ["string", "null"]
},
"kernel_version": {
"description": "Output of uname -v (live mode only), e.g. '#1 SMP Debian …'. Null in other modes.",
"type": ["string", "null"]
},
"kernel_arch": {
"description": "Output of uname -m (live mode only), e.g. 'x86_64'. Null in other modes.",
"type": ["string", "null"]
},
"kernel_image": {
"description": "Path to the kernel image passed via --kernel. Null in live mode.",
"type": ["string", "null"]
},
"kernel_config": {
"description": "Path to the kernel config passed via --config. Null if not provided.",
"type": ["string", "null"]
},
"kernel_version_string": {
"description": "Kernel version banner extracted from the image. Null if unavailable.",
"type": ["string", "null"]
},
"kernel_cmdline": {
"description": "Kernel command line from /proc/cmdline (live mode) or the image. Null if unavailable.",
"type": ["string", "null"]
},
"cpu_count": {
"description": "Number of logical CPUs detected (max core ID + 1). Null if undeterminable.",
"type": ["integer", "null"],
"minimum": 1
},
"smt_enabled": {
"description": "Whether SMT (HyperThreading) is currently enabled. Null if the script could not determine the state.",
"type": ["boolean", "null"]
},
"hypervisor_host": {
"description": "Whether this machine is detected as a VM host (running KVM, Xen, VMware, etc.). Null if undeterminable.",
"type": ["boolean", "null"]
},
"hypervisor_host_reason": {
"description": "Human-readable explanation of why hypervisor_host was set. Null if hypervisor_host is false or null.",
"type": ["string", "null"]
}
}
},
"cpu": {
"description": "CPU hardware identification. Null when --no-hw is active. Contains an 'arch' discriminator ('x86' or 'arm') and a matching arch-specific sub-object with identification fields and capabilities.",
"oneOf": [
{ "type": "null" },
{
"type": "object",
"description": "x86 CPU (Intel, AMD, Hygon).",
"required": ["arch", "vendor", "friendly_name", "x86"],
"additionalProperties": false,
"properties": {
"arch": { "type": "string", "const": "x86" },
"vendor": {
"description": "CPU vendor string: 'GenuineIntel', 'AuthenticAMD', or 'HygonGenuine'.",
"type": ["string", "null"]
},
"friendly_name": {
"description": "Human-readable CPU model from /proc/cpuinfo, e.g. 'Intel(R) Core(TM) i7-9700K CPU @ 3.60GHz'.",
"type": ["string", "null"]
},
"x86": {
"type": "object",
"required": ["family", "model", "stepping", "cpuid", "platform_id", "hybrid", "codename", "capabilities"],
"additionalProperties": false,
"properties": {
"family": {
"description": "CPU family number.",
"type": ["integer", "null"]
},
"model": {
"description": "CPU model number.",
"type": ["integer", "null"]
},
"stepping": {
"description": "CPU stepping number.",
"type": ["integer", "null"]
},
"cpuid": {
"description": "Full CPUID leaf 1 EAX value as a hex string, e.g. '0x000906ed'.",
"type": ["string", "null"],
"pattern": "^0x[0-9a-f]+$"
},
"platform_id": {
"description": "Intel platform ID from MSR 0x17. Null on AMD.",
"type": ["integer", "null"]
},
"hybrid": {
"description": "Whether this is a hybrid CPU (P-cores + E-cores, e.g. Alder Lake). Null if undeterminable.",
"type": ["boolean", "null"]
},
"codename": {
"description": "Intel CPU codename, e.g. 'Coffee Lake'. Null on AMD.",
"type": ["string", "null"]
},
"capabilities": {
"description": "CPU feature flags detected via CPUID and MSR reads. Each value is true (present), false (absent), or null (not applicable or could not be read).",
"type": "object",
"additionalProperties": false,
"properties": {
"spec_ctrl": { "type": ["boolean", "null"], "description": "SPEC_CTRL MSR present (Intel; enables IBRS + IBPB via WRMSR)" },
"ibrs": { "type": ["boolean", "null"], "description": "Indirect Branch Restricted Speculation" },
"ibpb": { "type": ["boolean", "null"], "description": "Indirect Branch Prediction Barrier" },
"ibpb_ret": { "type": ["boolean", "null"], "description": "IBPB on return (enhanced form)" },
"stibp": { "type": ["boolean", "null"], "description": "Single Thread Indirect Branch Predictors" },
"ssbd": { "type": ["boolean", "null"], "description": "Speculative Store Bypass Disable" },
"l1d_flush": { "type": ["boolean", "null"], "description": "L1D cache flush instruction" },
"md_clear": { "type": ["boolean", "null"], "description": "VERW clears CPU buffers (MDS mitigation)" },
"arch_capabilities": { "type": ["boolean", "null"], "description": "IA32_ARCH_CAPABILITIES MSR is present" },
"rdcl_no": { "type": ["boolean", "null"], "description": "Not susceptible to RDCL (Meltdown-like attacks)" },
"ibrs_all": { "type": ["boolean", "null"], "description": "Enhanced IBRS always-on mode supported" },
"rsba": { "type": ["boolean", "null"], "description": "RSB may use return predictions from outside the RSB" },
"l1dflush_no": { "type": ["boolean", "null"], "description": "Not susceptible to L1D flush side-channel" },
"ssb_no": { "type": ["boolean", "null"], "description": "Not susceptible to Speculative Store Bypass" },
"mds_no": { "type": ["boolean", "null"], "description": "Not susceptible to MDS" },
"taa_no": { "type": ["boolean", "null"], "description": "Not susceptible to TSX Asynchronous Abort" },
"pschange_msc_no": { "type": ["boolean", "null"], "description": "Page-size-change MSC not susceptible" },
"tsx_ctrl_msr": { "type": ["boolean", "null"], "description": "TSX_CTRL MSR is present" },
"tsx_ctrl_rtm_disable": { "type": ["boolean", "null"], "description": "RTM disabled via TSX_CTRL" },
"tsx_ctrl_cpuid_clear": { "type": ["boolean", "null"], "description": "CPUID HLE/RTM bits cleared via TSX_CTRL" },
"gds_ctrl": { "type": ["boolean", "null"], "description": "GDS_CTRL MSR present" },
"gds_no": { "type": ["boolean", "null"], "description": "Not susceptible to Gather Data Sampling" },
"gds_mitg_dis": { "type": ["boolean", "null"], "description": "GDS mitigation disabled" },
"gds_mitg_lock": { "type": ["boolean", "null"], "description": "GDS mitigation locked" },
"rfds_no": { "type": ["boolean", "null"], "description": "Not susceptible to Register File Data Sampling" },
"rfds_clear": { "type": ["boolean", "null"], "description": "VERW clears register file stale data" },
"its_no": { "type": ["boolean", "null"], "description": "Not susceptible to Indirect Target Selection" },
"sbdr_ssdp_no": { "type": ["boolean", "null"], "description": "Not susceptible to SBDR/SSDP" },
"fbsdp_no": { "type": ["boolean", "null"], "description": "Not susceptible to FBSDP" },
"psdp_no": { "type": ["boolean", "null"], "description": "Not susceptible to PSDP" },
"fb_clear": { "type": ["boolean", "null"], "description": "Fill buffer cleared on idle/C6" },
"rtm": { "type": ["boolean", "null"], "description": "Restricted Transactional Memory (TSX RTM) present" },
"tsx_force_abort": { "type": ["boolean", "null"], "description": "TSX_FORCE_ABORT MSR present" },
"tsx_force_abort_rtm_disable": { "type": ["boolean", "null"], "description": "RTM disabled via TSX_FORCE_ABORT" },
"tsx_force_abort_cpuid_clear": { "type": ["boolean", "null"], "description": "CPUID RTM cleared via TSX_FORCE_ABORT" },
"sgx": { "type": ["boolean", "null"], "description": "Software Guard Extensions present" },
"srbds": { "type": ["boolean", "null"], "description": "SRBDS affected" },
"srbds_on": { "type": ["boolean", "null"], "description": "SRBDS mitigation active" },
"amd_ssb_no": { "type": ["boolean", "null"], "description": "AMD: not susceptible to Speculative Store Bypass" },
"hygon_ssb_no": { "type": ["boolean", "null"], "description": "Hygon: not susceptible to Speculative Store Bypass" },
"ipred": { "type": ["boolean", "null"], "description": "Indirect Predictor Barrier support" },
"rrsba": { "type": ["boolean", "null"], "description": "Restricted RSB Alternate (Intel Retbleed mitigation)" },
"bhi": { "type": ["boolean", "null"], "description": "Branch History Injection mitigation support" },
"tsa_sq_no": { "type": ["boolean", "null"], "description": "Not susceptible to TSA-SQ" },
"tsa_l1_no": { "type": ["boolean", "null"], "description": "Not susceptible to TSA-L1" },
"verw_clear": { "type": ["boolean", "null"], "description": "VERW clears CPU buffers" },
"autoibrs": { "type": ["boolean", "null"], "description": "AMD AutoIBRS (equivalent to enhanced IBRS on Intel)" },
"sbpb": { "type": ["boolean", "null"], "description": "Selective Branch Predictor Barrier (AMD Inception mitigation)" },
"avx2": { "type": ["boolean", "null"], "description": "AVX2 supported (relevant to Downfall / GDS)" },
"avx512": { "type": ["boolean", "null"], "description": "AVX-512 supported (relevant to Downfall / GDS)" }
}
}
}
}
}
},
{
"type": "object",
"description": "ARM CPU (ARM, Cavium, Phytium).",
"required": ["arch", "vendor", "friendly_name", "arm"],
"additionalProperties": false,
"properties": {
"arch": { "type": "string", "const": "arm" },
"vendor": {
"description": "CPU vendor string: 'ARM', 'CAVIUM', or 'PHYTIUM'.",
"type": ["string", "null"]
},
"friendly_name": {
"description": "Human-readable CPU model, e.g. 'ARM v8 model 0xd0b'.",
"type": ["string", "null"]
},
"arm": {
"type": "object",
"required": ["part_list", "arch_list", "capabilities"],
"additionalProperties": false,
"properties": {
"part_list": {
"description": "Space-separated list of ARM part numbers detected across cores, e.g. '0xd0b 0xd05' (big.LITTLE).",
"type": ["string", "null"]
},
"arch_list": {
"description": "Space-separated list of ARM architecture levels detected across cores, e.g. '8 8'.",
"type": ["string", "null"]
},
"capabilities": {
"description": "ARM-specific CPU capability flags. Currently empty; reserved for future use.",
"type": "object",
"additionalProperties": false,
"properties": {}
}
}
}
}
}
]
},
"cpu_microcode": {
"description": "Microcode version and firmware database status. Null under the same conditions as cpu.",
"type": ["object", "null"],
"required": [
"installed_version", "latest_version", "microcode_up_to_date",
"is_blacklisted", "message", "db_source", "db_info"
],
"additionalProperties": false,
"properties": {
"installed_version": {
"description": "Currently running microcode revision as a hex string, e.g. '0xf4'. Null if unreadable.",
"type": ["string", "null"],
"pattern": "^0x[0-9a-f]+$"
},
"latest_version": {
"description": "Latest known-good microcode version from the firmware database, as a hex string. Null if the CPU is not in the database.",
"type": ["string", "null"],
"pattern": "^0x[0-9a-f]+$"
},
"microcode_up_to_date": {
"description": "True when installed_version equals latest_version. Null if either is unavailable.",
"type": ["boolean", "null"]
},
"is_blacklisted": {
"description": "True when the installed microcode is known to cause instability and must be rolled back immediately.",
"type": "boolean"
},
"message": {
"description": "Human-readable note from the firmware database (e.g. changelog excerpt). Null if absent.",
"type": ["string", "null"]
},
"db_source": {
"description": "Which firmware database was used, e.g. 'Intel-SA', 'MCExtractor'. Null if unavailable.",
"type": ["string", "null"]
},
"db_info": {
"description": "Firmware database revision or date string. Null if unavailable.",
"type": ["string", "null"]
}
}
},
"vulnerabilities": {
"description": "Array of CVE check results, one per checked CVE, in check order.",
"type": "array",
"items": {
"type": "object",
"required": [
"cve", "name", "aliases", "cpu_affected",
"status", "vulnerable", "info",
"sysfs_status", "sysfs_message"
],
"additionalProperties": false,
"properties": {
"cve": {
"description": "CVE identifier, e.g. 'CVE-2017-5753'. May be 'CVE-0000-0001' for non-CVE checks such as SLS.",
"type": "string",
"pattern": "^CVE-[0-9]{4}-[0-9]+$"
},
"name": {
"description": "Short key name used across batch formats, e.g. 'SPECTRE VARIANT 1'.",
"type": "string"
},
"aliases": {
"description": "Full name including all known aliases, e.g. 'Spectre Variant 1, bounds check bypass'. Null if not in the registry.",
"type": ["string", "null"]
},
"cpu_affected": {
"description": "Whether this CPU's hardware design is affected by this CVE. False when hardware is architecturally immune.",
"type": "boolean"
},
"status": {
"description": "Check outcome: 'OK'=not vulnerable or unaffected, 'VULN'=vulnerable, 'UNK'=could not determine.",
"type": "string",
"enum": ["OK", "VULN", "UNK"]
},
"vulnerable": {
"description": "Boolean encoding of status: false=OK, true=VULN, null=UNK.",
"type": ["boolean", "null"]
},
"info": {
"description": "Human-readable description of the specific mitigation state or reason for the verdict.",
"type": "string"
},
"sysfs_status": {
"description": "Status as reported by the kernel via /sys/devices/system/cpu/vulnerabilities/. Null if sysfs was not consulted for this CVE (older kernels, or CVE not tracked by the kernel).",
"type": ["string", "null"],
"enum": ["OK", "VULN", "UNK", null]
},
"sysfs_message": {
"description": "Raw text from the sysfs vulnerability file, e.g. 'Mitigation: PTI'. Null if sysfs was not consulted.",
"type": ["string", "null"]
}
}
}
}
}
}

View File

@@ -1,149 +0,0 @@
# NRPE Output Format
`--batch nrpe` produces output that conforms to the
[Nagios Plugin Development Guidelines](https://nagios-plugins.org/doc/guidelines.html),
making it directly consumable by Nagios, Icinga, Zabbix (via NRPE), and
compatible monitoring stacks.
```sh
sudo ./spectre-meltdown-checker.sh --batch nrpe
```
## Output structure
The plugin emits one mandatory status line followed by optional long output:
```
STATUS: summary | checked=N vulnerable=N unknown=N
NOTE: ... ← context notes (when applicable)
[CRITICAL] CVE-XXXX-YYYY (NAME): description
[UNKNOWN] CVE-XXXX-YYYY (NAME): description
```
### Line 1 (status line)
Always present. Parsed by every Nagios-compatible monitoring system.
```
STATUS: summary | perfdata
```
| Field | Values | Meaning |
|---|---|---|
| `STATUS` | `OK` / `CRITICAL` / `UNKNOWN` | Overall check outcome (see below) |
| `summary` | human-readable string | Count and CVE IDs of affected checks |
| `perfdata` | `checked=N vulnerable=N unknown=N` | Machine-readable counters for graphing |
#### Status values
| Status | Exit code | Condition |
|---|---|---|
| `OK` | `0` | All CVE checks passed |
| `CRITICAL` | `2` | At least one CVE is vulnerable |
| `UNKNOWN` | `3` | No VULN found, but at least one check is inconclusive **or** the script was not run as root and found apparent vulnerabilities (see below) |
#### Summary format
| Condition | Summary |
|---|---|
| All OK | `All N CVE checks passed` |
| VULN only | `N/T CVE(s) vulnerable: CVE-A CVE-B ...` |
| VULN + UNK | `N/T CVE(s) vulnerable: CVE-A CVE-B ..., M inconclusive` |
| UNK only | `N/T CVE checks inconclusive` |
| Non-root + VULN | `N/T CVE(s) appear vulnerable (unconfirmed, not root): CVE-A ...` |
### Lines 2+ (long output)
Shown in the detail/extended info view of most monitoring frontends.
Never parsed by the monitoring core; safe to add or reorder.
#### Context notes
Printed before per-CVE details when applicable:
| Note | Condition |
|---|---|
| `NOTE: paranoid mode active, stricter mitigation requirements applied` | `--paranoid` was used |
| `NOTE: hypervisor host detected (reason); L1TF/MDS severity is elevated` | System is a VM host (KVM, Xen, VMware…) |
| `NOTE: not a hypervisor host` | System is confirmed not a VM host |
| `NOTE: not running as root; MSR reads skipped, results may be incomplete` | Script ran without root privileges |
#### Per-CVE detail lines
One line per non-OK CVE. VULN entries (`[CRITICAL]`) appear before UNK
entries (`[UNKNOWN]`); within each group the order follows the CVE registry.
```
[CRITICAL] CVE-XXXX-YYYY (SHORT NAME): mitigation status description
[UNKNOWN] CVE-XXXX-YYYY (SHORT NAME): reason check was inconclusive
```
## Exit codes
| Code | Nagios meaning | Condition |
|---|---|---|
| `0` | OK | All checked CVEs are mitigated or hardware-unaffected |
| `2` | CRITICAL | At least one CVE is vulnerable (script ran as root) |
| `3` | UNKNOWN | At least one check inconclusive, or apparent VULN found without root |
| `255` | - | Script error (bad arguments, unsupported platform) |
Exit code `1` (WARNING) is not used; there is no "degraded but acceptable"
state for CPU vulnerability mitigations.
## Non-root behaviour
Running without root privileges skips MSR reads and limits access to some
kernel interfaces. When the script finds apparent vulnerabilities without root:
- The status word becomes `UNKNOWN` instead of `CRITICAL`
- The exit code is `3` instead of `2`
- The summary says `appear vulnerable (unconfirmed, not root)`
- A `NOTE: not running as root` line is added to the long output
**Recommendation:** always run with `sudo` for authoritative results. A
`CRITICAL` from a root-run scan is a confirmed vulnerability; an `UNKNOWN`
from a non-root scan is a signal to investigate further.
## Hypervisor hosts
When `NOTE: hypervisor host detected` is present, L1TF (CVE-2018-3646) and
MDS (CVE-2018-12126/12130/12127) carry significantly higher risk because
they can be exploited across VM boundaries by a malicious guest. Prioritise
remediation on these hosts.
## Examples
**All mitigated (root):**
```
OK: All 31 CVE checks passed | checked=31 vulnerable=0 unknown=0
NOTE: not a hypervisor host
```
Exit: `0`
**Two CVEs vulnerable (root):**
```
CRITICAL: 2/31 CVE(s) vulnerable: CVE-2018-3615 CVE-2019-11135 | checked=31 vulnerable=2 unknown=0
NOTE: not a hypervisor host
[CRITICAL] CVE-2018-3615 (L1TF SGX): your CPU supports SGX and the microcode is not up to date
[CRITICAL] CVE-2019-11135 (TAA): Your kernel doesn't support TAA mitigation, update it
```
Exit: `2`
**Apparent vulnerabilities, non-root scan:**
```
UNKNOWN: 2/31 CVE(s) appear vulnerable (unconfirmed, not root): CVE-2018-3615 CVE-2019-11135 | checked=31 vulnerable=2 unknown=0
NOTE: not a hypervisor host
NOTE: not running as root; MSR reads skipped, results may be incomplete
[CRITICAL] CVE-2018-3615 (L1TF SGX): your CPU supports SGX and the microcode is not up to date
[CRITICAL] CVE-2019-11135 (TAA): Your kernel doesn't support TAA mitigation, update it
```
Exit: `3`
**Inconclusive checks, paranoid mode, VMM host:**
```
UNKNOWN: 3/31 CVE checks inconclusive | checked=31 vulnerable=0 unknown=3
NOTE: paranoid mode active, stricter mitigation requirements applied
NOTE: hypervisor host detected (kvm); L1TF/MDS severity is elevated
[UNKNOWN] CVE-2018-3646 (L1TF VMM): SMT is enabled on a hypervisor host, not mitigated under paranoid mode
```
Exit: `3`

View File

@@ -1,377 +0,0 @@
# Prometheus Batch Mode
`--batch prometheus` emits Prometheus text-format metrics that can be fed into any
Prometheus-compatible monitoring stack. It is designed for **fleet-scale security
monitoring**: run the script periodically on every host, push the output to a
Prometheus Pushgateway (or drop it into a node_exporter textfile directory), then
alert and dashboard from Prometheus/Grafana like any other infrastructure metric.
---
## Quick start
### Pushgateway (recommended for cron/batch fleet scans)
```sh
#!/bin/sh
PUSHGATEWAY="http://pushgateway.internal:9091"
INSTANCE=$(hostname -f)
spectre-meltdown-checker.sh --batch prometheus \
| curl --silent --show-error --data-binary @- \
"${PUSHGATEWAY}/metrics/job/smc/instance/${INSTANCE}"
```
Run this as root via cron or a systemd timer on every host. The Pushgateway
retains the last pushed value, so Prometheus scrapes it on its own schedule.
A stale-data alert (`smc_last_scan_timestamp_seconds`) catches hosts that stopped
reporting.
### node_exporter textfile collector
```sh
#!/bin/sh
TEXTFILE_DIR="/var/lib/node_exporter/textfile_collector"
TMP="${TEXTFILE_DIR}/smc.prom.$$"
spectre-meltdown-checker.sh --batch prometheus > "$TMP"
mv "$TMP" "${TEXTFILE_DIR}/smc.prom"
```
The atomic `mv` prevents node_exporter from reading a partially written file.
node_exporter must be started with `--collector.textfile.directory` pointing at
`TEXTFILE_DIR`.
---
## Metric reference
All metric names are prefixed `smc_` (spectre-meltdown-checker). All metrics
are **gauges**: they represent the state at the time of the scan, not a running
counter.
---
### `smc_build_info`
Script metadata. Always value `1`; all data is in labels.
| Label | Values | Meaning |
|---|---|---|
| `version` | string | Script version (e.g. `25.30.0250400123`) |
| `mode` | `live` / `offline` | `live` = running on the active kernel; `offline` = inspecting a kernel image |
| `run_as_root` | `true` / `false` | Whether the script ran as root. Non-root scans skip MSR reads and may miss mitigations |
| `paranoid` | `true` / `false` | `--paranoid` mode: stricter criteria (e.g. requires SMT disabled) |
| `sysfs_only` | `true` / `false` | `--sysfs-only` mode: only the kernel's own sysfs report was used, not independent detection |
| `reduced_accuracy` | `true` / `false` | Kernel information was incomplete (no kernel image, config, or map); some checks may be less precise |
| `mocked` | `true` / `false` | Debug/test mode: CPU values were overridden. Results do **not** reflect the real system |
**Example:**
```
smc_build_info{version="25.30.0250400123",mode="live",run_as_root="true",paranoid="false",sysfs_only="false",reduced_accuracy="false",mocked="false"} 1
```
**Important labels for fleet operators:**
- `run_as_root="false"` means the scan was incomplete. Treat those results as
lower confidence and alert separately.
- `sysfs_only="true"` means the script trusted the kernel's self-report without
independent verification. The kernel may be wrong about its own mitigation
status (known to happen on older kernels).
- `paranoid="true"` raises the bar: a host with `paranoid="true"` and
`vulnerable_count=0` is held to a higher standard than one with `paranoid="false"`.
Do not compare counts across hosts with different `paranoid` values.
- `mocked="true"` must never appear on a production host; if it does, the results
are fabricated and every downstream alert is unreliable.
---
### `smc_system_info`
Operating system and kernel metadata. Always value `1`.
Absent in offline mode when neither `uname -r` nor `uname -m` is available.
| Label | Values | Meaning |
|---|---|---|
| `kernel_release` | string | Output of `uname -r` (live mode only) |
| `kernel_arch` | string | Output of `uname -m` (live mode only) |
| `hypervisor_host` | `true` / `false` | Whether this machine is detected as a hypervisor host (running KVM, Xen, VMware, etc.) |
**Example:**
```
smc_system_info{kernel_release="5.15.0-100-generic",kernel_arch="x86_64",hypervisor_host="false"} 1
```
**`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. Always prioritise remediation on hosts where
`hypervisor_host="true"`.
---
### `smc_cpu_info`
CPU hardware and microcode metadata. Always value `1`. Absent when `--no-hw`
is used.
| Label | Values | Meaning |
|---|---|---|
| `vendor` | string | CPU vendor (e.g. `Intel`, `AuthenticAMD`) |
| `model` | string | CPU friendly name from `/proc/cpuinfo` |
| `family` | integer string | CPU family number |
| `model_id` | integer string | CPU model number |
| `stepping` | integer string | CPU stepping number |
| `cpuid` | hex string | Full CPUID value (e.g. `0x000906ed`); absent on some ARM CPUs |
| `codename` | string | Intel CPU codename (e.g. `Coffee Lake`); absent on AMD and ARM |
| `smt` | `true` / `false` | Whether SMT (HyperThreading) is currently enabled |
| `microcode` | hex string | Installed microcode version (e.g. `0xf4`) |
| `microcode_latest` | hex string | Latest known-good microcode version from the firmware database |
| `microcode_up_to_date` | `true` / `false` | Whether `microcode == microcode_latest` |
| `microcode_blacklisted` | `true` / `false` | Whether the installed microcode is known to cause problems and should be rolled back |
**Example:**
```
smc_cpu_info{vendor="Intel",model="Intel(R) Core(TM) i7-9700K CPU @ 3.60GHz",family="6",model_id="158",stepping="13",cpuid="0x000906ed",codename="Coffee Lake",smt="true",microcode="0xf4",microcode_latest="0xf4",microcode_up_to_date="true",microcode_blacklisted="false"} 1
```
**Microcode labels:**
- `microcode_up_to_date="false"` means a newer microcode is available in the
firmware database. This does not necessarily mean the system is vulnerable
(the current microcode may still provide all required mitigations), but it
warrants investigation.
- `microcode_blacklisted="true"` means the installed microcode is known to
cause system instability or incorrect behaviour and must be rolled back
immediately. Treat this as a P1 incident.
- `microcode_latest` may be absent if the CPU is not in the firmware database
(very new, very old, or exotic CPUs).
**`smt`** affects the risk level of several CVEs (MDS, L1TF). For those CVEs,
full mitigation requires disabling SMT in addition to kernel and microcode updates.
The script accounts for this in its status assessment; use this label to audit
which hosts still have SMT enabled.
---
### `smc_vulnerability_status`
One time series per CVE. The **numeric value** encodes the check result:
| Value | Meaning |
|---|---|
| `0` | Not vulnerable (CPU is unaffected by design, or all required mitigations are in place) |
| `1` | Vulnerable (mitigations are missing or insufficient) |
| `2` | Unknown (the script could not determine the status, e.g. due to missing kernel info or insufficient privileges) |
| Label | Values | Meaning |
|---|---|---|
| `cve` | CVE ID string | The CVE identifier (e.g. `CVE-2017-5753`) |
| `name` | string | Human-readable CVE name and aliases (e.g. `Spectre Variant 1, bounds check bypass`) |
| `cpu_affected` | `true` / `false` | Whether this CPU's hardware design is concerned by this CVE |
**Example:**
```
smc_vulnerability_status{cve="CVE-2017-5753",name="Spectre Variant 1, bounds check bypass",cpu_affected="true"} 0
smc_vulnerability_status{cve="CVE-2017-5715",name="Spectre Variant 2, branch target injection",cpu_affected="true"} 1
smc_vulnerability_status{cve="CVE-2022-29900",name="Retbleed, arbitrary speculative code execution with return instructions (AMD)",cpu_affected="false"} 0
```
**`cpu_affected` explained:**
A value of `0` with `cpu_affected="false"` means the CPU hardware is architecturally
immune to this CVE, no patch was needed or applied.
A value of `0` with `cpu_affected="true"` means the CPU has the hardware weakness
but all required mitigations (kernel, microcode, or both) are in place.
This distinction is important when auditing a fleet: if you need to verify that
all at-risk systems are patched, filter on `cpu_affected="true"` to exclude
hardware-immune systems from the analysis.
---
### `smc_vulnerable_count`
Number of CVEs with status `1` (vulnerable) in this scan. Value is `0` when
no CVEs are vulnerable.
---
### `smc_unknown_count`
Number of CVEs with status `2` (unknown) in this scan. A non-zero value
typically means the scan lacked sufficient privileges or kernel information.
Treat unknown the same as vulnerable for alerting purposes.
---
### `smc_last_scan_timestamp_seconds`
Unix timestamp (seconds since epoch) when the scan completed. Use this to
detect hosts that have stopped reporting.
---
## Alerting rules
```yaml
groups:
- name: spectre_meltdown_checker
rules:
# Fire when any CVE is confirmed vulnerable
- alert: SMCVulnerable
expr: smc_vulnerable_count > 0
for: 0m
labels:
severity: critical
annotations:
summary: "{{ $labels.instance }} has {{ $value }} vulnerable CVE(s)"
description: >
Run spectre-meltdown-checker.sh interactively on {{ $labels.instance }}
for remediation guidance.
# Fire when status is unknown (usually means scan ran without root)
- alert: SMCUnknown
expr: smc_unknown_count > 0
for: 0m
labels:
severity: warning
annotations:
summary: "{{ $labels.instance }} has {{ $value }} CVE(s) with unknown status"
description: >
Ensure the checker runs as root on {{ $labels.instance }}.
# Fire when a host stops reporting (scan not run in 8 days)
- alert: SMCScanStale
expr: time() - smc_last_scan_timestamp_seconds > 8 * 86400
for: 0m
labels:
severity: warning
annotations:
summary: "{{ $labels.instance }} has not reported scan results in 8 days"
# Fire when installed microcode is known-bad
- alert: SMCMicrocodeBlacklisted
expr: smc_cpu_info{microcode_blacklisted="true"} == 1
for: 0m
labels:
severity: critical
annotations:
summary: "{{ $labels.instance }} is running blacklisted microcode"
description: >
The installed microcode ({{ $labels.microcode }}) is known to cause
instability. Roll back to the previous version immediately.
# Fire when scan ran without root (results may be incomplete)
- alert: SMCScanNotRoot
expr: smc_build_info{run_as_root="false"} == 1
for: 0m
labels:
severity: warning
annotations:
summary: "{{ $labels.instance }} scan ran without root privileges"
# Fire when mocked data is detected on a production host
- alert: SMCScanMocked
expr: smc_build_info{mocked="true"} == 1
for: 0m
labels:
severity: critical
annotations:
summary: "{{ $labels.instance }} scan results are mocked and unreliable"
```
---
## Useful PromQL queries
```promql
# All vulnerable CVEs across the fleet
smc_vulnerability_status == 1
# Vulnerable CVEs on hosts that are also hypervisor hosts (highest priority)
smc_vulnerability_status == 1
* on(instance) group_left(hypervisor_host)
smc_system_info{hypervisor_host="true"}
# Vulnerable CVEs on affected CPUs only (excludes hardware-immune systems)
smc_vulnerability_status{cpu_affected="true"} == 1
# Fleet-wide: how many hosts are vulnerable to each CVE
count by (cve, name) (smc_vulnerability_status == 1)
# Hosts with outdated microcode, with CPU model context
smc_cpu_info{microcode_up_to_date="false"}
# Hosts with SMT still enabled (relevant for MDS/L1TF remediation)
smc_cpu_info{smt="true"}
# For a specific CVE: hosts affected by hardware but fully mitigated
smc_vulnerability_status{cve="CVE-2018-3646", cpu_affected="true"} == 0
# Proportion of fleet that is fully clean (no vulnerable, no unknown)
(
count(smc_vulnerable_count == 0 and smc_unknown_count == 0)
/
count(smc_vulnerable_count >= 0)
)
# Hosts where scan ran without root, results less reliable
smc_build_info{run_as_root="false"}
# Hosts with sysfs_only mode, independent detection was skipped
smc_build_info{sysfs_only="true"}
# Vulnerable CVEs joined with kernel release for patch tracking
smc_vulnerability_status == 1
* on(instance) group_left(kernel_release)
smc_system_info
# Vulnerable CVEs joined with CPU model and microcode version
smc_vulnerability_status == 1
* on(instance) group_left(vendor, model, microcode, microcode_up_to_date)
smc_cpu_info
```
---
## Caveats and edge cases
**Offline mode (`--kernel`)**
`smc_system_info` will have no `kernel_release` or `kernel_arch` labels (those
come from `uname`, which reports the running kernel, not the inspected one).
`mode="offline"` in `smc_build_info` signals this. Offline mode is primarily
useful for pre-deployment auditing, not fleet runtime monitoring.
**`--no-hw`**
`smc_cpu_info` is not emitted. CPU and microcode labels are absent from all
queries. CVE checks that rely on hardware capability detection (`cap_*` flags,
MSR reads) will report `unknown` status.
**`--sysfs-only`**
The script trusts the kernel's sysfs report (`/sys/devices/system/cpu/vulnerabilities/`)
without running its own independent detection. Some older kernels are known to
misreport their mitigation status. `sysfs_only="true"` in `smc_build_info`
flags this condition. Do not use `--sysfs-only` for production fleet monitoring.
**`--paranoid`**
Enables defense-in-depth checks beyond the security community consensus (e.g.
requires SMT to be disabled, IBPB always-on). A host is only `vulnerable_count=0`
under `paranoid` if it meets this higher bar. Do not compare `vulnerable_count`
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 `unknown` for CVEs that are
actually mitigated. This typically happens when the script runs without root or
on a kernel with an inaccessible image.
**Label stability**
Prometheus identifies time series by their full label set. If a script upgrade
adds or renames a label (e.g. a new `smc_cpu_info` label is added for a new CVE),
Prometheus will create a new time series and the old one will become stale. Plan
for this in long-retention dashboards by using `group_left` joins rather than
hardcoding label matchers.

File diff suppressed because it is too large Load Diff