You might be familiar with containers, but have you come across the rootless variety? In this article I’ll cover what they are, and how they are created, but first, let me tell you why I’m interested in them. For a long time I’ve been encouraging people to stop running their containers as root for security reasons. Rootless containers are going to make this much easier – almost effortless, even!
In this post I’ll talk about why it’s a good idea to avoid root in containers, and how rootless containers are going to help.
Regular containers run as root by default
If you’ve spent any time trying out containers, you’ve probably at some point done something like this:
docker run -it alpine
This starts a container running the Alpine image, and gives you a shell prompt where you can start entering commands. And if you run a command like id or whoami in this shell, you’ll see that inside the container you’re running as root.
That’s right: when you run a container today, the chances are that it’s running as root (unless you’ve done something to change the user ID). This root inside the container is the same root as root on the host (virtual) machine. You can see me demonstrating that this is the case in my “Running With Scissors” KubeCon keynote in Copenhagen or you can try it for yourself: run a long-running process inside the container (I typically use sleep when I’m showing this) and then find the corresponding process on the host with ps -eaf | grep sleep. You’ll see that not only is the containerized process visible from the host, but also that it’s running as root.
WHEN AN ATTACKER MANAGES TO COMPROMISE A CONTAINER THAT’S RUNNING AS ROOT, THEY ARE JUST ONE STEP AWAY FROM ROOT CONTROL OVER THE HOST.
Why shouldn’t you run as root in a container?
When an attacker manages to compromise a container that’s running as root, they are just one step away from root control over the host. That “one step” could be a container escape vulnerability – not a common event but they do happen from time to time. Often when a new container escape vulnerability is found they need privileges to be exploited, so a simple mitigation is to make sure your containers aren’t running as root.
Much more likely, a process can effectively escape from a container through misconfiguration – for example, access to files that have been mounted into the container. Unless you have policy enforcement of some kind in place, there is nothing to stop anyone mounting the host’s root directory into any container! From there, if the container is running as root, file and directory permissions will do nothing to protect the host from access or tampering by the container. If you want to keep your users’ data safe, you want to make it a lot harder than that for an attacker to gain host root access!
What are rootles containers and how will they help?
Containers use Linux namespaces to isolate themselves from the host they run on. The extra thing that’s used to make containers rootless is the User namespace. This maps user (and group) IDs so that a process can appear from inside the namespace to be running under a different ID – including the root identity 0. Inside the namespace it can also have broader capabilities than it would have outside the namespace.
If you’d like to dive into a bit more detail on what happens when you create a user namespace, you might like to check out my talk at the Linux Foundation Open Source Summit, where I write a rootless container in a few lines of Go code.
From inside a rootless container (or more precisely, inside its user namespace) application code can appear to be running as root, and it can perform privileged operations that it would not be permitted to perform outside that namespace. But from the host’s perspective it’s a regular user, and if an attacker manages to escape the user namespace onto the host, it will have that regular non-root user ID, and none of the extra capabilities that it might have had inside the namespace.
The other great thing about user namespaces is that you don’t need to be a privileged user to create one. With rootless containers, users can be authorized to run containers without giving them the equivalent of root privileges on the host. This will be a huge advantage in environments like academia where it’s common for many users to share access to a common machine. Without rootless support, giving people permission to run containers on a machine is effectively the same as giving them root access.
In summary, rootless containers are good for security for two reasons:
- You don’t need to be a privileged user to create a rootless container
- Code can run inside a rootless container with root privileges, without having to run as the host’s root user.
Rootles containers today
Some tools, like Red Hat’s podman and Singularity containers have supported rootless containers for a while – Singularity call it “fakeroot”, which is arguably a more descriptive name! The latest release 20.10 of Docker graduates its support for rootless mode so that it’s no longer considered “experimental”, allowing unprivileged users to install and run the Docker daemon as well as individual rootless containers.
Until rootless support is ready in Kubernetes, what can you do? The bottom line is that you want to avoid running containers as root, and there are tools you can use to help you. Admission control webhooks can provide checks to stop the deployment of containers that run as root. (PodSecurityPolicy can do this too, although it may not be long for this world, so I wouldn’t advise taking your first steps with it now.) There are configuration checking tools that run over YAML looking for best practices, including whether workloads are defined not to run as root – we have included one of these tools, Polaris, in our open source project Starboard for surfacing security issues through the Kubernetes API. There are also several commercial container security solutions (including Aqua) that include flexible policy checks and surface any violations that can alert you if you have containers running under the root identity.
If you’d like to dig deeper into the topic of rootless containers there is a great website full of resources and details at rootlesscontainer.rs, and for more on the dangers of running containers as root, check out canihaznonprivilegedcontainers.info.
Chief Open Source Officer at Isovalent
About Liz Rice
Liz Rice is Chief Open Source Officer with eBPF specialists Isovalent, creators of the Cilium cloud native networking, security and observability project. She was Chair of the CNCF’s Technical Oversight Committee in 2019-2022, and Co-Chair of KubeCon + CloudNativeCon in 2018. She is also the author of Container Security, published by O’Reilly.
She has a wealth of software development, team, and product management experience from working on network protocols and distributed systems, and in digital technology sectors such as VOD, music, and VoIP. When not writing code, or talking about it, Liz loves riding bikes in places with better weather than her native London, competing in virtual races on Zwift, and making music under the pseudonym Insider Nine.