GitOps Security Checklist (Practitioner Guide)
A GitOps security checklist is a set of controls to protect Git-based workflows, automation, and cluster controllers that continuously apply desired state to infrastructure and applications. It reduces supply-chain, credential, and misconfiguration risk while improving auditability.
A GitOps security checklist helps you secure Kubernetes GitOps end-to-end—protecting Git as a production control plane, hardening CI/CD, verifying signed artifacts, handling secrets safely, and enforcing least privilege for GitOps controllers.
How GitOps works (and where trust breaks)#
GitOps uses Git repositories as the source of truth for declarative configuration (Kubernetes manifests, Helm, Kustomize, Terraform). A GitOps controller (in-cluster or adjacent) watches Git and reconciles the live environment to match the repo.
Security hinges on three trust boundaries:
- Git + identity: who can change desired state and how changes are approved/recorded.
- Build + artifact provenance: how code becomes deployable artifacts and how you verify them.
- Deploy + reconciliation: what the controller can do, where it runs, and what it is allowed to apply.
Below is a practitioner checklist organized by those boundaries.
Practitioner checklist (what to do next)#
1) Secure Git as a production control plane
- Enforce MFA/SSO for all users with write access; disable legacy auth (passwords, long-lived PATs) where possible.
- Branch protection on main/release branches:
- Require pull requests (no direct pushes).
- Require reviews (2+ for production paths).
- Require status checks (CI, policy, secret scanning).
- Require linear history and/or signed commits where feasible.
- CODEOWNERS for sensitive paths (e.g.,
clusters/prod/**,platform/**,rbac/**). - Signed commits/tags for release branches. Prefer org-managed keys and documented key rotation.
- Repository segmentation:
- Separate app repos from environment/config repos (blast radius reduction).
- Separate prod from non-prod if maturity is low-to-medium.
- Audit logging enabled and retained (Git provider + CI + cluster).
2) Harden CI/CD and automation credentials
- Minimize CI permissions: CI should not be cluster-admin; ideally CI builds/pushes artifacts and GitOps handles deploy.
- Use short-lived credentials (OIDC federation to cloud registries and secret managers) instead of static keys.
- Pin and verify third-party actions/tools in pipelines (version pinning; prefer checksums/signatures).
- Protect CI runners:
- Isolate runners per trust level (public PRs vs internal).
- Restrict outbound egress where possible.
- Separate duties:
- Build pipeline produces signed artifacts.
- GitOps deploy path verifies signatures and applies.
3) Secure artifacts: registries, signing, and provenance
- Use a private registry (or private namespace) with strict push permissions.
- Immutable tags for production (or enforce digest-pinning).
- Image scanning in CI and/or admission:
- Block critical CVEs based on policy.
- Define exceptions with expiry and ticket reference.
- Sign artifacts (images, Helm charts, or manifests) and verify on deploy.
- Provenance: generate provenance attestations for builds; store and verify them during deployment gates.
Tip: For endpoint protection on CI runners and build machines, compare business-grade options here: best antivirus for Windows business endpoints.
If you want a lightweight “baseline” anti-malware layer for developer or CI endpoints (especially where you can’t fully control software installs), you can evaluate Malwarebytes here: Malwarebytes website. (Still prioritize least privilege, runner isolation, and signed/pinned dependencies over “scan-and-hope.”)
4) Secrets: keep them out of Git (or encrypt correctly)
- Prefer external secrets patterns:
- Pull secrets from a secret manager (cloud secret manager, Vault) at runtime.
- If you must store secrets in Git:
- Use strong encryption and restrict access tightly.
- Ensure PR checks prevent accidental plaintext secrets.
- Rotate secrets on leak suspicion; treat repo exposure as compromise.
- Detect leaks:
- Pre-commit hooks + server-side secret scanning.
- Alerting to a security channel with runbooks.
If your GitOps model requires humans to handle fewer shared credentials, enforce strong identity hygiene and vaulting. For small teams, a business password manager can help reduce ad-hoc secret sharing—see options here: best password manager for small business or consider 1Password Business: Try 1Password →.
5) Lock down the GitOps controller and cluster permissions
- Least privilege RBAC:
- Separate controllers per namespace/team where practical.
- Avoid cluster-admin; grant only required API groups/namespaces.
- Network policies:
- Restrict controller egress to Git server, registry, and required endpoints.
- Limit ingress to controller webhook endpoints (if any).
- Harden controller runtime:
- Run as non-root.
- Read-only root filesystem where possible.
- Drop Linux capabilities.
- Cluster separation:
- Different clusters (or at least separate controller instances) for prod vs non-prod.
- Credential scope:
- Git deploy keys should be read-only where possible.
- Controller should not have write-back permissions unless required.
6) Policy-as-code and admission controls (prevent bad config)
Add policy checks in PR (fast feedback) and enforce at admission (hard stop):
- Disallow privileged pods, hostPath, hostNetwork unless approved.
- Enforce resource limits/requests.
- Enforce allowed registries and signed images.
- Require namespace labeling and ownership metadata.
Also validate manifest schemas—Kubernetes API validation is not enough to catch org-specific rules.
7) Drift detection, reconciliation safety, and break-glass
- Drift detection:
- Alert when live state differs from Git (manual changes, compromised credentials).
- Reconciliation safety:
- Use progressive delivery (canary/blue-green) for risky services.
- Require approvals for high-impact changes (e.g., cluster-wide CRDs, RBAC).
- Break-glass access:
- Documented emergency path with time-bound elevated privileges.
- Post-incident reconciliation and audit review.
8) Monitoring, logging, and incident readiness
- Centralize logs:
- Git audit events (pushes, PR merges, permission changes).
- CI logs (builds, artifact uploads).
- Controller logs (sync/apply events).
- Kubernetes audit logs (resource changes).
- Create alerts for:
- Unexpected controller syncs outside change windows.
- New deploy keys/tokens created.
- Policy denials spikes.
- Deployment of unsigned images / unapproved registries.
- Runbooks:
- How to revoke tokens, pause reconciliation, roll back to known-good commit.
Technical notes: branch protection and ownership controls (Git)#
Example CODEOWNERS pattern for production-impacting paths:
# Require platform team review for prod cluster changes
clusters/prod/ @platform-team
rbac/ @security-team @platform-team
policies/ @security-team
Recommended branch protection (provider-specific UI/settings):
- Require PR reviews (2)
- Require status checks:
lint,policy,scan,unit-tests - Require signed commits (if supported)
- Restrict who can push to matching branches (release managers only)
Technical notes: detecting suspicious GitOps activity (log patterns)#
Look for:
- Syncs to production without an associated merge to the production branch.
- Rapid successive reconciliations (possible automated tampering).
- Controller authentication failures to Git/registry (token abuse or rotation mismatch).
Example (generic) controller log grep ideas:
# Reconciliation events (names depend on controller)
kubectl -n gitops logs deploy/gitops-controller | grep -Ei 'sync|reconcile|apply|error'
# Sudden spikes in permission errors or forbidden requests
kubectl -n gitops logs deploy/gitops-controller | grep -Ei 'forbidden|denied|unauthorized|permission'
Technical notes: Kubernetes admission guardrails (policy-as-code)#
A minimal example of an admission-time control concept (pseudo-policy) to require images by digest and from approved registries:
DENY if container.image does NOT match:
^(registry\.example\.com|ghcr\.io/your-org)/.+@sha256:[a-f0-9]{64}$
In practice, implement with your chosen policy engine and enforce in:
- CI (pre-merge policy checks)
- Cluster admission (enforce mode for production)
Technical notes: RBAC sanity check for GitOps controllers#
Quickly inspect what a controller service account can do:
# List RBAC bindings in the gitops namespace
kubectl -n gitops get rolebindings,clusterrolebindings -o wide
# Can the service account create/update sensitive resources?
SA="system:serviceaccount:gitops:gitops-controller"
kubectl auth can-i --as="$SA" create clusterroles
kubectl auth can-i --as="$SA" create validatingwebhookconfigurations
kubectl auth can-i --as="$SA" patch secrets -n prod
Target state: the controller can only change the namespaces and resource types it must manage—nothing more.
When you’ll encounter GitOps security checklist requirements#
You’ll run into GitOps security checklist requirements when:
- Migrating from imperative deployments (kubectl/SSH/manual changes) to declarative Kubernetes operations.
- Undergoing SOC 2 / ISO 27001 audits where change management and least privilege must be demonstrated.
- Implementing multi-team platform engineering where repo and environment boundaries are critical.
- Responding to a supply-chain incident (compromised CI token, malicious dependency, poisoned container image).
- Scaling from dev/test GitOps to production and needing formal controls (approvals, policy, break-glass).
Related terms
Ops model using Git as the source of truth and automated reconciliation.
Codified rules enforced in CI and/or admission to prevent insecure configs.
Identifying differences between desired (Git) and actual (running) state.
Inventory of components in an artifact; useful for vulnerability response.
Maturity framework for build integrity and provenance.
Cryptographic assurance that images/manifests were produced by trusted pipelines.
Minimum required permissions for controllers, CI, and humans.
Keeping credentials out of repos and minimizing secret exposure and lifetime.