How the ledger is computed
Nothing on the dashboard is a heuristic score with a hidden constant. Each figure comes from a rule you can check against the report JSON, and every rule has a stated failure mode.
01 / reachability
Present, reachable, used — three different questions
Most auditors conflate them, and that is why their output is unactionable.
present — the element exists in this kernel build or on this filesystem: a syscall compiled in, a module available under /lib/modules, a device node in /dev, a sysctl that reads back. Presence alone says nothing about risk.
reachable_unpriv — an unprivileged local user can actually get to it: the syscall is not blocked by seccomp for the processes that matter, the device node is mode 0666, the sysctl is writable, the module can be autoloaded. This is the tier that turns a CVE from trivia into exposure.
used — something on this host touched it during the observation window. Reachable and not used is the orphan class: removable with provably zero functional impact, because nothing was using it.
A CVE in a module that cannot be loaded is irrelevant. A CVE in a module any local user can autoload with a single socket() call is critical. The gate reason for each element is carried in the report so the judgement is auditable, not asserted.
02 / the trap
Module autoload: 'not loaded' is not 'not reachable'
Kernel module autoloading means an unprivileged process can cause a module to load on demand — creating a socket of an obscure family, opening a filesystem type, touching a netlink protocol. Tools that enumerate /proc/modules and stop there report a clean host while the dangerous module is one syscall away.
ksl walks modules.dep for available modules, not just loaded ones, and marks anything autoloadable by an unprivileged trigger as reachable. That is why the gates table separates present but gated from reachable and unused — the second class is where the free wins are.
03 / attribution
Surface debt: who keeps this open?
A host's kernel surface is a jointly held liability. The ledger splits it.
Every workload's syscall, device and capability usage is mapped to the surface elements it touches. An element touched by exactly one workload is that workload's sole-owned surface — stop the workload and the surface can go. An element touched by several is shared, and its weight is divided between them.
surface debt is a workload's total share of reachable weight. marginal contribution is how much reachable weight would disappear if that one workload went away and nothing else changed — the number that answers "is this container worth its blast radius?".
The pinned ORPHANED row carries whatever is left: reachable surface no workload claims. On most hosts it is the single largest row in the ledger, and it is the row that costs nothing to pay off.
04 / ranking
Hardening as weighted set cover
Each candidate change (blacklist a module, tighten a sysctl, drop a capability, apply a seccomp filter) covers a set of reachable CVE clusters at an estimated breakage cost. The plan is a greedy weighted set cover: maximise CVE mass neutralized per unit of predicted breakage, then order the steps.
The result is a plan, not a findings list. Each step ships the artifact that implements it, the command that detects breakage afterwards, and the exact revert. Reversibility is not a nicety here — an irreversible hardening step is one nobody applies.
05 / honesty
What this cannot tell you
Every limit below is recorded in the report itself rather than papered over.
- Observation window. "used" means used during the trace window. A nightly job that runs at 03:00 looks orphaned at noon. Trace longer, or trace repeatedly, before removing surface a workload might need.
- Trace backend availability. eBPF tooling is frequently missing or broken on a host. When no backend works the report records
trace_backend: noneand marks everything unused — the attribution half degrades honestly instead of lying. - Non-root collection. Without root, some
/procand/sysreads fail. Each one is listed inmeta.skippedwith its reason, and the dashboard shows a partial-data chip. - Userspace collection. ksl reads the kernel's own interfaces; it is not a kernel module. It measures the surface the kernel exposes, from outside.
- CVE clusters, not a CVE database. Elements are mapped to clusters of known kernel vulnerability classes. It is a mapping, and it is as current as the shipped map.