In a quiet disclosure that every container operator needs to understand, maintainers of Podman and the open-source Moby project (the engine behind Docker) revealed a subtle but dangerous initialization mistake. The bug, assigned CVE‑2022‑27649 for Podman and closely related CVE‑2022‑24769 for Moby/Docker, meant containers were started with a non‑empty inheritable capability set. That oversight opened a door for an attacker with local access inside a container to escalate privileges by executing a carefully prepared binary. Patches shipped in Podman v4.0.3 and Docker Engine 20.10.14, but updating the runtime is only the first step. The real security work — auditing images, recreating running containers, and hardening your capability hygiene — is what will keep your deployments safe.
What Actually Went Wrong
Linux containers rely on a fine‑grained privilege model called capabilities. Instead of giving a process all‑or‑nothing root access, capabilities break down root powers into specific bits — like CAP_NET_BIND_SERVICE to bind to a privileged port, or CAP_SYS_ADMIN for broad administrative control. The kernel manages these capabilities in several sets: the process’s permitted, effective, and inheritable sets, plus the file’s capability metadata. When a process calls execve(), the kernel combines these sets according to rigid rules. Crucially, if a process already has non‑empty inheritable capabilities and the new executable file also declares inheritable capabilities, the kernel can promote those bits into the new process’s permitted set — essentially granting it more power.
Normally, container runtimes start every new process with an empty inheritable set, closing off that escalation path. But in early 2022, security researchers discovered that both Podman and Moby were shipping containers with a non‑empty inheritable set by default. The result: a binary inside a container that had been marked with file capabilities (via setcap) could, when exec’d, have those capabilities added to its permitted set, even if the container’s launch configuration never intended for such elevation. This is not a container escape — the process remains confined by the container’s bounding set — but it is a local privilege escalation that can break the internal security model of the container.
The flaw is best understood by comparing what should happen with what did happen. In a correctly configured environment, a container’s root process might start with a capability like CAP_SETUID in its permitted set, but its inheritable set is empty. A non‑root process that exec’s a binary with CAP_SETUID in its file inheritable bits would not gain that capability, because the kernel requires the process’s own inheritable set to also contain the bit. But with the bug, the process already had CAP_SETUID in its inheritable set from the start, so the exec transition silently granted the new process the ability to change user IDs — a privilege it wasn’t supposed to have.
Who’s at Risk — and Why It Matters
This is not a remote attack. An attacker needs two things: a foothold inside a running container (for example, through a shell, a compromised web application, or a maliciously built image), and an executable file in that container that has inheritable file capabilities. Such files are more common than you might think — many official images include utilities like ping or setcap helpers that carry file capabilities, and custom CI/build images often bake in privileged binaries for automation tasks.
If both conditions are met, an intruder can execute that binary and instantly gain extra capabilities. What can they do with them? It depends on the specific bits elevated. Gaining CAP_SETUID allows changing user IDs, which can be used to bypass internal user restrictions. CAP_NET_RAW opens the door to network spoofing. CAP_SYS_ADMIN is practically root inside the container, allowing mount operations, process tracing, and more. The escalation stays inside the container, but in multi‑tenant environments — Kubernetes clusters, CI/CD runners, build farms — a compromised container might be a stepping stone to attacking other services or the host, especially if other misconfigurations exist.
For home users and single‑purpose containers, the practical risk is lower. If you run a container that only you access and it contains no setcap’d binaries, an unpatched runtime alone won’t harm you. But the danger is that you may not know what’s inside every layer of your images. A base image pulled from a registry might contain a setcap’d binary that you never intended to use. The safe assumption is to treat every affected installation as vulnerable until verified.
Administrators should pay special attention to container orchestration platforms. Kubernetes Pod Security Policies (or their replacement, Pod Security Standards) often specify allowed capabilities, but they typically do not guard against inheritable‑set anomalies at the runtime level. If you have untrusted tenants or users who can submit arbitrary images, the bug is a tangible escalation vector.
How We Got Here
The timeline is telling. The Linux capability model has existed for decades, and the execve() transformation rules are well documented. Yet even mature runtimes can overlook a detail in startup code. Sometime before March 2022, multiple parties independently noticed that containers were starting with unexpectedly populated inheritable capabilities. The open‑source communities for Podman and Moby moved quickly to assign CVEs and prepare fixes.
Podman’s issue was published as CVE‑2022‑27649, and the upstream team incorporated a patch into v4.0.3 that explicitly clears inheritable capability arrays when a new container is created. The Moby project (the open‑source core of Docker Engine) tracked its variant as CVE‑2022‑24769, rolling the correction into Docker Engine 20.10.14. In both cases, the remedy was small but surgical: stop leaking inheritable bits from the runtime’s initialization into the container’s first process. Distributions like Fedora, Ubuntu, and openSUSE backported the fixes to their package repositories shortly after.
It’s worth understanding that vendor severity scores varied. The Podman advisory was treated more seriously because the impact in rootless and multi‑tenant deployments was more pronounced. The Moby/Docker side was scored lower by some trackers because of additional prerequisites, but upstream maintainers universally recommended prompt patching.
What to Do Now: An Action Checklist
Patching the runtime is just the beginning. Because the capability state is baked into a running container’s processes at creation time, simply upgrading the host binaries doesn’t retroactively fix existing containers. Here’s a step‑by‑step plan:
-
Inventory your runtimes. List all nodes running Podman or Docker/Moby. Check versions: Podman must be >= 4.0.3, Docker Engine must be >= 20.10.14. Use
podman --versionordocker --versionin a script, or query your package manager. -
Deploy the vendor patches. Use your distribution’s official packages. For Podman, that means upgrading to the latest stable build. For Docker, follow the vendor’s upgrade guide to reach 20.10.14 or later. Confirm the fix by reviewing the package changelog or checking the runtime version after the update.
-
Recreate all running containers. This is the most operationally intrusive but critical step. For each container that was started before the patch: stop it, remove it, and re‑run it from the same image. In Docker:
docker stop <id> && docker rm <id> && docker run .... In Podman, use the analogous commands. If you use orchestration like Kubernetes, rolling restart of deployments will automatically recreate pods with the corrected runtime state. -
Audit your images for file capabilities. Not all images contain setcap’d binaries, but you need to know. Use
getcap -r /inside a temporary container from each image, or scan image layers directly with tools liketrivyor custom scripts. Flag any image that contains files with inheritable capabilities — they are the necessary ingredient for exploitability. Remove unnecessary capabilities from your own images, and notify vendors of base images that carry risky ones. -
Verify the fix. Once containers are recreated, check a process’s inheritable capability set. Inspect
/proc/<pid>/statusand decode theCapInhhex value withcapsh --decode. It should be empty (0000000000000000). If it isn’t, the container may not have been restarted correctly, or an old runtime binary is still handling its lifecycle. -
Harden your runtime configuration. Review your Docker daemon options and Podman command‑line flags. Avoid granting unnecessary
--cap-addrights to untrusted containers. In Kubernetes, enforce a restrictivespec.containers[].securityContext.capabilities.droplist that includes inheritable‑sensitive bits. Remember: the vulnerability arose because the runtime default was too permissive; your own configurations can either compound that or compensate for it.
If you cannot patch immediately, a stopgap is to modify container entry‑points to clear inheritable capabilities early using a tool like capsh or a wrapper script. This is fragile and requires rebuilding images, so it’s only a temporary bridge until a proper runtime upgrade is possible.
Quick Reference: Essential Commands
| Task | Command |
|---|---|
| Check Podman version | podman --version |
| Check Docker version | docker --version |
| Find files with capabilities in a container | getcap -r / or find / -xattrname security.capability -print |
| Inspect capability sets of a process (PID 1) | cat /proc/1/status \\| grep Cap then capsh --decode HEXVALUE |
| Recreate a Docker container | docker stop ID && docker rm ID && docker run ... |
Outlook
The Podman and Docker flaws are a classic case of a small initialization mistake with large downstream consequences. The lessons go beyond these specific CVEs. Container runtime defaults are not neutral — they directly affect the security contract between an image author and the runtime environment. A feature as seemingly innocuous as inheritable capability propagation, if misused, can unravel internal privilege separation.
Going forward, expect more rigorous capability scanning to become a standard part of image CI pipelines. Tools that detect file capabilities and flag them as security concerns are already being integrated into vulnerability scanners. Runtimes themselves may eventually provide stronger guardrails — for example, refusing to start containers that mix non‑empty inheritable sets with file‑capability‑bearing images unless explicitly allowed.
For now, the message is clear: upgrade your runtimes, recreate your workloads, and cultivate a habit of assuming nothing about the starting state of your containers. The fix for CVE‑2022‑27649 and CVE‑2022‑24769 is available; putting it into practice is the only way to close the door on an unnecessary, yet very real, escalation risk.