Finding Unused Kubernetes Secrets: How Kor Detects Orphaned Secrets
Discover how Kor identifies orphaned Kubernetes Secrets by building a full reference graph across workloads, helping reduce security risks and operational uncertainty.
Kubernetes Secrets are everywhere. They back application config, service identity, API tokens, TLS certs, registry credentials—nearly every workload depends on them. But clusters change constantly: apps are redeployed, Helm releases upgraded, namespaces deleted, controllers removed.
What doesn’t change nearly as fast? Secrets.
Over time, clusters quietly accumulate unused Secrets with no clear owner and no obvious way to tell whether they’re still safe to delete. The result is a larger attack surface, harder audits, and growing operational uncertainty.
Kor is an open-source Kubernetes orphaned-resource finder built to solve exactly this problem. It doesn’t rely on labels, naming conventions, or best guesses. Instead, Kor builds a full reference graph across Pods, controllers, ServiceAccounts, Ingresses, and more—so it can reliably determine which Secrets are actually in use and which are truly orphaned.
In this post, we’ll break down every way Secrets can be referenced in Kubernetes, why unused Secrets are risky, and how Kor detects orphaned Secrets even in complex, real-world clusters.
Why Unused Secrets Are a Problem
-
Security exposure
A Secret that’s no longer used still contains sensitive data. The more unused Secrets you have, the larger your attack surface becomes. -
Compliance & auditing complexity
Teams struggle to track whether a Secret is actually required by production workloads. Auditors often ask for validation of live usage. -
Operational confusion
When multiple versions of a Secret exist (e.g.,api-token-v1,api-token-v2,api-token-v3), it’s hard to know what is safe to delete. -
Drift from GitOps
GitOps systems often leave Secrets behind after rollbacks or chart removals.
Kor solves this by deeply analyzing all references to Secrets across Pods, controllers, and workload types.
All the Ways Kubernetes Secrets Can Be Used
Kor’s Secret detection logic needs to understand every reference type. Here are all the mechanisms Kubernetes provides—and how workloads typically use them.
1. Mounted as volume sources
The most common pattern:
yamlvolumes: - name: api-key secret: secretName: payment-api-token
Or mounted via a CSI SecretStore provider.
Kor detects:
secret.secretNamein all Pod templates- References in Deployments, StatefulSets, DaemonSets, ReplicaSets, Jobs, CronJobs
2. Injected as environment variables
Secrets can populate environment variables one-by-one:
yamlenv: - name: API_TOKEN valueFrom: secretKeyRef: name: payment-api-token key: token
Or all keys can be injected at once:
yamlenvFrom: - secretRef: name: payment-api-token
Kor detects:
secretKeyRefsecretRefenvFrom.secretRef- All keys under them
3. Referenced by imagePullSecrets
Used to authenticate to private Docker registries:
yamlimagePullSecrets: - name: registry-login
Kor detects:
- Secret usage in all Pod specs and ServiceAccounts’
imagePullSecrets
4. Used by ServiceAccounts
Secrets can be explicitly linked:
yamlsecrets: - name: my-service-account-token
This is especially relevant for:
- Manually created tokens
- Legacy (non-projected) ServiceAccount token Secrets
Kor detects:
- Explicit
sa.secrets[*].name - Auto-generated tokens associated with ServiceAccounts
- Whether a ServiceAccount is actually used by running Pods (Kor’s unused SA logic)
5. TLS Secrets used by Ingress resources
TLS certs are stored as Secrets:
yamltls: - hosts: - example.com secretName: example-tls
Kor detects:
tls.secretNamein Ingress definitions- Whether the Ingress actually exists and routes traffic
6. CSI Secret providers (external secrets)
Some clusters use Secret Store CSI:
yamlvolumes: - name: vault-secrets csi: driver: secrets-store.csi.k8s.io volumeAttributes: secretProviderClass: vault-provider
This may result in ephemeral Secrets being synced to Kubernetes.
Kor detects:
- K8s-level Secrets produced by CSI sync (static Secrets)
- If those Secrets are mounted or referenced by Pods
- (Kor does not inspect provider-specific external secrets outside Kubernetes, staying OSS-friendly.)
7. Webhook or controller certificates
Some controllers create their own TLS Secrets:
- Admission webhook certs
- Operator self-signed certs
- Mutating/validating webhook configurations referencing Secrets
Example:
yamlwebhooks: clientConfig: caBundle: ... service: name: webhook-service
Or:
yamlclientConfig: url: https://webhook.svc caBundle: ...
Kor’s scope:
- Detect Secrets referenced explicitly in webhook configurations
- Detect unused Secrets in the namespace when controllers are removed
8. Helm-managed Secrets
Helm creates Secrets for release metadata, e.g.:
textsh.helm.release.v1.my-app.v3
These can remain after:
- Failed installs
- Partial upgrades
- Namespace deletions
- Manual cleanup
Kor note: Helm release Secrets (helm.sh/release.v1) are ignored by default to reduce noise, since they are Helm metadata rather than application secrets.
How Kor Detects Orphaned Secrets Across All These Patterns
Kor builds a resource reference graph:
- Collect Secrets across all namespaces.
- Collect workload specs (Pods and controllers) and scan for all reference types.
- Collect ServiceAccounts & image pull Secret associations.
- Collect Ingress TLS references.
- Consider controller-generated Secrets (except excluded types).
- Mark a Secret as “used” if any reference is found.
- All remaining Secrets are reported as unused.
Secret types Kor ignores by default
Kor does not flag the following Secret types as unused to avoid noisy or low-value findings:
helm.sh/release.v1(Helm metadata)kubernetes.io/dockerconfigjsonkubernetes.io/dockercfgkubernetes.io/service-account-token
This approach ensures Kor catches the edge cases other scanners miss.
Example Kor output
yamlunusedSecrets: - namespace: default name: payment-api-token-old - namespace: staging name: registry-cred-backup - namespace: team-a name: sh.helm.release.v1.service.v5 # stale release
Every reported Secret is one that has no live consumer anywhere in the cluster.
Using Kor to Scan for Unused Secrets
Run:
bashkor secrets
Or full scan:
bashkor all
You can also target a namespace:
bashkor all --namespace team-a
Results are exported in YAML or JSON for automation.
Conclusion
Secrets are referenced in many different ways throughout Kubernetes—volumes, env vars, ServiceAccounts, Ingresses, image pull creds, and more. This makes detecting unused Secrets difficult to do manually or with simple scripts.
Kor solves this cleanly, by performing a full graph-based analysis and identifying Secrets that are truly unused anywhere in the cluster.
Cleaning up these Secrets reduces risk, simplifies audits, and improves operational clarity.
Scale Secret Detection Across Your Fleet
Kor handles single-cluster scanning. For multi-cluster, multi-cloud visibility with cost impact analysis and continuous monitoring, create your free KorPro account. KorPro extends Kor's detection capabilities across your entire Kubernetes estate. Need help securing your clusters? Contact us for a security assessment.
Ready to Clean Up Your Clusters?
KorPro automatically detects unused resources, orphaned secrets, and wasted spend across all your Kubernetes clusters. Start optimizing in minutes.
Related Articles
Extended Kubernetes Support: How Kor Pro Helps Teams Reduce Risk, Optimize Cost, and Modernize Safely
Extended Kubernetes support helps teams manage aging clusters safely. Learn how Kor Pro improves visibility into workloads, pods, ingress, and cost to reduce risk and plan modernization.
Kor: The Open-Source Kubernetes Cleanup Tool (and How KorPro Extends It)
Kor is an open-source CLI that finds unused Kubernetes resources in your cluster. Learn how to install and use Kor, what it detects, and how KorPro extends it to multi-cloud with cost analysis.
Kubernetes End of Life and Extended Support: What Happens When Your Version Expires [2026]
Kubernetes versions lose support faster than most teams realize. Learn the release cycle, what extended support means on EKS, GKE, and AKS, and how to plan upgrades before your cluster becomes a liability.
Written by
Yonah Dissen