mirror of
https://github.com/speed47/spectre-meltdown-checker.git
synced 2026-06-06 06:33:04 +02:00
Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fd7caec415 | |||
| 68116d87fd | |||
| 3f4801e6a7 | |||
| 9a3688b6fd | |||
| c060a2d2c9 | |||
| 0c89d162a3 | |||
| 02fa416bab | |||
| 1c067add59 | |||
| fe0d3f49f4 | |||
| 00bb4a951c | |||
| 43d5b77885 | |||
| 78a6e4a418 | |||
| 5af1a9fec9 | |||
| b93027640f | |||
| 5c27284119 | |||
| f2e5999fc0 | |||
| 25f20b8860 | |||
| 77e3dbd6b2 | |||
| 8a6f9d5d63 | |||
| 73b67b4a80 | |||
| ea6b8efd18 | |||
| 24d92540a7 | |||
| f2d871acff | |||
| 553a9ec60f | |||
| 83ebe2f75f | |||
| 75ad60f42a | |||
| 931c955765 | |||
| c5ef0c488a | |||
| a05f8aab34 | |||
| 99301d1cbb | |||
| f9c3d19f72 | |||
| 8389d9593c | |||
| 3a822fdcf2 |
@@ -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
|
||||||
@@ -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) }}
|
||||||
@@ -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
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
#
|
#
|
||||||
# Stephane Lesimple
|
# Stephane Lesimple
|
||||||
#
|
#
|
||||||
VERSION='26.36.0602719'
|
VERSION='26.36.0601873'
|
||||||
|
|
||||||
# --- Common paths and basedirs ---
|
# --- Common paths and basedirs ---
|
||||||
readonly VULN_SYSFS_BASE="/sys/devices/system/cpu/vulnerabilities"
|
readonly VULN_SYSFS_BASE="/sys/devices/system/cpu/vulnerabilities"
|
||||||
@@ -3936,18 +3936,11 @@ parse_cpu_details() {
|
|||||||
# cpu_variant_list and cpu_revision_list are consumed by ARM64 errata affection checks
|
# cpu_variant_list and cpu_revision_list are consumed by ARM64 errata affection checks
|
||||||
# that need to match a specific revision range.
|
# that need to match a specific revision range.
|
||||||
if grep -q 'CPU implementer' "$g_procfs/cpuinfo"; then
|
if grep -q 'CPU implementer' "$g_procfs/cpuinfo"; then
|
||||||
# keep these single-line (space-separated) so consumers and outputs (JSON, prometheus)
|
cpu_impl_list=$(awk '/CPU implementer/ {print $4}' "$g_procfs/cpuinfo")
|
||||||
# don't end up with embedded newlines; per-core order is preserved for the errata checks
|
cpu_part_list=$(awk '/CPU part/ {print $4}' "$g_procfs/cpuinfo")
|
||||||
cpu_impl_list=$(awk '/CPU implementer/ {print $4}' "$g_procfs/cpuinfo" | tr '\n' ' ')
|
cpu_arch_list=$(awk '/CPU architecture/ {print $3}' "$g_procfs/cpuinfo")
|
||||||
cpu_impl_list=${cpu_impl_list% }
|
cpu_variant_list=$(awk '/CPU variant/ {print $4}' "$g_procfs/cpuinfo")
|
||||||
cpu_part_list=$(awk '/CPU part/ {print $4}' "$g_procfs/cpuinfo" | tr '\n' ' ')
|
cpu_revision_list=$(awk '/CPU revision/ {print $4}' "$g_procfs/cpuinfo")
|
||||||
cpu_part_list=${cpu_part_list% }
|
|
||||||
cpu_arch_list=$(awk '/CPU architecture/ {print $3}' "$g_procfs/cpuinfo" | tr '\n' ' ')
|
|
||||||
cpu_arch_list=${cpu_arch_list% }
|
|
||||||
cpu_variant_list=$(awk '/CPU variant/ {print $4}' "$g_procfs/cpuinfo" | tr '\n' ' ')
|
|
||||||
cpu_variant_list=${cpu_variant_list% }
|
|
||||||
cpu_revision_list=$(awk '/CPU revision/ {print $4}' "$g_procfs/cpuinfo" | tr '\n' ' ')
|
|
||||||
cpu_revision_list=${cpu_revision_list% }
|
|
||||||
fi
|
fi
|
||||||
# Map first-seen implementer to cpu_vendor; note that heterogeneous systems
|
# Map first-seen implementer to cpu_vendor; note that heterogeneous systems
|
||||||
# (e.g. DynamIQ with ARM+Kryo cores) would all map to one vendor here, but
|
# (e.g. DynamIQ with ARM+Kryo cores) would all map to one vendor here, but
|
||||||
@@ -5058,12 +5051,6 @@ check_kernel_info() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Collapse a whitespace-separated list to its unique values, preserving first-seen order.
|
|
||||||
# Used to prettify the per-core ARM lists for display (e.g. "0x41 0x41 0x41 0x41" -> "0x41").
|
|
||||||
_uniq_list() {
|
|
||||||
echo "$1" | awk '{ for (i = 1; i <= NF; i++) if (!seen[$i]++) printf "%s%s", (n++ ? " " : ""), $i }'
|
|
||||||
}
|
|
||||||
|
|
||||||
# Display hardware-level CPU mitigation support (microcode features, ARCH_CAPABILITIES, etc.)
|
# Display hardware-level CPU mitigation support (microcode features, ARCH_CAPABILITIES, etc.)
|
||||||
check_cpu() {
|
check_cpu() {
|
||||||
local capabilities ret spec_ctrl_msr codename ucode_str
|
local capabilities ret spec_ctrl_msr codename ucode_str
|
||||||
@@ -5073,13 +5060,13 @@ check_cpu() {
|
|||||||
pr_info " * Vendor: $cpu_vendor"
|
pr_info " * Vendor: $cpu_vendor"
|
||||||
pr_info " * Model name: $cpu_friendly_name"
|
pr_info " * Model name: $cpu_friendly_name"
|
||||||
if [ -n "${cpu_impl_list:-}" ]; then
|
if [ -n "${cpu_impl_list:-}" ]; then
|
||||||
pr_info " * Implementer(s): $(_uniq_list "$cpu_impl_list")"
|
pr_info " * Implementer(s): $cpu_impl_list"
|
||||||
fi
|
fi
|
||||||
if [ -n "${cpu_part_list:-}" ]; then
|
if [ -n "${cpu_part_list:-}" ]; then
|
||||||
pr_info " * Part(s): $(_uniq_list "$cpu_part_list")"
|
pr_info " * Part(s): $cpu_part_list"
|
||||||
fi
|
fi
|
||||||
if [ -n "${cpu_arch_list:-}" ]; then
|
if [ -n "${cpu_arch_list:-}" ]; then
|
||||||
pr_info " * Architecture(s): $(_uniq_list "$cpu_arch_list")"
|
pr_info " * Architecture(s): $cpu_arch_list"
|
||||||
fi
|
fi
|
||||||
if has_runtime; then
|
if has_runtime; then
|
||||||
pr_info_nol " * Running as VM guest: "
|
pr_info_nol " * Running as VM guest: "
|
||||||
|
|||||||
Reference in New Issue
Block a user