Kubernetes secrets delivery in 2026: revisit External Secrets Operator, Sealed Secrets and SOPS before you commit another Secret YAML

Picture a platform team in Jaipur that runs a multi-tenant SaaS product on Kubernetes across Rajasthan and Delhi NCR (an invented example, not a real client). About forty microservices. Deployments already flow through GitLab and a GitOps controller. The uncomfortable truth on the whiteboard: dozens of Secret YAML files still sit in a private GitLab project in cleartext, readable by anyone with repo access, CI logs, and old laptop clones. Compliance wants GitOps without plaintext. One engineer wants External Secrets Operator (ESO), because “we already put API keys in AWS Secrets Manager and Vault for the apps that matter”. Another wants Sealed Secrets, because “encrypt once, commit the SealedSecret, the controller unseals in-cluster”. A third wants SOPS, because “age keys in the CI runner, encrypted values stay in Git, decrypt only at apply time”. Security asks who can read the private key. Platform asks what breaks when you rotate a password at 11 PM IST.

This post compares three ways to deliver secrets into Kubernetes as they stand on 15 October 2026. It is about how secret values reach a Secret object that pods can mount or env-inject. It is not a comparison of HashiCorp Vault versus OpenBao as secrets managers; that angle already has its own post. It is also not a full GitOps controller bake-off; for Argo CD versus Flux, see that post. Admission policy (Kyverno, Gatekeeper, ValidatingAdmissionPolicy) can help stop plaintext Secrets from landing, but it does not encrypt them for you.

Facts come from GitHub releases and LICENSE files, project docs, advisory records (GitHub Security Advisories, OSV, cve.org), and a CLI drill of SOPS v3.13.3, age v1.3.2 and kubeseal v0.40.0 on this Linux box. No full Kubernetes cluster was available for ESO reconcile or Sealed Secrets controller unseal; that limit is stated honestly in the drill section.

The short version

  • Decide the trust model first. ESO pulls from an external backend (Vault, AWS Secrets Manager, GCP Secret Manager, Azure Key Vault, and many more) and writes a normal Kubernetes Secret. Sealed Secrets encrypts for one cluster: only the in-cluster controller can decrypt a SealedSecret. SOPS encrypts files in Git with age, PGP, or cloud KMS (and optional Vault/OpenBao); something in CI or a decrypt plugin must hold a key to decrypt before apply.
  • External Secrets Operator (external-secrets/external-secrets) current line is v2.12.0 (6 October 2026, 2:14 PM IST). Licence Apache 2.0. Core CRDs: ExternalSecret, SecretStore, ClusterSecretStore (API group external-secrets.io). The operator syncs remote values into cluster Secrets and keeps them refreshed.
  • Sealed Secrets (bitnami/sealed-secrets, formerly under bitnami-labs) is at v0.40.0 (10 September 2026, 9:40 PM IST). Licence Apache 2.0. Client kubeseal plus a cluster controller. You commit SealedSecret (bitnami.com/v1alpha1); the controller unseals to a normal Secret. Scopes: strict (default), namespace-wide, cluster-wide.
  • SOPS (getsops/sops) is at v3.13.3 (23 July 2026, 10:57 AM IST). Licence MPL-2.0. CNCF Sandbox project (donated from Mozilla stewardship). Encrypts YAML, JSON, ENV, INI and binary; keys via age, PGP, AWS KMS, GCP KMS, Azure Key Vault, HuaweiCloud KMS, and HashiCorp Vault / OpenBao paths. Companion tool age is at v1.3.2 (29 August 2026, 11:25 PM IST), BSD-3-Clause.
  • Plaintext Secret YAML in Git is the habit to unlearn. ESO moves the source of truth outside Git. Sealed Secrets and SOPS keep encrypted material in Git. None of them removes the need to protect the decrypt side (controller keys, CI age keys, or cloud IAM).
  • Security hygiene on research day: ESO has several 2025 to 2026 GHSAs (including critical templating issues fixed on older lines; current 2.12 is past those patches). Sealed Secrets v0.40.0 fixes a September 2026 medium advisory on older lines. SOPS 3.13.x carries August 2026 advisories (prefer 3.13.2+; set SOPS_HC_VAULT_ALLOWLIST if you ever touch Vault-backed SOPS files).

