How we measure

We publish our benchmark โ€” misses included.

Most scanners ask you to trust their accuracy. 1.000 on a corpus the author wrote is necessary but not sufficient โ€” the fixtures and the rules are tuned to each other. So we also run a held-out set the engine was never tuned on, score it with the same harness, and publish the numbers and the misses. That's the whole thesis: provable, not promised.

The numbers

Two corpora, scored by the same gate.

CorpusFixturesPrecisionRecallDeterminism
Published โ€” in-repo, what we tuned on 75 1.00 1.00 75/75
Held-out โ€” never tuned on 18 0.92 1.00 18/18

Held-out raw: 12 true positives ยท 1 false positive ยท 0 false negatives. The single false positive is a K8S-CONTAINER-RUNS-AS-ROOT finding on a privileged pod that sets no runAsNonRoot โ€” a correct detection the external fixture under-labeled, not an engine error. Adjudicated, that's precision 1.00 too โ€” but we report the raw number, because the honest figure is the point.

Method

What "held-out" means here.

18 fixtures the engine had never seen, staying strictly inside Sentinel's stated scope (the 6 formats, the published rule IDs) โ€” no strawman checks for things it never claimed:

  • 11 recall probes โ€” realistic, current variants of in-scope misconfigurations (the modern /run/docker.sock path, IPv6 ::/0, the standalone aws_vpc_security_group_ingress_rule, an Ingress-fronted privileged pod, newer secret formats).
  • 7 precision probes โ€” hardened/clean configs that a naive scanner over-flags (a localtime mount, a fully-hardened pod, a private-CIDR security group, a ref-only .env).

The first run found real gaps โ€” including a Critical miss. We fixed them, added the fixtures to the repo, and re-ran. That find โ†’ fix โ†’ re-measure loop is the product working as intended; the full write-up keeps the original numbers next to the current ones.

What we don't catch

Known gaps, in the open.

Configuration is one layer. We name the limitations rather than imply we catch everything โ€” the full list is in KNOWN-GAPS.md. The headlines:

  • K8s reachability resolves an Ingress/Gateway โ†’ Service โ†’ Workload chain via the Service selector; a selectorless Service (manual Endpoints) isn't chained yet.
  • Helm / templated YAML isn't rendered โ€” it's detected and skipped (run it on rendered manifests).
  • Sentinel does configuration misconfiguration only โ€” not CVEs, source-code SAST, secrets in git history, or runtime. Pair it with Trivy / CodeQL / gitleaks / Falco.

Re-run it yourself

Don't trust it โ€” reproduce it.

The harness and both corpora are in the repo. Same engine the CLI and this page's scanner use; same deterministic report_digest:

# the published corpus (the CI gate)
cargo run -p harness

# the held-out set, scored the same way
cargo run -p harness -- crates/harness/corpus-holdout