SOPS in CI/CD
Decrypt safely in pipelines.
Outside GitOps, pipelines often need to decrypt SOPS secrets to deploy or configure something — and the goal is to do it without ever writing plaintext where it can leak. The pattern: give the CI job access to the decryption key via the platform’s secret store or, best, cloud OIDC (so the runner assumes a role with kms:Decrypt and no static key exists), then decrypt into the environment for the exact command that needs it using sops exec-env, avoiding a plaintext file on disk.
jobs:deploy:permissions: { id-token: write, contents: read } # OIDC -> assume a role with kms:Decryptsteps:- uses: aws-actions/configure-aws-credentials@v4with: { role-to-assume: arn:aws:iam::ACCT:role/ci-sops-decrypt, aws-region: us-east-1 }- run: sops exec-env secrets.enc.yaml './deploy.sh' # decrypt into env for this command only
Keep plaintext transient and out of logs
Two rules make CI decryption safe. First, prefer KMS + OIDC over a committed or stored age key, so the pipeline has short-lived, scoped, audited decrypt access rather than a long-lived key that a compromised runner exfiltrates. Second, never let decrypted values reach logs or artifacts — use exec-env (not sops -d > file), avoid echoing secrets, and mark them masked in the CI system. The blast radius of a CI compromise is proportional to how much and how long plaintext exists in it.