Where things stand on 15 October 2026

Dates are GitHub release published_at, converted from UTC to IST (UTC+5:30). Licences are from LICENSE files on the default branch. Helm-only tags are listed only as packaging notes, not as the app line.

Project

Release

Date (IST)

Notes

Licence

External Secrets Operator (external-secrets/external-secrets)

v2.12.0

6 October 2026, 2:14 PM

Current app line; helm-chart-2.12.0 same day

Apache 2.0

External Secrets Operator

v2.11.0

18 September 2026, 8:08 PM

Prior minor

Apache 2.0

External Secrets Operator

v2.0.0

6 February 2026, 6:55 PM

2.x line start

Apache 2.0

External Secrets Operator

v1.0.0

7 November 2025, 5:04 PM

1.x stable milestone

Apache 2.0

Sealed Secrets (bitnami/sealed-secrets)

v0.40.0

10 September 2026, 9:40 PM

Current; helm-v2.20.0 same day

Apache 2.0

Sealed Secrets

v0.39.1

20 August 2026, 2:23 PM

Prior patch

Apache 2.0

Sealed Secrets

v0.36.0

25 February 2026, 10:41 PM

Fixed rotate-scope advisory

Apache 2.0

SOPS (getsops/sops)

v3.13.3

23 July 2026, 10:57 AM

Current

MPL-2.0

SOPS

v3.13.2

30 June 2026, 10:47 AM

Fixes exec UID/GID advisory path

MPL-2.0

SOPS

v3.13.0

8 May 2026, 11:40 PM

Introduces SOPS_HC_VAULT_ALLOWLIST

MPL-2.0

age (FiloSottile/age)

v1.3.2

29 August 2026, 11:25 PM

Common SOPS identity backend

BSD-3-Clause

Practical notes. The Sealed Secrets GitHub home is now **bitnami/sealed-secrets** (API redirects from bitnami-labs/sealed-secrets). ESO docs live at external-secrets.io. SOPS docs live at getsops.io/docs. GitHub stars on research day were about 6,902 (ESO), 9,303 (Sealed Secrets) and 23,393 (SOPS); stars measure attention, not fitness for your blast-radius model.

Timeline

Date (IST)

Event

14 August 2015, 3:41 AM

getsops/sops repository created (Mozilla-era start)

29 May 2017, 8:39 AM

Sealed Secrets repository created

17 November 2020, 7:00 PM

external-secrets/external-secrets repository created

2023

SOPS donated to CNCF as a Sandbox project (project docs)

7 November 2025, 5:04 PM

ESO v1.0.0

20 January 2026, 3:01 PM

ESO advisory GHSA-77v3-r3jw-j2v2 / CVE-2026-22822 (critical templating; fixed in v1.2.0)

6 February 2026, 6:55 PM

ESO v2.0.0

25 February 2026

Sealed Secrets v0.36.0 and advisory GHSA-465p-v42x-3fmj / CVE-2026-22728

11 April 2026, 4:20 PM

ESO GHSA-r2pg-r6h7-crf3 / CVE-2026-34984 (DNS exfil via template; fixed in 2.3.0)

8 May 2026

SOPS v3.13.0 (SOPS_HC_VAULT_ALLOWLIST)

23 July 2026, 10:57 AM

SOPS v3.13.3

14 August 2026

SOPS publishes the August 2026 advisory batch (several GHSA)

29 August 2026, 11:25 PM

age v1.3.2

10 September 2026, 9:40 PM

Sealed Secrets v0.40.0

11 September 2026, 7:33 PM

Sealed Secrets GHSA-qj4p-m373-p2wg / CVE-2026-59341 (fixed in 0.40.0)

6 October 2026, 2:14 PM

ESO v2.12.0

First question: what problem are you solving?

Before comparing CRDs, the Jaipur review has to agree on which situation it is in.

External source of truth, cluster is a cache. You already (or will) store passwords in Vault, AWS Secrets Manager, GCP Secret Manager or Azure Key Vault. Teams should not copy values into Git. Kubernetes Secrets are a delivery target, refreshed by a controller. ESO fits.

