1. Chronology of the disclosure
Dates verbatim where the source provides them; relative phrasing converted where today's date (2026-05-04) makes it unambiguous.
| Date (2026) | Event |
|---|---|
| ≈ mid-April | Silent fix lands in the upstream Linux source tree (in-place AEAD path reverted to out-of-place). Source available roughly two weeks before public disclosure per heise. |
| Late April / pre-extended-weekend | Coordinated public disclosure of CVE-2026-31431 ("Copy Fail"). CVSS 7.8. Theori publishes the technical write-up; multiple PoC variants appear on GitHub (theori-io repository). |
| 2026-05-01 | CISA issues alert. |
| 2026-05-04 (heise, 08:44 UTC) | Active exploitation confirmed in the wild. Greg Kroah-Hartman has shipped patches for 6.18.22, 6.19.12 and 7.0; backports to LTS branches in flight. Most major distributions have published fixed packages. |
Two timing observations matter for downstream analysis:
- Patch-gap window (~2 weeks) between the silent commit and the public disclosure. Standard pattern: attackers diff the upstream commit against the previous tree, identify the fix, derive the bug, and weaponise. The speed of in-the-wild appearance after disclosure is consistent with this reverse-engineering pathway, not with independent rediscovery.
- Forensic invisibility. The exploit primitive writes only into the page cache. No on-disk artefact persists from the corruption itself; the on-disk
/etc/passwdis unchanged. Detection requires either page-cache-vs-disk divergence checks or syscall-level visibility intoAF_ALG+authencesn+splice()patterns.
The corruption never touches disk. /etc/passwd on storage stays intact while the page-cache copy resolves UID=0 for the attacker's own username. Any detection that compares only on-disk state will miss the entire incident.
2. Underlying flaw — primary TLCTC classification
Unchanged from the original analysis.
Cluster #2 Exploiting Server, sub-cluster #2.2 (core function vector — internal processing/parsing flaws in a server-role component).
Reasoning chain, condensed:
- R-ROLE. The Linux kernel, exposed via
AF_ALG, receives and processes inbound requests from the attacker's unprivileged userspace process. The kernel is in server role for this interaction → #2, not #3. - #1 vs #2. A logic error in the in-place AEAD scatterlist construction is required for the write to land. An implementation flaw is present → #2 / #3, not #1 (no designed-feature abuse within intended boundaries).
- #2 sub-clustering. Not socket-protocol parsing (#2.1), not delegated external processing (#2.3). The locus is the kernel's own internal AEAD processing logic; the upstream fix reverts the in-place optimisation, confirming core-function-logic placement → #2.2.
Generic vulnerability: code imperfection in server-side software (internal kernel processing path).
3. What the kernel primitive does, in one sentence
Four attacker-controlled bytes per shot are written into a page-cache page of any file the unprivileged process can read; the failed AEAD auth check returns EBADMSG but the scratch write has already landed.
The published exploit is a 732-byte Python script. From local unprivileged shell to root in under a minute. No race window, no kernel offset disclosure required, deterministic across distributions since 2017.
4. Attack paths now observed in the wild
The kernel exploit step is structurally a terminal privilege-escalation primitive: it requires prior local code execution as an unprivileged user and yields root (or host kernel control from a container). It therefore appears as the last technical step in a chain whose earlier steps come from the operator's preferred initial-access cluster. Four chains are currently realistic; all four end identically.
Notation: #2.2 is the kernel exploitation; |[kernel][@user→@kernel]| is the v2.1 intra-system boundary marking the userspace→kernel crossing. Δt values reflect typical operator pacing post-foothold.
Path A — Local foothold from a server-side compromise
Most common ITW pattern reported for opportunistic exploitation of Linux hosts running internet-facing services.
#2 ||[api][@External→@Org]|| (initial RCE: web app, edge appliance, etc.) →[Δt=minutes–hours] #7 (webshell or implant established as service user) →[Δt=minutes] #2.2 |[kernel][@user→@kernel]| (algif_aead primitive) →[Δt<1s] + [DRE: I — /etc/passwd page cache] → SRE: Loss of Control (root) + [DRE: C, I, A — host]
Path B — Container escape in multi-tenant infrastructure
This is the chain that elevates the CVE from "local privesc" to "cloud incident". The Linux page cache is shared across containers on the same host kernel; corruption of a host-readable file is observable in every sibling namespace. Containers are not a security boundary against #2 in the host kernel.
[any path delivering code execution into tenant container] → #2.2 |[kernel][@container→@host-kernel]| (same primitive, escapes namespace by design) →[Δt<1s] + [DRE: I — host page cache, shared across tenants] → SRE: Cross-tenant compromise + [DRE: C, I, A — host and sibling containers]
Path C — Endpoint chain via phishing / malware
Where the targeted host is a Linux workstation or developer machine.
#9 ||[human][@External→@Org]|| (lure → user runs attacker code) →[Δt=hours] #7 (stage-1 loader / dropper as user) →[Δt<1m] #2.2 |[kernel][@user→@kernel]| →[Δt<1s] + [DRE: I — /etc/passwd] → SRE: Loss of Control + [DRE: C, I, A — host]
Path D — Supply-chain delivery to a build / dev / CI host
Particularly relevant given the public PoCs are small Python scripts — trivial to embed in a postinstall hook or a CI step.
#10 ||[update][@Vendor→@Org]|| (poisoned package, TAE = install) →[Δt=seconds] #7 (post-install hook executes) →[Δt<1m] #2.2 |[kernel][@user→@kernel]| →[Δt<1s] + [DRE: I — /etc/passwd] → SRE: Loss of Control on the build host + [DRE: C, I, A — host, with onward supply-chain blast radius]
Notes on the chains
- The
su/ login step that follows the/etc/passwdrewrite is not a separate#4 Identity Theft. The attacker is corrupting the authoritative identity data store, not presenting a stolen credential. R-CRED does not apply: there is no credential acquisition and no credential presentation — the kernel resolves UID=0 for the attacker's own username because the backing data has been falsified. This is a Loss-of-Integrity DRE flowing from #2.2, not a new step. - "Privilege escalation" is not a TLCTC cluster (SG4). It is the outcome of #2.2 plus the Loss-of-Integrity DRE.
- All four paths share identical SRE and DRE structure once the kernel primitive fires. They differ only in the cause-side cluster delivering initial local code execution.
5. Bow-Tie placement
| Position | Element |
|---|---|
| Cause | #2.2 Exploiting Server — algif_aead in-place scatterlist logic flaw |
| Generic vulnerability | Code imperfection in server-side software (kernel internal processing) |
| SRE / Central event | Loss of Control — kernel forced to write attacker-controlled bytes outside intended buffer |
| DRE (primary) | Loss of Integrity — page cache of arbitrary readable file (canonical target: /etc/passwd) |
| DRE (containerised) | Loss of Integrity — host page cache, propagating to all co-tenant namespaces |
| Consequence | Full Loss of C-I-A on the host; cross-tenant compromise in shared-kernel multi-tenancy |
6. Velocity & containment
- Exploit primitive:
Δt<1s. End-to-end privesc:<1 minute. - Velocity class VC-4 for the kernel step itself; surrounding chain velocity bounded by the initial-access cluster (typically VC-2 / VC-3).
- Detection-only controls are structurally weak: the operation completes in a single syscall sequence and leaves no on-disk trace. CDE_max for behavioural detection is bounded by syscall-level visibility into
AF_ALG+authencesn(hmac(sha256),cbc(aes))+splice(). - Cause-side prevention dominates the ECR ceiling.
7. Controls grouped by Bow-Tie position
Cause-side (against #2.2)
- Apply the upstream kernel patch (6.18.22 / 6.19.12 / 7.0 + LTS backports as they ship). The in-place→out-of-place revert is the only control that closes the generic vulnerability.
- Block
AF_ALGfor unprivileged workloads via seccomp profiles or--security-opton container runtimes. Eliminates the entry path even while patching lags. - For multi-tenant: replace shared-kernel namespace isolation with a hardware/VM boundary for any workload running untrusted code. Containers are not a security boundary against #2 in the host kernel.
Cause-side (against the chains delivering local exec)
- Path A: edge-service patching, WAF, server hardening (against #2).
- Path B: image provenance, runtime admission control, drop ambient capabilities (against the various #2/#7/#10 paths into the container).
- Path C: anti-phishing, mail gateway, user education (against #9); EDR/AV (against #7).
- Path D: dependency pinning, signed packages, sandboxed builds, isolation of CI runners from production trust (against #10 at the TAE).
Consequence-side (after SRE)
- File integrity monitoring that compares on-disk state to served page cache content — catches the
/etc/passwddivergence that the exploit produces but does not flush. auditdrules on UID changes,setuidbinary modifications, and unexpected use ofAF_ALGfrom non-privileged processes.- Host-level egress controls and process-tree anomaly detection to bound blast radius once root is achieved.
8. Cross-framework note
In MITRE ATT&CK this maps to T1068 (Exploitation for Privilege Escalation), a technique that conflates cause (server-side coding flaw) and effect (privilege escalation). TLCTC keeps these separate: the cause is #2.2, the effect is a Loss-of-Integrity DRE that enables the SRE. Dirty Pipe (CVE-2022-0847) is a different subsystem, same TLCTC class (#2.2). The clustering is stable across both incidents; the ATT&CK T1068 label is not.
9. Summary
CVE-2026-31431 is — at the level of generic vulnerability — a single #2.2 step. What changed between the original advisory and the 2026-05-04 heise reporting is the environmental context, not the classification: the silent fix has been public long enough for diff-based weaponisation, distro patches are shipping, CISA has issued an alert, and operators are chaining the primitive onto whichever initial-access cluster they already use. The four chains in §4 cover the realistic ITW shapes. All four end with #2.2 and the same SRE + DRE structure; defensive priority should be patching first, AF_ALG lockdown second, and detection investments aimed at page-cache-vs-disk divergence and AF_ALG syscall patterns rather than at the post-root behaviour, which is too fast and too varied to gate on.
The kernel flaw is one cluster, one sub-cluster: #2.2 Exploiting Server.
The chain shape is determined by the operator's initial-access cluster (#2, #9, or #10) plus #7, then a single #2.2 step at the userspace→kernel boundary.
Privilege escalation is the SRE outcome, not a separate cluster. R-CRED excludes a follow-up #4 because no credential is presented — the identity store itself is rewritten.
ATT&CK T1068 conflates cause and effect; the cluster mapping does not. Patch first, lock AF_ALG second, and invest detection where on-disk forensics fail: page-cache divergence and AF_ALG syscall patterns.
Final classification
algif_aead in-place scatterlist logic flaw/etc/passwd)
This analysis applies the TLCTC v2.1 framework: ten cause-oriented threat clusters, the Bow-Tie SRE/DRE separation, attack path notation with Δt velocity classes and v2.1 boundary operators (||...|| for system-edge crossings, |...| for intra-system crossings such as userspace→kernel). For framework definitions: tlctc.net.
Licensed under CC BY 4.0. Framework: tlctc.net · Source: github.com/Barnes70/TLCTC