Container image scanning tells you what could go wrong with an image before it runs, runtime threat detection tells you what is going wrong after it starts, and most container programmes fund the first, drown in its findings and have little visibility of the second. A scanner reports every vulnerable package in every layer; it cannot say which ones are loaded, reachable from the network or running with a privileged service account. A runtime sensor sees processes, syscalls and API calls in real time; it cannot see the vulnerable library that has not yet been exploited. This guide compares the two for containers and Kubernetes only: the gaps between build and run, how runtime context should reorder scanner backlogs, and how to detect abuse of the workload identities that containers carry. It is for platform, cloud security and detection engineers deciding where the next pound of effort goes. The broader lifecycle and budget question across code, IaC and cloud is covered in Shift-Left vs Runtime Security, and scanner mechanics in Container Image Scanning vs SCA.
Key takeaways
- They answer different questions. Scanning asks "is this artefact known to be vulnerable or misconfigured?"; runtime detection asks "is this workload behaving like an attacker?" Neither answers the other's question.
- Runtime context is the best prioritisation signal scanners lack. Whether a package is loaded, the pod is internet facing and its service account can create pods changes a finding's urgency more than its CVSS score.
- The build-to-run gap is where incidents live. Images that bypass the pipeline, old digests still running, CVEs disclosed after deployment and changes made inside running containers are invisible to a build-time scan.
- Workload identity abuse is a runtime problem. A stolen service account token or cloud credential looks legitimate to every static control; only behaviour against the API server or cloud APIs reveals it.
- Fund both, but sequence them. Scanning with admission gates is cheap to start; runtime detection needs tuning and an owner. Start runtime on internet-facing and highly privileged workloads first.
The short answer
Use image scanning to keep known-vulnerable, secret-laden and misconfigured images from reaching production, and to produce the inventory (SBOM) that tells you where a newly disclosed CVE lands. Use runtime threat detection to catch exploitation, post-exploitation and credential abuse in running workloads, and to feed back which scanner findings matter. Running only scanning leaves you blind to zero-days, misused credentials and anything that changes after deployment. Running only runtime detection leaves you to discover known, fixable vulnerabilities by watching them be exploited. NIST SP 800-190 treats image vulnerabilities and runtime risks as separate risk categories with separate countermeasures for the same reason.
Side-by-side comparison
| Dimension | Image scanning | Runtime threat detection |
|---|---|---|
| What it inspects | Image layers: OS packages, language dependencies, embedded secrets, Dockerfile and configuration | Live behaviour: process execution, syscalls, file and network activity, Kubernetes API calls, cloud API calls by the workload |
| When it runs | CI build, registry push, scheduled registry rescans, admission time | Continuously on nodes (kernel sensor, often eBPF) and against control plane audit logs |
| Threat model | Known vulnerabilities and weaknesses that an attacker could exploit later | Exploitation and post-exploitation in progress, including unknown vulnerabilities and credential misuse |
| Output | Findings list per image digest, SBOM, policy pass or fail | Alerts and events tied to pod, namespace, node, process tree and identity |
| Typical false positive | Vulnerable package present but never loaded or not reachable | Legitimate admin activity, debug shells, new deployments that change normal behaviour |
| Cost driver | Triage volume and developer fix time | Sensor operation, rule tuning and 24x7 response |
| Ownership | Application and platform teams | Detection engineering and SOC, with platform team for sensors |
| Enforcement point | Build failure, registry quarantine, admission control rejection | Alert, kill process, isolate or delete pod, revoke credential |
Where the build-to-run gap opens
The gap is the set of conditions under which a clean scan and a compromised workload co-exist. Each has a different owner and fix.
| Gap | Why the scanner misses it | Runtime signal | Closing control |
|---|---|---|---|
| Image never went through the pipeline | Pulled straight from a public registry, injected as a sidecar or installed by a third-party chart | Running digest with no scan record; new container image seen on a node | Admission policy requiring signed, scanned digests from approved registries |
| CVE disclosed after deployment | The image was clean when scanned | None until exploitation; inventory of running digests is the link | Continuous rescanning of SBOMs for running digests |
| Old digest still running | Registry shows the fixed tag; a forgotten namespace runs the old one | Runtime inventory of digests per pod | Map running digests to findings daily; alert on digests older than policy |
| Change inside a running container | Binaries written or packages installed after start are not in the image | Falco's stable rule "Drop and execute new binary in container"; execution from writable paths | readOnlyRootFilesystem, minimal images, detection on drift |
| Fileless and in-memory activity | Nothing on disk to scan | Falco's stable rule "Fileless execution via memfd_create" | Runtime detection, seccomp profiles |
| Credential misuse | Tokens are issued at runtime, not baked in (if hygiene is good) | Service account calling APIs it never calls; Falco's stable rule "Contact K8S API Server From Container" | Least-privilege RBAC, disabling token automount, behavioural detection |
| Secrets baked into layers | Scanner catches it if secret scanning is on, but the credential remains valid after the image is rebuilt | Use of that credential from unexpected sources | Secret scanning in CI, revocation on detection, runtime injection |
The last row shows why scanning findings sometimes need a runtime follow-up. Researchers scanning Docker Hub found 10,456 public images uploaded in a single month with exposed cloud keys, tokens and AI API keys, many never revoked after removal from the image; see the Docker Hub Secrets Leak 2025. Deleting the layer does not end the exposure. Revocation and runtime monitoring of the credential does.
Using runtime context to prioritise scanner findings
A medium-sized cluster easily produces tens of thousands of image findings. Severity scores alone rank them poorly because CVSS describes the vulnerability, not your deployment. Runtime data supplies the missing factors. The Reachability Analysis Guide covers code-level reachability; this section covers what the running environment adds.
| Runtime factor | How it is observed | Effect on priority |
|---|---|---|
| Package loaded in memory | Sensor records which shared libraries and language modules processes actually open | Not loaded: deprioritise and record as a candidate for removal from the image |
| Image actually running | Map running digests from the cluster to scanned digests | Not running anywhere: fix at next rebuild, not urgent |
| Network exposure | Service type, ingress and load balancer configuration, observed inbound connections | Internet facing with a network-reachable CVE: raise |
| Privilege | Pod securityContext (privileged, hostPath, added capabilities), node access | Privileged or host-mounted: raise, because exploitation leads to node compromise (ATT&CK T1611 Escape to Host) |
| Identity blast radius | Service account RBAC bindings, cloud role attached through workload identity | Can create pods, read secrets or assume a broad cloud role: raise |
| Exploitation evidence | CISA KEV listing, EPSS probability, runtime alerts on the same workload | Listed in KEV or alerts present: fix now |
Record the outcome so it travels with the image. OpenVEX (spec v0.2.0) defines the statuses not_affected, affected, fixed and under_investigation, with justifications for not_affected including vulnerable_code_not_in_execute_path and inline_mitigations_already_exist. Treat runtime "not loaded" evidence as support for a VEX statement only when it has been observed over a representative period, including startup and rarely used code paths; a library that loads once a month during a batch job will be missed by a one-day sample. See the VEX Guide, the EPSS Guide and the CISA KEV Catalogue Guide.
Detecting workload identity abuse
Containers carry two kinds of identity: the Kubernetes service account token projected into the pod, and the cloud identity the pod assumes through workload identity federation or the node's instance metadata service. Both are non-human identities that attackers target because their use looks legitimate. No image scan can tell you a token has been stolen; runtime and audit data can.
Kubernetes service account tokens
- Bound token claims: Kubernetes documentation states that a pod-bound token carries the pod's name and UID as private claims, plus the node name and UID where available, and a jti credential ID. Tokens from the TokenRequest API expire when the pod is deleted or after their lifespan (one hour by default). Deleting the pod is the documented way to invalidate its bound tokens.
- Audit trail: API server audit events record user.username as system:serviceaccount:<namespace>:<name> with source IPs and user agent. Auditing only runs when kube-apiserver is started with --audit-policy-file; at the Metadata level you record who did what to which resource without storing secret payloads. See the Kubernetes Audit Log Detection Guide.
- What abuse looks like: a service account listing secrets or pods across namespaces when it normally reads one ConfigMap (ATT&CK T1613 Container and Resource Discovery), creating pods or exec sessions (T1610 Deploy Container, T1609 Container Administration Command), or the same credential ID used from a source IP outside the pod network (T1552.007 Container API).
The Kubeflow Cryptomining Attacks 2020 show the pattern: attackers reached exposed dashboards, then deployed a container and used its mounted service account to spread mining containers across the cluster. The images were malicious but would never have passed through the victim's scanner; the signal was a service account creating pods it had never created before.
Cloud credentials from inside the pod
- Metadata service access: a container reaching the node's instance metadata endpoint to borrow the node role is a classic escalation path. Block it at the network layer or with hop limits and detect any attempt. See the EC2 Instance Metadata Service Hardening Guide.
- Federated workload identity: correlate cloud audit logs for the workload's role with the pod that should hold it. Calls from outside the cluster's egress addresses, or API actions the workload never performs, indicate token theft (ATT&CK T1078.004 Cloud Accounts). See the Cloud Workload Identity Guide.
- Credential files: reads of cloud credential files or kubeconfig by an unexpected process; Falco ships stable rules "Read sensitive file untrusted" and "Read sensitive file trusted after startup" as a starting point.
Response for identity alerts differs from vulnerability response: revoke first (delete the pod to expire its bound tokens, rotate the cloud role's trust or keys), then investigate. See the Kubernetes Service Account Token Guide.
Runtime sensor architecture in brief
Open source projects are listed alphabetically. Falco evaluates rules against kernel events and plugin sources such as the Kubernetes audit log; its stable rules file includes "Terminal shell in container", "Packet socket created in container", "PTRACE attached to process" and "Clear Log Activities". Tetragon, from the Cilium project, observes process execution, syscalls and file and network I/O with Kubernetes namespace and pod awareness, and its documentation describes in-kernel enforcement that can stop a process before a syscall completes. Commercial CNAPP and CWPP platforms package similar sensors with scanning. Sensor tuning, driver choice and response models are covered in the Container Runtime Security Guide and the Falco Runtime Security Guide; the point here is that the sensor must emit pod, image digest and service account on every event, or its data cannot be joined to scanner findings.
Decision criteria
- Start with scanning and admission control if you have no image inventory, deploy from public registries, or cannot say which digests run where. Scanning plus an admission gate is the cheapest risk reduction and creates the inventory runtime prioritisation needs. See the Kubernetes Admission Control Guide.
- Add runtime detection next for internet-facing workloads, pods with privileged settings or host mounts, workloads whose identity can create pods or read secrets, and multi-tenant clusters. These are where a zero-day or stolen token causes the most damage.
- Choose detect-only first for runtime; move individual high-confidence rules to enforcement after a tuning period.
- Small organisations on a managed Kubernetes service: use the registry's built-in scanning, enforce admission, enable control plane audit logs, and deploy one open source sensor with the default stable rules on production nodes. Route alerts to an on-call channel, not a dashboard nobody watches.
- Large organisations: join the data. A single findings model keyed by image digest, with runtime facts (running, loaded, exposed, privileged, identity scope) attached, is worth more than either tool alone. This is what CNAPP platforms sell; it can also be built from open data. See the CWPP vs CSPM guide.
Worked scenario: a Log4j-class disclosure on a Friday
A critical remote code execution CVE is published in a Java logging library. The registry rescan reports 340 images containing the vulnerable version. Without runtime context, every team is paged.
With runtime context the platform team filters: 190 images are not running anywhere and go to the rebuild queue. Of 150 running, sensor data shows the vulnerable class loaded in 60. Of those, 12 sit behind an internet-facing ingress. Four of the twelve run with service accounts that can create pods in their namespace. Those four are patched or taken offline within hours; the rest follow over days. Meanwhile, detection engineers deploy a rule for the exploit's runtime behaviour (a Java process spawning a shell or making unexpected outbound connections) across all 150, because the scan cannot prove nobody exploited the window before patching. On Sunday the rule fires on one of the 48 internal services: an internal tool proxying user input reached the vulnerable call. The team deletes the pod, which expires its bound token, checks audit logs for that service account's credential ID, and finds no API calls beyond its normal pattern. Scanning found the exposure; runtime found the one case the prioritisation logic got wrong.
How to implement
- Inventory running digests: export pod to image digest mappings from every cluster daily and join them to scan results. This single join is the foundation of everything else.
- Gate admission: require images from approved registries, scanned within policy and ideally signed; run the policy in audit mode for two weeks, then enforce per namespace, keeping a documented break-glass exemption.
- Enable control plane audit logs at Metadata level for secrets and RequestResponse for pods and exec, and ship them off cluster.
- Deploy a runtime sensor in detect-only mode on a pilot ring of internet-facing and privileged workloads; tune default rules for two to four weeks against known admin activity.
- Feed runtime facts back to triage: mark findings with running, loaded, exposed, privileged and identity scope, and change SLAs to match.
- Add identity detections: baseline API calls per service account and cloud role; alert on new verbs, resources, namespaces or source IPs.
- Move to enforcement selectively: kill or isolate only on high-confidence rules such as fileless execution or writes to host paths; roll back a rule to detect-only if it causes an outage, and record why.
Detection and measurement
- Coverage: percentage of running pods on nodes with a healthy sensor, and percentage of running digests with a scan record under seven days old.
- Admission: number of rejected or exempted deployments per week, with exemption age.
- Prioritisation yield: share of critical and high findings downgraded or upgraded by runtime context, and time to remediate for findings on running, exposed, loaded packages.
- Identity: service accounts with token automount disabled where not needed; alerts on anomalous service account or workload role use and their mean time to revocation.
- Detection quality: runtime alert true positive rate per rule after tuning, and sensor heartbeat gaps (an attacker disabling the agent maps to ATT&CK T1685 Disable or Modify Tools).
Common failure patterns
- Scanner backlog as the security programme: thousands of findings triaged by CVSS alone, with no view of which images run, so effort goes to dormant images while exposed ones wait.
- Runtime sensor with no owner: alerts land in a console nobody watches, so the sensor provides compliance evidence rather than detection.
- Events that cannot be joined: sensor alerts without image digest or service account, making it impossible to link an alert to a finding or a credential.
- Treating "not loaded" as permanent: marking findings not_affected from a short runtime sample and missing code paths that load later.
- Ignoring identity after a secret finding: removing a leaked key from an image without revoking it or watching for its use.
- Admission bypasses that never expire: exemptions granted during an incident or for a vendor chart that become the path for unscanned images, as in the Kubeflow case where attacker images ran through a legitimate service account.
Framework mapping
| Framework | Reference | Image scanning | Runtime detection |
|---|---|---|---|
| NIST CSF 2.0 | ID.RA-01 | Primary: vulnerabilities in assets identified and recorded | Supporting: confirms which vulnerabilities are exposed |
| NIST CSF 2.0 | DE.CM-09 | Supporting | Primary: runtime environments monitored for adverse events |
| NIST SP 800-53 Rev 5 | RA-5 | Vulnerability monitoring and scanning | Context for prioritisation |
| NIST SP 800-53 Rev 5 | SI-4 | Not applicable | System monitoring |
| NIST SP 800-53 Rev 5 | CM-7, SC-39 | Minimal images, least functionality | Process isolation, syscall restriction |
| MITRE ATT&CK v20 | T1525, T1610 | Implant Internal Image caught by registry scanning and signing | Deploy Container detected at admission and in audit logs |
| MITRE ATT&CK v20 | T1611, T1609, T1552.007, T1496 | Reduced by hardened configuration checks | Escape, exec, token theft and resource hijacking detected in behaviour |
Practitioner checklist
- Join running image digests to scan results daily, for every cluster.
- Enforce admission for approved registries and recent scans, with expiring exemptions.
- Rescan SBOMs of running digests whenever new CVEs are published.
- Enable API server audit logging and ship it off cluster.
- Run a runtime sensor on internet-facing and privileged workloads first, in detect-only mode, then tune.
- Attach running, loaded, exposed, privileged and identity scope to every critical finding.
- Baseline service account and workload cloud role behaviour and alert on deviations.
- Revoke credentials found in images and monitor for their use.
- Record runtime-based not_affected decisions as VEX with an evidence window.
Standards and references
- NIST: SP 800-190 Application Container Security Guide
- Kubernetes: Auditing
- Kubernetes: Managing Service Accounts
- MITRE ATT&CK: Containers Matrix
- OpenVEX: Specification
- Falco: Stable Default Rules
- Tetragon: Overview
Related NHI Mgmt Group resources: Shift-Left vs Runtime Security · Container Runtime Security Guide · Container Image Scanning vs SCA · IaC Scanning vs Runtime Cloud Scanning · Kubernetes NHI Security Guide