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: Get Malwarebytes →. (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.