cid 410e731c4e784f37d5cbf2e731982a436939a001997aeb3359e60fbbf4ad8aa5 · original · open access · via owasp
Title: Docker Security - OWASP Cheat Sheet Series
Authors:
Venue: owasp
Year: unknown
Canonical: owasp:Docker_Security_Cheat_Sheet
URL: https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html
Collector: owasp
OA: true
ABSTRACT
Docker Security - OWASP Cheat Sheet Series Skip to content RULE #6 - Use Linux Security Module (seccomp, AppArmor, or SELinux) for Runtime Security RULE #7 - Limit resources (memory, CPU, file descriptors, processes, restarts) RULE #8 - Set filesystem and volumes to read-only RULE #9 - Integrate container scanning tools into your CI/CD pipeline RULE #10 - Keep the Docker daemon logging level at info Rule #11 - Run Docker in rootless mode RULE #12 - Utilize Docker Secrets for Sensitive Data Management RULE #13 - Enhance Supply Chain Security Podman as an alternative to Docker References DotNet Security Drone Security Email Validation and Verification Error Handling FastAPI Security File Upload Forgot Password GitHub Actions Security GraphQL HTML5 Security HTTP Headers HTTP Strict Transport Security Identity Propagation Patterns Infrastructure as Code Security Injection Prevention Injection Prevention in Java Input Validation Insecure Direct Object Reference Prevention JAAS JSON Web Token JavaScript and TypeScript Security Java Security Key Management Kubernetes Security LDAP Injection Prevention LLM Prompt Injection Prevention Laravel Legacy Application Management Logging Logging Vocabulary MCP Security Mass Assignment Micro Frontend Security Microservices Security Microservices based Security Arch Doc Mobile Application Security Multi Tenant Security Multifactor Authentication NPM Security Network Segmentation Nextjs Security NoSQL Security NodeJS Docker Nodejs Security OAuth2 OS Command Injection Defense PHP Configuration Passkey Security Password Storage Pinning Post Quantum Cryptography Prototype Pollution Prevention Query Parameterization RAG Security REST Assessment REST Security Ruby on Rails SAML Security SQL Injection Prevention Secrets Management Secure AI Model Ops Secure Cloud Architecture Secure Code Review Secure Coding with AI Secure Product Design Security Terminology Server Side Request Forgery Prevention Server Side Template Injection Prevention Serverless FaaS Security Session Management Software Supply Chain Security Subdomain Takeover Prevention Symfony TLS Cipher String Third Party Javascript Management Third Party Payment Gateway Integration Threat Modeling Transaction Authorization Transport Layer Protection Transport Layer Security Unvalidated Redirects and Forwards User Privacy Protection Verifying Third Party Agent Execution Evidence Virtual Patching Vulnerability Disclosure Vulnerable Dependency Management WebSocket Security Web Cache Security Web Frontend Security Web Service Security Webhook Security Workload Identity Federation XML External Entity Prevention XML Security XPath Injection Prevention XSS Filter Evasion XS Leaks Zero Trust Architecture gRPC Security RULE #6 - Use Linux Security Module (seccomp, AppArmor, or SELinux) for Runtime Security RULE #7 - Limit resources (memory, CPU, file descriptors, processes, restarts) RULE #8 - Set filesystem and volumes to read-only RULE #9 - Integrate container scanning tools into your CI/CD pipeline RULE #10 - Keep the Docker daemon logging level at info Rule #11 - Run Docker in rootless mode RULE #12 - Utilize Docker Secrets for Sensitive Data Management RULE #13 - Enhance Supply Chain Security Podman as an alternative to Docker References Docker Security Cheat Sheet¶ Introduction¶ Docker is the most popular containerization technology. When used correctly, it can enhance security compared to running applications directly on the host system. However, certain misconfigurations can reduce security levels or introduce new vulnerabilities. The aim of this cheat sheet is to provide a straightforward list of common security errors and best practices to assist in securing your Docker containers. Rules¶ RULE #0 - Keep Host and Docker up to date¶ To protect against known container escape vulnerabilities like Leaky Vessels, which typically result in the attacker gaining root access to the host, it's vital to keep both the host and Docker up to date. This includes regularly updating the host kernel as well as the Docker Engine. This is due to the fact that containers share the host's kernel. If the host's kernel is vulnerable, the containers are also vulnerable. For example, the kernel privilege escalation exploit, Dirty COW, executed inside a well-insulated container would still result in root access on a vulnerable host. RULE #1 - Do not expose the Docker daemon socket (even to the containers)¶ Docker socket /var/run/docker.sock is the UNIX socket that Docker is listening to. This is the primary entry point for the Docker API. The owner of this socket is root. Giving someone access to it is equivalent to giving unrestricted root access to your host. Do not enable tcp Docker daemon socket. If you are running docker daemon with -H tcp://0.0.0.0:XXX or similar you are exposing unencrypted and unauthenticated direct access to the Docker daemon, if the host is internet connected this means the docker daemon on your computer can be used by anyone from the public internet. If you really, really have to do this, you should secure it. Check how to do this following Docker official documentation. Do not expose /var/run/docker.sock to other containers. If you are running your docker image with -v /var/run/docker.sock://var/run/docker.sock or similar, you should change it. Mounting the socket read-only does not make the Docker API read-only: a process that can connect to the socket can still send requests that modify containers or the host. Docker grants access to all daemon commands by default; filesystem mount flags do not replace API authorization. Equivalent in the docker compose file is something like this: volumes: - "/var/run/docker.sock:/var/run/docker.sock" RULE #2 - Set a user¶ Configuring the container to use an unprivileged user is the best way to prevent privilege escalation attacks. This can be accomplished in three different ways as follows: During runtime using -u option of docker run command e.g.: docker run -u 4000 alpine During build time. Simply add user in Dockerfile and use it. For example: FROM alpine RUN groupadd -r myuser && useradd -r -g myuser myuser # USER myuser Enable user namespace support (--userns-remap=default) in Docker daemon More information about this topic can be found at Docker official documentation. For additional security, you can also run in rootless mode, which is discussed in Rule #11. In Kubernetes, this can be configured in Security Context using the runAsUser field with the user ID e.g: apiVersion: v1 kind: Pod metadata: name: example spec: containers: - name: example image: gcr.io/google-samples/node-hello:1.0 securityContext: runAsUser: 4000 # ), maximum number of file descriptors (--ulimit nofile=) and maximum number of processes (--ulimit nproc=). Check documentation for more details about ulimits You can also do this for Kubernetes: Assign Memory Resources to Containers and Pods, Assign CPU Resources to Containers and Pods and Assign Extended Resources to a Container RULE #8 - Set filesystem and volumes to read-only¶ Run containers with a read-only filesystem using --read-only flag. For example: docker run --read-only alpine sh -c 'echo "whatever" /tmp' If an application inside a container has to save something temporarily, combine --read-only flag with --tmpfs like this: docker run --read-only --tmpfs /tmp alpine sh -c 'echo "whatever" /tmp/file' The Docker Compose compose.yml equivalent would be: version: "3" services: alpine: image: alpine read_only: true Equivalent in Kubernetes in Security Context: apiVersion: v1 kind: Pod metadata: name: example spec: containers: - name: example image: gcr.io/google-samples/node-hello:1.0 securityContext: readOnlyRootFilesystem: true In addition, if the volume is mounted only for reading mount them as a read-only It can be done by appending :ro to the -v like this: docker run -v volume-name:/path/in/container:ro alpine Or by using --mount option: docker run --mount source=volume-name,destination=/path/in/container,readonly alpine RULE #9 - Integrate container scanning tools into your CI/CD pipeline¶ CI/CD pipelines are a crucial part of the software development lifecycle and should include various security checks such as lint checks, static code analysis, and container scanning. Many issues can be prevented by following some best practices when writing the Dockerfile. However, adding a security linter as a step in the build pipeline can go a long way in avoiding further headaches. Some issues that are commonly checked are: Ensure a USER directive is specified Ensure the base image version is pinned Ensure the OS packages versions are pinned Avoid the use of ADD in favor of COPY Avoid curl bashing in RUN directives References: Docker Baselines on DevSec Use the Docker command line Overview of Docker Compose v2 CLI Configuring Logging Drivers View logs for a container or service Dockerfile Security Best Practices Container scanning tools are especially important as part of a successful security strategy. They can detect known vulnerabilities, secrets and misconfigurations in container images and provide a report of the findings with recommendations on how to fix them. Some examples of popular container scanning tools are: Free Clair Grype Trivy Commercial Snyk (open source and free option available) Anchore (open source and free option available) Docker Scout (open source and free option available) JFrog XRay Qualys To detect secrets in images: ggshield (open source and free option available) Gitleaks (open source) TruffleHog (open source) To detect misconfigurations in Kubernetes: kubeaudit kubesec.io kube-bench To detect misconfigurations in Docker: inspec.io dev-sec.io Docker Bench for Security To detect misconfigurations in Docker Compose files before deployment: DockSec (with --compose) KICS RULE #10 - Keep the Docker daemon logging level at info¶ By default, the Docker daemon is configured to have a base logging level of info. This can be verified by checking the daemon configuration file /etc/docker/daemon.json for thelog-level key. If the key is not present, the default logging level is info. Additionally, if the docker daemon is started with the --log-level option, the value of the log-level key in the configuration file will be overridden. To check if the Docker daemon is running with a different log level, you can use the following command: ps aux | grep '[d]ockerd.*--log-level' | awk '{for(i=1;i