README + site + binary: surface 22-of-26 VM-verified count

Updates the visible 'how trustworthy is this' signal across all three
touchpoints after the verifier sweep landed 22 modules confirmed in
real Linux VMs:

README.md
  - Badge: '28 verified + 3 ported' → '22 VM-verified / 26'.
  - Headline tagline: emphasizes the 22-of-26 empirical confirmation.
  - 'Corpus at a glance' restructured: tier counts unchanged, but the
    stale '3 ported-but-unverified' subsection is replaced by a new
    'Empirical verification' table breaking the 22 records down by
    distro/kernel.
  - 'Status' section refreshed for v0.6.0 reality: 88 tests + 22
    verifications + mainline kernel fetch + --explain + KEV/CWE/ATT&CK
    metadata + 119 detection rules. The four still-unverified entries
    (vmwgfx, dirty_cow, dirtydecrypt, fragnesia) are listed with their
    blocking reasons.

docs/index.html
  - Hero stats row gets a new '22 ✓ VM-verified' chip (emerald-styled
    via new .stat-vfy CSS class), keeping modules/KEV/rules siblings.
  - Hero tagline calls out '22 of 26 CVEs empirically verified'.
  - Meta description + og:description updated.
  - Bento card 'Verifier ready' rewritten as '22 modules empirically
    verified' with concrete distro/kernel breakdown; styled with new
    .bento-vfy class for emerald accent (matches the stat chip).
  - Timeline 'shipped' column adds the verifier wins; 'in flight'
    swapped to current open items (drift fixes, packagekit provisioner,
    custom <=4.4 box for dirty_cow).

docs/og.svg + docs/og.png
  - 4-chip stats row instead of 3: 31 modules · 22 ✓ VM-verified · 10
    ★ in CISA KEV · 119 detection rules. Tagline now '22 of 26 CVEs
    verified in real Linux VMs.' Re-rendered to PNG via rsvg-convert.

skeletonkey.c (binary)
  - --list footer now prints '31 modules registered · 10 in CISA KEV
    (★) · 22 empirically verified in real VMs (✓)'. Counts computed
    from the registry + cve_metadata + verifications tables at runtime
    (so it stays accurate as more verifications land — the JSONL
    refresh propagates automatically).

