DirtyDecrypt: Linux kernel LPE in the RxGK subsystem (CVE-2026-31635) with public PoC
18 May 2026. The V12 team has released a working exploit for “DirtyDecrypt” (also “DirtyCBC”): a Linux kernel local privilege escalation in rxgk_decrypt_skb of the RxGK subsystem, triggered by a missing copy-on-write guard that enables page-cache corruption and gives local users root. Will Dormann technically attributes the bug to CVE-2026-31635, quietly merged upstream on 25 April. Affected: distributions with CONFIG_RXGK enabled — mainly Fedora, Arch and openSUSE Tumbleweed; in container land, Kubernetes nodes on rolling-release distros are the real operational risk.

TL;DR — 90 seconds
| Affected? | Linux kernels with CONFIG_RXGK=y (or =m as a module) before the upstream commit of 25 April 2026 (CVE-2026-31635). In practice: Fedora (incl. Rawhide), Arch Linux, openSUSE Tumbleweed; in container platforms, all worker nodes running one of these kernels or a bleeding-edge mainline build. Stable distros (Debian Stable, RHEL, Ubuntu LTS) usually have RxGK disabled — a quick check with zcat /proc/config.gz | grep RXGK is mandatory. |
|---|---|
| Risk? | Local privilege escalation to root via page-cache corruption. Public PoC available, validated primarily against Fedora. In a container context, relevant as an escape path from a pod (Linux LPE → host kernel → container boundary break). |
| Immediate action? | Pull the kernel update with the 25 April patch or newer. If you cannot patch: unload esp4, esp6 and rxrpc via modprobe blacklist, clear caches — aware that this breaks IPsec/VPN and AFS. Move container hosts to a stable kernel line where the workload allows. |
| Recommendation? | German Mittelstand: ask your hosting provider about the kernel line; patch your own bare-metal and developer workstations today. Enterprise / Kubernetes: rebuild node images this week, check Karpenter/autoscaler TTL, verify pod security defaults. |
| Criticality? | high — public PoC + CISA KEV precedent on the sister bug “Copy Fail“ + container escape path. Escalation to critical possible once active exploitation in the container environment is documented. |
What is the problem?
The bug sits in the Linux kernel's RxGK subsystem. RxGK is the GSS-API-based security layer for RxRPC, the network transport used by the Andrew File System client (afs.ko) and a few related distributed filesystems. If you have never worked with AFS in production, the subsystem looks like a historical curiosity; in fact, CONFIG_RXGK is standard equipment in all mainline Linux builds and in rolling-release distributions, because being compiled into the kernel says nothing about whether the module is actually loaded. It is loaded only when a userspace process touches the AFS code path — or when a local user runs modprobe.
The specific fault sits in rxgk_decrypt_skb(), the function that decrypts an incoming sk_buff (socket buffer) on the receive side. In this code path the kernel handles memory pages that are partly shared with the page cache of other processes — a normal Linux optimisation protected by copy-on-write: as soon as a write to a shared page happens, a private copy is made beforehand so that the write doesn't bleed into another process's data. In rxgk_decrypt_skb() that guard is missing. A decryption write goes directly to a shared page-cache page, and the write lands in memory that belongs to another, privileged process, or, depending on the exploit path, in the page cache of a privileged file (e.g. /etc/shadow, /etc/sudoers or a SUID binary).
V12 describes the bug in their disclosure as “rxgk pagecache write due to missing COW guard in rxgk_decrypt_skb”. The team reported the finding to the kernel maintainers on 9 May and were told the issue had already been identified internally as a duplicate and patched. Will Dormann (CERT/CC, later Analygence) technically attributes the V12 bug to the quietly merged commit of 25 April, which carries CVE-2026-31635. At press time, there is no formal CVE tracking label for “DirtyDecrypt” as an alias.
Bug class in the context of the “Dirty” family
Typologically, DirtyDecrypt joins the family of recent Linux kernel LPEs that all sit on subtle memory-management weaknesses: Dirty Frag (CVE-2026-43284 / CVE-2026-43500, covered in our 10 May post), Fragnesia, Copy Fail (reference page UID 732, currently in CISA KEV), Pack2TheRoot in the PackageKit daemon. The common factor is not the module but the bug class: race conditions or missing synchronisation guarantees on page-cache operations that, with precise enough timing, lead to a privileged write. DirtyDecrypt sits at the intersection of the network subsystem and the page cache, which makes the trigger more specific than for Copy Fail but the exploit path no less dangerous.
Who is affected?
“Am I affected” takes two seconds on the command line — and for most German Mittelstand platforms the answer is “no, but you should still look closely at where you run rolling-release kernels”.
| Layer | Affected | Not affected | Conditions |
|---|---|---|---|
| Kernel build | CONFIG_RXGK=y or =m with a kernel baseline before the 25 April 2026 commit | Kernels with RxGK disabled (Debian Stable, RHEL, Ubuntu LTS standard builds), or that include the 25 April patch | Check via zcat /proc/config.gz | grep RXGK or grep RXGK /boot/config-$(uname -r) |
| Distribution (rolling-release) | Fedora Rawhide, Fedora Workstation (until patch pull), Arch Linux, openSUSE Tumbleweed | Fedora Stable after kernel update, Arch after pacman -Syu, Tumbleweed after zypper dup with a current snapshot | Update cadence of the workstation matters — if you have not updated for 14 days, you are likely still vulnerable |
| Distribution (stable) | Bleeding-edge packages (mainline PPA on Ubuntu, ELRepo kernel-ml on RHEL/CentOS Stream) | Debian Bookworm, RHEL 8/9 with vendor kernel, Ubuntu 22.04/24.04 LTS standard kernel | Rarely affected; a sweep across every host is still worthwhile |
| Container image | Container image builds do not influence the host kernel — RxGK does not load itself inside a container | – | No direct container image patch needed; the patch must sit on the host |
| Container host (Kubernetes worker) | Worker nodes on Fedora CoreOS Rawhide, Arch-based custom builds, bleeding-edge Talos nightly | Talos stable, Flatcar Stable, Bottlerocket, Ubuntu LTS workers, AWS Bottlerocket | Pod escape path: compromised container + kernel LPE = host root |
| Bare-metal server (hosting) | Hosting providers with custom rolling kernels (rare) | Hetzner standard Debian, Mittwald hosting (Debian backports line), STRATO/Plesk stacks | Ask the provider if unclear |
| Developer workstation | Fedora/Arch/Tumbleweed workstations of platform engineers, SREs, security teams | macOS, Windows, Debian Stable workstations | High risk profile because of privileged access (kubectl contexts, AWS profiles, SSH keys) |
The finding most relevant to the Mittelstand is not in the first row but in the second-to-last: developer workstations on Fedora or Arch are common in our customer base because they are the natural choice for container, Kubernetes and AI tooling work. These are the machines holding productive kubectl contexts, AWS profiles with production roles and SSH keys to production systems. A local root on an SRE workstation is operationally more painful than a local root on an isolated build server.
Impact
With DirtyDecrypt, “what does this enable in theory” is less interesting than “what does this enable in a realistic attack chain”. In theory: full compromise of the Linux host, read/write access to all files, persistence, container boundary break, and — depending on hardening — kernel module loading. In practice, the chain is almost always two-stage.
Stage one is the initial foothold on the host. An attacker usually does not get that with DirtyDecrypt itself — the bug is an LPE, not an RCE. Entry comes through the usual paths: compromised SSH credentials (stuffing, phishing, leaked keys), an exploitable public-facing application (a PHP platform with an upload flaw, Sylius with an auth bug, an old nginx worker), or, on container platforms, a compromised pod image in the cluster. In each of these cases the attacker lands as an unprivileged identity in a Linux userspace.
Stage two is DirtyDecrypt. The attacker checks grep RXGK /boot/config-$(uname -r) to see whether the subsystem is active, loads the rxrpc module if needed (modprobe rxrpc), runs the V12 PoC and gets root. On a Kubernetes worker node, “root on the host” means “access to every pod, every container runtime socket, every Kubernetes secret mounted on this node”. On an SRE workstation, “root” means “access to every cloud profile, every kubeconfig, every SSH agent, every GPG key in the keyring”.
In CVSS terms this is a local privilege escalation with AC:L/PR:L/AI:N/CIA:H — typically in the 7.8–8.1 range. The score is less informative here than the context. CISA added the sister bug “Copy Fail“ to the KEV catalogue on 8 May, with a 15 May 2026 patch deadline for Federal Civilian Executive Branch agencies, precisely because the federal risk profile of a kernel LPE is higher than the CVSS score implies. If you are on the NIS-2 obligation list in the German Mittelstand, treat the CISA classification as an indicator, not the CVSS score.
Mitigation / immediate actions
Order: patch first (if possible), then workaround, then sort out the container-host strategy structurally.
Path 1 — pull the kernel patch
# Fedora / Fedora CoreOS
sudo dnf upgrade --refresh kernel kernel-core kernel-modules
sudo systemctl reboot
uname -r
# Target: kernel with build date after 25 April 2026 or explicit CVE-2026-31635 in the patch notes
# Arch Linux / Arch-based hosts
sudo pacman -Syu linux linux-headers
sudo systemctl reboot
uname -r
# openSUSE Tumbleweed
sudo zypper dup
sudo systemctl reboot
# Ubuntu Mainline PPA (if used)
sudo apt update
sudo apt upgrade linux-image-generic linux-headers-generic
sudo systemctl reboot
Before rebooting, check whether the rxrpc module is live and which files have an afs kernel module lock — otherwise a mount will hang after the reboot:
lsmod | grep -E "(rxrpc|afs)"
fuser -m /afs 2>/dev/null
Path 2 — workaround (no patch available)
If you cannot apply a patch today (no maintenance window, vendor kernel lagging), unload the affected modules and blacklist them until the update lands. Caveat: this breaks IPsec VPN and AFS.
# 1. Create module blacklist
sudo tee /etc/modprobe.d/dirtydecrypt-mitigation.conf > /dev/null <<'EOF'
# Temporary mitigation for DirtyDecrypt / CVE-2026-31635
# Remove this file after kernel patch is applied
blacklist esp4
blacklist esp6
blacklist rxrpc
install esp4 /bin/false
install esp6 /bin/false
install rxrpc /bin/false
EOF
# 2. Unload active modules (check beforehand that nothing live depends on them)
sudo modprobe -r esp4 esp6 rxrpc 2>&1 | tee /tmp/modprobe-remove.log
# 3. Flush module cache and page cache
sudo depmod -a
sudo sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
# 4. Verify modules are not loaded after reboot
lsmod | grep -E "(esp4|esp6|rxrpc)" && echo "WARN: module still loaded" || echo "OK: blacklisted"
Caveat: the workaround breaks IPsec VPN connections (StrongSwan, libreswan, Algo — but not WireGuard, which uses a different path) and the AFS distributed filesystem. In enterprise environments with site-to-site VPN, this is an operational incident, not a harmless precaution. Patch first, then unwind the workaround.
Path 3 — container host strategy for Kubernetes
If you run Kubernetes workers on rolling-release distros, make an architecture decision today. The fastest mitigation is not patching the kernel on every individual node but switching to a declarative host strategy:
# Check Talos Linux worker pool
talosctl --nodes worker-01 version
# If the Talos version is before 1.10.x with a custom kernel build:
# Lift the worker via `talosctl upgrade --image ghcr.io/siderolabs/installer:v1.10.x`
# Check Flatcar worker pool
ssh worker-01 cat /etc/os-release | grep VERSION
# Flatcar pulls kernel patches via the automated OS update;
# control reboot windows via Kured or Karpenter
# Check Bottlerocket worker pool
aws ssm send-command --instance-ids i-... \
--document-name "AWS-RunShellScript" \
--parameters 'commands=["uname -r"]'
In normal Kubernetes operation, imagePullPolicy: Always, allowPrivilegeEscalation: false, readOnlyRootFilesystem: true, runAsNonRoot: true should be defaults. If you do not yet enforce these, you have a bigger problem than DirtyDecrypt — pod security standards (restricted profile) should be active cluster-wide, and this very bug is a reason to follow through.
Detection
A specific detection for a DirtyDecrypt exploit is hard with classical logs: the exploit runs in userspace and writes via a kernel path into the page cache of another process, without a noticeable execve or suspicious syscall. Detection sits in three places.
Version sweep (inventory, not a real-time signal)
# Iterate over all hosts (ansible / mssh / clusterssh)
for host in $(cat hosts.txt); do
ssh "$host" '
echo "=== $(hostname) ==="
uname -r
zcat /proc/config.gz 2>/dev/null | grep RXGK || grep RXGK /boot/config-$(uname -r) 2>/dev/null
lsmod | grep -E "(rxrpc|afs|esp4|esp6)"
'
done
Falco rule for rxgk module load
- rule: rxgk_module_loaded_on_production_host
desc: rxrpc kernel module loaded on a production host outside the maintenance window (heuristic for DirtyDecrypt exploit attempt)
condition: >
spawned_process and
proc.name = "modprobe" and
proc.cmdline contains "rxrpc"
output: >
rxrpc module load detected (proc=%proc.name cmdline=%proc.cmdline user=%user.name pid=%proc.pid host=%container.hostname)
priority: WARNING
tags: [cve-2026-31635, dirtydecrypt, linux-kernel, lpe]
- rule: unexpected_rxgk_decrypt_skb_activity
desc: Unusual kernel activity around rxgk decryption path
condition: >
evt.type = "syscall" and
syscall.name in ("setresuid", "setreuid", "setuid") and
proc.aname[1] != "systemd" and
user.uid != 0 and
fd.name contains "/proc/self/status"
output: >
Unprivileged process attempting UID change (proc=%proc.name pid=%proc.pid parent=%proc.aname[1])
priority: NOTICE
tags: [linux-lpe, post-exploitation]
Tetragon TracingPolicy as an alternative
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: detect-rxgk-module-load
spec:
kprobes:
- call: "do_init_module"
syscall: false
args:
- index: 0
type: "module"
selectors:
- matchArgs:
- index: 0
operator: "Equal"
values:
- "rxrpc"
- "rxgk"
matchActions:
- action: Sigkill
The Sigkill action is aggressive — in production environments, start with Override plus logging, validate, then raise the action.
Operator recommendation
Operational decision block
- Mitigate immediately if … you run Kubernetes workers on Fedora CoreOS Rawhide, Arch-based custom builds or bleeding-edge Talos nightly, or if engineers with privileged cloud profiles work on Fedora/Arch/Tumbleweed workstations. Patch today, module blacklist as backup.
- Maintenance window is fine if … your hosts run on Debian Stable, RHEL, Ubuntu LTS or Talos Stable and
CONFIG_RXGKis disabled. Patch on the next kernel cycle, no special slot needed — but still sweep every host so you know rather than guess. - Pure bare-metal stable stacks, if … you don't run a rolling-release kernel and don't operate a container platform. Standard patch cycle is fine.
German Mittelstand
In the German Mittelstand, DirtyDecrypt is not an acute issue for the majority of pure web platforms because the standard hosting stacks sit on Debian-stable lines. It becomes acute in two places: first on developer workstations, which are typically Fedora or Arch; second on Kubernetes clusters, if the workers run rolling distros. Both are more common than people think — the question “which distro does your dev cluster run” often produces “Fedora CoreOS Rawhide, because we need the latest container features”. Exactly those clusters need the patch or the workaround today.
Enterprise / Kubernetes
On Kubernetes, the operational question is not “do we patch the workers” but “how fast does our node pool rotate”. With Karpenter or a cluster autoscaler with a short TTL and automatic node-image refresh, the patch lands within hours once the patched worker image hits the image registry. With quarterly pinned AMIs, the window is longer — and you need pod security defaults as a safety net during that time. Clear recommendation: enforce the restricted pod security standard cluster-wide, set allowPrivilegeEscalation: false as default, and require an explicit, documented exception for privileged workloads (CSI drivers, CNI plugins, monitoring agents) rather than silent tolerance.
Declarative stacks (NixOS / Talos / Flatcar / Bottlerocket)
Talos Linux is the path with the smallest worry factor here: the entire worker host is a declarative image, CONFIG_RXGK is removable in the Talos kernel config, the patch lands via the normal image upgrade. Flatcar is analogous. NixOS users (occasionally found in platform teams) pull the patch via a pin bump in the Nix flake and a rebuild. Bottlerocket, one of the cleanest worker-OS concepts on the market, has RxGK disabled in the standard configuration — and even in that world you should document the incident pattern, because it is the pattern for the next “Dirty” variant in twelve months.
What we actually did
We read the V12 disclosure this morning and rolled out the patch sweep on our own platforms — on the Moselwal infrastructure and the three customer clusters we actively operate.
First, we ran the version sweep: on the Linux hosts (bare-metal servers, Kubernetes workers) via Ansible playbook, on the NixOS-based hosts via the flake evaluation. The developer workstations at Moselwal run on macOS, are not directly affected by the Linux kernel LPE, and dropped out of the sweep. Result on the Linux side: one Kubernetes worker pool on Talos 1.10 stable (RxGK disabled, not affected), the remaining hosts on Debian Bookworm or Bottlerocket (both disabled). No hit in the sweep — which is not luck but the outcome of a declarative worker-OS strategy we pushed through consistently after Copy Fail in April.
Second, on the hosts where an update was sensible, we applied the patches: via Ansible rollout for the imperatively managed servers, via NixOS flake bump and rebuild for the declaratively managed ones. We verified after reboot via uname -r and against the CVE-2026-31635 patch notes.
Third, we added the Falco rule above to our central rule library, priority WARNING, routed to the Slack #sec-events channel. An additional Tetragon policy would theoretically be the sharper alternative at kernel level; we rolled it out in override mode on the clusters that run Tetragon, not in sigkill mode, because an initial false positive on modprobe rxrpc can well come from a legitimate operations script.
What we deliberately did not do: roll out the module-blacklist workaround across the board. IPsec is not currently in use at Moselwal, so blacklisting esp4/esp6 would not have broken anything for us — but as a default it would be a line that a colleague could silently undo in a later setup step the moment a VPN use case appears. Patching was the clean path here; the workaround remains a documented emergency option for hosts where patching today is not possible.
Architecturally, the same pattern sits underneath this episode as for Copy Fail and Dirty Frag last quarter: the operational safety of a Kubernetes cluster does not hang on the individual pod manifest, it hangs on whether the worker hosts run on a distribution that is built declaratively and reproducibly. Talos, Flatcar, Bottlerocket go one way; an old-fashioned server Linux with five admins and a hand-rolled kernel goes the other. If you still operate in the second world, DirtyDecrypt at the latest is the moment to plan the migration into the first.
Frequently asked about DirtyDecrypt
Is my Debian/Ubuntu LTS production directly at risk from DirtyDecrypt?+
Usually no. Debian Stable, RHEL and Ubuntu LTS build their vendor kernels without CONFIG_RXGK, because the subsystem is not relevant for the standard workloads on those distros. Quick check: grep RXGK /boot/config-$(uname -r) — if the output contains # CONFIG_RXGK is not set or is missing entirely, you are not affected. Exception: if you run the linux-image-generic-hwe package on Ubuntu LTS or kernel-ml from ELRepo on RHEL, you have a bleeding-edge kernel installed and must verify against the 25 April patch line.
Do Kubernetes container images need rebuilding because of DirtyDecrypt?+
No — the patch sits on the host kernel, not in the container image. Containers share the kernel with the host; a patched worker node protects every pod running on it. Image rebuilds (Wolfi, Chainguard, distroless) make sense for other reasons (userspace CVEs, supply-chain hygiene), but they are irrelevant to DirtyDecrypt. The operational question is: when was the worker image last rebuilt, and does it carry the 25 April kernel commit?
How do I check whether my Talos Linux worker is affected?+
talosctl --nodes <worker> get kernelmodulesall shows the loaded and configurable kernel modules. Talos images before 1.10.x with a custom kernel build (rare, usually only on self-compiled Talos variants) are potentially affected; Talos stable releases from 1.10.x onwards carry the patch. When in doubt, run talosctl upgrade --image ghcr.io/siderolabs/installer:v1.10.5 — Talos rotates the entire host image, not just the kernel, which is the clean variant.
Is the module-blacklist workaround enough, or do I still need to patch?+
The workaround unloads the rxrpc module and prevents the vulnerable code path from being loaded — that is a valid temporary mitigation. But: it breaks IPsec VPN and AFS, and it is a fragile solution because an operations script or a cluster operator may reload the module later if the blacklist file disappears from the /etc/modprobe.d/ path. Patching is the sustainable solution; the workaround is the bridge when the patch maintenance window is still two days away.
Do we have to report DirtyDecrypt as a NIS-2 incident if we had an unprivileged pod compromise?+
A NIS-2 reporting obligation arises with a “significant security incident” that has operational consequences. An unprivileged pod compromise alone usually does not cross that threshold. But if there are signs that the pod compromise escalated to a host compromise via a kernel LPE like DirtyDecrypt — a Falco/Tetragon hint of rxrpc module load, unusual UID-change events, or a direct forensic finding on a worker node — the threshold for the 24/72-hour NIS-2 report to BSI is likely crossed. In parallel, a GDPR Art. 33 report to the supervisory authority within 72 hours if personal data may be affected.
Bottom line
DirtyDecrypt forces two decisions on the same day. The tactical decision is trivial: patch today where a rolling-release kernel is in play; sweep today where you are unsure; leave the workaround in place for hosts where patching does not work. The strategic decision is the harder one: whether the worker distribution of your Kubernetes clusters and the distribution of your SRE workstations belongs to the “hand-rolled kernel with five admins” category or the “declaratively built worker OS” category. The “Dirty” family of Linux kernel LPEs in 2026 is the empirical answer to why the second world is structurally safer than the first.
The question is not whether the next kernel LPE will arrive. The question is whether your worker nodes are built such that the next bug doesn't catch them off-guard again.
This article reflects our technical assessment. It does not replace a data protection impact assessment or legal advice on specific NIS-2 reporting obligations.
We test, mitigate and validate your Linux kernel line against DirtyDecrypt.
We run the inventory sweep across your hosts (workstations, bare metal, Kubernetes workers), check the CONFIG_RXGK state, apply the kernel patch or the module-blacklist workaround, validate with the V12 PoC that the bug is closed, and add Falco/Tetragon detection to your central rule library. Where it makes structural sense: a migration plan to Talos, Flatcar or Bottlerocket as the worker OS, instead of replaying the rolling-release risk every quarter.
Platform operations, not advice-on-paper. We know the kernel lines of the common DACH hosting providers and the quirks of Talos and Flatcar in German Mittelstand practice because we run them daily. More on the service line at DevSecOps and Services.
![[Translate to English:] Foto von Kai Ole Hartwig.](/fileadmin/_processed_/e/9/csm_ole-neu_73323ad80d.jpeg)


