Compare commits

..

21 Commits

Author SHA1 Message Date
Stéphane Lesimple 3f4801e6a7 autoupdate workflow: add missing pkg 2026-06-01 20:55:08 +00:00
Stéphane Lesimple 9a3688b6fd chore: use scripts in autoupdate workflow (#572) 2026-06-01 20:52:54 +00:00
Stéphane Lesimple 0c89d162a3 chore: fix autoupdate workflow 2026-05-31 14:50:31 +02:00
林博仁 Buo-ren Lin 02fa416bab doc: readme: correct markdown indentation for unordered list items (#569)
Signed-off-by: 林博仁(Buo-ren Lin) <buo.ren.lin@gmail.com>
2026-04-20 16:02:47 +00:00
Stéphane Lesimple 1c067add59 release v26.33.0420460 (#567) 2026-04-20 15:18:11 +00:00
Stéphane Lesimple 00bb4a951c workflow: expose reconsider_age_days input + env var 2026-04-19 14:46:56 +02:00
Stéphane Lesimple 43d5b77885 chore: workflow: add manual model + window_hours inputs, add reconsider 2026-04-19 12:55:03 +02:00
Stéphane Lesimple 78a6e4a418 chore: move cron vuln-watch workflow script files to their own branch 2026-04-19 11:14:21 +02:00
Stéphane Lesimple 5af1a9fec9 chore: workflow: add scan id 2026-04-18 16:23:47 +02:00
Stéphane Lesimple b93027640f chore: vuln workflow: use opus, no persist creds, conditional upload 2026-04-18 16:19:10 +02:00
Stéphane Lesimple 5c27284119 chore: workflow: save logs 2026-04-18 16:05:15 +02:00
Stéphane Lesimple f2e5999fc0 chore: explicit prompt for workflow 2026-04-18 15:41:03 +02:00
Stéphane Lesimple 25f20b8860 chore: fix workflow perms (#558) 2026-04-18 15:29:54 +02:00
Stéphane Lesimple 77e3dbd6b2 add scheduled vuln research (#557) 2026-04-18 15:14:13 +02:00
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 9497abbee2723cedc561b6b785fe01fbe965ec1c
 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
8 changed files with 386 additions and 782 deletions
+41
View File
@@ -0,0 +1,41 @@
name: autoupdate
on:
workflow_dispatch:
schedule:
- cron: '42 9 * * *'
permissions:
pull-requests: write
contents: write
jobs:
autoupdate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
with:
ref: source
- name: Install prerequisites
run: sudo apt-get update && sudo apt-get install -y --no-install-recommends iucode-tool sqlite3 unzip shfmt
- name: Update microcode versions
run: ./scripts/update_mcedb.sh
- name: Update Intel models
run: ./scripts/update_intel_models.sh
- name: Check git diff
id: diff
run: |
echo change="$(git diff | awk '/MCEDB/ { if(V) { print V" to "$4; exit } else { V=$4 } }')" >> "$GITHUB_OUTPUT"
echo nbdiff="$(git diff | grep -cE -- '^\+# [AI],')" >> "$GITHUB_OUTPUT"
git diff
cat "$GITHUB_OUTPUT"
- name: Create Pull Request if needed
if: steps.diff.outputs.nbdiff != '0'
uses: peter-evans/create-pull-request@v7
with:
branch: autoupdate-fwdb
commit-message: "update: fwdb from ${{ steps.diff.outputs.change }}, ${{ steps.diff.outputs.nbdiff }} microcode changes"
title: "[Auto] Update fwdb from ${{ steps.diff.outputs.change }}"
body: |
Automated PR to update fwdb from ${{ steps.diff.outputs.change }}
Detected ${{ steps.diff.outputs.nbdiff }} microcode changes
+4 -75
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
+1 -1
View File
@@ -1 +1 @@
32
26
+33
View File
@@ -0,0 +1,33 @@
name: 'Manage stale issues and PRs'
on:
schedule:
- cron: '37 7 * * *'
workflow_dispatch:
inputs:
action:
description: "dry-run"
required: true
default: "dryrun"
type: choice
options:
- dryrun
- apply
permissions:
issues: write
pull-requests: write
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v10
with:
any-of-labels: 'needs-more-info,answered'
labels-to-remove-when-unstale: 'needs-more-info,answered'
days-before-stale: 30
days-before-close: 7
stale-issue-label: stale
remove-stale-when-updated: true
debug-only: ${{ case(inputs.action == 'dryrun', true, false) }}
+190
View File
@@ -0,0 +1,190 @@
name: Online search for vulns
on:
schedule:
- cron: '42 8 * * *'
workflow_dispatch:
inputs:
model:
description: 'Claude model to use (cron runs default to Sonnet)'
required: false
type: choice
default: claude-sonnet-4-6
options:
- claude-sonnet-4-6
- claude-opus-4-7
- claude-haiku-4-5-20251001
window_hours:
description: 'Lookback window in hours (cron runs use 25)'
required: false
type: string
default: '25'
reconsider_age_days:
description: 'Only reconsider backlog entries last reviewed ≥ N days ago (0 = all, default 7)'
required: false
type: string
default: '7'
permissions:
contents: read
actions: read # needed to list/download previous run artifacts
id-token: write # needed by claude-code-action for OIDC auth
concurrency:
group: vuln-watch
cancel-in-progress: true
jobs:
watch:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
# The scripts driving this workflow live on the `vuln-watch` branch so
# they don't clutter master (which is what ships to production). The
# workflow file itself MUST stay on the default branch, as GitHub only
# honors `schedule:` triggers on the default branch.
- name: Checkout vuln-watch branch (scripts + prompt)
uses: actions/checkout@v5
with:
ref: vuln-watch
fetch-depth: 1
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install Python dependencies
run: python -m pip install --quiet feedparser
# ---- Load previous state ---------------------------------------------
# Find the most recent successful run of THIS workflow (other than the
# current one) and pull its `vuln-watch-state` artifact. On the very
# first run there will be none — that's fine, we start empty.
- name: Find previous successful run id
id: prev
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -e
run_id=$(gh run list \
--workflow="${{ github.workflow }}" \
--status=success \
--limit 1 \
--json databaseId \
--jq '.[0].databaseId // empty')
echo "run_id=${run_id}" >> "$GITHUB_OUTPUT"
if [ -n "$run_id" ]; then
echo "Found previous successful run: $run_id"
else
echo "No previous successful run — starting from empty state."
fi
- name: Download previous state artifact
if: steps.prev.outputs.run_id != ''
uses: actions/download-artifact@v5
continue-on-error: true # tolerate retention expiry
with:
name: vuln-watch-state
path: state/
run-id: ${{ steps.prev.outputs.run_id }}
github-token: ${{ secrets.GITHUB_TOKEN }}
# ---- Fetch + diff (token-free; runs every time) ---------------------
# Performs conditional GETs (ETag / If-Modified-Since) against every
# source, parses RSS/Atom/HTML, dedups against state.seen + state.aliases,
# applies the time-window filter, and emits new_items.json.
# Updates state.sources (HTTP cache metadata + per-source high-water
# marks) in place so the cache survives even when Claude doesn't run.
- name: Fetch + diff all sources
id: diff
env:
SCAN_DATE: ${{ github.run_started_at }}
# Cron runs have no `inputs` context, so the fallback kicks in.
WINDOW_HOURS: ${{ inputs.window_hours || '25' }}
RECONSIDER_AGE_DAYS: ${{ inputs.reconsider_age_days || '7' }}
run: python -m scripts.vuln_watch.fetch_and_diff
# ---- Fetch checker code so Claude can grep it for coverage ---------
# The orphan vuln-watch branch has none of the actual checker code,
# so we pull the `test` branch (the dev branch where coded-but-
# unreleased CVE checks live) into ./checker/. The prompt tells
# Claude this is the canonical source of truth for "is CVE-X already
# implemented?". Only fetched on days with something to classify.
- name: Checkout checker code (test branch) for coverage grep
if: steps.diff.outputs.new_count != '0' || steps.diff.outputs.reconsider_count != '0'
uses: actions/checkout@v5
with:
ref: test
path: checker
fetch-depth: 1
persist-credentials: false
# ---- Classify new items with Claude (skipped when nothing is new) ---
# Model selection: a manual workflow_dispatch run picks from a dropdown
# (defaulting to Sonnet). Scheduled cron runs have no `inputs` context,
# so the `|| 'claude-sonnet-4-6'` fallback kicks in — cron always uses
# Sonnet to keep the daily cost floor low.
- name: Run classifier with Claude
id: classify
if: steps.diff.outputs.new_count != '0' || steps.diff.outputs.reconsider_count != '0'
uses: anthropics/claude-code-action@v1
env:
SCAN_DATE: ${{ github.run_started_at }}
with:
prompt: |
Read the full task instructions from scripts/daily_vuln_watch_prompt.md
and execute them end-to-end. Your input is new_items.json (already
deduped, windowed, and pre-filtered — do NOT re-fetch sources).
Write the three watch_${TODAY}_*.md files and classifications.json.
Use $SCAN_DATE as the canonical timestamp.
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
# model + tool allowlist pass through claude_args (v1 dropped the
# dedicated `model:` and `allowed_tools:` inputs). Job-level
# `timeout-minutes: 20` above bounds total runtime.
claude_args: |
--model ${{ inputs.model || 'claude-sonnet-4-6' }}
--allowedTools "Read,Write,Edit,Bash,Grep,Glob,WebFetch"
- name: Upload Claude execution log
if: ${{ always() && steps.classify.outputs.execution_file != '' }}
uses: actions/upload-artifact@v5
with:
name: claude-execution-log-${{ github.run_id }}
path: ${{ steps.classify.outputs.execution_file }}
retention-days: 30
if-no-files-found: warn
# ---- Merge classifications back into state --------------------------
# Also writes stub watch_*.md files if the classify step was skipped, so
# the report artifact is consistent across runs.
- name: Merge classifications into state
if: always()
env:
SCAN_DATE: ${{ github.run_started_at }}
run: python -m scripts.vuln_watch.merge_state
- name: Upload new state artifact
if: always()
uses: actions/upload-artifact@v5
with:
name: vuln-watch-state
path: state/seen.json
retention-days: 90
if-no-files-found: error
- name: Upload daily report
if: always()
uses: actions/upload-artifact@v5
with:
name: vuln-watch-report-${{ github.run_id }}
path: |
watch_*.md
current_toimplement.md
current_tocheck.md
new_items.json
classifications.json
retention-days: 90
if-no-files-found: warn
-8
View File
@@ -40,14 +40,6 @@ CVE | Name | Aliases
[CVE-2024-45332](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-45332) | Branch Privilege Injection | BPI
[CVE-2025-54505](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2025-54505) | AMD Zen1 Floating-Point Divider Stale Data Leak | FPDSS
The following entries are ARM64 silicon errata that the kernel actively works around. They have no assigned CVE; they are tracked only by ARM's erratum numbers. Select them with `--errata <number>` or the associated `--variant` mnemonic.
ID | Name | Affected cores
-- | ---- | --------------
CVE-0001-0001 | Speculative AT TLB corruption (errata 1165522, 1319367, 1319537, 1530923) | Cortex-A55/A57/A72/A76
CVE-0001-0002 | Speculative unprivileged load (errata 2966298, 3117295) | Cortex-A510/A520
CVE-0001-0003 | MSR SSBS not self-synchronizing (erratum 3194386 + siblings) | Cortex-A76/A77/A78/A78C/A710/A715/A720/A720AE/A725, X1/X1C/X2/X3/X4/X925, Neoverse-N1/N2/N3/V1/V2/V3/V3AE
## Am I at risk?
Depending on your situation, the table below answers whether an attacker in a given position can extract data from a given target.
-10
View File
@@ -307,13 +307,3 @@ A weakness in AMD's microcode signature verification (AES-CMAC hash) allows load
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.
## No CVE — Jump Conditional Code (JCC) Erratum
- **Issue:** [#329](https://github.com/speed47/spectre-meltdown-checker/issues/329)
- **Intel whitepaper:** [Mitigations for Jump Conditional Code Erratum](https://www.intel.com/content/dam/support/us/en/documents/processors/mitigations-jump-conditional-code-erratum.pdf)
- **Affected CPUs:** Intel 6th through 10th generation Core and Xeon processors (Skylake through Cascade Lake)
A microarchitectural correctness erratum where a conditional jump instruction that straddles or ends at a 64-byte instruction fetch boundary can corrupt the branch predictor state, potentially causing incorrect execution. Intel addressed this in a November 2019 microcode update. Compilers and assemblers (GCC, LLVM, binutils) also introduced alignment options (`-mbranch-alignment`, `-x86-branches-within-32B-boundaries`) to pad jump instructions away from boundary conditions, preserving performance on CPUs with updated microcode.
**Why out of scope:** The JCC erratum is a microarchitectural correctness bug, not a transient or speculative execution side-channel vulnerability. No CVE was ever assigned. Red Hat noted that privilege escalation "has not been ruled out" but made no definitive security finding, and no exploit has been demonstrated. There is no Linux sysfs entry, no CPUID bit, and no MSR flag exposing the mitigation status. The microcode fix introduces no detectable hardware indicator, so checking for it would require maintaining a per-CPU-stepping minimum microcode version table (the design principle 3 exception) — costly to maintain without a CVE anchor or confirmed exploitability to justify the ongoing work. The kernel compiler mitigation is a build-time-only change (instruction alignment) with no observable runtime state.
File diff suppressed because it is too large Load Diff