What Is Container Security?
Container security is the process of securing containers against malware, data leaks, and other threats at all stages of the container lifecycle. From the time when you build your container image, to when you load it into a registry, to when you deploy it into a production environment, you should implement tools and processes to ensure that the container is secured against potential threats.
This article walks through everything you need to know about managing container security across the container lifecycle.
Common Threats to Container Security
Understanding container security starts with understanding the security threats that can impact containers.
These threats come in too many forms to detail here. However, the most common types of container security threats include the following:
Malware is malicious code that is deployed within a container. It can sneak into containers at multiple stages of the container lifecycle. An attacker who compromises your CI/CD environment could insert malware into the source code repositories that are later used to build container images, for instance. Or, attackers could breach your container registry and replace your images with tainted ones that contain malware. A third type of container malware attack involves tricking users into downloading malicious container images from external sources.
In all cases, malware that is not detected before a container is launched will enter your runtime environment, which could lead to any number of security issues, such as collecting sensitive data from an application or disrupting other containers.
Insecure Container Privileges
Typically, containers should run in unprivileged mode, which means they don’t have access to any resources outside of the containerized environment that they directly control. Communications between containers should also be restricted unless the containers have a reason to communicate with each other (which would be the case if, for instance, you are running a sidecar container that collects logs from an application container).
When containers are allowed to run with more privileges than they strictly require, security risks result. Insecure privileges are usually caused by problematic configurations with the container orchestrator. For example, containers orchestrated by Kubernetes may have more privileges than they should if Kubernetes security contexts and network policies are not properly defined.
Containers with Sensitive Data
Containers are not intended to be used to store data. But sometimes, organizations make the mistake of storing sensitive information inside container images. For example, Vine’s entire source code was exposed when someone discovered a container registry that Vine thought was private, but which was publicly accessible, and which turned out to be hosting images that contained the source code. (To be fair, this happened relatively early in the container era, when best practices surrounding container image management were not yet well established. It’s understandable how a mistake like this occurred.)
Managing Security Across the Container Lifecycle
To avoid risks like these, businesses should implement security controls that protect containers at all stages of the container lifecycle. The following is an overview of each stage and which types of threats teams must manage in each one.
The Development Pipeline
The container lifecycle starts with the development pipeline, which is where the code that will later make its way into containers originates.
As noted above, attackers who compromise development tools can insert malicious code into source repositories, leading to a so-called software supply chain attack. If developers don’t catch the malicious code before they use it to build images, the code can flow down the pipeline and into production environments.
Implementing access controls for development tools and enforcing the principle of least privilege helps to prevent this risk. So does scanning source code for malware prior to building and shipping it.
A container image is a file that contains the code required to run a container. The image is not the container itself, but rather a blueprint on which a running container will be based. Thus, if the contents of a container image include malware or sensitive data, the containers that are created from the image will be insecure.
As noted above, you should scan your internal source code to help ensure that malware doesn’t make its way into your container images.
However, because container images often include resources imported from third-party sources, scanning your own code is not enough. You should also scan the entire container image using a container scanner, which will assess the image contents and flag any components that are known to be insecure. Image scanning can’t detect every type of threat (in particular, custom malware that has not yet been recorded in vulnerability databases may elude detection), but they will alert you to the majority of known threats.
After container images are created, they are usually stored in a container registry, from which users can download them.
There are a few best practices to follow to address registry security. First, you should enforce access controls to ensure that only authorized users can access the images in your registry. Doing so helps prevent accidental data leaks that may occur if images contain private applications or data.
Second, audit registries regularly so you know which images they contain. Outdated images that contain obsolete versions of an application should be removed in order to minimize your attack surface.
Finally, when working with container images from third-party registries, be sure that you trust the source. Half of all of the images in Docker Hub, the most popular public container registry, contain at least one security vulnerability. And sometimes, attackers deliberately upload malicious images with names (like mysqlimage or nginxapp) that are designed to attract unsuspecting users. Avoid pulling images from any unofficial public registry, and be sure to scan all images no matter how much confidence you have in the organization that created them.
Container Runtime Environment
The final stage of the container lifecycle is runtime. This is when containers are deployed into a live environment using container images that were downloaded from a registry.
Runtime security is one of the most complex aspects of container security because it involves multiple moving pieces, which can vary depending on which type of container application stack you use. In most cases, however, runtime security is based on securing:
- The container runtime: This is the process on the server that actually executes containers. You should ensure that your runtime software is up-to-date and patched against known security vulnerabilities.
- The orchestrator: The container orchestrator deploys and manages containers. Most orchestrators offer a variety of tools to help restrict containers’ privileges and minimize security risks, but you should also use third-party monitoring and analysis tools to help detect security issues at the orchestrator level.
- Nodes: Nodes are the servers that host containers. You need to secure the node operating system, user accounts, networking configurations, and other resources in order to ensure that a breach at the node level doesn’t allow attackers to impact your container environment.
Continuous Container Security
The container lifecycle is a circular, continuous process. After containers for a given application have been deployed into a runtime environment, the cycle starts anew when the application is updated, which leads to a new set of containers being pushed down the pipeline. Each new container could contain new risks.
Thus, container security is never a set-it-and-forget-it affair. You must continuously monitor for risks across the container lifecycle, while also updating your monitoring tools, vulnerability databases, and configurations to ensure that you continue to adhere to best practices for container security as your environment evolves.