Kubernetes Secrets stored without encryption at rest are base64-encoded plaintext in etcd — any operator with etcd access, a backup file, or an etcd snapshot command can decode every database password and API key in the cluster (CWE-312, OWASP A02). NIST 800-53 SC-28 requires encryption of data at rest. Secrets checked into ConfigMaps are worse — they appear in kubectl get configmap -o yaml with no access differentiation from application configuration. A hardcoded credential in a manifest that enters git history is exposed to every developer, CI system, and repository fork for the lifetime of the repo.
Medium because etcd encryption at rest is often disabled by default, making Kubernetes Secrets accessible to anyone with cluster backup or etcd read access without application-layer attack.
Enable etcd encryption at rest and reference secrets via secretKeyRef in all manifests. Configure etcd encryption in /etc/kubernetes/encryption.yaml on the control plane:
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: <base64-encoded-32-byte-key>
- identity: {}
Then reference secrets in Deployments:
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: password
For stronger guarantees, use HashiCorp Vault with the Vault Agent Injector or the Secrets Store CSI driver to mount secrets at runtime without storing them in etcd.
ID: infrastructure-hardening.access-control-rbac.secrets-encrypted
Severity: medium
What to look for: Enumerate every location where secrets are referenced across all manifests and configuration files. For each secret reference, classify it as: (a) dedicated secrets manager (Kubernetes Secrets, Vault, AWS Secrets Manager, Azure Key Vault, GCP Secret Manager), (b) ConfigMap or plaintext, or (c) hardcoded in manifest. Count the total secret references and how many use proper encryption at rest.
Pass criteria: 100% of secrets are stored in a dedicated secrets manager (Kubernetes Secrets with encryption at rest, HashiCorp Vault, or cloud provider service) and referenced via secretKeyRef rather than inline values. No secrets appear in ConfigMaps, git history, or hardcoded in manifests. Report: "X secret references found, all Y use encrypted secret stores."
Fail criteria: Any secret is stored in a ConfigMap, checked into git, hardcoded in manifests, or uses plaintext Kubernetes Secrets without encryption at rest.
Skip (N/A) when: The application does not use secrets (extremely rare).
Cross-reference: The no-secrets-in-layers check covers secrets leaked into Docker image layers specifically.
Detail on fail: Quote the offending reference. Example: "Kubernetes manifests reference secrets via ConfigMap instead of Secrets. Secrets are not encrypted at rest." or "Database password found in deployment environment variable as literal value instead of secret reference"
Remediation: Use Kubernetes Secrets with encryption at rest, or a dedicated secrets manager:
# Create secret from literal or file
kubectl create secret generic db-secret \
--from-literal=password=securepassword \
--from-file=ca.crt=./ca.crt
# Reference in Deployment
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
Enable encryption at rest in etcd (Kubernetes secret storage):
# In kube-apiserver startup args
--encryption-provider-config=/etc/kubernetes/encryption.yaml