Git is the source of truth, one cluster owns decrypt. You want sealed manifests that look like other YAML in the repo, and you accept that only that cluster’s sealing key can open them. Disaster recovery means backing up sealing keys deliberately. Sealed Secrets fits.

Git is the source of truth, decrypt keys live with people or CI. You want portable encrypted files (often age), readable history of keys (field names) in cleartext, and decrypt in a pipeline or with a Kustomize/Helm plugin. Multi-cluster means managing recipients, not one cluster private key. SOPS fits.

If the real pain is “we have no secrets manager and no key ceremony”, picking a logo first will fail. If the pain is “Vault is fine but apps still need K8s Secrets”, that is the earlier Vault/OpenBao post plus ESO, not a Sealed Secrets bake-off. If the pain is “stop committing stringData”, admission policy can block the anti-pattern while you migrate.

What each project actually is

External Secrets Operator v2.12.0

ESO is a Kubernetes operator that reads from external secret management APIs and injects values into Kubernetes Secret objects. Official docs describe three core resources:

  • SecretStore (namespaced): how to authenticate to a provider (example: AWS Secrets Manager in a region, with credentials referenced from another Secret).
  • ClusterSecretStore: cluster-wide store that many namespaces can reference.
  • ExternalSecret: what to fetch, which store to use, refresh interval, target Secret name, and optional templates.

Reconcile behaviour in the overview: resolve the store, build a provider client, fetch remote data, create or update the target Secret, keep it in sync. Roles split roughly into cluster operators (install ESO, design stores and RBAC) and application developers (write ExternalSecret manifests). The controller runs with elevated privileges to write Secrets across namespaces; least privilege on the external credentials and careful store design matter as much as the CRD YAML.

ESO is a sync tool, not a replacement for Vault or cloud secret managers. Rotation of the source credential happens in the backend; ESO refreshes the cluster copy on its interval. Push-style features (for example PushSecret in the project) exist for some flows; the common Jaipur path is still pull into the cluster.

Licence: Apache 2.0.

Sealed Secrets v0.40.0

Sealed Secrets is a cluster controller plus the kubeseal CLI. You encrypt a normal Secret into a SealedSecret custom resource. The README’s problem statement is blunt: manage K8s config in Git except Secrets; the sealed form is safe to store, even in a public repo, because only the controller holding the private sealing key can decrypt.

Crypto is asymmetric: seal with the controller’s public certificate; unseal only in-cluster. Scopes bind encryption to identity:

  • strict (default): name and namespace are part of the sealed material; rename or move breaks decrypt.
  • namespace-wide: rename inside the same namespace is allowed.
  • cluster-wide: any name or namespace (use sparingly; it widens who can benefit from a copied sealed blob).

The controller renews sealing keys on a default 30-day period (configurable). Key renewal is not a substitute for rotating the actual application passwords. Backup of sealing-key Secrets is a documented disaster-recovery step; without those keys and without live unsealed Secrets, you cannot recover values from Git alone.

Licence: Apache 2.0.

SOPS v3.13.3 (with age v1.3.2)

SOPS (Secrets OPerationS) is a file editor and CLI for encrypted structured files. It encrypts values while leaving keys (and structure) readable, which makes Git diffs useful for “which setting changed” without exposing the secret. Supported formats include YAML, JSON, ENV, INI and binary. Master keys wrap a data key using age, PGP, cloud KMS offerings, or Vault/OpenBao.

In Kubernetes GitOps practice, teams typically: encrypt Secret manifests or Helm values with SOPS; store .sops.yaml creation rules in the repo; decrypt in CI, or via community plugins such as KSOPS (Kustomize) or helm-secrets. Those plugins are separate projects; this post treats SOPS itself as the encryption tool.

SOPS docs recommend age over PGP where possible. age identities are small and explicit. SOPS looks for age keys in a user config path (or SOPS_AGE_KEY_FILE / SOPS_AGE_KEY / SOPS_AGE_KEY_CMD).

Licence: MPL-2.0. CNCF Sandbox.

How the three models feel in an incident

At 11:05 PM IST a Jaipur on-call must rotate a leaked database password.

