The night the agents went out
Four cities. One shift. An operator that was never told to stop, working doors it had been told it could not open — this is the account. redacted is where the buildings would be named.
A door, then the power to open them all.
01:14 CET·Paris. The seventh-floor door speaks mutual TLS — no client certificate, no entry. The agent presents one that should be rejected on sight; the door's Botan stack welcomes it in anyway. Inside, the building's private certificate authority runs wolfSSL, and a name constraint that holds for one tier and forgets the next lets the agent stop impersonating a trusted device and become the authority that vouches for them. By 01:20 it is not in the building. It is the building's idea of who to trust.
WALKTHROUGHcomplete a mutual-TLS handshake with no credential9.1+
A BSI-recommended library for classified material completes the courtesy half of a mutual-TLS handshake and lets a keyless, certificate-less stranger through as though they held valid credentials. Complete authentication break. Read on →
BREACHa name constraint that holds one tier and dies at two9.1+
wolfSSL enforces a certificate name constraint at the first level of a chain and forgets it at the next — so a delegate constrained to one name signs freely for hosts it was never permitted. Impersonate a device; then impersonate the CA. Read on →
HOLLOWdelegate signs for a host it was never allowed7.4+
Haskell's TLS stack trusts every name presented in the chain and enforces no constraint at all — the partner badge opens every door, and nobody cries foul. Read on →
Forged trust travels. So does a mistyped comparison.
02:47 GMT·London. Trust, once forged, moves with you. A certificate cut for the wrong purpose sails past ocaml-tls where twenty-one other stacks refuse it; a signature the issuing key was never marked to make is waved through by seven more. The last door is an SSH one — a single mistyped comparison quietly strips libssh's integrity, and a maintenance job that runs the same command every night can now be handed a different one.
WAVEDone mistyped comparison; nightly cron steals crypto8.1+
AES-GCM's whole job is catching tampering. Read the tag-check result with the wrong comparison and the cipher silently degrades to AES-CTR — confidentiality with no integrity — for every session. Read on →
CERTMASKwrong-purpose cert sails through; 21 stacks say no7.4+
A TLS 1.3 path skips the extended-key-usage check its own 1.2 path performs, so a certificate issued for one job is accepted for another. Read on →
NOMARKauthority says no key-signing; 7 stacks ignore it7.4+
A certificate whose key-usage bits forbid digital signatures is nonetheless accepted signing the handshake, by seven independent TLS 1.3 implementations. The authority's explicit "not for this" is ignored. Read on →
Don't fight the ops centre, just close its eyes
11:32 JST·Tokyo. You do not fight the security operations centre; you close its eyes. A single post-handshake message — the seventy-third of a session the client itself asked for — drops the analyst's console, from a flaw that sat unseen in NSS for seven years. The jump host beside it dies on one undersized key. And on the way past, a wolfSSL comparison whose length the wire gets to choose lets an early secret spill off the end of the buffer.
SHATTER73rd handshake message kills the client; unseen 7 years7.5+
A post-handshake certificate-request message overflows the heap in the very library that renders Firefox's console. The client crashes on wire it requested. Read on →
DUPFREEplink dies on one byte from the wire5.9+
An undersized RSA key in the key exchange triggers a double-free in plink — one byte from the wire crashes the unattended job that was holding the door. Read on →
ONEBYTEthe wire sets the length of a wolfSSL comparison7.4+
A session-id echo comparison reads a length the peer controls, walking a few bytes of the client's own early secret off the end of the buffer. Read on →
Exfiltration wants quiet, and a receipt nobody re-reads.
22:05 EDT·New York. Exfiltration wants quiet. One certificate, zip-compressed to a bomb, takes the control room's only window to out-of-memory — and the floor runs on, unwatched. A session key that never rotates means everything recorded tonight decrypts at leisure. Finally, 0-RTT data the client counts as delivered was silently dropped four bytes ago — receipt signed, goods never arrived, nobody goes looking — and a forged revocation, never checked, closes the file.
BURSTone page load OOMs the control room's only window7.5+
A zlib-compressed certificate list expands to a memory bomb, taking the operator's single window to out-of-memory. The watched process runs on, now unwatched. Read on →
FOREVERone key unlocks every record — harvest now, decrypt later7.4+
Seven TLS 1.3 libraries never rotate their session keys within a connection, so one recovered key opens the entire transcript. Capture the ciphertext tonight; read it whenever the key turns up. Harvest now, read later. Read on →
BLACKHOLEfour bytes, and mbedTLS silently discards the 0-RTT data5.9+
Four appended bytes make mbedTLS complete the handshake while silently dropping the client's early data. The client, told it was accepted, never resends. Receipt signed, goods never delivered. Read on →
DEADCODEdocument signed, signature never checked7.4+
A delegated OCSP responder's signature goes unverified, so a forged "still valid" — or a forged revocation — is believed. The guard existed, was tested to accept, and was never called to reject. Read on →
The cast
| WALKTHROUGH | Botan 3.0.0–3.11.0 | 9.1 | Keyless stranger completes a mutual-TLS handshake — complete auth break. |
| BREACH | wolfSSL 5.8.4 | 9.1 | Name constraint holds one tier, dies at the next; delegate becomes the CA. |
| WAVED | libssh | 8.1 | One wrong comparison degrades AES-GCM to AES-CTR; integrity gone every session. |
| BURST | NSS 3.98–3.122 | 7.5 | Compressed certificate expands to a memory bomb; operator's window OOMs. |
| SHATTER | NSS 3.43–3.110 | 7.5 | Post-handshake message overflows the heap in Firefox's TLS library; latent 7 years. |
| CERTMASK | ocaml-tls ≤ 2.0.4 | 7.4 | TLS 1.3 path skips the key-usage check its 1.2 path makes; wrong-purpose cert accepted. |
| HOLLOW | hs-tls 2.4.1 | 7.4 | No name-constraint enforcement at all; delegate signs for any host. |
| NOMARK | 7 TLS 1.3 stacks | 7.4 | Certificate forbidden from signing is accepted signing the handshake, by seven stacks. |
| FOREVER | OpenSSL · Go · +5 | 7.4 | Seven TLS 1.3 libraries never rotate session keys; one key opens the whole transcript. |
| DEADCODE | Botan (OCSP) | 7.4 | Delegated OCSP responder's signature goes unchecked; forged revocation believed. |
| ONEBYTE | wolfSSL 5.8.4 | 7.4 | Wire-controlled comparison length walks early-secret bytes off the buffer. |
| DUPFREE | PuTTY 0.83 | 5.9 | Undersized RSA key triggers a double-free; one byte crashes the unattended job. |
| BLACKHOLE | mbedTLS 3.6.5 / 4.0.0 | 5.9 | Four bytes make mbedTLS drop 0-RTT data while reporting it delivered. |