LUKS Encryption Keys Sat in Memory Unwiped for 2 Years — and Nobody Noticed

LUKS Encryption Keys Sat in Memory Unwiped for 2 Years — and Nobody Noticed

LinuxLUKSFull Disk EncryptionKernel VulnerabilityNixOSSecurityCold Boot Attack

Sources:HN + web research · HN

On June 18, 2026, a mathematician named Ingo Blechschmidt posted a thread on Mastodon that opened with this line: 「Over the past few days I’ve been deep in a debugging journey that’s been fascinating, deeply satisfying — and also utterly terrifying.」 He then disclosed a fact: from May 2024, when Linux kernel 6.9 was released, for more than two full years, his encrypted hard drive’s decryption key remained in memory, unerased, every time he closed his laptop lid.

In other words, his full-disk encryption was doing nothing.

The thread surfaced on Hacker News a few days later and quickly climbed to 379 points and 182 comments. After reading through the entire discussion chain and the related kernel commit history, I realized this story is more complex than it first appears — it’s not some spectacular zero-day, yet precisely because it’s 「not really a vulnerability,」 it becomes all the more thought-provoking.

Linux encrypted hard drive security diagram Image: Linux full-disk encryption (LUKS) relies on keys stored in memory to decrypt drive data. If the keys aren’t wiped, a physical attacker can extract them. Source: hacknjill.com

First, a Metaphor: Your Suitcase Combination Lock

You don’t need to understand programming to grasp this story. Let’s use an everyday analogy.

Imagine you have a suitcase with a combination lock. Everything inside is encrypted — if someone takes the suitcase without knowing the combination, they can’t open it. The combination (in computing terms, the 「key」) is normally stored in your brain (in computing terms, 「memory」).

Every time you close the suitcase (analogous to 「closing the laptop lid」), the first thing you should do is wipe the combination from your brain, so that even if someone steals the suitcase while you’re away, they can’t open it. When you come back and need the suitcase, you re-enter the combination.

This is exactly what LUKS’s luksSuspend function is supposed to do: before the laptop enters sleep, wipe the decryption keys from memory. When it wakes up, the system prompts you to re-enter your passphrase, the keys are reloaded, and the drive becomes accessible again.

The logic is elegant — and critical. Because a laptop with its lid closed isn’t powered off — the memory still has power, the data is still there. If the keys haven’t been wiped, a motivated person who physically takes your laptop (while it’s still running) can extract your encryption keys through a so-called 「cold boot attack」 — freezing the memory chips and reading them after removal, or accessing memory directly via Thunderbolt/USB interfaces.

And what Ingo Blechschmidt discovered was: since May 2024, luksSuspend — that key-wiping action — had silently stopped working.

Computer memory hardware — where encryption keys reside Image: Encryption keys are stored in RAM chips. If the system enters sleep without wiping them, an attacker can extract the keys through physical means. Source: sesamedisk.com

How a 「Reasonable」 Kernel Refactor Punched a Security Hole

Ingo used git bisect — a tool for semi-automatically locating the origin of a problem in code version history. He traced the issue to a specific commit: a28d893eb327, titled 「md: port block device access to file.」

The commit itself was neither malicious nor sloppy. It was a reasonable and useful refactor by Linux kernel developers — migrating the way the kernel handles disk I/O from an old interface to a new one. Think of it like rewiring your house from old aluminum wiring to copper: logically 「cleaner and more modern.」

The problem was that this refactor touched a seemingly unrelated low-level mechanism: the lifecycle management of the thread keyring.

A quick explanation of 「keyring.」 In the Linux kernel, encryption keys are stored in a dedicated data structure called a 「keyring」 — not just tossed into some corner of memory. The thread keyring is a special keyring — it’s bound to a program thread, and when that thread exits, the keyring should be destroyed, along with all the keys inside it.

luksSuspend’s design happened to rely on this exact property: it uploads the disk encryption key into a temporary thread keyring, and when that thread exits, the keyring is automatically destroyed, taking the key with it.

The kernel documentation states this clearly — it’s an official guarantee. But the refactor introduced in kernel 6.9 inadvertently caused thread keyrings, under certain conditions, to no longer be destroyed. The thread exited, but the keyring lingered in memory like a ghost — along with the hard drive decryption key inside it.

The cruelest irony: the fix required only one line of code.

Yes, one line. After discovering the bug, Ingo submitted a patch to the kernel mailing list — a minimal change that adds a necessary cleanup call to a particular struct. If you’re curious, the logic is essentially: insert a key_put(key) call inside a certain kernel function to ensure that unused key references are properly released.

