There was a stretch, roughly 2015 to 2018, when you could add a single HTTP response header to your website and, if you got it slightly wrong, lock every returning visitor out of your own domain for up to a year. Not a typo that 404s a page. A header that tells browsers to refuse your site — the real one, with a valid certificate — and keep refusing it until a timer you already set runs out.
That header was HPKP, HTTP Public Key Pinning, and it’s the clearest example I know of a security feature that was more dangerous than the thing it was protecting against.
What it was trying to fix
The problem HPKP attacked is real and nasty. Your browser trusts around 150 certificate authorities, and any one of them can issue a certificate for any domain. That’s the structural weakness of the whole CA system: it only takes one compromised or careless CA to mint a valid-looking certificate for your bank. It has happened. In 2011 the Dutch CA DigiNotar was breached and issued fraudulent certificates for Google and others, used to intercept traffic in Iran. The certificates were, from the browser’s point of view, perfectly valid.
Pinning was the answer. Instead of trusting any of 150 CAs, you tell the browser: for my domain, only accept this specific public key (or one of a small set). RFC 7469, published in 2015, let you ship that instruction in a header:
Public-Key-Pins: pin-sha256="base64=="; pin-sha256="backup==";
max-age=5184000; includeSubDomains
The browser sees it on first visit, remembers the pinned keys for max-age seconds, and from then on rejects any certificate for your domain whose key isn’t in the set — even if a trusted CA signed it. A fraudulent cert from a compromised CA doesn’t match your pin, so the attack fails. On paper it closes the hole completely.
The footgun nobody could hold safely
Read that mechanism again and the problem jumps out. The browser remembers the pin, and it refuses certificates that don’t match, and it does both for as long as you told it to. There’s no override click-through — if there were, the feature would be pointless, because an attacker would just tell users to click through. So what happens when the key you pinned is gone?
You brick your site. This got a name: HPKP suicide. You rotate your key and forget the pin. Your server is compromised and the key is stolen, so you have to rotate. Your backup pin was for a key you also lost. Any of these, and every browser that ever saw your header now rejects your new, valid, correctly-issued certificate — because it doesn’t match the old pin — and keeps rejecting it until max-age expires. You can’t fix it by buying a new certificate. You can’t fix it by talking to your CA. You wait out the timer, watching returning visitors get an error page you can’t turn off. The RFC tried to defend against this by requiring at least one backup pin for a key not in your current chain, but a backup pin you’ve lost, or never generated properly, protects nothing.
Then researchers noticed the mirror image, which was worse. Call it RansomPKP. An attacker who briefly gets control of your server — a short breach, a hijacked subdomain — doesn’t need to steal anything durable. They just turn HPKP on, pinning keys they control, with a long max-age. Now even after you kick them out and restore everything, every visitor who loaded a page during the breach has your domain pinned to the attacker’s keys. Your legitimate certificate fails their pin. You’re locked out of your own site by a header you never set, and the attacker offers to sell you the keys. Scott Helme, who tracked HPKP adoption for years, ended up arguing the feature should be killed precisely because the ways to hurt yourself so badly outnumbered the ways to use it safely.
Almost nobody used it, and that told the story
Here’s the number that settled the argument. At its peak, HPKP was deployed on roughly 3,500 sites in the top million — about a third of a percent. And it was falling, down toward 650, as the people who’d tried it quietly took it back off after a scare or a near-miss. When a security feature has been available for years and the people most equipped to use it — the ones running the top thousand sites on the internet — overwhelmingly refuse to, that’s not apathy. That’s a collective risk assessment. The blast radius of a mistake was a bricked domain, and the payoff was defense against an attack that, by then, had a better answer.
Because while HPKP was failing, Certificate Transparency was working. CT takes a different angle on the same threat: instead of every site individually pinning keys and praying they never lose them, every certificate a CA issues has to be logged to public, append-only, monitored logs. A CA that mis-issues a certificate for your domain can’t do it in the dark anymore — the certificate shows up in the logs, and you (or a monitor watching on your behalf) see it. It catches the DigiNotar scenario without asking any website to arm a device that can blow off its own foot.
How it actually ended
Chrome’s security team made the call. Chris Palmer’s “Intent to Deprecate and Remove: Public Key Pinning” laid it out bluntly: low adoption, high risk of hostile pinning and accidental self-DoS, and a better tool already in place. Chrome deprecated HPKP in version 67 in mid-2018 and ripped it out entirely by version 72. Firefox followed and dropped its support too. The header still parses in some places out of inertia, but no current browser will pin from it. It’s dead.
For a while the official replacement was another header, Expect-CT, which let sites demand that certificates be CT-logged and report violations. Then came the tidy final irony: Expect-CT itself got deprecated a few years later — not because it failed, but because Certificate Transparency enforcement became the browser default. You don’t need a header to ask for the thing you now get automatically. The whole apparatus of site-configured certificate policy that HPKP started collapsed into “the browser just does this for you, and you can’t turn it into a weapon aimed at yourself.”
Pinning didn’t vanish, to be clear. Browsers still ship static pins for a handful of high-value domains — Google’s own properties, mostly — baked into the binary and curated by people who are not going to accidentally lose the keys to google.com. That’s the tell about what actually went wrong. Pinning as a concept was fine. Pinning as a self-service header, handed to every website operator with a footgun pointed inward and no undo button, was the mistake. The safe version of the feature is the one where you don’t get to configure it.
The lesson generalizes past TLS. A security control whose worst-case failure is worse than the attack it prevents — and whose failure mode is silent, delayed, and irreversible — isn’t a strong control with rough edges. It’s a liability wearing a security control’s clothes. HPKP was a good idea that could not survive contact with the people who’d have to operate it. The kindest thing the browser vendors ever did for it was take it away.