Container Runtime Hardening Depth
Beyond "is the daemon on TCP": the daemon defaults, socket ownership, confinement profiles, resource limits and image trust that decide what a compromised container can do to its host.
OpenVAPT Academy handout. Online, with the self-check quiz: https://openvapt.com/academy/a5.html. Offline: openvapt learn A5.
You Will Be Able To
- Read /etc/docker/daemon.json and a container's hostconfig.json and name each setting that limits blast radius.
- Explain why the Docker socket and the docker group are root, and what rootless mode changes.
- Judge a running container by four questions: who is it, what can it call, how much can it use, and can it change itself.
The Daemon Sets the Defaults
Every container inherits what the daemon does not forbid. The daemon's configuration file, /etc/docker/daemon.json, is therefore the first place to look. userns-remap maps container root to an unprivileged host user, and no-new-privileges stops setuid escalation. icc false keeps containers from talking to each other on the default bridge. live-restore keeps containers up through a daemon restart (HOST-CTR-002). The deeper checks add the settings that are easy to forget. A log driver with max-size stops one container filling the disk (HOST-CTR-005). userland-proxy false means no extra root process sits on each published port (HOST-CTR-006). default-ulimits bounds file descriptors and processes for every container (HOST-CTR-007). Insecure registries, debug and experimental flags should be off (HOST-CTR-010).
NIST SP 800-190 describes the same idea as hardening the host operating system and the container runtime together. The runtime's configuration is part of the host's attack surface, not something the images can fix later.
The Socket Is Root
The Docker API has no concept of a limited user. Anyone who can send it requests can start a privileged container with the host's root filesystem mounted, and is root a moment later. On a Unix socket that means whoever can write /var/run/docker.sock. The daemon creates it as root:docker mode 660, so the question becomes who is in the docker group. OpenVAPT lists the members and treats the group as a list of administrators without sudo, logging or a password prompt (HOST-CTR-008).
Rootless mode moves the daemon itself into a user namespace owned by an ordinary account. A breakout then lands in that account, not in root. It does not suit every workload (some network and storage features differ), so HOST-CTR-009 reports it as information to feed a design decision rather than as a failure.
Confinement, Limits and Identity Inside the Container
A container is ordinary processes with namespaces and cgroups around them, and three more layers that are easy to switch off. The default seccomp profile removes around 40 dangerous system calls; AppArmor or SELinux limits what the container's root may touch on the host. SecurityOpt entries such as seccomp=unconfined or apparmor=unconfined remove those layers for that container (HOST-CTR-011). Memory and PID limits (HOST-CTR-012) turn a fork bomb or a leak into one container's problem instead of the host's.
Finally, who runs inside matters. A process that is root in the container is root for every kernel bug, and a writable root filesystem lets an intruder install tools and persist. USER in the image and --read-only with a tmpfs for scratch space close both (HOST-CTR-013). The same questions apply to containerd and Podman. A containerd gRPC endpoint on TCP without TLS is the Docker API problem again. Podman's containers.conf sets the confinement defaults every container inherits (HOST-CTR-014).
Trusting What You Pull
docker pull takes whatever the registry returns for a tag. Docker Content Trust (DOCKER_CONTENT_TRUST=1) makes the client verify a signature first, so a substituted image fails to pull instead of running as root on your host (HOST-CTR-015). Pair it with pinning images by digest in production and scanning images before they are pushed.
In Summary
The Docker daemon sets the defaults every container inherits, and the socket is root. Bound logs, keep the userland proxy and ulimits deliberate, and restrict the socket and the docker group. Keep seccomp and AppArmor on and set memory and PID limits. Avoid root with a writable root filesystem, never expose a daemon over TCP without TLS, and verify what you pull.
Apply It
These OpenVAPT checks put this module into practice. Open one to see its detection logic and source code.
| Check | Title | Severity |
|---|---|---|
HOST-CTR-005 | Docker Container Logs Have No Size Limit | Low |
HOST-CTR-006 | Docker Userland Proxy Enabled | Low |
HOST-CTR-007 | Docker Default Ulimits Not Set | Low |
HOST-CTR-008 | Docker Socket Accessible to Non-Administrators | High |
HOST-CTR-009 | Docker Not Running in Rootless Mode | Info |
HOST-CTR-010 | Docker Daemon Allows Insecure Registries or Debug Features | Medium |
HOST-CTR-011 | Seccomp or AppArmor Disabled for Containers | High |
HOST-CTR-012 | Containers Run Without Memory or Process Limits | Medium |
HOST-CTR-013 | Containers Run as Root With a Writable Root Filesystem | Medium |
HOST-CTR-014 | containerd Remote API or Podman Unconfined Defaults | High |
HOST-CTR-015 | Docker Content Trust Not Enabled | Low |
Printable Worksheet · Teacher Answer Key · For Teachers · Print this page with your browser's Print command for a handout.
Also available as plain Markdown for notes, scripts and AI tools. Same facts, same source, no styling.
Lab
Run: openvapt demo --only HOST-CTR- --out a5 and sort the findings into daemon defaults, socket and group, per-container settings and image trust.Compare the vulnerable and hardened daemon.json and hostconfig.json in internal/lab/fixtures_containers_apps.go line by line; for each difference, name the check that would notice it.On a test machine you are allowed to assess: getent group docker, then stat -c '%a %U:%G %n' /var/run/docker.sock, and decide whether the group's members should instead use sudo docker.
Check Yourself
Answers are checked in your browser and never stored or sent.
References
- NIST SP 800-190, Application Container Security Guide
- Docker documentation, Docker Engine security
- Docker documentation, Rootless mode
- OWASP Docker Security Cheat Sheet
- CIS Docker Benchmark (recommendation numbers are cited in each check)
Adapted from the OpenVAPT Academy (openvapt.com), built by AI Cybersecurity Engineers, used under the OpenVAPT Source-Available Licence 1.3. Free teaching use under Teaching With OpenVAPT. Pre-release material may be wrong or unstable; use at your own risk.
Cite This Page
If this page helped your work, please cite it. The version and web address are filled in; the access date is today's date in your browser. Every other style, and when credit is required, is on How to Cite OpenVAPT.
OpenVAPT. (2026). A5: Container Runtime Hardening Depth (Version 0.1.0-alpha.6). OpenVAPT Academy. Retrieved October 16, 2026, from https://openvapt.com/academy/a5.html
In text: (OpenVAPT, 2026). Accessed: the date shown is today's date from your own browser (the site's build date without JavaScript); change it to the day you read the page.
@misc{openvapt_a5,
author = {{OpenVAPT}},
title = {{A5: Container Runtime Hardening Depth}},
year = {2026},
howpublished = {\url{https://openvapt.com/academy/a5.html}},
note = {OpenVAPT Academy, version 0.1.0-alpha.6. Accessed 16 October 2026}
}
Accessed: the date shown is today's date from your own browser (the site's build date without JavaScript); change it to the day you read the page.
Citing OpenVAPT does not mean OpenVAPT endorses, approves or has reviewed your work.