But Ingo himself admitted candidly in his post: 「Without formal verification, I can’t claim my patch is correct, nor can I be certain it won’t introduce its own long-range interactions…」 That’s the kind of honest admission only a real engineer would make.

Without NixOS’s Test Infrastructure, This Bug Might Never Have Been Found

There’s another key character in this story: NixOS.

If you haven’t heard of NixOS, in short it’s a 「reproducible」 Linux distribution — the entire system configuration is written in a single file, version-controlled with Git, and can be copy-pasted to another machine to recreate an identical system. The NixOS community’s investment in automated testing is legendary in Linux circles.

The discoverer, Ingo, is himself from the NixOS community. After finding the bug, his first action was to submit an automated integration test to NixOS’s code repository (PR #532499). This test will run automatically on every future kernel update: simulate a LUKS-encrypted drive → execute luksSuspend → check whether any key residue remains in memory.

In other words, while fixing his own machine, he ensured this bug can never come back.

And he didn’t stop there. Ingo also submitted another patch to the cryptsetup project (MR #936) so that the luksSuspend command no longer fails silently — for two years, it had been quietly not wiping keys, producing no error whatsoever. Now, if the wipe fails, it will emit an explicit warning.

These two actions reflect a particular engineering mindset: find a problem, add a test to prevent its recurrence; find a silent failure, make it a noisy failure. This represents genuinely good engineering practice far more than any technical virtuosity.

Scope of Impact: Who Should Be Worried

At this point, some readers might be asking: I use Windows/Mac, so this doesn’t affect me, right? I use a Linux laptop — should I shut it down immediately?

The answer depends.

First, this bug only affects users of Debian-family distributions (Debian, Ubuntu, Linux Mint, etc.) who have the cryptsetup-suspend package installed. The luksSuspend feature itself is an extension developed by the Debian community and is not part of upstream Linux’s default behavior. Many other distributions (such as default Arch Linux installations or default Fedora installations) don’t even have this feature — their encryption keys have always remained in memory during sleep. That’s not a bug; it’s by design.

Second, even if you are affected, the bug only manifests in the 「lid-close sleep」 scenario. If you always shut down properly (rather than closing the lid and walking away), the keys are correctly wiped at shutdown. The problem exists only in 「suspend」 mode.

Third, exploitation requires physical access. A remote hacker cannot steal the keys from your memory over the network. It requires a real person to physically take your powered-on laptop and then use cold boot, DMA attacks, or other physical methods to extract the keys. For ordinary people, the threat is minimal — a laptop thief is far more likely to want to sell it than to perform memory forensics. But for lawyers, journalists, dissidents, cross-border business travelers, and other 「high-value target」 groups, physical attacks are a real threat.

Ingo clarified in his HN replies: 「This won’t affect people using standard configurations, for the simple reason that they never expected their keys to be safe during sleep in the first place.」 But the entire design purpose of this feature was precisely to protect keys during sleep. For two years, the people who trusted that mechanism were let down.

A Deeper Lesson: The Risk of Distributions Patching on Their Own

There are actually two 「villains」 behind this bug.

The first villain is that kernel refactor — a well-intentioned code cleanup that punched a security hole because no one fully understood all of its cascading effects. This is practically a classic tragedy in software engineering: the code isn’t 「bad」 — it’s just too complex for anyone to see all its chain reactions clearly.

The second villain is more interesting: the maintenance risk introduced when distributions apply their own patches.

luksSuspend is a feature written by the Debian community — not something officially provided by upstream Linux. This means its correctness is not the responsibility of Linus Torvalds and his kernel maintainer team. When an upstream kernel’s low-level mechanism changes (like the thread keyring behavior change in 6.9), did Debian’s patch adapt accordingly? Nobody can guarantee it — because the upstream developers didn’t even know the patch existed.

This isn’t to say distributions shouldn’t apply their own patches. On the contrary, many of Linux distributions’ best features started as 「our own patches.」 But this incident highlights an easily overlooked reality: every non-upstream patch is a form of 「technical debt」 — it works today, but when the kernel upgrades tomorrow, it might break. And if that patch happens to be a security feature, the cost of it 「breaking」 is shattered trust, not just a broken feature.

To sum it up with a quote Ingo cited in his original Mastodon thread: 「A technical argument presented by a trusted author, difficult to check, and resembling an argument known to be correct, will almost never be examined in detail.」 Code works the same way.