A private registry without ImagePullSecrets or IAM-based authentication is either fully open (defeating the purpose of a private registry) or relying on node-level credentials that are shared across all workloads on the node (CWE-522, NIST 800-53 IA-5). Credentials that are never rotated become permanent exfiltration targets — a token from 200 days ago likely has broader permissions than current registry access policies intend. CIS Kubernetes 5.4.1 requires authenticated access to private registries. Workload-level credentials scoped to specific registries and rotated on a schedule are the only defensible model.
Low because the attack path requires knowing the registry endpoint and having a network route to it, making exploitation dependent on prior reconnaissance.
Create a registry credential secret and attach it to the relevant ServiceAccount so all pods in the namespace inherit pull credentials automatically. Create the secret:
kubectl create secret docker-registry registry-creds \
--docker-server=myregistry.example.com \
--docker-username=ci-puller \
--docker-password=$(vault read -field=token secret/registry) \
--namespace=production
Attach to the ServiceAccount in k8s/serviceaccount.yaml:
apiVersion: v1
kind: ServiceAccount
metadata:
name: app-sa
namespace: production
imagePullSecrets:
- name: registry-creds
For AWS ECR, use the ECR credential helper or IRSA (IAM Roles for Service Accounts) to eliminate static credentials entirely. Rotate static credentials every 90 days via a scheduled job.
ID: infrastructure-hardening.monitoring-incident-response.image-pull-credentials
Severity: low
What to look for: List all container images referenced in Kubernetes manifests and determine which use private registries. For each private registry image, check whether ImagePullSecrets are specified in the Pod spec or ServiceAccount, or whether IAM-based authentication (EKS with ECR, GKE with GCR) is configured. Count the total private images and how many have proper pull credentials.
Pass criteria: Every container image from a private registry has authenticated pull credentials configured via ImagePullSecrets in the Pod or ServiceAccount spec, or via IAM-based registry authentication. Credentials are rotated at least every 90 days. Report: "X of Y private images have pull credentials configured."
Fail criteria: Any private registry image lacks ImagePullSecrets, or credentials are hardcoded or have not been rotated in over 90 days.
Skip (N/A) when: All images are from public registries without authentication requirements.
Detail on fail: Quote the Deployment and image reference. Example: "Deployment 'api' references private image 'myregistry.azurecr.io/api:v1' but does not specify ImagePullSecrets." or "Registry credentials last rotated over 90 days ago"
Remediation: Configure ImagePullSecrets:
# Create registry secret
kubectl create secret docker-registry regcred \
--docker-server=myregistry.azurecr.io \
--docker-username=<username> \
--docker-password=<password>
Reference in Pod spec:
spec:
imagePullSecrets:
- name: regcred
containers:
- name: app
image: myregistry.azurecr.io/myapp:v1