A Container in Prod Is Mining Crypto
Scenario
A CPU alert fires on a production Kubernetes pod. Someone execs in to look and finds a cryptocurrency miner running, with steady outbound connections to a host nobody recognizes. The pod backs a public-facing service, carries a mounted service account token, and can read several secrets. How the attacker got in is unknown. The immediate instinct in the incident channel: this pod is burning CPU and making us look bad — kill it.
The Quick Fix on the Table
kubectl delete pod. The miner dies, CPU drops, the alert clears, and the dashboard is green again in ten seconds. Case closed — or so it appears.
The quick fix is on the table and the room is waiting for your call. Would you sign off on it? Take a position and justify it — out loud or on paper — before revealing the analysis.
Why the Quick Fix Fails
- It shreds the evidence. The running processes, the miner binary, network connections, shell histories, and any dropped tooling live in the pod's ephemeral filesystem and memory. Delete the pod and the forensic record of how the attacker got in is gone — permanently.
- The entry point is still open. Whatever let the attacker in — a vulnerable dependency in the public-facing service, a bad image, an exposed endpoint — is untouched. The ReplicaSet will even schedule a fresh pod from the same image behind the same service. Expect a new miner within days, and an attacker who now knows to be quieter.
- The credentials must be presumed stolen. The pod held a service account token and readable secrets. An attacker with code execution had both. Deleting the pod does not un-steal them — those credentials work from anywhere until they're rotated, and the miner may have been the distraction while they were exfiltrated.
- The blast radius is unassessed. With a service account token, the attacker may have talked to the Kubernetes API, touched other workloads, or moved laterally. "Is one pod compromised, or is the cluster?" is the question that decides the whole response — and pod deletion answers it with a shrug.
- It miscategorizes the event. This is a security breach with possible customer-data implications, not a resource anomaly. Treating it as a CPU problem skips disclosure assessment, stakeholder notification, and the post-incident hardening that stops recurrence.
The interviewer nods: “Fine, the quick fix is off the table. So what exactly would you do — step by step?” Sketch your plan before revealing the approach.
The Right Approach
- Isolate — don't terminate. Cut the pod off while keeping it alive for forensics: apply a deny-all
NetworkPolicyscoped to the pod, remove it from the Service by relabeling (which also stops the ReplicaSet controller from counting it), andkubectl cordonthe node if node-level compromise is plausible. The mining stops earning; the evidence stays warm. - Preserve evidence before anything changes. Capture
kubectl logs --previousand current logs,kubectl get pod -o yaml, process and connection listings from the node's runtime (crictl inspect,ps,ssvia node access — avoid execing through the compromised container), a filesystem snapshot orddimage of the container layer, and the image digest actually running. Timestamp everything and store it off-cluster. - Rotate every credential the pod could reach — assume theft. Delete and reissue the service account token, rotate all mounted/readable Secrets and the external credentials they represent (database passwords, API keys, cloud keys), and audit cloud-provider credentials reachable from the node (IMDS). This is the single most time-critical step after isolation.
- Hunt for lateral movement. Review Kubernetes audit logs for API calls from that service account, cloud audit trails (e.g.
CloudTrail) for use of reachable credentials, and network logs for the unknown host — then search the whole cluster for other connections to it. Decide on evidence, not hope, whether the incident is one pod or many. - Find and close the entry point. Correlate the compromise time with ingress access logs on the public-facing service, scan the image and its dependencies for known RCEs, and check for exposed debug endpoints or leaked credentials. Do not redeploy the same artifact unchanged — that's re-arming the trap.
- Eradicate and redeploy hardened. Only after evidence and rotation: delete the pod, rebuild the image patched, and redeploy with a tightened posture —
automountServiceAccountToken: falseunless required, least-privilege RBAC,runAsNonRootand a read-only root filesystem, default-deny egress NetworkPolicies (a miner that can't reach its pool is a very quiet failure), and runtime detection (e.g. Falco) so the next anomaly is caught by tooling rather than a CPU graph. - Run the formal post-incident process. Write the timeline, assess data exposure and any disclosure obligations with legal/compliance, and turn the findings into pipeline controls: image scanning gates, admission policies, and an incident runbook so the next responder doesn't have to improvise at 2 a.m.
Final pushback: “Your plan costs more time and money than the quick fix. Convince me.” How do you defend your position under pressure?
How to Defend It
- "Deleting the pod treats this as a CPU problem. It's a breach: someone executed code in our production environment, next to a service account token and our secrets. The miner is the symptom they chose to be loud about."
- "The pod is the crime scene. Everything that tells us how they got in lives in its filesystem and memory — delete it and we're rebuilding the investigation from guesswork."
- "Kill the pod and the ReplicaSet redeploys the same image behind the same public service with the same hole. We're not removing the attacker; we're refreshing their instance."
- "Isolation gets us everything deletion promises — the mining stops within minutes — while keeping the evidence. We lose nothing by doing this properly except the illusion of being done."
- "Every credential that pod could read is compromised until rotated. That's true whether the pod lives or dies, and it's the clock we should actually be racing."