Your AppArmor profiles are enforced. Your containers are isolated. Your kernel is protected — or so you thought. On March 12, 2026, Qualys Threat Research Unit dropped a disclosure that quietly invalidated nine years of those assumptions.
TL;DR
- Qualys TRU found 9 “confused deputy” vulnerabilities in Linux AppArmor’s kernel implementation, collectively named CrackArmor
- Root cause: AppArmor’s pseudo-files (
/sys/kernel/security/apparmor/.load,.replace,.remove) are world-writable (mode 0666), and trusted SUID binaries like Sudo and Postfix can be weaponized as proxies to load attacker-controlled profiles- Consequences: local privilege escalation (LPE) to root, container isolation collapse, KASLR bypass via out-of-bounds reads, and DoS via stack exhaustion
- Affects all Linux kernels since 4.11 (2017) — Ubuntu, Debian, SUSE with AppArmor enabled by default — 12.6 million enterprise instances exposed
- No CVE assigned yet; PoC withheld; patches are available — patch now
Why This Matters
AppArmor is not an optional hardening layer for most production Linux deployments. It ships enabled by default on Ubuntu, Debian, and SUSE. Docker applies AppArmor profiles to every container. Kubernetes uses it for pod-level confinement. This is the layer that security teams trust to contain compromised services, enforce least-privilege on containerized workloads, and prevent lateral movement after initial access.
CrackArmor doesn’t break AppArmor’s policy logic. It breaks the kernel mechanism that loads and enforces those policies. The attacker doesn’t need to craft a clever profile bypass — they manipulate the security subsystem itself.
If you’re running Ubuntu 22.04 LTS, 24.04 LTS, Debian 12, or any SUSE/openSUSE release, this is your environment. And it has been vulnerable since 2017.
Table of Contents
- AppArmor Internals: How It Actually Works
- The CrackArmor Research: What Qualys Found
- Root Cause: The Confused Deputy Problem
- The Nine Vulnerability Classes
- Attack Chain: From Unprivileged User to Root
- Container Isolation Bypass
- KASLR Bypass and Stack Exhaustion
- Detection Opportunities
- What You Can Do Today
AppArmor Internals: How It Actually Works
AppArmor is a Linux Security Module (LSM) — a kernel-level framework that intercepts security-sensitive operations before they execute. Where DAC (Discretionary Access Control) asks “who owns this file?”, LSMs like AppArmor and SELinux ask “is this process allowed to do this operation at all?”
AppArmor works through profiles: per-process policy documents that define exactly what files, capabilities, network sockets, and system calls a process may access. A profile can be in one of two modes:
- Enforce mode — violations are blocked and logged
- Complain mode — violations are logged but permitted (used during profile development)
Profiles are loaded into the kernel at boot or runtime through a set of pseudo-files exposed under /sys/kernel/security/apparmor/:
/sys/kernel/security/apparmor/.load # Load a new profile/sys/kernel/security/apparmor/.replace # Replace an existing profile/sys/kernel/security/apparmor/.remove # Remove a profile by name/sys/kernel/security/apparmor/.access # Query profile permissionsThese files aren’t regular filesystem objects — they’re kernel interfaces that directly manipulate the LSM’s internal policy database. Writing a profile blob to .load is functionally equivalent to executing kernel policy code.
The apparmor_parser userspace tool is the standard way to interact with these files — it compiles human-readable profiles into a binary format and writes them to the kernel interface. But nothing stops a direct write() syscall to these paths.
The CrackArmor Research: What Qualys Found
Qualys TRU published their findings on March 12, 2026 after coordinated disclosure with the Linux kernel security team and major distributions. The research identifies nine distinct vulnerability classes in AppArmor’s kernel implementation — all tracing back to a single design oversight that has existed since Linux kernel 4.11, released in May 2017.
The name “CrackArmor” reflects the nature of the attack: not breaking the lock, but manipulating the mechanism that installs it.
Key facts from the disclosure:
| Factor | Detail |
|---|---|
| Discovered by | Qualys Threat Research Unit (TRU) |
| Disclosed | March 12, 2026 |
| Vulnerability age | ~9 years (since kernel 4.11, 2017) |
| CVE status | Not assigned (upstream process, ~1-2 weeks post-patch) |
| PoC status | Withheld by Qualys |
| Affected kernels | All with AppArmor enabled since 4.11 |
| Exposed systems | 12.6 million enterprise Linux instances |
| Primary distros | Ubuntu, Debian, SUSE (AppArmor default-enabled) |
| Patch status | Available — Ubuntu confirmed fixes |
The flaws reside in AppArmor’s kernel implementation — the C code inside the Linux kernel that processes profile data, not the profile syntax itself. This distinction is critical: profiles written correctly for AppArmor remain logically sound. The attack surface is the parsing and loading infrastructure, not the policy language.
Root Cause: The Confused Deputy Problem
The confused deputy problem is a classic privilege escalation pattern: a high-privilege process (the “deputy”) is tricked by a low-privilege attacker into performing a privileged operation on the attacker’s behalf.
In CrackArmor, the deputies are trusted SUID binaries like Sudo and Postfix. The mechanism is the AppArmor pseudo-file interface.
Here’s the fundamental issue: the three primary AppArmor profile pseudo-files are world-writable:
$ ls -la /sys/kernel/security/apparmor/.load--w--w--w-- 1 root root 0 Mar 13 /sys/kernel/security/apparmor/.loadMode 0666 — any unprivileged local user can open .load and .replace in O_WRONLY mode. What prevents an attacker from just writing an attacker-controlled profile directly? The kernel checks the process credentials at write time and enforces that only privileged processes can load profiles that modify existing confinement.
But here’s where the confused deputy comes in. When a privileged binary like sudo or postfix opens one of these pseudo-files as part of its normal operation — or can be coerced into doing so — the kernel sees the binary’s credentials, not the attacker’s. The attacker’s data travels through a trusted channel.
The nine vulnerabilities exploit variations of this pattern:
- Attacker opens the pseudo-file (permitted by 0666 mode)
- Attacker passes the open file descriptor to a privileged SUID binary via standard UNIX mechanisms (fd passing, symlinks, race conditions in temp file handling)
- Privileged binary writes attacker-controlled data to the kernel interface
- Kernel loads the malicious profile under the authority of the privileged process
The result: the attacker has loaded an AppArmor profile that grants unrestricted capabilities to an attacker-controlled process — bypassing the kernel protection that was supposed to prevent exactly this.
The Nine Vulnerability Classes
Qualys has not released full technical details for all nine flaws pending wider patch adoption. Based on the public advisory, they fall into these categories:
1. World-Writable Pseudo-File Interface
The foundational issue. Profile interface files expose write access to all users, enabling the subsequent attack classes.
2. SUID Binary Proxy via FD Passing
Open pseudo-file descriptors can be inherited or passed to SUID processes. The kernel evaluates credentials at the time of the privileged write, not at open time.
3. Symlink Race in Temporary Profile Staging
Race condition between temp file creation and kernel read — attacker substitutes a malicious profile blob in the window between creation and consumption by a privileged loader.
4. User Namespace Restriction Bypass
AppArmor enforces restrictions on what user namespaces (unprivileged containers) can do. The confused deputy path bypasses the namespace-level restriction checks, allowing a confined namespace to load profiles that should require host-level privileges.
5. Profile Replacement Without Authorization Check
The .replace interface lacks a consistent authorization check across all code paths. An attacker can replace an existing, restrictive profile with a permissive one for a target process without triggering the expected privilege verification.
6. Out-of-Bounds Read in Profile Parser
Malformed profile data causes the kernel parser to read beyond allocated buffer bounds. Depending on kernel memory layout, this leaks kernel addresses — enabling KASLR defeat and informing subsequent exploitation.
7. Stack Exhaustion via Recursive Profile Parsing
A specially crafted profile with deeply nested or circular references triggers unbounded recursion in the profile parser, causing kernel stack exhaustion — denial of service without any special privileges.
8. Arbitrary Code Execution via Profile Blob Injection
Once profile loading is achieved through a deputy, carefully constructed binary profile data can corrupt kernel memory structures. Combined with KASLR bypass (class 6), this enables arbitrary kernel code execution.
9. Permission Cache Poisoning
AppArmor caches permission decisions for performance. A race condition in cache invalidation allows an attacker to poison the cache with incorrect (permissive) entries that persist after a stricter profile is loaded.
Attack Chain: From Unprivileged User to Root
The realistic exploitation path for a threat actor with a local shell (post initial access, container escape attempt, or insider threat scenario):
[1] Reconnaissance - Confirm AppArmor enabled: cat /sys/module/apparmor/parameters/enabled - Identify kernel version: uname -r (target: >= 4.11) - List loaded profiles: cat /sys/kernel/security/apparmor/profiles - Check pseudo-file permissions: ls -la /sys/kernel/security/apparmor/
[2] Deputy Identification - Find SUID binaries that interact with AppArmor or have predictable file operation patterns: find / -perm -4000 2>/dev/null - Target: sudo, postfix, or custom SUID binaries with file write behavior
[3] Pseudo-File FD Acquisition - Open .load or .replace in O_WRONLY (permitted by 0666) - Establish a position for fd-passing or race exploitation
[4] Deputy Execution - Coerce target SUID binary into writing attacker-controlled profile data through the held file descriptor - The kernel sees trusted credentials; loads the profile
[5] Profile Activation - Loaded profile grants CAP_SYS_ADMIN or unrestricted capabilities to an attacker-controlled process - Execute the privileged process under the new profile
[6] Root Shell - Profile permits unrestricted syscalls and capability acquisition - Escalate to UID 0The critical insight for red teamers: this is a local privilege escalation vector. It requires an existing foothold with local user access. The realistic threat scenarios are:
- Post-exploitation — after a web app RCE drops a shell as
www-data, LPE to root via CrackArmor - Container escape — containerized attacker exploits user namespace restriction bypass to load host-level profiles
- Insider threat — unprivileged employee escalates to root on a shared Linux workstation or build server
- Cloud instance — exploiting any RCE in a hosted app to chain into full instance compromise
Container Isolation Bypass
This is the CrackArmor vector most relevant to modern infrastructure. Docker, LXC, and Kubernetes all rely on AppArmor profiles as part of their container isolation stack. Docker’s default docker-default profile blocks a significant portion of dangerous syscalls and capabilities for contained processes.
The user namespace restriction bypass (class 4) is particularly severe in container contexts. Unprivileged containers operate within their own user namespace — they appear to have root inside the container but are mapped to an unprivileged UID on the host. AppArmor is supposed to enforce that even apparent-root inside a container cannot modify host-level profiles.
CrackArmor breaks this guarantee.
Exploitation path in a containerized environment:
[1] Attacker has code execution inside a container (e.g., via app vulnerability)[2] User namespace restriction bypass allows writing to host AppArmor interface from within the container's namespace context[3] Attacker loads a custom profile that grants the container process CAP_SYS_ADMIN on the host[4] Container process escapes to host namespace[5] Full host compromiseThe impact extends to Kubernetes deployments. Many Kubernetes configurations apply AppArmor profiles via pod annotations. The assumption that AppArmor provides a meaningful security boundary for untrusted workloads is invalidated on unpatched kernels.
KASLR Bypass and Stack Exhaustion
Two of the nine classes target the kernel hardening layer directly rather than profile loading.
KASLR Bypass via Out-of-Bounds Read
Kernel Address Space Layout Randomization (KASLR) randomizes where the kernel loads in memory at boot, making it harder for exploits to predict the location of specific kernel functions or data structures. Modern kernel exploits that require RIP control or structure overwrites first need to defeat KASLR.
The AppArmor profile parser out-of-bounds read (class 6) leaks kernel pointer values when parsing malformed profile data. An attacker submits a crafted profile blob that triggers the OOB read, captures the output (visible through the return value or side-channel), and derives the kernel base address. This reduces KASLR from a hard barrier to a one-shot information disclosure.
Combined with the arbitrary code execution class (8), KASLR bypass completes the full kernel exploitation chain:
OOB read → kernel base address → calculate target offsets → overwrite kernel structure → rootStack Exhaustion as DoS
Less exciting than root escalation but operationally relevant: any unprivileged user can craft a recursive profile that causes the kernel parser to recurse without bound, consuming the kernel stack until it hits the guard page.
The result is an unrecoverable kernel panic — system down, immediate reboot required. No authentication needed. Against any unpatched system with AppArmor enabled, this is a trivial denial-of-service primitive.
Detection Opportunities
Qualys is withholding PoC exploits, but detection engineering doesn’t require a working exploit. The attack chain has observable artifacts at multiple points.
Audit Log Monitoring
AppArmor writes to the kernel audit subsystem. Enable detailed auditing and watch for:
# Monitor AppArmor pseudo-file accessauditctl -w /sys/kernel/security/apparmor/.load -p w -k apparmor_profile_loadauditctl -w /sys/kernel/security/apparmor/.replace -p w -k apparmor_profile_replaceauditctl -w /sys/kernel/security/apparmor/.remove -p w -k apparmor_profile_removeAny write to these files outside of expected management processes (apparmor_parser, system init scripts) is anomalous. The audit record captures UID, PID, and the calling binary — the confused deputy pattern shows a SUID binary writing on behalf of an unexpected caller.
Sigma Rule — Profile Modification by Unexpected Process
title: AppArmor Profile Modified by Unexpected Processid: a9f3b2e1-7c44-4d80-9e12-3fa850d6b1c7status: experimentaldescription: Detects writes to AppArmor kernel pseudo-files from processes other than known management toolslogsource: product: linux service: auditddetection: selection: type: SYSCALL syscall: write key: apparmor_profile_load filter_legitimate: exe|endswith: - '/apparmor_parser' - '/aa-exec' - '/systemd' condition: selection and not filter_legitimatefalsepositives: - Custom AppArmor management scripts — add to filter - Configuration management (Ansible, Puppet) — add to filterlevel: hightags: - attack.privilege_escalation - attack.T1548Profile Inventory Baselining
Maintain a baseline of loaded profiles and alert on additions or replacements:
# Capture current profile statecat /sys/kernel/security/apparmor/profiles | sort > /var/lib/security/apparmor_baseline.txt
# Compare at interval (cron or systemd timer)diff /var/lib/security/apparmor_baseline.txt \ <(cat /sys/kernel/security/apparmor/profiles | sort)Any delta outside a change window is a detection signal.
eBPF-Based Monitoring
For environments with modern kernels and eBPF tooling, hook the security_profile_load and security_profile_replace LSM hooks directly:
// Pseudo-code — attach to LSM hookSEC("lsm/bpf")int BPF_PROG(apparmor_profile_load_hook, ...){ // Log caller credentials, pid, and profile data hash // Alert if caller is not in allowlist}Tools like Falco with its kernel module or eBPF driver can be configured with custom rules against AppArmor pseudo-file access without writing kernel code directly.
Kernel Panic Correlation
Stack exhaustion manifests as a sudden kernel panic with a stack trace involving apparmor_ functions. If you see:
BUG: kernel stack overflowCall Trace: apparmor_parse_rules+... aa_unpack+... aa_replace_profiles+...That’s the DoS variant being triggered — whether accidental or intentional.
What You Can Do Today
1. Patch — This Is Mandatory
Ubuntu has published fixes. Patch immediately:
# Ubuntu / Debiansudo apt update && sudo apt dist-upgrade
# Verify kernel version post-patchuname -r
# SUSE / openSUSEsudo zypper refresh && sudo zypper update kernel-defaultCheck Ubuntu’s security advisories for the specific kernel version that includes the fix for your release (20.04, 22.04, 24.04).
2. Harden the Pseudo-File Interface
While patching, restrict access to the AppArmor pseudo-files. The world-writable permission is the root cause — tighten it:
# Restrict write access to root only# NOTE: This may break AppArmor management tools running as non-root# Test in non-production firstchmod 0200 /sys/kernel/security/apparmor/.loadchmod 0200 /sys/kernel/security/apparmor/.replacechmod 0200 /sys/kernel/security/apparmor/.removeA more robust approach is to use a systemd-tmpfiles rule to enforce permissions at boot:
m /sys/kernel/security/apparmor/.load 0200 root root -m /sys/kernel/security/apparmor/.replace 0200 root root -m /sys/kernel/security/apparmor/.remove 0200 root root -3. Deploy Detection Rules
Implement the auditd rules from the detection section immediately. They have near-zero performance impact and give you visibility into any exploitation attempts before or after patching.
4. Review Container Security Posture
Audit your Docker and Kubernetes deployments:
# Check which AppArmor profiles are applied to running containersdocker inspect --format='{{.HostConfig.SecurityOpt}}' <container>
# Kubernetes — check pod security contextkubectl get pod <pod> -o jsonpath='{.metadata.annotations}'Any container running with --security-opt apparmor=unconfined is already outside AppArmor’s protection. Any container on an unpatched host is now also at risk even with profiles applied.
5. Assess Exposure Surface
Identify systems where AppArmor is enabled and local access exists for untrusted users:
- Shared Linux workstations
- Build servers with developer access
- Any system running containerized multi-tenant workloads
- Cloud VMs where application-layer RCE could chain to LPE
Priority patching order: container hosts > shared systems > single-tenant VMs with no local untrusted access.
6. Monitor for Exploitation Attempts
Set up alerts in your SIEM for:
- AppArmor profile writes from unexpected processes
- New profiles loaded outside change windows
- Kernel panics with AppArmor stack traces
- SUID binary execution followed by kernel interface access (behavioral correlation)
Related Posts
- AD Attack Chains: From Initial Access to Domain Admin — And How to Detect Every Step — Understanding full attack chains from initial foothold to complete compromise; the post-exploitation LPE pattern mirrors CrackArmor exploitation flow
- LSASS Dumping: Techniques, Evasion, and Detection — Another privileged memory access technique with similar detection principles: behavioral anomaly in trusted process interaction
- Threat Hunting with Wazuh: Building Effective Detection Rules — Practical guide to implementing the kind of detection rules described above in an open-source SIEM stack
- Purple Teaming on a Budget: Free Tools and Frameworks That Actually Work — Framework for testing your detection coverage against privilege escalation techniques
Sources
- CrackArmor: Critical AppArmor Flaws Enable Local Privilege Escalation to Root — Qualys TRU
- Nine CrackArmor Flaws in Linux AppArmor Enable Root Escalation, Bypass Container Isolation — The Hacker News
- Critical CrackArmor Vulnerabilities Expose 12.6 Million Linux Servers to Complete Root Takeover — CyberSecurityNews
- AppArmor Vulnerability Fixes Available — Ubuntu Security Blog
- Breaking the Shield: CrackArmor Flaws Expose 12.6 Million Linux Servers — SecurityOnline
- oss-security Mailing List: Multiple Vulnerabilities in AppArmor
- AppArmor Security Profiles for Docker — Docker Documentation