Skip to main content

Why Copy Fail Couldn't Touch Workloads Under a Tailored AppArmor Profile

Copy Fail (CVE-2026-31431) is a Linux kernel LPE that's already in CISA KEV and reaches every container that inherits the AF_ALG kernel surface by default. For workloads running under a behavior-generated AppArmor profile, the exploit's required syscall path was never allowed in the first place. Here's why, and how to confirm your exposure in seconds.

H

Hannes Ullman

bifrost security

Why Copy Fail Couldn't Touch Workloads Under a Tailored AppArmor Profile

Copy Fail (CVE-2026-31431) was disclosed on April 29 and was added to CISA’s Known Exploited Vulnerabilities list within days. It’s a logic bug in the Linux kernel’s authencesn cryptographic template that enables a 4-byte arbitrary write into the page cache of any readable file. From there, a 732-byte script flips a setuid binary and grants the local user root access. Every Linux distribution shipped since 2017 is affected.

Copy Fail is a local privilege escalation, not a remote exploit. The attacker has to land code in your container first, whether through a compromised dependency, an RCE in your app, leaked credentials, or another initial-access vector. Copy Fail is the tool they reach for once they’re inside to turn a low-privilege foothold into root on the host. The container angle is what makes that foothold dangerous: Docker, LXC, and Kubernetes grant processes inside a container access to the AF_ALG kernel subsystem by default whenever the algif_aead module is loaded on the host. The vulnerable kernel path is reachable from a low-privileged in-container process the moment the host boots, and patching a Kubernetes fleet realistically takes days to weeks. That creates a dangerous patch window, which is exactly where a tailored AppArmor profile does its job.

A single chokepoint

The exploit needs exactly one thing to work: socket(AF_ALG, SOCK_SEQPACKET, 0) followed by bind() to an aead type with authencesn(...). No AF_ALG socket, no kernel path reached, no 4-byte write, no root.

AF_ALG is also a kernel surface that almost no normal application uses. Python’s cryptography and pycryptodome route through OpenSSL or pure C, not the kernel crypto API. Go and Node use their own userspace crypto. OpenSSL’s afalg engine is opt-in and rarely compiled in. The legitimate users of AF_ALG are HSM offloads, embedded crypto on ARM platforms with hardware engines, and a few niche performance-tuned workloads. None of these are typically what’s running in a Python web app, an ML inference pod, a Go microservice, or a Node API gateway.

Empirically, if you were to grep a representative sample of containerized workloads’ observed socket traces for AF_ALG binds, the hit rate would be well under one percent.

Why tailored profiles made this a non-event

A bifrost-generated AppArmor profile only allows the network families and syscalls a workload actually exercised during the learning window. AF_ALG doesn’t appear in the observed set for normal application traffic, so the generated profile implicitly denies it. That’s the whole point of behavior allow-listing: you don’t need to predict tomorrow’s CVE, you just need the profile to reflect what the app actually does.

When Copy Fail dropped, the protection was already in place. No detection rule had to be written, no patch had to land, no policy had to be authored. The attacker who found their way into a protected container, ran the 732-byte exploit, and tried to open the AF_ALG socket got a denial from the kernel, attributed to the AppArmor policy. The attack was stopped at line one.

Assess your exposure in seconds

In bifrost, every running workload is continuously analyzed against its allow-listed profile, and that profile is mapped against the syscall and capability requirements of known CVEs. To check your exposure to Copy Fail:

  1. Open the bifrost dashboard.
  2. Search for CVE-2026-31431.
  3. Read the per-workload verdict.

For Copy Fail, the expected output is a list of every protected workload showing not exploitable, because no profile in the cluster permits the AF_ALG socket family. You can hand the resulting view to your CISO, confirm that the Linux kernel patch can roll out at a normal cadence rather than as a fire drill, and stop carrying the CVE as a P0.

Two caveats, kept honest

This claim survives scrutiny only if it’s stated precisely. Here are two things worth keeping in mind:

Node-level coverage matters. Copy Fail compromises the host. If your application pods are profiled but a sidecar, an unconfined DaemonSet, a node agent, or a CI runner on the same node lacks a profile, the kernel is reachable from that other process. The resulting root compromise affects every pod on the node, including the profiled ones. The strongest version of the claim is: Copy Fail is unreachable for any workload running under a bifrost-generated profile, and if you cover the cluster comprehensively, it’s unreachable cluster-wide.

Profile drift matters. If a workload happened to exercise AF_ALG during the learning window, legitimately or otherwise, the rule would be allowed. Bifrost surfaces unusual capability and family allowances on profile review, so a human can sanity-check before enforcement. For Copy Fail in particular, an AF_ALG allowance is the kind of finding that should trigger a question, not a rubber stamp.

The takeaway

Patching is still the right long-term answer. But during the patch window, the blast radius for Copy Fail collapses to whatever fraction of your workloads legitimately need kernel crypto offload—which, for most clusters, is essentially zero. You didn’t have to know the CVE existed to be protected. You just needed the profile to reflect what the app actually does.

That’s the case for tailored, behavior-generated AppArmor profiles in one CVE. There will be another one next month.

Tags

apparmor container security kubernetes cve runtime

Ready to see runtime security in action?

bifrost automatically generates tailored security profiles for your containers and cuts CVE noise by up to 90%. Free trial, no credit card required.