Skip to main content
governance · kubernetes

Secrets that bundle more than 30 credentials into one object

resource types
1
rule IDs covered
3
severity
low

What does ZopNight detect here?

ZopNight raises a governance finding for any Kubernetes Secret on EKS, GKE or AKS holding more than 30 keys. Kubernetes authorizes access per Secret object, never per key, so one crowded Secret hands every credential inside it to whoever can read it or mount it, and a single leak exposes all of them.

Signal and threshold

How ZopNight evaluates Secrets that bundle more than 30 credentials into one object.
Field Value
Rule IDsRC-1753 · RC-1853 · RC-1953
Categorygovernance
Severitylow
Metrickey count
Thresholdmore than 30 keys
SourceZopNight
Permissions usedlist secrets

Why credential count per Secret matters

Kubernetes RBAC can narrow access down to individual objects through resourceNames, as the RBAC reference shows, but no further. There is no rule that grants one key of a Secret and withholds another. A role that can get a Secret with 40 keys can read all 40.

Mounting behaves the same way by default. The distribute credentials task explains that each key in the Secret’s data becomes a file in the mounted directory unless the volume lists specific items. A pod that needs one database password therefore receives the payment API key and the SMTP password too. The Secrets documentation also caps individual Secrets at 1 MiB, which a bundle of certificates can approach.

This is a governance and security posture finding. Secrets have no cloud charge of their own, so there is no savings figure.

Listing crowded Secrets

The command below needs list on Secrets, which returns the encoded values as well as the names, so run it with an identity that is already trusted with that data:

Terminal window
kubectl get secrets -A -o json | jq -r '
.items[]
| ((.data // {}) | length) as $n
| select($n > 30)
| "\(.metadata.namespace)/\(.metadata.name) type=\(.type) keys=\($n)"'

kubectl get secrets -A without -o json prints a DATA column with the same count if you prefer not to pull values at all.

When the finding appears

ZopNight reads the number of keys it recorded for each Secret and raises the finding once that number passes 30. The threshold is stricter than the 50 used for ConfigMaps because the contents are credentials. The check is a point-in-time read with no lookback window, and it clears as soon as the Secret is back to 30 keys or fewer.

Secrets it leaves alone

A Secret without a recorded key count is skipped. The rule does not inspect Secret types, so TLS, Docker registry and Opaque Secrets are all judged by the same count. Legacy service-account token Secrets are handled by a separate check, Legacy service-account-token Secret.

Splitting credentials by consumer

  1. For each key, find the workloads that reference it through secretKeyRef, envFrom or a volume mount.
  2. Create one Secret per consumer, or per trust boundary, holding only the keys that consumer uses.
  3. Update each workload to reference its own Secret, or, as a stopgap, list only the needed keys under .spec.volumes[].secret.items.
  4. Tighten RBAC with resourceNames so each service account can read only its own Secret.
  5. Rotate any credential that was broadly readable before the split, then delete the old bundle.

See it fire on your bill.

Connect an account read-only. The first findings land in minutes.

472 rule families across 353 resource types on 22 platforms. Every threshold, metric, and IAM action is documented on these pages before you grant anything.

472 rule families documented
353 resource types covered
read-only default access level
Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console· Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console·