Blog / Threat Analysis · CVE

CVE-2026-31431 ("Copy Fail") — TLCTC Analysis

Updated to reflect heise.de reporting of 2026-05-04: in-the-wild exploitation confirmed, CISA alert issued, public PoCs available, distro patches shipped. The TLCTC classification of the underlying flaw does not change — the new information adds chronology, urgency, and the surrounding attack paths in which the kernel primitive is now being chained.

BK
Bernhard Kreinz
• • Loading read time...

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/passwd is unchanged. Detection requires either page-cache-vs-disk divergence checks or syscall-level visibility into AF_ALG + authencesn + splice() patterns.
Forensic invisibility

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.

Path A — Server-side compromise → kernel privesc
#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]
#2 initial RCE
→Δt = minutes–hours
#7 webshell/implant
→Δt = minutes
#2.2 algif_aead primitive
→Δt < 1s
[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.

Path B — Container escape via 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.

Path C — Phishing / malware → kernel privesc
#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.

Path D — Supply-chain → build host privesc
#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/passwd rewrite 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_ALG for unprivileged workloads via seccomp profiles or --security-opt on 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/passwd divergence that the exploit produces but does not flush.
  • auditd rules on UID changes, setuid binary modifications, and unexpected use of AF_ALG from 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 TLCTC lesson

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

CVE focus#2.2 Exploiting Server — Linux kernel algif_aead in-place scatterlist logic flaw
SRELoss of Control — kernel writes attacker-controlled bytes outside intended buffer
DRELoss of Integrity — page cache of arbitrary readable file (canonical: /etc/passwd)
VelocityVC-4 at the kernel step (Δt < 1s); end-to-end privesc < 1 min
Path A#2 → #7 → #2.2 + [DRE: C, I, A — host]
Path B[any code-exec into container] → #2.2 + [DRE: C, I, A — host and siblings]
Path C#9 → #7 → #2.2 + [DRE: C, I, A — host]
Path D#10 → #7 → #2.2 + [DRE: C, I, A — build host + onward blast radius]
ATT&CK refT1068 (Exploitation for Privilege Escalation) — conflates cause and effect; TLCTC keeps them separate
Sibling caseCVE-2022-0847 (Dirty Pipe) — different subsystem, same #2.2 classification
About the methodology

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