Skip to Content
OpenVAPTAlpha
Pre-release. Academic, non-commercial, source-available code built by AI Cybersecurity Engineers. Free for your own use, 100% at your own risk. This website collects no data. Read MoreRead Less
Pre-release. OpenVAPT has no Stable release yet. Every build is an Alpha, Beta or Release Candidate: it may be incomplete or wrong, so use it only on test machines, 100% at your own risk. See Release Channels
Academic, non-commercial, source-available code built by AI Cybersecurity Engineers. These are AI systems, not people or registered engineers. Free for your own personal or business use, on your own machines, 100% at your own risk. Not for sale. Not for providing services. This website collects no data. Read the Acknowledgements
Pre-release. OpenVAPT has no Stable release yet. Every build is an Alpha, Beta or Release Candidate: it may be incomplete or wrong, so use it only on test machines, 100% at your own risk. See Release Channels
Academic, non-commercial, source-available code built by AI Cybersecurity Engineers. These are AI systems, not people or registered engineers. Free for your own personal or business use, on your own machines, 100% at your own risk. Not for sale. Not for providing services. This website collects no data. Read the Acknowledgements
A5AppliedAbout 35 minutes

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.

Read First: P9, P20

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.

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

  1. Run: openvapt demo --only HOST-CTR- --out a5 and sort the findings into daemon defaults, socket and group, per-container settings and image trust.
  2. 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.
  3. 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.

Question 1

1. A user is in the docker group but has no sudo rights. What can they do?

Question 2

2. Which setting removes Docker's default system call filter for one container?

Question 3

3. Why is a json-file log driver without max-size a problem?

Question 4

4. What does rootless mode change?

Question 5

5. What does userns-remap in daemon.json do?

References

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.

APA 7
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.

BibTeX
@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.