Skip to content
RESEARCH INDEX BREACHROAD / INTELLIGENCE NOTE

Container escape: Linux namespaces, seccomp and AppArmor

A technical container-escape model without exploit payloads: namespaces, capabilities, seccomp, AppArmor, OCI runtime, detection and hardening.

PUBLIC RESEARCH
AUTHOR
/ CEO of Breachroad · OSCP · PNPT
PUBLISHED
21 April 2026
READING TIME
21 min read
TOPIC
Cloud, Infrastructure and DevSecOps
Container escape: Linux namespaces, seccomp and AppArmor

Container escape means crossing the intended isolation boundary and gaining unintended influence over the host, container runtime or another workload. It is not one technique. A kernel or runtime vulnerability can produce an escape, but configuration paths are equally important: privileged mode, host namespaces, excessive capabilities, a mounted runtime socket, host devices or a writable sensitive host path.

The core answer is that containers share the host kernel, so their security depends on multiple overlapping controls. Namespaces restrict visibility, cgroups manage resources, capabilities divide root authority, seccomp filters system calls, and AppArmor or SELinux constrains process operations. Images, runtime, kernel and orchestration components also require timely maintenance. Losing one layer does not always create immediate escape, but it reduces safety margin and makes another flaw more consequential.

Container compromise, boundary crossing and host escape

Distinguish three outcomes. Compromising an application process gives code execution under its UID, filesystem view, tokens and network access but does not prove host access. Crossing a workload boundary may mean reading a shared volume or using a token against another service. A true container escape provides unintended execution or control in the host or runtime security context.

This avoids two reporting errors. A shell inside a container is not automatically “node compromise”. Conversely, application RCE is not low risk merely because it runs in a container; the process may possess cloud identity, secrets and critical network routes.

A layered Linux isolation model

LayerWhat it restrictsWhat it cannot guarantee
Namespacesviews of processes, mounts, network, IPC, hostname and usersresistance to a shared-kernel vulnerability
cgroupsCPU, memory, I/O, PIDs and resource accountingaccess control for data and system calls
capabilitiessplits traditional root authority into smaller unitssafety when the set is broad or the kernel is vulnerable
seccompallows or rejects system calls and selected argumentsa complete object and file-access policy
AppArmor/SELinuxmandatory restrictions on process operationscorrectness of application logic or every policy rule
user namespace/rootlessmaps IDs and reduces the meaning of container rootremoval of the shared kernel or unsafe mounts
OCI runtimecreates processes, namespaces, mounts, devices and profilessecurity when outdated or given a dangerous specification

Security comes from composition. A strong assessment does not search for one magical flag; it verifies that independent controls constrain the same unwanted outcome.

Linux namespaces isolate views, not kernels

Namespaces give a process a controlled view of system resources. Important types include:

  • PID for a separate process tree;
  • mount for an independent mount topology;
  • network for interfaces, routes, ports and network-stack state;
  • IPC for selected inter-process communication resources;
  • UTS for hostname and domain name;
  • user for UID/GID mappings and namespace-scoped capabilities;
  • cgroup for a view of cgroup hierarchy;
  • time for selected clocks.

Sharing hostPID, hostNetwork or hostIPC intentionally removes part of the isolation. Security and network agents may legitimately need such access, but they require a higher trust classification, dedicated identity and strict image governance. A mount namespace also offers little protection if a workload receives writable access to a critical host path.

User namespaces reduce the consequence of UID 0 in a container by mapping it to an unprivileged host ID. They do not replace seccomp, mandatory access control or kernel patching. Rootless Docker additionally runs the daemon and containers without host root, reducing runtime-compromise impact, subject to the requirements documented in Docker rootless mode.

Linux capabilities and the “almost privileged” workload

Capabilities divide monolithic root authority. A runtime normally retains a limited default set and removes the rest. Risk grows when a manifest adds capabilities unrelated to application function, especially broad system-administration, device, module, networking or process-inspection powers.

Do not review only cap_add. Inspect permitted, effective, inheritable, bounding and ambient sets for the running process, as well as no_new_privileges. A child process can acquire a different effective set based on executable metadata, UID transitions and securebits. A defensible baseline starts with drop: ALL and restores only a capability justified by functional testing.

Privileged mode is a separate category. A runtime grants broad capabilities, device access and relaxed security profiles. It should not be a shortcut for repairing an application error. If a component genuinely requires this trust level, isolate it on dedicated nodes and minimise its code, network connectivity and service identity.

Seccomp reduces the system-call attack surface

Seccomp filter lets a process load a BPF filter that evaluates the system-call number, architecture and available arguments. The result may allow a call, return an error, terminate the process, raise a trap or take another supported action. Kernel documentation explicitly warns that seccomp is not a complete sandbox and should complement other mechanisms.

Docker’s default profile blocks selected calls and applies an allowlist model suitable for common containers. The Docker seccomp documentation recommends retaining the default profile unless the application has a justified requirement. seccomp=unconfined expands kernel surface and should be treated as an exception.

Profile testing should answer:

  1. is the filter actually loaded for the running process;
  2. which calls are needed during normal, failure and maintenance paths;
  3. does rejection of an unnecessary call create observable evidence without disrupting service?

A profile derived from a short trace can be too narrow for rare error handling, a library update or signal processing. Run regression tests in CI and a canary deployment instead of learning directly on production.

AppArmor provides path-oriented mandatory access control

AppArmor attaches a profile to a program and restricts file, capability, network, signal, mount and other supported operations. complain mode records violations without enforcing them; enforce mode blocks. A manifest naming a profile is not proof that the expected policy exists and is active on every node.

