Skip to content

Security Footguns

Mistakes that get you breached, fail audits, or create vulnerabilities you won't find until it's too late.


1. Running containers as root

Your Dockerfile doesn't have a USER directive. Everything runs as root inside the container. A container escape exploit now has root on the host.

Fix: Add USER nonroot in Dockerfile. Set runAsNonRoot: true in pod securityContext. Use distroless or scratch base images.


2. Wildcard RBAC rules

You create a ClusterRole with verbs: ["*"] and resources: ["*"] because figuring out exact permissions is hard. Any service account bound to this role can now do anything — create pods, read secrets, delete namespaces.

Fix: Follow least privilege. Grant only the specific verbs and resources needed. Audit RBAC regularly: kubectl auth can-i --list --as=system:serviceaccount:ns:sa.


3. Secrets in environment variables visible in process listing

You pass secrets as environment variables. Anyone who can kubectl exec into the pod can run env and see every secret. Secrets are also visible in /proc/1/environ and in container inspect output.

Fix: Mount secrets as files (volumeMounts), not env vars. Use external secret stores (Vault, ESO). Set readOnlyRootFilesystem: true and mount secrets to specific paths.


4. Not scanning images in CI

You push images to production without vulnerability scanning. Six months later, your base image has 47 critical CVEs. You find out from a penetration test — or worse, from an actual breach.

Fix: Scan in CI with Trivy, Grype, or Snyk. Fail the pipeline on critical/high CVEs. Scan running images periodically (they accumulate vulns over time).


5. Using default ServiceAccount

Every pod gets the default service account. In many clusters, the default SA has a mounted token that can talk to the API server. A compromised pod can now enumerate your entire cluster.

Fix: Create dedicated service accounts per workload. Set automountServiceAccountToken: false on the default SA. Use Pod Security Standards to enforce this.


6. NetworkPolicy that only covers ingress

You write a NetworkPolicy with ingress rules but forget egress. A compromised pod can still make outbound connections — exfiltrate data, reach the metadata API (169.254.169.254), contact C2 servers.

Fix: Always define both policyTypes: [Ingress, Egress]. Start with default-deny for both, then add explicit allows.


7. Storing secrets in ConfigMaps

"It's not really a secret" — you put the database connection string (with password) in a ConfigMap. ConfigMaps aren't encrypted at rest, aren't access-controlled separately, and show up in kubectl describe.

Fix: Use Secrets for anything sensitive. Enable etcd encryption at rest. Better yet, use an external secret store.


8. --privileged containers

You set privileged: true because the container needs to do something with the network or devices. A privileged container has full access to the host — all devices, all capabilities, no seccomp. It's as if the container doesn't exist.

Fix: Grant only the specific capability needed: capabilities: { add: ["NET_ADMIN"] }. Never use privileged: true in production.


9. ImagePullPolicy: Always without image signing

You set imagePullPolicy: Always but don't verify image signatures. An attacker who compromises your registry can push a malicious image with the same tag. Every pod restart now pulls the backdoored image.

Fix: Pin images by digest (@sha256:...). Sign images with cosign. Verify signatures at admission with Kyverno or Gatekeeper.


10. AWS metadata API accessible from pods

On EKS without IRSA, pods can curl 169.254.169.254 and get the node's IAM role credentials. If the node role has broad permissions, a compromised pod has access to your entire AWS account.

Fix: Use IRSA (IAM Roles for Service Accounts) so each pod gets its own scoped credentials. Block the metadata API with NetworkPolicy or iptables rules on the node.


11. Audit logging disabled

You don't have Kubernetes audit logging enabled. Someone deletes a namespace. You have no record of who did it, when, or from where. Your incident response is flying blind.

Fix: Enable audit logging from day one. Log at least Metadata level for all resources, RequestResponse for secrets. Ship logs to a tamper-proof location.


12. SSH keys with no passphrase on shared servers

You generate an SSH key without a passphrase for convenience. The key file is on a server that multiple people access. Anyone who can read the file can impersonate you.

Fix: Always use a passphrase on SSH keys. Use ssh-agent for convenience. Consider SSH certificates instead of static keys for infrastructure access.