KubeCap, a preprint published on arXiv and accepted to ISSRE 2026, automates the least-privilege capability audit almost no team performs: its authors report, self-reported and not independently reproduced, that 74.67% of studied projects ship no capability configuration at all. What its LLM-inferred rules miss is everything a workload only reveals at runtime, which is why the right destination for its output is a CI suggestion, not fleet policy.
Why does nobody configure capabilities in the first place?
Most Kubernetes workloads run with more Linux capabilities than they need because the manual audit required to trim them is tedious, easy to get wrong, and produces no visible reward when it succeeds. The KubeCap authors put a number on the neglect: across three open-source datasets, 74.67% of studied projects ship no capability configuration whatsoever, according to their own empirical study. Three out of four projects, by the paper’s count, simply accept whatever the container runtime and the base image give them.
The reason is structural, not lazy. Kubernetes is an open-source orchestration system built on fifteen years of production workload experience at Google, and it has accumulated sensible defaults for scheduling, networking, and storage. Capability configuration is not one of them. The pod spec will happily run anything you hand it, and nothing in the default path tells you which of the available capabilities your binary actually exercises. The platform gives you the knob and no reason to turn it.
Turning the knob by hand means reading your own binary’s syscall surface, mapping those syscalls to the capabilities that gate them, and then living with the consequences when you guess wrong. Guess too tight and the workload fails, sometimes only under a code path that fires in production at 3 a.m. Guess too loose and you have done security theater. Faced with that asymmetry, most teams do what the paper’s dataset shows them doing: nothing.
The timing matters. Kubernetes 1.36.4 shipped on August 20, 2026, per Wikipedia’s release history, nine days before the KubeCap preprint surfaced on feeds. Capability minimization has been theoretically available for as long as the pod security context has existed. What has been missing is a way to compute the answer that costs less than ignoring the question.
How does KubeCap compute a minimal capability set?
KubeCap combines static analysis of workload code with rules that map syscall-parameter pairs to the capabilities they require, and it uses an LLM to help derive those rules from Linux kernel source. The pipeline, as described in the KubeCap preprint, has two halves that deserve separate scrutiny, because they have very different failure modes.
The first half is conventional static analysis. Given a workload’s code, determine which syscalls it can invoke and with what parameters. This is well-trodden ground: you trace the call graph, you find the syscall sites, you collect the arguments where they are statically determinable. Nothing about this requires a language model, and nothing about it is new in principle.
The second half is the novel and the fragile part. The kernel does not ship a tidy table that says “this syscall with this parameter requires this capability.” The capability checks live inside kernel code, scattered across subsystems, written in C, and expressed in whatever idiom the subsystem maintainer preferred. KubeCap’s answer is LLM-assisted rule specification to derive syscall-parameter-capability relations from Linux kernel code: point a language model at the kernel source and have it produce the mapping rules a human auditor would otherwise have to write by reading that code themselves.
This is a genuinely reasonable use of an LLM. Kernel capability checks are formulaic enough to be extractable and voluminous enough that nobody wants to extract them by hand. It is also a use that transfers every known LLM reliability problem directly into your security policy, a point this analysis returns to below. The point here is the architecture: static analysis answers “what can this workload do,” inferred rules answer “what does doing that require,” and the minimal capability set is whatever the intersection demands.
How much should you trust the 54.97% reduction?
You should treat the headline number as a paper result from a narrow evaluation, not a benchmark your fleet will reproduce. The average capability reduction of 54.97% comes from the authors’ own evaluation of 10 representative Go-based Kubernetes projects. Three qualifiers in that sentence do real work: self-reported, ten projects, Go-based.
Self-reported means exactly what it says. The evaluation was designed, executed, and reported by the same people proposing the tool. That is normal for a preprint, and ISSRE 2026 acceptance means peers found the work credible enough to publish. It does not mean anyone outside the author group has run KubeCap against a workload they did not choose and reported what broke. As of today, no independent reproduction exists in the available record.
Ten projects is a proof of concept, not a population. It is enough to show the approach produces plausible output on real code. It is not enough to say anything about the distribution of outcomes across the long tail of actual workloads, where the interesting failures live.
Go-based is the qualifier with the longest reach. Kubernetes itself is written in Go, so evaluating on Go projects from the Kubernetes ecosystem is a defensible choice: the workloads that run the control plane are exactly the ones where capability hygiene matters most. But Go is also the friendliest possible target for static analysis. It compiles to static binaries, it has a syscall surface the toolchain can enumerate, and its runtime behavior is comparatively legible. A polyglot fleet looks nothing like this. Interpreted languages resolve behavior at runtime. C binaries with dynamically loaded plugins hide syscall sites behind dlopen. Sidecars injected by a service mesh are binaries you did not write and may not have source for.
The honest reading: KubeCap demonstrates that automated capability minimization can cut granted capabilities roughly in half on the easiest category of workload, per its authors. That is a real result. It is also the floor of what you need to know before enforcement.
What can static analysis not see?
Static analysis cannot see kernel-level needs a binary only discovers when it runs, and that blind spot is where over-aggressive drop sets do their damage. Every capability inference pipeline built on static analysis inherits this limit, regardless of how good the rule set is.
The gap has a few distinct shapes. Some syscalls only fire under runtime conditions: a failover path, a signal handler, a garbage-collection or resharding event that happens weekly. If the code path is reachable, good static analysis will find it, but parameters that determine which capability a syscall requires are often computed at runtime from configuration, environment, or network input. The static pass sees the syscall; it cannot always see the argument.
Then there is behavior that never appears in the workload’s own code at all. A container’s effective capability needs are the union of everything running in it: the main binary, the init process, the injected sidecar, the observability agent, the debugging shell someone execs in during an incident. Static analysis of your application tells you what your application needs. It says nothing about the tracing daemon that starts dropping packets the day you enforce the inferred set.
This is why the remediation path has to involve observed runtime behavior rather than more analysis. The general shape of the validation loop is well established operator practice, though the specific tooling choices are beyond what the KubeCap evidence covers: run the workload with the proposed drop set in an environment where denials are logged rather than fatal, or trace capability checks at runtime and diff what was exercised against what the inferred rules granted. Where the observed set and the inferred set disagree, the observed set wins, because it is evidence and the inferred set is a prediction.
Where static analysis alone is sufficient: workloads with a narrow, stable syscall surface, no dynamically computed syscall parameters, no sidecars, and a failure mode you can afford. Internal batch jobs that reprocess data on retry are a reasonable first enforcement target. Anything serving live traffic is not.
How do you validate LLM-inferred rules before they become policy?
You validate them the way you validate any ML-generated configuration: assume the model is sometimes confidently wrong, and never let an unverified inference become an enforced control. The rule-inference half of KubeCap is an LLM reading kernel source, and LLM output reliability degrades when training data is biased or inaccurate, a failure mode documented in the general literature on these models. Translated to this pipeline: a wrong syscall-parameter-capability rule produces a drop set that looks correct, passes static review, and silently removes a capability the workload needs.
The asymmetry is worth stating plainly. A rule that grants a capability the workload does not need costs you a slightly wider permission set: the common, boring outcome of the manual process everyone already skips. A rule that drops a capability the workload does need costs you an outage with a permission-denied error several layers removed from the change that caused it. LLM inference errors are not symmetric in their blast radius, and the dangerous direction is the one that looks like success.
LLMs are transformer-based models trained on large text corpora for natural language tasks, and kernel C code is text, so the extraction task is within their competence. But competence at the task class is not correctness on the instance. The kernel’s capability checks include corner cases, subsystem-specific idioms, and code that has changed meaning across versions. An inferred rule is a claim about kernel behavior, and claims about kernel behavior are checkable, which is the saving grace: this is one of the friendlier domains for LLM validation because the ground truth is a compile target, not a vibe.
The practical validation posture has three layers. First, treat inferred rules as proposals with provenance: which kernel version, which code site, which model produced them. Second, verify rules against runtime observation before they gate anything, using the tracing and logging-denial loop described above. Third, pin the rule set. An inferred rule set that silently changes when someone re-runs the pipeline with a different model version is not a security control; it is a random number generator with a compliance dashboard.
None of this is an argument against the approach. Manual rule-writing has its own error rate, and unlike the LLM’s, it is never measured. The argument is that the trust model for inferred rules has to be explicit, because the failure mode is silent.
What does a safe rollout look like?
A safe rollout is three stages: CI suggestion, shadow enforcement, then gate, with the promotion between stages earned by observed behavior rather than elapsed time. This sequencing is the direct consequence of everything above: the static half of the pipeline is trustworthy enough to automate, the inferred half is not trustworthy enough to enforce unvalidated.
Stage one is CI suggestion. KubeCap-style analysis runs on pull requests and posts the proposed capability set as a comment or check annotation. Nothing is blocked. The value here is making the delta visible: developers see which capabilities their change adds or removes from the inferred requirement, and the security team accumulates a record of what the tool proposes against real workloads. This stage also flushes out the obvious misfires, the workloads where the inferred set is visibly wrong, before anything depends on it.
Stage two is shadow enforcement. The proposed drop set is applied in a staging or canary environment with denials logged rather than fatal, or applied for real in environments where failure is cheap. This is where the runtime validation loop lives. A proposed set that survives weeks of real traffic, including the boring periodic events that only happen in production-shaped environments, has earned promotion. A proposed set that generates denial logs tells you exactly which rule to examine.
Stage three is the CI gate. The validated set becomes enforced policy, and new workloads or changes that would widen capabilities beyond the validated set fail the check. This is the endgame the paper’s framing points at: least-privilege defaults enforced by the pipeline rather than by a per-team review that happens once and rots.
Two operational details matter more than they look. Denial logging needs an owner; a log nobody reads is stage two theater. And the gate needs an escape hatch that is audited, not frictionless, because the first on-call engineer blocked by a false negative at 3 a.m. will route around anything routable-around.
Should you adopt KubeCap-style automation now?
Adopt the pattern now and the headline numbers later, once someone outside the author group reproduces them. The practical verdict: capability minimization has crossed the line from manual chore to CI-automatable, at least for the Go-based workload category the evaluation covers, and the cost of least-privilege defaults across a fleet drops accordingly. But the 54.97% reduction and the 74.67% configuration gap are self-reported figures from a single preprint evaluated on ten Go projects, and the LLM-inferred rule layer imports reliability risks that static analysis cannot catch.
The strongest limitation bears repeating because it bounds every decision above: the evidence base is one paper, one evaluation, one language ecosystem. Nothing in the published work addresses polyglot fleets, mesh sidecars, or runtime breakage from over-aggressive drops. If your estate is mostly Go services you control end to end, KubeCap-style tooling is ready for a staged pilot. If it is a mixed fleet with injected sidecars and vendor binaries, the tool’s output is a starting hypothesis, full stop.
The deeper reason this tooling has to exist at all is worth holding onto after the preprint leaves the feed. Linux capabilities are coarse: a handful of broad permissions standing between a container and the kernel, each one gating a grab-bag of unrelated operations. Finer granularity would make least-privilege cheap to express. What we have instead is a permission model coarse enough that auditing it by hand is miserable and wrong defaults are nearly free, which is how three quarters of studied projects end up shipping no configuration at all. Automating the audit treats the symptom competently. The coarse granularity underneath remains, and every inferred-rule failure mode in this article is ultimately a tax that granularity collects.
Frequently Asked Questions
Does KubeCap’s 54.97% reduction rate apply to C++ or Rust workloads?
No, the evaluation scope is strictly limited to Go-based projects. The paper does not provide data for C++, Rust, or interpreted languages, so the reduction figure cannot be extrapolated to polyglot fleets or binaries with dynamic linking.
How does KubeCap’s LLM-inferred rule approach differ from manual capability auditing?
Manual auditing relies on human expertise to map syscalls to capabilities, a process that is error-prone and rarely performed, resulting in 74.67% of projects shipping with no configuration. KubeCap automates this mapping using LLMs to parse kernel source, but introduces a new failure mode where biased training data can generate incorrect rules that static analysis cannot detect.
What is the primary risk of enforcing LLM-inferred capability drops without runtime validation?
The main risk is silent availability failures caused by over-aggressive drops. If an LLM incorrectly infers that a capability is unnecessary, the workload may fail during rare runtime events like failovers or signal handling, creating an outage with a confusing permission-denied signature that is difficult to trace back to the inference error.
Why is the 74.67% lack of capability configuration considered a structural issue rather than a lack of effort?
Kubernetes defaults do not include capability minimization, and the manual process of mapping syscalls to capabilities is tedious with no immediate reward for success. This structural gap means teams often accept the default permissive state because the cost of manual auditing outweighs the perceived security benefit.