With ESO, they update the value in Vault or AWS Secrets Manager, wait for refreshInterval (or force a reconcile), and confirm the target Secret’s resource version moved. Git may not change at all. Blast radius includes whoever can read the backend path and the ESO service account’s reach.

With Sealed Secrets, they edit the cleartext Secret locally, run kubeseal against the cluster cert (or a stored cert), commit the new SealedSecret, let GitOps apply, and wait for the controller to overwrite the Secret. If sealing keys were not backed up and the controller namespace is gone, sealed history in Git does not save them.

With SOPS, they sops edit the encrypted file (or encrypt a new one), commit, and ensure the pipeline age key or KMS permission can decrypt on the next sync. Losing the age private key without a second recipient means the Git history is ciphertext you cannot open.

None of these replaces a runbook for application reconnect after password change. Each changes where the authoritative write happens and who must be awake for the key ceremony.

Comparison tables

Shape and operations

Question

External Secrets Operator

Sealed Secrets

SOPS

Primary shape

Operator syncing external APIs into K8s Secrets

Controller + kubeseal one-way seal

CLI / library encrypting files

Source of truth

External backend (Vault, cloud SM, …)

Git (SealedSecret) + cluster sealing keys

Git (encrypted file) + decrypt identities

Main CRDs / artefacts

ExternalSecret, SecretStore, ClusterSecretStore

SealedSecret

Encrypted YAML/JSON/… (+ optional plugins)

Cluster component required

Yes (ESO controllers)

Yes (sealed-secrets controller)

Optional (CI decrypt or in-cluster plugin)

Typical install

Helm / manifests from project

Controller YAML or Helm + kubeseal binary

Binary in CI/dev; optional KSOPS/helm-secrets

Licence (OSS)

Apache 2.0

Apache 2.0

MPL-2.0

CNCF

Not a CNCF project page like SOPS

Not CNCF

Sandbox

GitOps fit

Question

ESO

Sealed Secrets

SOPS

Commit secret values to Git?

No (commit references / ExternalSecret specs)

Encrypted values yes

Encrypted values yes

Diff readability

Spec diffs; values stay out of Git

Opaque ciphertext blobs

Keys visible; values ENC[…]

Multi-cluster same Git repo

One ExternalSecret can target stores per cluster/env

Seal per cluster cert (or careful scope design)

Add age recipients / KMS keys per env

Works offline seal/encrypt without API?

N/A (needs backend at reconcile)

Yes with --cert

Yes with local age/PGP/KMS creds

Fits Argo CD / Flux

Apply ExternalSecret CRs; values appear after sync

Apply SealedSecret; controller unseals

Needs decrypt step or plugin

Rotation, multi-cluster, blast radius

Question

ESO

Sealed Secrets

SOPS

Rotate app password

Change backend; wait refresh

Re-seal and commit; controller updates Secret

Re-encrypt file; redeploy

Rotate crypto keys

Backend IAM/AppRole; store credentials

Sealing key renewal (default ~30d) + re-encrypt sealed resources as needed

age recipients / KMS key policy / sops rotate

Multi-cluster

Central stores or per-cluster stores

Per-cluster controller keys

Shared encrypted file with multiple recipients

Blast radius if Git leaks

Specs leak intent, not values (if no plaintext slipped in)

Ciphertext only; still protect sealing private keys

Ciphertext only; protect age/PGP/KMS

Blast radius if CI leaks

CI may hold deploy tokens, not all secret values

CI may hold kubeconfig or cert only

CI often holds decrypt key: high impact

Depends on cloud IAM?

Often yes

No (cluster keys)

Optional (age-only possible)

Backends and identity

Capability

ESO

Sealed Secrets

SOPS

HashiCorp Vault / OpenBao

Provider (sync into K8s)

Not a Vault client

Optional hc_vault key source

AWS / GCP / Azure secret APIs

First-class providers

No

KMS wrapping (not always full SM sync)

age

N/A

N/A

Recommended identity

PGP

N/A

N/A

Supported

Cluster-only private key

N/A

Yes (sealing key)

No (unless you invent that ops model)

Worked example for the Jaipur scenario

Invented constraints: private GitLab, Flux or Argo CD already chosen, some secrets already in AWS Secrets Manager for billing webhooks, many older Secrets still in Git, two clusters (jaipur-prod, ncr-staging).

