Repository navigation
Releases
v0.7.0
k8s-guardian v0.7.0: accuracy and CI ergonomics
This release makes the existing checks right in more situations. The new behaviour is tested against a real API server and against 30 public Helm charts in CI.
New
diff --server-sidesends each object to the API server as a server-side apply dry run. Nothing is stored.- DF008 reports what the server would reject: immutable or invalid fields, fields the schema doesn't have, and denials by ValidatingAdmissionPolicies, webhooks, quotas or Pod Security.
- Fields that defaulting, mutating policies or webhooks would change (sidecar injection, for example) appear in the diff, marked by the API server. If they would restart the pods, there is a note.
- If RBAC doesn't allow the dry run, the namespace or CRD doesn't exist yet, or a webhook can't do dry runs, you get a note instead of a false error.
- The MCP server stays read-only.
--live: LV003 now filters nodes the way the scheduler does. It skips cordoned nodes, required node affinity (In,NotIn,Exists,DoesNotExist,Gt,Lt,matchFields) and taints the pod doesn't tolerate. The message says which nodes were excluded and why:
nodes with enough room are excluded (taint dedicated=gpu:NoSchedule: gpu-1)
DaemonSets get the tolerations their controller adds. A DaemonSet that no node accepts is a warning ("runs no pods").- Helm
--kube-version(orkubeVersion:in.k8s-guardian.yaml) renders charts for your cluster's version. With--liveanddiff, the connected cluster's version is used automatically.
Fixes
- KG017 is now checked against the official deprecation guide: 50 removed APIs, including the 1.22 TokenReview/SubjectAccessReview betas. Newer API kinds in groups that had old betas, such as ValidatingAdmissionPolicy, ClusterTrustBundle and LeaseCandidate, are no longer flagged as removed.
--fixon Windows files keeps CRLF line endings, and baselines match on any path separator.
Quality
- Unit tests run on macOS and Windows too.
- The 30-chart test runs in CI on every push, weekly, and on pull requests. Chart sources are pinned, and the findings per chart and rule must match
hack/charts/expected.json, so any change in behaviour on real charts shows up in review.
Full changelog: v0.6.0...v0.7.0
v0.6.0
Adopt it in an existing repository
Baseline: fail only on new findings
k8s-guardian check -f k8s/ --update-baseline # record today's findings
k8s-guardian check -f k8s/ --baseline .k8s-guardian-baseline.jsonFindings are matched without line numbers, so moving code doesn't turn a known finding into a new one. A finding recorded once hides one occurrence, so a second identical problem is still reported.
Config file: .k8s-guardian.yaml
skip: [KG015]
severity: {KG006: error}
failOn: warning
exclude: [vendor]
rules: [policies/]
baseline: .k8s-guardian-baseline.jsonThe file is read from the working directory, or passed with --config. The GitHub Action picks it up automatically. Unknown keys and unknown rules are errors, so a typo can't silently disable a setting.
Helm values
Check what you actually deploy:
k8s-guardian check -f charts/app --values values-prod.yaml --set replicaCount=3New
- Argo Rollouts are checked like Deployments, including cost estimates.
- KG018
rbac-wildcardflags Roles and ClusterRoles that grant"*"verbs or resources, with one finding per role. On the 30-chart test it reports 7 roles, all of which really grant wildcards. - KG015 counts an HPA's
minReplicas, so a Deployment scaled by an HPA withminReplicas: 2is no longer flagged.
Fixed
check --fixchecks all files together, likecheckdoes, so an HPA in one file and its Deployment in another no longer produce a false KG015.export vap|kyvernoalso exports the custom rules listed underrules:in the config file.
Docs
- README is now a short overview with a diagram. The details moved to docs/.
cost, the interactive TUI andrule createare marked experimental. They work and are tested, but their output and flags may change.
v0.5.0
Tested on 30 real Helm charts
k8s-guardian was run against 30 popular Helm charts (652 objects). The run found five bugs in k8s-guardian itself, and this release fixes all of them. Methodology, per-chart results and a script to reproduce the run: docs/real-world-test.md.
⚠️ Behaviour change: --fix is now safe by default
--fix only applies fixes that can't change how a workload runs: allowPrivilegeEscalation: false and seccompProfile: RuntimeDefault.
The other deterministic fixes (runAsNonRoot, readOnlyRootFilesystem, capabilities.drop: [ALL], default resource requests and limits) can stop root images, apps that write to their filesystem and memory-hungry apps from running. They now need --fix --unsafe-fixes and a review. The report marks these findings [unsafe fix].
Privileged containers (KG004) and host namespaces (KG011) are reported but never changed. Node agents such as CSI and CNI drivers or node-exporter need them on purpose. Use the k8s-guardian.io/ignore annotation for those resources.
To keep the old behaviour, use check --fix --unsafe-fixes. Even then, privileged and host-namespace settings are no longer removed.
Fixed
--fixrewrote whole files. Documents a fix does not change are now written back byte for byte. Before, every document was re-encoded, which reformatted up to 85,000 lines, and in one case it dropped the leading empty line of a ConfigMap block scalar.--fixcould produce manifests the API server rejects. It turned offprivilegedon a container with Bidirectional mount propagation.- KG016 numeric
targetPort: no longer reported when the container declares no ports (containerPortis informational). - KG016 selectors: no longer reported for Services whose pods are created by an operator. A near miss (some, but not all, selector labels match) is still reported.
- KG008/KG009: run-once Pods (
restartPolicy: Never/OnFailure, e.g. Helm test hooks) no longer need probes. - KG005/KG007: skipped for privileged containers, which have every privilege anyway (KG004 reports them). The exported ValidatingAdmissionPolicy and Kyverno policies match.
Also
- The MCP
fix_manifesttool has anunsafe_fixesoption. k8s-guardian rulesmarks unsafe fixes asauto*.- New demo GIF and
hack/charts/run.shfor the real-world test.
v0.4.0
Install
# Binary: download the archive for your platform below, or
go install github.com/andronaft/k8s-guardian/cmd/k8s-guardian@v0.4.0
# Docker
docker run --rm -v "$PWD:/work" ghcr.io/andronaft/k8s-guardian:0.4.0 check -f .
# GitHub Action
# - uses: andronaft/k8s-guardian@v0.4.0kubectl-guard_* archives contain the kubectl plugin (kubectl guard ...).
Changelog
- f4ddc63 Refine action.yml description for K8s validation
- 03248d3 Fix symlink escape in directory walks, atomic writes, gosec clean
- 053f31a Move to Go 1.26 and update golang.org/x/sys (GO-2026-5024)
- 6ef3269 CI: show govulncheck details
- 1ee65ba Security fixes: kubectl flag injection, secret leaks, AI guardrails
- 4b67544 Bump golang from 1.24-alpine to 1.27-alpine (#1)
- 2f1f877 Bump github.com/charmbracelet/x/term in the go-deps group (#2)
- 116593b Bump rajatjindal/krew-release-bot in the actions group (#3)
- b0e2b77 Add Kyverno export, Prometheus usage history and a demo GIF
- 514c93f Export rules as ValidatingAdmissionPolicies and add real API server e2e tests
- 0ee84e8 Add Kustomize support, usage-based right-sizing and Krew manifest
- 97919d9 Point README at the v0.3.0 release
v0.3.0
Install
# Binary: download the archive for your platform below, or
go install github.com/andronaft/k8s-guardian/cmd/k8s-guardian@v0.3.0
# Docker
docker run --rm -v "$PWD:/work" ghcr.io/andronaft/k8s-guardian:0.3.0 check -f .
# GitHub Action
# - uses: andronaft/k8s-guardian@v0.3.0kubectl-guard_* archives contain the kubectl plugin (kubectl guard ...).
Changelog
- 5f09655 Release notes in commit order; document the Docker image
- 3125e6b Publish a multi-arch Docker image to GHCR on release
- 5a4a215 Update GitHub Actions to Node 24 majors
- 48154a5 Add GitHub Action, github/markdown output formats and CLI end-to-end tests
- f763bad Add live cluster checks, breaking-change diff, cost estimation, TUI and custom rules
- e0d6df4 Add k8s-guardian: Kubernetes guardrails CLI, kubectl plugin and MCP server
- ede94e4 Initial commit