Building secure images

Container images are often a key source of vulnerabilities that can be introduced into cloud-native environments. A core part of an effective security strategy is to ensure adherence to secure image-building practices across the organization. While image scanning is an important part of the organization’s security posture, securing images is a way to proactively ensure the security of your containerized applications earlier in the application life cycle.

Adopt the following best practices for creating container images securely:

1. Use minimal base images

The image should contain only the libraries and tools that the container will need to reduce the attack surface.

2. Use base images from trusted sources

If you’re not building an image from scratch, choose base images that come from a trusted source. You should be able to see the Dockerfile and the source code for all of the image components, and it should be hosted in a reputable registry. Base images should also be updated frequently.

3. Specify a user

If the Dockerfile doesn’t specify a user, the container will default to executing with the root user, which both expands the potential attack surface and provides an easy path to privilege escalation if the application is compromised.

4. Verify Docker images

Ensuring image authenticity is a challenge, but it is an important component of building secure images. Any base images should be signed and validated. Only pulling images from trusted registries is a way to ensure all images are authentic.

5. Scan for vulnerabilities

It is important to find and fix vulnerabilities that exist within container images, including those introduced by open-source libraries.

6. Keep secrets out

Secrets, which include sensitive data such as credentials and keys, should not be embedded within container images.

7. Set resource limits

Limiting the amount of CPU or memory resources a container can access helps to restrict the damage it can do if it is used inappropriately.

8. Limit privileges

Set the container’s privileges to be as restrictive as possible and configure the container to make sure that privileges can not be escalated.

9. Use multi-stage builds

The build tools used to generate and compile applications can be exploited when they’re run on production systems. Instead of using the same images in the build and run phase, use multi-stage Dockerfiles to strip any unnecessary complication tools out of the runtime images. Debuggers should also be taken out of production images.

10. Use secure coding practices

These can be enforced by using a linter to catch insecure code during the development process.

While these steps are specific to the image-building process, the principles behind building secure images should also inform security practices in other parts of the application. These practices include keeping the attack surface as small as possible, limiting privileges, and tightening configurations rather than using the default settings in Kubernetes and other aspects of the cloud-native stack.

Last updated: Jul-3-2020