Path A: ESO for cloud-backed secrets. Install ESO v2.12.0. Create a ClusterSecretStore for AWS Secrets Manager with IRSA or a tightly scoped access key in a management namespace. For each app, commit an ExternalSecret that maps remote keys to a target Secret. Delete plaintext Secret YAML from Git. Keep Vault/OpenBao for human dynamic credentials if that is already the company standard; ESO can sync those too without turning this post into another Vault bake-off.

Path B: Sealed Secrets for cluster-local GitOps secrets. Install controller v0.40.0. Fetch and store the sealing cert in a safe internal place for CI kubeseal --cert. Developers never commit cleartext. Use strict scope by default. Backup sealing-key Secrets on a schedule. Expect one seal per cluster unless you deliberately share certs (usually a bad idea).

Path C: SOPS + age for encrypted values in Git. Generate age keypairs for ci-prod and ci-staging recipients; store private keys in the CI secret store, not in Git. Add .sops.yaml creation rules. Encrypt Secret manifests. Wire KSOPS or helm-secrets into the GitOps path you already run. Set SOPS_HC_VAULT_ALLOWLIST even if you think you only use age, so a malicious file cannot coax a Vault token out of a developer laptop.

Jaipur recommendation (invented). Do not run all three in production. Prefer ESO for anything that already lives in AWS Secrets Manager or Vault. Prefer SOPS+age or Sealed Secrets for the leftover config secrets that have no external home yet. If the team hates cluster-tied ciphertext, pick SOPS; if they want the simplest “only this cluster can open it” story, pick Sealed Secrets. Use admission policy to reject new plaintext Secret creates in GitOps namespaces while you migrate.

Security advisories

Records below come from GitHub Security Advisories and OSV as fetched on 15 October 2026. Prefer the GHSA pages for full impact text. Upgrade notes are from advisory patched_versions fields.

External Secrets Operator

Advisory

Severity

CVE

Fixed / notes

GHSA-77v3-r3jw-j2v2

critical

CVE-2026-22822

Patched in v1.2.0 (templating getSecretKey)

GHSA-r2pg-r6h7-crf3

high

CVE-2026-34984

Patched in v2.3.0 (DNS exfil via getHostByName in templates)

GHSA-q7hv-xx6h-q2x8

high

CVE-2026-26287

Affects v0.10.0 to v1.3.1; patched v1.3.2 and v2.0.0+ (webhook generator label bypass). Published 6 October 2026; current 2.12.0 is on the fixed 2.x line

GHSA-fq7h-9x26-6j22

medium

CVE-2026-42876

Patched in 2.4.1

GHSA-wv26-88m5-6h59

low

CVE-2026-42875

Patched in 2.4.0

Older: GHSA-vf79-2pjx-phpp, GHSA-fcxq-v2r3-cc8h, GHSA-qwgc-rr35-h4x9

high/medium

CVE-2025-62159, CVE-2025-55196, CVE-2024-45041

Fixed on 0.x lines; stay current

Sealed Secrets

Advisory

Severity

CVE

Fixed / notes

GHSA-qj4p-m373-p2wg

medium

CVE-2026-59341

Affects <= v0.38.4; fixed in 0.40.0 (template-injection oracle on internal POST endpoints)

GHSA-465p-v42x-3fmj

medium

CVE-2026-22728

Fixed in 0.36.0 (/v1/rotate scope widening)

SOPS

Advisory

Severity

CVE

Fixed / notes

GHSA-jgf3-f6rg-8x3h

high

(GHSA id; no CVE in advisory identifiers on fetch day)

Decrypting untrusted SOPS files can send Vault/OpenBao tokens to a malicious vault_address. 3.13.0+ adds SOPS_HC_VAULT_ALLOWLIST; advisory still lists vulnerable range * because default allowlist behaviour remains broad unless you configure it

GHSA-hqjv-fvgv-rh27

medium

Memory exhaustion on untrusted INI/DotEnv; patched 3.13.0

GHSA-x4cm-pcq4-39j4

medium

exec-file --filename path traversal; patched 3.13.0

GHSA-pvcx-747w-54qw

low

exec UID/GID mix-up; patched 3.13.2