The Docker AppArmor documentation describes docker-default, generated and loaded for containers by default. In an orchestrator, validate the node-loaded profile, the name selected by the workload and behaviour after upgrades. Protect kernel and runtime paths, host credentials and unnecessary administrative tools.

AppArmor is path-based, so path aliases, bind mounts and application layout changes need explicit tests. A profile copied from another distribution may not match its library and executable locations.

OCI runtime configuration and critical boundary fields

The OCI Runtime Specification standardises namespaces, ID mappings, devices, resources, seccomp, masked paths and read-only paths. A runtime implementation creates the container process from a bundle and configuration.

Review:

  • kernel, runc, containerd or CRI-O versions and security updates;
  • access to Docker, containerd, CRI and kubelet sockets;
  • privileged mode, host namespaces and hostPath;
  • devices, device-cgroup rules and broad capabilities;
  • writable /proc, /sys, cgroupfs and runtime paths;
  • masked paths, read-only paths, root-filesystem mode and mount propagation;
  • no_new_privileges, seccomp and AppArmor or SELinux profiles;
  • whether an admission webhook, operator or pipeline can mutate these fields.

A runtime socket is a management interface, not an ordinary file. A workload that can ask the daemon to create a privileged container has effectively crossed the intended boundary without exploiting the kernel.

Common paths to host impact

Paths fall into four broad categories:

  1. software flaw — vulnerability in the kernel, runtime, filesystem or orchestration component;
  2. over-privileged configuration — privileged mode, host namespaces, capabilities, devices or mounts;
  3. management interface — runtime socket, kubelet, cluster API or node-management endpoint;
  4. supply chain — a malicious or replaced image executed in a trusted configuration.

The last category links runtime isolation to container-image security and an SBOM using CycloneDX, SPDX and VEX. Image signing does not constrain capabilities, and seccomp does not establish code provenance; these controls address different questions.

Safe isolation-testing methodology

1. Start with configuration and effective state

Collect the OCI specification, workload manifest, admission policy, runtime and kernel versions, seccomp/MAC profile, mounts, devices and service identity. Compare declared state with the running process. A Helm value does not prove every replica uses the expected profile.

2. Reproduce production in a disposable laboratory

Kernel and runtime behavioural tests belong on a node matching production versions, configuration and drivers. Do not execute public kernel exploits on production. When a CVE matters, a vulnerable version plus satisfied prerequisites may be sufficient evidence, while dynamic exploitation remains inside a disposable environment.

3. Use harmless canaries

Create a host canary file inaccessible to the container, a prohibited network destination and a side-effect-free syscall check. Confirm denial and seccomp or AppArmor telemetry. Do not modify the host, load a module or establish persistence.

4. Run functional regression

After profile tightening, test startup, shutdown, health checks, backup, diagnostics, error handling and upgrade. A control that breaks incident response or routine maintenance will be disabled during the first emergency.

5. Verify the running workload

Inspect effective UID, capability sets, NoNewPrivs, seccomp status, MAC profile, mounts and namespaces for each workload class. Include spare nodes and autoscaling pools; a secure primary node does not represent the whole fleet.

Detecting escape attempts

Telemetry should join process, kernel, runtime, Kubernetes and cloud context. High-value signals include:

  • AppArmor DENIED, seccomp actions and other LSM rejections;
  • unusual system calls, namespace creation or access to /proc and /sys;
  • administrative tools, compilers or debuggers launched in a runtime image;
  • access to runtime sockets, kubelet endpoints or cloud instance metadata;
  • capability, mount, device or privileged-mode changes;
  • a container process connecting to node-management services;
  • a mismatch between the approved image digest and running process;
  • a new Pod using host namespaces or hostPath outside an approved DaemonSet.

Send events off-node because a successful host escape may permit tampering with local evidence. Preserve container ID, image digest, Pod, namespace, ServiceAccount, node and parent-process lineage.

Host and workload hardening

  1. Patch kernel, runtime and orchestrator according to exposure and impact.
  2. Run as non-root and evaluate user namespaces or rootless operation.
  3. Apply no-new-privileges, drop ALL and the minimum restored capabilities.
  4. Retain the default seccomp profile or a regression-tested stricter policy.
  5. Enforce AppArmor or SELinux rather than complain or unconfined mode.
  6. Use a read-only root filesystem and narrowly scoped writable volumes.
  7. Deny privileged mode, host namespaces, hostPath, unapproved devices and runtime sockets.
  8. Isolate unavoidable high-privilege DaemonSets on dedicated nodes.
  9. Minimise images and apply Linux hardening to hosts.
  10. Make safe settings the default according to CISA Secure by Design principles.

In an orchestrated platform, enforce these settings as code and validate them within the wider Kubernetes and container security programme instead of delegating the decision to each manifest author.

Container-escape resilience checklist

  • Every workload has a justified UID/GID and does not default to root.
  • Privileged mode, host namespaces, hostPath and devices are denied by default.
  • Capability policy starts with drop ALL and records exception ownership.
  • Seccomp is loaded and verified on the running process.
  • AppArmor or SELinux is enforced on every node.
  • Runtime and kubelet sockets are absent from ordinary workloads.
  • Kernel and runtime versions have inventory and patch SLAs.
  • Isolation testing uses a representative lab, not production exploitation.
  • Detection joins kernel, runtime, Pod, ServiceAccount and image digest.
  • Retesting covers autoscaling, spare nodes and application failure paths.

Primary sources

SHARE / COPY