SELinux confinement, compiled from behavior. Proven under Enforcing.
Give hardener a legacy RPM, a tarball, or a vendor
binary — no source required. It derives the least privilege the application actually needs, generates a
proper SELinux policy, packages it as an installable RPM, and verifies the app still works with
enforcement on. The alternative it replaces is setenforce 0.
Observe, classify, enforce, prove
The refine step is what separates this from audit2allow: a denial whose path
falls under the app's own file-context claims but carries a generic label is a labeling problem —
fixed with restorecon, never an allow rule. Privileged capabilities, sensitive targets
(shadow_t), and broad shared types (var_log_t, tmp_t) are never
granted silently; they route to a review gate.
What a pass proves
ps -o label=) — a failed transition cannot fake a pass with a clean log.sesearch; accepted exceptions are named in the verdict, never hidden.Coverage honesty: static import analysis predicts what the binary can do (bind, drop privileges, exec); anything the exercise never drove is reported as a coverage gap instead of assumed safe.
Six ways real vendor software breaks naive policy generation
Each of these was found on a real artifact, and each is diagnosed by name instead of surfacing as a mystery:
Symlinked entrypointnats-server
The resolved inode decides the transition. Label the symlink and the service runs unconfined while looking healthy.
Mislabeled entrypointemby
The service can never start — with zero denials in its own domain. Caught by watching denials against owned types from every source domain.
NoNewPrivileges unitsplunk
The kernel permits only bounded transitions; no policy fixes it. Diagnosed up front with the systemd remediation named.
Base-policy collisionwebmin
Redeclaring a path the distro claims kills the whole module. Detected, deferred, reported.
Interpreter ExecStartplex
ExecStart=/bin/sh -c — labeling the shell would confine the entire OS. Guarded; the transition fires on the exec'd app binary.
App bug ≠ policy bugall
Failing in a permissive domain with zero denials is not SELinux. One round, honest diagnosis, stop.
One pipeline, three contracts
Third party
COTS/OSS — no counterparty holds a claim.
Observation is discovery; privileged rules go to review.
Second party
Supplier deliverable with a privilege declaration.
Observed-but-undeclared behavior fails acceptance — noncompliance or compromise.
First party
Your code, with a committed privilege baseline.
Drift fails the build until reviewed (--update-baseline).
The verdict is an attestation
Every run emits the verdict as an in-toto statement: subjects are the policy RPM and
.te/.fc by digest; the predicate carries every gate, flagged rule, conformance
outcome, coverage gap, and the exact verifier baseline. Signing (ed25519 DSSE) and Archivista upload are
built in and strictly optional — both off by default. For keyless signing, timestamps, and
full execution provenance, wrap the run with CI/Lock; the two compose.
Manifests are meant to be written by AI agents
The one input that takes judgment is the workload manifest — install, start, exercise, stop. The repo ships a skill that teaches an agent to inspect your artifact, write a scenario-based exercise, and iterate against the report's coverage gaps. Point your agent at an artifact; review the manifest like you'd review a test plan.