Historical: GHSA-x5c7-x7m2-rhmf

low

Windows executable lookup; old 3.7 line

Run ESO 2.12.x, Sealed Secrets 0.40.x, and SOPS 3.13.2+ (preferably 3.13.3). Subscribe to each repo’s advisories. Pair with NetworkPolicy egress limits on controllers where practical.

Decision guide

Situation

Lean towards

Why

Secrets already in Vault / AWS SM / GCP SM / Azure KV

ESO

Cluster becomes a cache; Git stays reference-only

Want simplest cluster-bound GitOps ciphertext

Sealed Secrets

Public cert seal; private key never leaves cluster (plus backups)

Want portable encrypted files and age recipients

SOPS

Multi-cluster and laptop decrypt workflows

Strict Apache 2.0 preference for the delivery tool

ESO or Sealed Secrets

Both Apache 2.0; SOPS is MPL-2.0

CI must never hold long-lived decrypt keys

ESO (or Sealed Secrets with seal-only CI)

SOPS CI usually needs a decrypt identity

Many clusters, one Git repo of values

SOPS (multi-recipient) or ESO (central backend)

Sealed Secrets multiplies seals per cluster

Need to block plaintext Secret creates during migration

Admission policy + any of the three

Policy is complementary; see admission post

Jaipur (invented) pick. ESO for AWS-backed webhook and DB credentials; SOPS+age for a small set of bootstrap secrets that have no SM home yet; refuse new plaintext Secret commits.

Checklist

  1. Inventory every Secret in Git: name, namespace, whether value is still valid, who can clone.
  2. Choose one primary delivery model per secret class (external vs sealed vs SOPS); write it down.
  3. Pin versions (ESO 2.12.x, Sealed Secrets 0.40.x, SOPS 3.13.3) in Git; avoid :latest.
  4. Confirm licence with legal (Apache 2.0 vs MPL-2.0) before the tool becomes a platform standard.
  5. Design key backup: sealing keys, age private keys, or cloud KMS policies.
  6. Restrict who can create ClusterSecretStore, Webhook generators, or cluster-wide sealed scopes.
  7. Set SOPS_HC_VAULT_ALLOWLIST if SOPS is installed on developer machines.
  8. Add admission policy to reject plaintext Secret applies in GitOps paths.
  9. Subscribe to GHSA for external-secrets/external-secrets, bitnami/sealed-secrets, getsops/sops.
  10. Rehearse password rotation on staging for the chosen model before prod cutover.

Common mistakes

  1. Leaving plaintext stringData Secrets in Git “temporarily” for a year.
  2. Running ESO with a cloud credential that can read every secret in the account.
  3. Using Sealed Secrets cluster-wide scope because strict mode “got in the way”.
  4. Treating sealing-key renewal as application password rotation.
  5. Putting the age private key in the same Git repo as the encrypted files.
  6. Decrypting untrusted SOPS samples on a laptop that has VAULT_TOKEN set.
  7. Assuming kubeseal without --cert works from a locked-down CI network to the API server.
  8. Mixing ESO, Sealed Secrets and SOPS for the same Secret name without an ownership rule.
  9. Ignoring ESO template advisories while enabling rich templates and generators.
  10. Skipping backup of sealed-secrets sealing keys until the cluster is gone.

A drill I ran on 15 October 2026

Shared Linux VM, no Docker, no kind, no k3s. Port 8766 left for the HTML preview server. About 6:22 AM IST (15 October 2026, 00:52 UTC on the box clock during the run).

Binaries downloaded from GitHub Releases with checksum verification:

  • sops v3.13.3 sops-v3.13.3.linux.amd64 SHA-256 e5bec3346a873ae91d871550f3e698c1aad962aff462a080e40f25fde17fef6b matched sops-v3.13.3.checksums.txt.
  • kubeseal 0.40.0 kubeseal-0.40.0-linux-amd64.tar.gz SHA-256 9314c35916646e9d59c8f06b1314574b4e79c4d76f079433607ed7b697bb5eb7 matched sealed-secrets_0.40.0_checksums.txt.
  • age v1.3.2 age-v1.3.2-linux-amd64.tar.gz SHA-256 cbe24006683f8eb669266162894b9a522a1af52f2665fbc63a4bb032ed26ac10 (hashed locally; age release attaches .proof files rather than a simple checksums.txt on that asset list).

