Skip to content

v0.5.0

Choose a tag to compare

@github-actions github-actions released this 21 Jul 20:27
· 33 commits to main since this release

Security-focused release covering 25 issues from a self-run audit, plus a redesign of the core verification/enforcement model that most of them shared a root cause with, plus ArgoCD/GitOps documentation for the gpg key backend.

⚠️ Upgrade notes / behavior changes

  • verify now requires the key to be available. It authenticates every candidate ciphertext instead of trusting a magic-byte prefix, so it needs to actually decrypt. If your CI ran verify without key access before, it will now fail with exit code 2 instead of a false "OK" — this is intentional (see #1, #2).
  • Ambient CI=1 no longer bypasses hooks. Only the explicit SECRETIZE_SKIP_HOOKS=1 does now. If your CI relied on the ambient CI var to skip encryption/push-protection, set SECRETIZE_SKIP_HOOKS=1 explicitly (#21).
  • kubectl-secret ciphertext is now bound to the full object identity (apiVersion/kind/metadata.name/namespace), not just the file and key. Values encrypted with prior versions were sealed under the old, narrower AAD and will need to be re-encrypted with encrypt-value under this version (#23).
  • kubectl secret encrypt-value reads the plaintext from stdin by default now (echo -n VALUE | kubectl secret encrypt-value -f FILE -k KEY). Scripts passing it as a positional argument need --allow-argv (#5).
  • k8s_secret_paths manifests are now enforced by verify/pre-commit. A stringData value that isn't ciphertext and isn't explicitly allowlisted via the new k8s_plaintext_keys config field will now be flagged — add it to the allowlist if it's intentionally plaintext (#15).

Verification & enforcement redesign

The core design change: verify/hooks used to check encryption status via a magic-byte prefix, only at HEAD, using working-tree config — a checkpoint with several independent ways around it. verify is now revision-pinned and authenticated; pre-push walks every commit in the pushed range via git's ref-update protocol, not just HEAD.

  • #1 — verify accepted fake RENC-prefixed plaintext as encrypted
  • #2 — verify used mutable index/worktree config, could miss plaintext at HEAD
  • #3 — pre-push verified only HEAD, letting earlier leaked commits reach remotes
  • #4 — a committed raw file-backend key wasn't detected by verify
  • #6 — git path parsing wasn't NUL-safe, letting quoted filenames bypass protection
  • #15 — k8s_secret_paths were ignored by hooks and verify
  • #16 — a global config could silently disable repo-local encryption policy via exclude
  • #20 — root-anchored patterns (/secrets/**) validated but failed open
  • #21 — ambient CI disabled both encryption and push-protection hooks

Path, symlink, and key-lifecycle safety

  • #7 — key_source and explicit paths could escape the repository root
  • #8 — GPG recipients weren't validated as full fingerprints
  • #9 — unlock wrote plaintext secrets with world-readable 0644 mode
  • #10 — removeuser saved the recipient removal before key rotation succeeded
  • #11 — global GPG recipients could be silently included in the committed key.gpg
  • #12 — adduser could grant a new GPG recipient even when the config save failed
  • #18 — matched symlinks could capture local files into encrypted commits
  • #19 — a failed rotate-keys could leave an unignored raw staging key

kubectl-secret per-value crypto

  • #5 — encrypt-value exposed plaintext through argv
  • #23 — Kubernetes value ciphertext wasn't bound to the Secret identity
  • #24 — YAML aliases could copy decrypted stringData into other fields
  • #25 — manifest-state verification gaps (undetected plaintext, argv leak, ArgoCD selfHeal race) — all three sub-items fixed

Release/supply-chain hardening

  • #13 — ArgoCD CMP docs now carry ArgoCD's own warning about manifest-generation secret injection
  • #14 — release binaries are now checksummed (.sha256 assets below); the ArgoCD install snippet verifies before chmod +x
  • #17 — the release workflow no longer interpolates the pushed tag name directly into shell (was shell-injectable)
  • #22 — the ArgoCD CMP key-copy step no longer follows a repo-controlled symlink

Docs

New "Recommended: use the gpg backend instead of file" section for the ArgoCD integration — granting/revoking ArgoCD's access becomes the same adduser/removeuser commands used for teammates, and no raw key material ever needs to be copied into the repo checkout.


Every fix has a regression test. Full commit history: v0.4.1...v0.5.0