No code logic changed; only surfacing.
This commit is contained in:
2026-05-23 18:03:38 -04:00
parent 312e7d89b5
commit 6e0f811a2c
6 changed files with 108 additions and 67 deletions
+55 -36
View File
@@ -2,12 +2,12 @@
[![Latest release](https://img.shields.io/github/v/release/KaraZajac/SKELETONKEY?label=release)](https://github.com/KaraZajac/SKELETONKEY/releases/latest) [![Latest release](https://img.shields.io/github/v/release/KaraZajac/SKELETONKEY?label=release)](https://github.com/KaraZajac/SKELETONKEY/releases/latest)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
[![Modules](https://img.shields.io/badge/modules-28%20verified%20%2B%203%20ported-brightgreen.svg)](CVES.md) [![Modules](https://img.shields.io/badge/CVEs-22%20VM--verified%20%2F%2026-brightgreen.svg)](docs/VERIFICATIONS.jsonl)
[![Platform: Linux](https://img.shields.io/badge/platform-linux-lightgrey.svg)](#) [![Platform: Linux](https://img.shields.io/badge/platform-linux-lightgrey.svg)](#)
> **One curated binary. 28 verified Linux LPE exploits, 2016 → 2026 > **One curated binary. 31 Linux LPE modules covering 26 CVEs from 2016 → 2026.
> (+3 ported-but-unverified). Detection rules in the box. One command > 22 confirmed end-to-end against real Linux VMs via `tools/verify-vm/`.
> picks the safest one and runs it.** > Detection rules in the box. One command picks the safest one and runs it.**
```bash ```bash
curl -sSL https://github.com/KaraZajac/SKELETONKEY/releases/latest/download/install.sh | sh \ curl -sSL https://github.com/KaraZajac/SKELETONKEY/releases/latest/download/install.sh | sh \
@@ -43,15 +43,15 @@ for every CVE in the bundle — same project for red and blue teams.
## Corpus at a glance ## Corpus at a glance
**28 verified modules** spanning the 2016 → 2026 LPE timeline, plus **31 modules covering 26 distinct CVEs** across the 2016 → 2026 LPE
**3 ported-but-unverified** modules (`dirtydecrypt`, `fragnesia`, timeline. **22 of the 26 CVEs have been empirically verified** in real
`pack2theroot` — see note below): Linux VMs via `tools/verify-vm/`; the 4 still-pending entries are
blocked by their target environment, not by missing code.
| Tier | Count | What it means | | Tier | Count | What it means |
|---|---|---| |---|---|---|
| 🟢 Full chain | **14** | Lands root (or its canonical capability) end-to-end. No per-kernel offsets needed. | | 🟢 Full chain | **14** | Lands root (or its canonical capability) end-to-end. No per-kernel offsets needed. |
| 🟡 Primitive | **14** | Fires the kernel primitive + grooms the slab + records a witness. Default returns `EXPLOIT_FAIL` honestly. Pass `--full-chain` to engage the shared `modprobe_path` finisher (needs offsets — see [`docs/OFFSETS.md`](docs/OFFSETS.md)). | | 🟡 Primitive | **14** | Fires the kernel primitive + grooms the slab + records a witness. Default returns `EXPLOIT_FAIL` honestly. Pass `--full-chain` to engage the shared `modprobe_path` finisher (needs offsets — see [`docs/OFFSETS.md`](docs/OFFSETS.md)). |
| ⚪ Ported, unverified | **3** | `dirtydecrypt`, `fragnesia`, `pack2theroot`. Built and registered with **version-pinned `detect()`** (Linux 7.0 / 7.0.9 / PackageKit 1.3.5 respectively), but the **exploit bodies** are not yet validated end-to-end. `--auto` auto-enables `--active` to confirm empirically on top of the version verdict. Excluded from the 28-module verified counts above. |
**🟢 Modules that land root on a vulnerable host:** **🟢 Modules that land root on a vulnerable host:**
copy_fail family ×5 · dirty_pipe · dirty_cow · pwnkit · overlayfs copy_fail family ×5 · dirty_pipe · dirty_cow · pwnkit · overlayfs
@@ -64,18 +64,29 @@ af_packet · af_packet2 · af_unix_gc · cls_route4 · fuse_legacy ·
nf_tables · nft_set_uaf · nft_fwd_dup · nft_payload · nf_tables · nft_set_uaf · nft_fwd_dup · nft_payload ·
netfilter_xtcompat · stackrot · sudo_samedit · sequoia · vmwgfx netfilter_xtcompat · stackrot · sudo_samedit · sequoia · vmwgfx
**⚪ Ported-but-unverified (not in the counts above):** ### Empirical verification (22 of 26 CVEs)
dirtydecrypt (CVE-2026-31635) · fragnesia (CVE-2026-46300) ·
pack2theroot (CVE-2026-41651) — ported from public PoCs, **exploit Records in [`docs/VERIFICATIONS.jsonl`](docs/VERIFICATIONS.jsonl) prove
bodies not yet VM-validated**. All three have version-pinned `detect()`: each verdict against a known-target VM. Coverage:
`dirtydecrypt` against mainline fix commit `a2567217` in Linux 7.0;
`fragnesia` against mainline 7.0.9 (older Debian-stable branches still | Distro / kernel | Modules verified |
unfixed); `pack2theroot` against PackageKit fix release 1.3.5 |---|---|
(commit `76cfb675`), version read from the daemon over D-Bus. | Ubuntu 18.04 (4.15.0) | af_packet · ptrace_traceme · sudo_samedit |
`--auto` auto-enables `--active` to confirm empirically on top. | Ubuntu 20.04 (5.4 stock + 5.15 HWE) | af_packet2 · cls_route4 · nft_payload · overlayfs · pwnkit · sequoia |
| Ubuntu 22.04 (5.15 stock + mainline 5.15.5 / 6.1.10) | af_unix_gc · dirty_pipe · entrybleed · nf_tables · nft_set_uaf · overlayfs_setuid · stackrot · sudoedit_editor |
| Debian 11 (5.10 stock) | cgroup_release_agent · fuse_legacy · netfilter_xtcompat · nft_fwd_dup |
| Debian 12 (6.1 stock) | pack2theroot |
**Not yet verified (4):** `vmwgfx` (VMware-guest-only — no public
Vagrant box), `dirty_cow` (needs ≤ 4.4 kernel — older than every
supported box), `dirtydecrypt` & `fragnesia` (need Linux 7.0 — not
shipping as any distro kernel yet). All four are flagged in
[`tools/verify-vm/targets.yaml`](tools/verify-vm/targets.yaml) with
rationale.
See [`CVES.md`](CVES.md) for per-module CVE, kernel range, and See [`CVES.md`](CVES.md) for per-module CVE, kernel range, and
detection status. detection status. Run `skeletonkey --module-info <name>` for the
embedded verification records per module.
## Quickstart ## Quickstart
@@ -186,29 +197,37 @@ also compile (modules with Linux-only headers stub out gracefully).
## Status ## Status
**v0.6.0 cut 2026-05-23.** 28 verified modules, plus 3 **v0.6.0 cut 2026-05-23.** 31 modules across 26 CVEs, **22 empirically
ported-but-unverified (`dirtydecrypt`, `fragnesia`, `pack2theroot`). verified** against real Linux VMs (Ubuntu 18.04 / 20.04 / 22.04 +
All 31 build clean on Debian 13 (kernel 6.12) and refuse cleanly on Debian 11 / 12 + mainline kernels 5.15.5 / 6.1.10 from
patched hosts. kernel.ubuntu.com). 88-test unit harness on every push.
Reliability + accuracy work in v0.6.0: Reliability + accuracy work in v0.6.0:
- Shared **host fingerprint** (`core/host.{h,c}`) populated once at - Shared **host fingerprint** (`core/host.{h,c}`) populated once at
startup — kernel/distro/userns gates/sudo+polkit versions — exposed startup — kernel/distro/userns gates/sudo+polkit versions — exposed
to every module via `ctx->host`. 26 of 27 distinct modules consume it. to every module via `ctx->host`.
- **Test harness** (`tests/test_detect.c`, `make test`) — 44 unit - **Test harness** (`tests/`, `make test`) — 88 tests: 33 kernel_range
tests over mocked host fingerprints; runs as a non-root user in CI. unit tests + 55 detect() integration tests over mocked host
- `--auto` upgrades: auto-enables `--active`, per-detect 15s timeout, fingerprints. Runs in CI on every push.
fork-isolated detect + exploit so a crashing module can't tear down - **VM verifier** (`tools/verify-vm/`) — Vagrant + Parallels scaffold
the dispatcher, structured per-module verdict table, scan summary. that boots known-vulnerable kernels (stock distro + mainline via
- `--dry-run` flag (preview without firing; no `--i-know` needed). kernel.ubuntu.com), runs `--explain --active` per module, records
- Pinned mainline fix commits for the 3 ported modules — `detect()` match/MISMATCH/PRECOND_FAIL as JSON. 22 modules confirmed end-to-end.
is version-pinned, not just precondition-only. - **`--explain <module>`** — single-page operator briefing: CVE / CWE
/ MITRE ATT&CK / CISA KEV status, host fingerprint, live detect()
trace, OPSEC footprint, detection-rule coverage, verified-on
records. Paste-into-ticket ready.
- **CVE metadata pipeline** (`tools/refresh-cve-metadata.py`) — fetches
CISA KEV catalog + NVD CWE; 10 of 26 modules cover KEV-listed CVEs.
- **119 detection rules** across auditd / sigma / yara / falco; one
command exports the corpus to your SIEM.
- `--auto` upgrades: per-detect 15s timeout, fork-isolated detect +
exploit, structured verdict table, scan summary, `--dry-run`.
Empirical end-to-end validation on a vulnerable-target VM matrix is Not yet verified (4 of 26 CVEs): `vmwgfx` (VMware-guest only),
the next roadmap item; until then, the corpus is best understood as `dirty_cow` (needs ≤ 4.4 kernel), `dirtydecrypt` + `fragnesia` (need
"compiles + detects + structurally correct + honest on failure" — Linux 7.0 — not shipping yet). Rationale in
and the three ported modules have not been run against a vulnerable [`tools/verify-vm/targets.yaml`](tools/verify-vm/targets.yaml).
target at all.
See [`ROADMAP.md`](ROADMAP.md) for the next planned modules and See [`ROADMAP.md`](ROADMAP.md) for the next planned modules and
infrastructure work. infrastructure work.
+23 -19
View File
@@ -3,10 +3,10 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SKELETONKEY — Linux LPE corpus with SOC-ready detection</title> <title>SKELETONKEY — Linux LPE corpus, VM-verified, SOC-ready detection</title>
<meta name="description" content="One binary. 31 Linux privilege-escalation modules from 2016 to 2026. 10 of 26 CVEs in CISA's Known Exploited Vulnerabilities catalog. 119 detection rules across auditd/sigma/yara/falco. MITRE ATT&CK and CWE annotated. --explain gives operator briefings."> <meta name="description" content="One binary. 31 Linux privilege-escalation modules from 2016 to 2026. 22 of 26 CVEs empirically verified in real Linux VMs. 10 KEV-listed. 119 detection rules across auditd/sigma/yara/falco. MITRE ATT&CK and CWE annotated. --explain gives operator briefings.">
<meta property="og:title" content="SKELETONKEY — Linux LPE corpus with SOC-ready detection"> <meta property="og:title" content="SKELETONKEY — Linux LPE corpus, VM-verified">
<meta property="og:description" content="31 Linux LPE modules (10 KEV). 119 detection rules. ATT&CK + CWE + OPSEC annotated. --explain in one command."> <meta property="og:description" content="31 Linux LPE modules; 22 of 26 CVEs empirically verified in real VMs. 119 detection rules. ATT&CK + CWE + KEV annotated.">
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<meta property="og:url" content="https://karazajac.github.io/SKELETONKEY/"> <meta property="og:url" content="https://karazajac.github.io/SKELETONKEY/">
<meta property="og:image" content="https://karazajac.github.io/SKELETONKEY/og.png"> <meta property="og:image" content="https://karazajac.github.io/SKELETONKEY/og.png">
@@ -62,8 +62,9 @@
<span class="display-wordmark">SKELETONKEY</span> <span class="display-wordmark">SKELETONKEY</span>
</h1> </h1>
<p class="hero-tag"> <p class="hero-tag">
One binary. <strong>31 Linux LPE modules</strong> from One binary. <strong>31 Linux LPE modules</strong> from 2016 to 2026.
2016 to 2026. SOC-ready detection rules in four SIEM formats. <strong>22 of 26 CVEs empirically verified</strong> against real
Linux kernels in VMs. SOC-ready detection rules in four SIEM formats.
MITRE ATT&amp;CK + CWE + CISA KEV annotated. MITRE ATT&amp;CK + CWE + CISA KEV annotated.
<span class="hero-tag-pop">--explain gives a one-page operator briefing per CVE.</span> <span class="hero-tag-pop">--explain gives a one-page operator briefing per CVE.</span>
</p> </p>
@@ -81,9 +82,9 @@
<div class="stats-row" id="stats-row"> <div class="stats-row" id="stats-row">
<div class="stat-chip"><span class="num" data-target="31">0</span><span>modules</span></div> <div class="stat-chip"><span class="num" data-target="31">0</span><span>modules</span></div>
<div class="stat-chip stat-vfy"><span class="num" data-target="22">0</span><span>✓ VM-verified</span></div>
<div class="stat-chip stat-kev"><span class="num" data-target="10">0</span><span>★ in CISA KEV</span></div> <div class="stat-chip stat-kev"><span class="num" data-target="10">0</span><span>★ in CISA KEV</span></div>
<div class="stat-chip"><span class="num" data-target="119">0</span><span>detection rules</span></div> <div class="stat-chip"><span class="num" data-target="119">0</span><span>detection rules</span></div>
<div class="stat-chip"><span class="num" data-target="88">0</span><span>tests passing</span></div>
</div> </div>
<div class="cta-row"> <div class="cta-row">
@@ -286,15 +287,17 @@ uid=0(root) gid=0(root)</pre>
</p> </p>
</article> </article>
<article class="bento-card"> <article class="bento-card bento-vfy">
<div class="bento-icon">🧪</div> <div class="bento-icon"></div>
<h3>Verifier ready</h3> <h3>22 modules empirically verified</h3>
<p> <p>
<code>tools/verify-vm/</code> ships a Vagrant + Parallels <code>tools/verify-vm/</code> spins up known-vulnerable
scaffold that spins up known-vulnerable kernels and runs kernels (stock distro + mainline from kernel.ubuntu.com), runs
<code>--explain</code> per module — verification records as <code>--explain --active</code> per module, and records the
JSON, ready to feed the per-module <code>verified_on</code> verdict. <strong>22 of 26 CVEs</strong> confirmed against
table. real Linux across Ubuntu 18.04 / 20.04 / 22.04 + Debian 11 / 12
+ mainline 5.15.5 / 6.1.10. Records baked into the binary;
<code>--list</code> shows ✓ per module.
</p> </p>
</article> </article>
</div> </div>
@@ -508,22 +511,23 @@ uid=0(root) gid=0(root)</pre>
<div class="tl-col tl-shipped"> <div class="tl-col tl-shipped">
<div class="tl-tag">shipped</div> <div class="tl-tag">shipped</div>
<ul> <ul>
<li><strong>22 of 26 CVEs empirically verified</strong> in real Linux VMs</li>
<li><strong>kernel.ubuntu.com/mainline/</strong> kernel fetch path — unblocks pin-not-in-apt targets</li>
<li>Per-module <code>verified_on[]</code> table baked into the binary</li>
<li><strong>--explain mode</strong> — one-page operator briefing per CVE</li> <li><strong>--explain mode</strong> — one-page operator briefing per CVE</li>
<li><strong>OPSEC notes</strong> — per-module runtime footprint</li> <li><strong>OPSEC notes</strong> — per-module runtime footprint</li>
<li><strong>CISA KEV + NVD CWE + MITRE ATT&amp;CK</strong> metadata pipeline</li> <li><strong>CISA KEV + NVD CWE + MITRE ATT&amp;CK</strong> metadata pipeline</li>
<li>119 detection rules across all four SIEM formats</li> <li>119 detection rules across all four SIEM formats</li>
<li><code>core/host.c</code> shared host-fingerprint refactor</li> <li><code>core/host.c</code> shared host-fingerprint refactor</li>
<li>88-test harness (kernel_range + detect integration)</li> <li>88-test harness (kernel_range + detect integration)</li>
<li>kernel_range drift detector → 9 corpus fixes</li>
<li>Vagrant + Parallels VM verification scaffold</li>
</ul> </ul>
</div> </div>
<div class="tl-col tl-active"> <div class="tl-col tl-active">
<div class="tl-tag">in flight</div> <div class="tl-tag">in flight</div>
<ul> <ul>
<li>Empirical end-to-end VM verification across the corpus</li>
<li>Per-module <code>verified_on[]</code> table fed by verifier records</li>
<li>9 deferred TOO_TIGHT kernel-range drift findings</li> <li>9 deferred TOO_TIGHT kernel-range drift findings</li>
<li>PackageKit provisioner so pack2theroot can hit the VULNERABLE path</li>
<li>Custom Vagrant box for kernels ≤ 4.4 (unblock dirty_cow verification)</li>
</ul> </ul>
</div> </div>
<div class="tl-col tl-next"> <div class="tl-col tl-next">
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

After

Width:  |  Height:  |  Size: 122 KiB

+15 -10
View File
@@ -39,25 +39,30 @@
Curated Linux LPE corpus. Curated Linux LPE corpus.
</text> </text>
<text x="80" y="282" font-family="'Inter',sans-serif" font-size="32" fill="#c5c5d3" font-weight="500"> <text x="80" y="282" font-family="'Inter',sans-serif" font-size="32" fill="#c5c5d3" font-weight="500">
SOC-ready detection in the box. 22 of 26 CVEs verified in real Linux VMs.
</text> </text>
<!-- stat chips --> <!-- stat chips -->
<g transform="translate(80,360)"> <g transform="translate(80,360)">
<!-- 31 modules --> <!-- 31 modules -->
<rect x="0" y="0" width="220" height="58" rx="29" fill="#161628" stroke="#25253c"/> <rect x="0" y="0" width="190" height="58" rx="29" fill="#161628" stroke="#25253c"/>
<text x="32" y="38" font-family="'JetBrains Mono',monospace" font-weight="700" font-size="22" fill="#ecedf7">31</text> <text x="28" y="38" font-family="'JetBrains Mono',monospace" font-weight="700" font-size="22" fill="#ecedf7">31</text>
<text x="68" y="37" font-family="'Inter',sans-serif" font-size="16" fill="#8a8a9d">modules</text> <text x="64" y="37" font-family="'Inter',sans-serif" font-size="16" fill="#8a8a9d">modules</text>
<!-- 22 VM-verified -->
<rect x="206" y="0" width="240" height="58" rx="29" fill="#161628" stroke="#10b981" stroke-opacity="0.5"/>
<text x="234" y="38" font-family="'JetBrains Mono',monospace" font-weight="700" font-size="22" fill="#34d399">22</text>
<text x="270" y="37" font-family="'Inter',sans-serif" font-size="16" fill="#8a8a9d">✓ VM-verified</text>
<!-- 10 KEV --> <!-- 10 KEV -->
<rect x="238" y="0" width="220" height="58" rx="29" fill="#161628" stroke="#ef4444" stroke-opacity="0.4"/> <rect x="482" y="0" width="218" height="58" rx="29" fill="#161628" stroke="#ef4444" stroke-opacity="0.4"/>
<text x="270" y="38" font-family="'JetBrains Mono',monospace" font-weight="700" font-size="22" fill="#ef4444">10</text> <text x="510" y="38" font-family="'JetBrains Mono',monospace" font-weight="700" font-size="22" fill="#ef4444">10</text>
<text x="306" y="37" font-family="'Inter',sans-serif" font-size="16" fill="#8a8a9d">★ in CISA KEV</text> <text x="546" y="37" font-family="'Inter',sans-serif" font-size="16" fill="#8a8a9d">★ in CISA KEV</text>
<!-- 119 rules --> <!-- 119 rules -->
<rect x="476" y="0" width="240" height="58" rx="29" fill="#161628" stroke="#25253c"/> <rect x="736" y="0" width="232" height="58" rx="29" fill="#161628" stroke="#25253c"/>
<text x="508" y="38" font-family="'JetBrains Mono',monospace" font-weight="700" font-size="22" fill="#ecedf7">119</text> <text x="764" y="38" font-family="'JetBrains Mono',monospace" font-weight="700" font-size="22" fill="#ecedf7">119</text>
<text x="554" y="37" font-family="'Inter',sans-serif" font-size="16" fill="#8a8a9d">detection rules</text> <text x="810" y="37" font-family="'Inter',sans-serif" font-size="16" fill="#8a8a9d">detection rules</text>
</g> </g>
<!-- terminal mockup --> <!-- terminal mockup -->

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

+5
View File
@@ -350,6 +350,8 @@ code, pre { font-family: var(--mono); font-size: 0.93em; }
} }
.stat-chip.stat-kev { border-color: rgba(239, 68, 68, 0.3); } .stat-chip.stat-kev { border-color: rgba(239, 68, 68, 0.3); }
.stat-chip.stat-kev .num { color: var(--danger); } .stat-chip.stat-kev .num { color: var(--danger); }
.stat-chip.stat-vfy { border-color: rgba(16, 185, 129, 0.4); }
.stat-chip.stat-vfy .num { color: var(--accent-hot); }
.cta-row { .cta-row {
display: flex; gap: 0.75rem; display: flex; gap: 0.75rem;
@@ -635,6 +637,9 @@ code, pre { font-family: var(--mono); font-size: 0.93em; }
.bento-card.bento-kev { border-color: rgba(239, 68, 68, 0.3); } .bento-card.bento-kev { border-color: rgba(239, 68, 68, 0.3); }
.bento-card.bento-kev .bento-icon { color: var(--danger); background: rgba(239, 68, 68, 0.1); } .bento-card.bento-kev .bento-icon { color: var(--danger); background: rgba(239, 68, 68, 0.1); }
.bento-card.bento-kev:hover { border-color: var(--danger); box-shadow: 0 20px 60px -10px rgba(239, 68, 68, 0.2); } .bento-card.bento-kev:hover { border-color: var(--danger); box-shadow: 0 20px 60px -10px rgba(239, 68, 68, 0.2); }
.bento-card.bento-vfy { border-color: rgba(16, 185, 129, 0.35); }
.bento-card.bento-vfy .bento-icon { color: var(--accent-hot); background: rgba(16, 185, 129, 0.1); font-weight: 800; }
.bento-card.bento-vfy:hover { border-color: var(--accent); box-shadow: 0 20px 60px -10px rgba(16, 185, 129, 0.25); }
.bento-code { .bento-code {
background: var(--bg-2); background: var(--bg-2);
+10 -2
View File
@@ -276,15 +276,23 @@ static int cmd_list(const struct skeletonkey_ctx *ctx)
"NAME", "CVE", "KEV", "VFY", "FAMILY", "SUMMARY"); "NAME", "CVE", "KEV", "VFY", "FAMILY", "SUMMARY");
fprintf(stdout, "%-20s %-18s %-3s %-3s %-25s %s\n", fprintf(stdout, "%-20s %-18s %-3s %-3s %-25s %s\n",
"----", "---", "---", "---", "------", "-------"); "----", "---", "---", "---", "------", "-------");
size_t n_kev = 0, n_vfy = 0;
for (size_t i = 0; i < n; i++) { for (size_t i = 0; i < n; i++) {
const struct skeletonkey_module *m = skeletonkey_module_at(i); const struct skeletonkey_module *m = skeletonkey_module_at(i);
const struct cve_metadata *md = cve_metadata_lookup(m->cve); const struct cve_metadata *md = cve_metadata_lookup(m->cve);
bool in_kev = md && md->in_kev;
bool verified = verifications_module_has_match(m->name);
if (in_kev) n_kev++;
if (verified) n_vfy++;
fprintf(stdout, "%-20s %-18s %-3s %-3s %-25s %s\n", fprintf(stdout, "%-20s %-18s %-3s %-3s %-25s %s\n",
m->name, m->cve, m->name, m->cve,
(md && md->in_kev) ? "" : "", in_kev ? "" : "",
verifications_module_has_match(m->name) ? "" : "", verified ? "" : "",
m->family, m->summary); m->family, m->summary);
} }
fprintf(stdout, "\n%zu modules registered · %zu in CISA KEV (★) · "
"%zu empirically verified in real VMs (✓)\n",
n, n_kev, n_vfy);
return 0; return 0;
} }