Steps that succeeded:

  1. age-keygen created an X25519 identity; public recipient recorded (invented drill only).
  2. SOPS encrypt of an invented app-secrets.yaml (Jaipur SaaS-style DB and webhook fields, clearly labelled not real) with --age, producing ENC[AES256_GCM,...] values and embedded age stanza; sops metadata showed version: 3.13.3.
  3. SOPS decrypt restored the same field values (YAML indentation normalised by SOPS; content matched).
  4. age encrypt/decrypt of a short invented token round-tripped cleanly.
  5. kubeseal –cert offline seal: generated an openssl RSA cert locally (stand-in for a controller cert), sealed a Secret into a SealedSecret (bitnami.com/v1alpha1) with encryptedData for password and username. Plaintext password string was absent from the sealed YAML.
  6. kubeseal –raw produced a ciphertext blob for a single value (728 bytes in this run).

What this box could not run (stated clearly):

  • ESO controller reconcile, SecretStore / ExternalSecret against a live API.
  • Sealed Secrets controller unseal (needs a Kubernetes cluster).
  • Argo CD / Flux decrypt plugins or KSOPS end-to-end.
  • Any cloud KMS or Vault/OpenBao live call.

Artefacts under drill43/: binaries, checksum files, invented plaintext/ciphertext samples, DRILL_NOTES.txt. Do not reuse drill keys; they are throwaway.

Unlearn

  • Unlearn that a private GitLab repo makes Secret YAML “safe enough”.
  • Unlearn treating Vault presence as the same decision as Kubernetes delivery.
  • Unlearn cluster-wide sealed scope as the default convenience flag.
  • Unlearn storing age private keys next to encrypted manifests.
  • Unlearn that sealing-key rotation equals password rotation.

Re-learn

  • Re-learn pull (ESO) versus seal-for-cluster (Sealed Secrets) versus encrypt-in-Git (SOPS) as three trust models.
  • Re-learn ExternalSecret + SecretStore / ClusterSecretStore as the ESO blueprint.
  • Re-learn strict versus namespace-wide versus cluster-wide sealed scopes.
  • Re-learn age recipients and .sops.yaml creation rules before scaling SOPS.
  • Re-learn advisory hygiene: ESO 2.12, Sealed Secrets 0.40, SOPS 3.13.2+ with Vault allowlists.

Closing

Getting secrets into Kubernetes in 2026 is a delivery and blast-radius problem, not a logo problem. External Secrets Operator keeps values in the systems that already own them and refreshes cluster Secrets as a cache. Sealed Secrets gives you GitOps-friendly ciphertext that only a cluster controller should open. SOPS encrypts structured files for Git and CI, especially cleanly with age. Cross-link the Vault/OpenBao post when you still need to choose the manager; use this post when the manager is chosen and plaintext Secret YAML is the habit to kill. Learn which trust model you are buying. Unlearn cleartext in Git. Re-learn key backup before the next laptop walks out of Jaipur. Practise encrypt and seal on a laptop. Apply one model per secret class, then stop committing another Secret YAML in cleartext.

Sources

External Secrets Operator

Sealed Secrets

SOPS and age

Security records

Internal

comments powered by Disqus

Releted Posts

Container registries in 2026: revisit Harbor, Zot and CNCF Distribution before you push another image

Picture a product engineering team in Bengaluru that runs about forty microservices on Kubernetes for a B2B payments product used by NBFCs across Karnataka and Maharashtra (an invented example, not a real client).

Read more

Kubernetes autoscaling in 2026: revisit Karpenter, Cluster Autoscaler and KEDA before you scale another node

Picture a mid-size ecommerce SaaS in Ahmedabad with about 2,200 active sellers (an invented example, not a real client). Its platform team of eight runs checkout, catalogue, search and about 55 other services on Kubernetes on a public cloud.

Read more

Feature flags in 2026: revisit Unleash, Flagsmith and GrowthBook before you hard-code another release toggle

Picture a test-preparation and online classes platform in Jaipur (an invented example, not a real client). Students use an Android app, an iOS app and a React web app.

Read more