Kritis: a deploy time policy gate in front of your Kubernetes admission chain
Deploy-time Policy Enforcer for Kubernetes applications
At a glance
- What is it?
- Kritis is a Go implementation of deploy time policy enforcement for Kubernetes, sitting between the cluster and the image registry to check vulnerability findings and image allowlists before a pod is admitted. It also ships signers that emit Grafeas attestations, so the same evidence can be reused by Binary Authorization.
- Who is it for?
- Kritis suits a team that wants to stop a vulnerable image from reaching a cluster and that is comfortable with a Go binary, a Kubernetes admission webhook and Grafeas as the evidence store. It does not suit a team that only needs a signature check, since Binary Authorization is the more common route for that, and it does not suit a team without Google Cloud Container Analysis access or with a stack that has moved off Grafeas.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 52 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The gate sits between the cluster and the registry, not inside the app
Kritis, which means judge in Greek, is described as an open-source solution for securing the software supply chain for Kubernetes applications. It enforces deploy time security policies using the Google Cloud Container Analysis API and, in a subsequent release, Grafeas.
The positioning matters more than the implementation details. This is not a scanner and not a runtime monitor. It is a decision point that runs when a workload is being admitted, and it answers a single question: should this pod be allowed to start, given what is known about the image it references.
The policy format is where that question becomes concrete. Here is the example the documentation gives for preventing deployment of a pod with a critical vulnerability unless the image is allowlisted.
imageAllowlist:
- gcr.io/my-project/allowlist-image@sha256:<DIGEST>
packageVulnerabilityPolicy:
maximumSeverity: HIGH
allowlistCVEs:
- providers/goog-vulnz/notes/CVE-2017-1000082
- providers/goog-vulnz/notes/CVE-2017-1000081Three things are visible in those twenty lines. The allowlist is by digest, not by tag, which is the only safe way to reference an image for a policy decision. The vulnerability threshold is a severity, with HIGH as the example cutoff, and the CVE exceptions are named as full provider note paths rather than bare identifiers, which tells you the findings are addressed through the Container Analysis note model rather than through a flat list. And the image allowlist and the vulnerability policy are separate structures, so an operator can pin one specific artefact and still be strict about everything else.
The audience is a platform or security team running a Kubernetes cluster with a registry they control, and who want the enforcement to happen before the workload exists rather than as a scan report afterwards.
The signers produce Grafeas attestations that other enforcers can reuse
The second half of the project is the signers, and it is the part that makes Kritis more than a single-purpose gate.
The documentation states that in addition to the enforcement, the project contains signers that can be used to create Grafeas Attestation Occurrences, to be used in other enforcement systems like Binary Authorization. Details are pointed at an upcoming Kritis Signer document, and there is a TODO in the README acknowledging that the link still needs fixing.
The architectural point is that evidence and enforcement are separated. The signers produce attestation records: statements of the form this image was built from this source, this policy was checked, this vulnerability set was found. The enforcer consumes those records. Kritis happens to be both, but the design lets you use the producer half with a different consumer half.
That is the interesting part, because Binary Authorization is a different model. Instead of evaluating a policy at admission time, it checks whether an image has been attested by an approved signer. The two approaches are not equivalent. A policy evaluated at admission time reflects the state of the vulnerability database at the moment of the request, and it needs the scanner to be reachable and reasonably fresh. A signature check reflects a decision that was made earlier and recorded, and it works when the registry is available but the vulnerability API is not.
The sample directory makes the split visible in the repository layout, with a policy-check sample and a signer sample, and the helm-hooks and kritis-charts directories at the top level indicate that the deployment story is Helm charts plus an admission hook.
So Kritis is a reasonable way to try the policy-evaluation model inside a Kubernetes cluster, and it also produces the artifacts you would need if you later move to the attestation model.
Standalone mode is the path that does not need a Google Cloud project
The getting started section offers two routes, and the difference between them is the most important operational fact in the project.
The first route is the tutorial for learning how to block vulnerabilities using GCP Container Analysis, with the Container Analysis API reference linked. That is the full production path: a Google Cloud project, credentials, the analysis service and the cluster.
The second is standalone mode. The standalone mode tutorial is linked as a way to try out Kritis with standalone Grafeas, and the resources directory in the top level listing includes a deploy/ directory alongside artifacts/, cmd/, pkg/, helm-hooks/, kritis-charts/ and integration/.
That distinction matters because Container Analysis is a hosted Google service. Its findings, its note identifiers and its severity model are the vocabulary the policy file above is written in, down to the providers/goog-vulnz/notes path. If your organisation's vulnerability data comes from a different scanner, the mapping work is yours, and the README does not document how to plug in an alternative findings source.
The Grafeas side is more open. The go.mod depends on the Grafeas protobuf definitions through google.golang.org/genproto and grpc, and the project also depends on go-containerregistry, which is how it resolves images and their digests, and on opencontainers/go-digest. Those are the pieces that make the attestation records portable between a signer and an enforcer.
There is also a community question behind the design. The Grafeas project is a general purpose metadata API for software supply chain components, and Kritis is the Kubernetes-specific implementation of an enforcement pattern on top of it. The whitepaper linked as the binary authorization document explains the concepts, and the InfoQ talk on software supply chain management with Grafeas and Kritis is offered as the starting watch.
The Go code is a cobra CLI with a kubectl plugin and vendored dependencies
The implementation is a Go 1.14 module with a dependency list that dates the project precisely.
The CLI framework is spf13/cobra, the logging is sirupsen/logrus, the YAML handling is gopkg.in/yaml.v2, and the Kubernetes client libraries are k8s.io/api, apimachinery and client-go all at 0.18.8, which corresponds to Kubernetes 1.18. The image handling is google/go-containerregistry at 0.2.1, the protobuf support is golang/protobuf 1.4.2 with google.golang.org/protobuf through genproto, and grpc is 1.29.1. Tests use stretchr/testify and the ginkgo and gomega suites.
The Makefile shows two more things that are useful to know. There is a kubectl plugin path, cmd/kritis/kubectl/plugins/resolve, with a corresponding resolve-tags binary installed into ~/.kube/plugins/resolve-tags, and a RESOLVE_TAGS_PROJECT variable that points at a separate repository, resolve-tags, under the grafeas GitHub organisation. So a piece of the tag resolution logic lives in its own project and is installed alongside kubectl.
The credentials handling is explicit in the Makefile. GAC_CREDENTIALS_PATH defaults to a path under a .secrets directory named after the project, and the comment notes that the basename must be gac.json, because that is what the code looks for.
GAC_CREDENTIALS_PATH ?= $(CURDIR)/.secrets/$(GCP_PROJECT)/gac.jsonThe build produces cross platform binaries for linux, darwin and windows on amd64, and the image tag defaults to the git commit. The test target is a chain of scripts rather than a single go test: a formatting check, a boilerplate header check, a code generation verification, a dependencies check and then the test script itself, which is a good sign for a project whose generated clients drift easily.
The integration test setup is visible too, with GCP_PROJECT, GCP_ZONE and GCP_CLUSTER variables and a target that pushes the images to a real project.
Where Kritis is the wrong tool
The first wrong-tool case is a team that only wants signature verification. Binary Authorization already does that, it is the model most people mean when they say enforce on deploy, and adding a policy evaluator in front of it is extra machinery for a problem it does not have. Kritis's own documentation points at Binary Authorization as a system that can consume what Kritis produces, which is the argument for the signer half and against the enforcer half in that case.
The second case is a stack that has moved on from Grafeas and Container Analysis. The policy vocabulary here is Google's: note identifiers under providers/goog-vulnz/notes, the severity threshold from the analysis API, and Grafeas occurrences as the evidence format. A team whose metadata store is something else, or whose vulnerability data comes from a different scanner, is looking at an integration project rather than an install.
The third case is a cluster that does not run Kubernetes, or runs a distribution where the admission path is different. The enforcement point is the Kubernetes admission webhook, and the repository's deploy tooling is Helm charts plus admission hooks, so the whole thing is Kubernetes specific.
There is also a freshness question that the design does not remove. Evaluating a policy at admission time means the answer depends on the vulnerability database as it stood at that moment, and it depends on the enforcer being able to reach that database. A registry-side or attestation-side check has different failure characteristics, and a team with a strict availability requirement for the admission path needs to think about which one they are buying.
On maintenance, the last push was on 2026-09-01, the repository has no GitHub releases, and the Makefile still carries a default VERSION of v0.2.2 from the original commit era. The CHANGELOG.md, SECURITY.md, RELEASING.md and the docs directory show a project with real process around it, but the Kubernetes client libraries it depends on are several major versions behind, and a 1.14 language level means you are building this with an old toolchain. The licence is Apache 2.0 with the LICENSE file at the root, which is permissive and suitable for a security component you intend to run in your own cluster.
Editorial conclusion
Kritis suits a team that wants to stop a vulnerable image from reaching a cluster and that is comfortable with a Go binary, a Kubernetes admission webhook and Grafeas as the evidence store. It does not suit a team that only needs a signature check, since Binary Authorization is the more common route for that, and it does not suit a team without Google Cloud Container Analysis access or with a stack that has moved off Grafeas. Before adopting, read the tutorial for the Container Analysis path and the standalone mode tutorial in parallel, check whether the policy file format covers the findings your scanner actually produces, and confirm the deployment path, since the Helm charts and the admission hook configuration are where this kind of project usually needs per-cluster work.
Frequently asked questions
What is Kritis?
Kritis, which means judge in Greek, is an open source solution for securing the software supply chain of Kubernetes applications. It enforces deploy time security policies using the Google Cloud Container Analysis API and, in a subsequent release, Grafeas.
What does a Kritis policy file look like?
The documented example has an imageAllowlist listing images by digest, and a packageVulnerabilityPolicy with a maximumSeverity and an allowlistCVEs list of provider note paths such as providers/goog-vulnz/notes/CVE-2017-1000082.
What is the difference between the Kritis signers and the enforcer?
The signers create Grafeas Attestation Occurrences that can be used in other enforcement systems such as Binary Authorization, while the enforcer evaluates policies at deploy time. The README notes that a document covering the signers in detail is still upcoming.
Can Kritis run without Google Cloud Container Analysis?
There is a standalone mode tutorial for trying Kritis with standalone Grafeas, alongside the tutorial for learning how to block vulnerabilities using GCP Container Analysis. The policy vocabulary itself, including the provider note identifiers, comes from the Container Analysis model.
What license is Kritis released under?
Kritis is under the Apache 2.0 license, with the LICENSE file at the root of the repository. The Go module requires Go 1.14 and the Kubernetes client libraries are at version 0.18.8.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/grafeas-kritis)Was this useful?