bb5ca48fe1
The drift-check job's if-gate already honors workflow_dispatch but the trigger itself was never added to the on: block. Without it, 'gh workflow run build.yml' fails with 422. Found while validating the v0.9.4 drift fix — wanted to confirm drift-check now passes without waiting for next Monday's cron.
200 lines
7.7 KiB
YAML
200 lines
7.7 KiB
YAML
name: build
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
pull_request:
|
|
branches: [main]
|
|
schedule:
|
|
# Weekly drift check against CISA KEV + Debian security tracker.
|
|
# Runs Monday 06:00 UTC; reports any new backports / KEV additions
|
|
# that haven't propagated into the corpus yet.
|
|
- cron: '0 6 * * 1'
|
|
workflow_dispatch:
|
|
# Lets us trigger the drift-check job on demand (e.g. after a
|
|
# metadata refresh) without waiting for the weekly cron. The
|
|
# drift-check job's `if:` gate honors this trigger.
|
|
|
|
jobs:
|
|
build:
|
|
runs-on: ubuntu-latest
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
cc: [gcc, clang]
|
|
flavor: [default, debug]
|
|
name: build (${{ matrix.cc }} / ${{ matrix.flavor }})
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: install build deps
|
|
run: |
|
|
sudo apt-get update -qq
|
|
sudo apt-get install -y --no-install-recommends \
|
|
build-essential clang make linux-libc-dev \
|
|
libglib2.0-dev pkg-config
|
|
|
|
- name: show compiler
|
|
run: ${{ matrix.cc }} --version
|
|
|
|
- name: build
|
|
env:
|
|
CC: ${{ matrix.cc }}
|
|
run: |
|
|
if [ "${{ matrix.flavor }}" = "debug" ]; then
|
|
make debug
|
|
else
|
|
make
|
|
fi
|
|
|
|
- name: sanity — skeletonkey --version
|
|
run: ./skeletonkey --version
|
|
|
|
- name: sanity — skeletonkey --list
|
|
run: ./skeletonkey --list
|
|
|
|
- name: sanity — skeletonkey --scan (no exploit; just detect)
|
|
run: ./skeletonkey --scan --no-color || true
|
|
# exit code may be nonzero (vulnerable host = exit 2, missing
|
|
# precond = exit 4) — that's diagnostic data, not CI failure
|
|
|
|
- name: sanity — --detect-rules auditd
|
|
run: ./skeletonkey --detect-rules --format=auditd | head -50
|
|
|
|
- name: sanity — --detect-rules sigma
|
|
run: ./skeletonkey --detect-rules --format=sigma | head -50
|
|
|
|
- name: tests — detect() unit suite
|
|
env:
|
|
CC: ${{ matrix.cc }}
|
|
run: |
|
|
# Run as a non-root user so modules' "already root" gates do
|
|
# not short-circuit before the synthetic host-fingerprint
|
|
# checks fire. The test binary itself is platform-agnostic;
|
|
# the assertions are #ifdef __linux__ guarded.
|
|
sudo useradd -m -s /bin/bash skeletonkeyci 2>/dev/null || true
|
|
sudo chown -R skeletonkeyci .
|
|
sudo -u skeletonkeyci make test
|
|
|
|
# ASan + UBSan run. clang-only; catches memory bugs and undefined
|
|
# behaviour the regular test suite can't see. Runs on the same 88
|
|
# tests as the main matrix; failures here are real bugs even if
|
|
# the assertions all pass.
|
|
sanitizers:
|
|
runs-on: ubuntu-latest
|
|
name: sanitizers (ASan + UBSan)
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- name: install deps
|
|
run: |
|
|
sudo apt-get update -qq
|
|
sudo apt-get install -y --no-install-recommends \
|
|
build-essential clang make linux-libc-dev \
|
|
libglib2.0-dev pkg-config sudo
|
|
- name: build + test under sanitizers
|
|
env:
|
|
CC: clang
|
|
# AddressSanitizer + UndefinedBehaviorSanitizer. -O1 keeps
|
|
# backtraces meaningful while still exercising optimizer paths;
|
|
# -fno-omit-frame-pointer for ASan stack traces; halt-on-error
|
|
# so the first finding fails CI loudly rather than scrolling
|
|
# past silently.
|
|
CFLAGS: "-O1 -g -fno-omit-frame-pointer -fsanitize=address,undefined -fno-sanitize-recover=all -Wall -Wextra -Wno-unused-parameter -Wno-pointer-arith -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64"
|
|
LDFLAGS: "-fsanitize=address,undefined"
|
|
run: |
|
|
sudo useradd -m -s /bin/bash skeletonkeyci 2>/dev/null || true
|
|
sudo chown -R skeletonkeyci .
|
|
sudo -u skeletonkeyci -E make test
|
|
|
|
# clang-tidy lint. Runs against core/ + skeletonkey.c (the files we
|
|
# control most tightly). Non-blocking for now — sets a baseline we
|
|
# can tighten incrementally. Module sources are excluded; many
|
|
# bundle published PoC code that we keep close to upstream style.
|
|
clang-tidy:
|
|
runs-on: ubuntu-latest
|
|
name: clang-tidy
|
|
continue-on-error: true
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- name: install deps
|
|
run: |
|
|
sudo apt-get update -qq
|
|
sudo apt-get install -y --no-install-recommends \
|
|
clang clang-tidy linux-libc-dev libglib2.0-dev pkg-config
|
|
- name: lint core + dispatcher
|
|
run: |
|
|
clang-tidy core/*.c skeletonkey.c \
|
|
--warnings-as-errors='' \
|
|
-- -Icore -Imodules/copy_fail_family/src \
|
|
-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64
|
|
|
|
# Drift check — runs the two refresh scripts in --check / drift mode
|
|
# against authoritative federal sources. Catches:
|
|
# - New CISA KEV additions touching CVEs in our corpus
|
|
# - New Debian security-tracker backport-version updates that move
|
|
# the kernel_patched_from table thresholds
|
|
# Network-required (fetches kev.csv + Debian tracker JSON). Runs on
|
|
# the weekly cron + on-demand via workflow_dispatch. NOT gated on
|
|
# PRs because random PRs shouldn't fail on upstream feed drift.
|
|
drift-check:
|
|
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
|
|
runs-on: ubuntu-latest
|
|
name: drift-check (CISA KEV + Debian tracker)
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- name: cve_metadata drift
|
|
run: |
|
|
# Exits 1 if the federal data has drifted from our committed
|
|
# JSON. Open a PR with `tools/refresh-cve-metadata.py` output
|
|
# if this fires.
|
|
python3 tools/refresh-cve-metadata.py --check || {
|
|
echo "::warning::cve_metadata drift detected — run tools/refresh-cve-metadata.py and commit the result"
|
|
exit 1
|
|
}
|
|
- name: kernel_range drift
|
|
run: |
|
|
# Exits 1 if any module's kernel_patched_from table is
|
|
# MISSING or TOO_TIGHT versus Debian's tracker. INFO-only
|
|
# findings are fine.
|
|
python3 tools/refresh-kernel-ranges.py || {
|
|
echo "::warning::kernel_range drift detected — see tools/refresh-kernel-ranges.py output"
|
|
exit 1
|
|
}
|
|
|
|
# Static build job: ensures the project links cleanly when -static is
|
|
# requested. Useful for deployment to minimal containers / fleet scans
|
|
# where shared-libc availability isn't guaranteed.
|
|
static-build:
|
|
runs-on: ubuntu-latest
|
|
name: static-build
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- name: install build deps
|
|
run: |
|
|
sudo apt-get update -qq
|
|
sudo apt-get install -y --no-install-recommends \
|
|
build-essential make linux-libc-dev libc6-dev \
|
|
libglib2.0-dev pkg-config
|
|
- name: make static
|
|
# Glibc static linking pulls in NSS at runtime which breaks
|
|
# getpwnam; the legacy DIRTYFAIL Makefile noted this. For now,
|
|
# we allow this job to fail loudly so we know if a regression
|
|
# makes the regular dynamic build also break, but we don't
|
|
# gate the merge on it. Migrate to musl-gcc when we want a
|
|
# truly portable static binary.
|
|
continue-on-error: true
|
|
run: make static && ls -la skeletonkey
|
|
|
|
# Phase 4 followup (placeholder): kernel-VM matrix. Each entry runs
|
|
# the binary against a VM running a specific (vulnerable or patched)
|
|
# kernel and asserts the correct detect() verdict + exploit behavior.
|
|
# Requires self-hosted runners or a paid VM service; not enabled yet.
|
|
#
|
|
# kernel-vm-matrix:
|
|
# strategy:
|
|
# matrix:
|
|
# distro: [ubuntu-22.04, debian-11, alma-9, fedora-40]
|
|
# kernel: [5.10.50, 5.13.0, 5.15.30, 6.1.x, 6.12.x]
|
|
# runs-on: [self-hosted, kvm-host]
|
|
# ...
|