HTTP Public Key Pinning (HPKP) middleware
The `hpkp` package provides HTTP Public Key Pinning (HPKP) middleware for Express and Connect applications. It facilitates adding the `Public-Key-Pins` or `Public-Key-Pins-Report-Only` headers to web responses, which allows sites to declare cryptographic identities for web servers. However, HPKP as a security standard has been widely deprecated by browser vendors, including Chrome, due to significant risks of misuse and the potential for self-inflicted denial-of-service by rendering a website permanently inaccessible to legitimate users. The package is currently at version 3.0.0 and is explicitly in maintenance mode, indicating it will not receive new feature development but will be maintained for critical bug fixes. Developers are strongly advised against implementing HPKP in new projects and should consider alternatives like Certificate Transparency and Expect-CT headers.
Common errors
-
NET::ERR_SSL_PINNING_FAILURE
cause The public key pins declared in the `Public-Key-Pins` HTTP header do not match the public key of the server's certificate presented during a TLS handshake.fixDuring testing, verify `sha256s` values. If in production, and users are locked out, you must either deploy a certificate matching one of the original pinned keys, or if no backup key is available, wait for `maxAge` to expire (which could be months). Using `reportOnly: true` initially can help avoid this. -
My HPKP header isn't being set on my Express/Connect application.
cause The `hpkp` middleware might be placed incorrectly in the middleware chain, or the `setIf` option is preventing it from being applied under current request conditions (e.g., not an HTTPS request).fixEnsure the `hpkp` middleware is applied before any routes that should be protected. Check your `setIf` function's logic to confirm it evaluates to `true` for the requests you intend to pin. Verify that `maxAge` is a positive integer.
Warnings
- deprecated The HTTP Public Key Pinning (HPKP) standard itself has been widely deprecated by browser vendors, including Chrome, due to its inherent risks and potential for website self-DDoS.
- breaking Misconfiguration of HPKP, particularly incorrect `sha256s` or loss of access to pinned keys, can permanently block legitimate users from accessing your website, as their browsers will refuse connections.
- gotcha The `hpkp` package is in maintenance mode and will not receive new feature development. This means it may not adapt to future security best practices or changes in related web standards.
- gotcha The `sha256s` array must contain Base64-encoded Subject Public Key Information (SPKI) fingerprints. Using incorrect hash formats or non-SPKI hashes will lead to pinning failures.
- gotcha Browser support for HPKP is inconsistent and has been largely removed. Modern browsers like Chrome have dropped support, rendering the header ineffective for many users.
Install
-
npm install hpkp -
yarn add hpkp -
pnpm add hpkp
Imports
- hpkp
import { hpkp } from 'hpkp'import hpkp from 'hpkp'
- hpkp
const hpkp = require('hpkp') - HpkpOptions
import { HpkpOptions } from 'hpkp'import type { HpkpOptions } from 'hpkp'
Quickstart
const express = require("express");
const hpkp = require("hpkp");
const app = express();
const ninetyDaysInSeconds = 7776000; // 90 days
app.use(
hpkp({
maxAge: ninetyDaysInSeconds,
sha256s: [
// These should be your actual SPKI hashes for primary and backup keys
"AbCdEf123=",
"ZyXwVu456="
],
includeSubDomains: true, // optional
reportUri: "https://example.com/hpkp-report", // optional
reportOnly: false, // optional, set to true for testing
// Set the header based on a condition. This is optional.
setIf(req, res) {
return req.secure; // Only set HPKP for HTTPS requests
},
}),
);
app.get('/', (req, res) => {
res.send('HPKP header should be set if using HTTPS');
});
app.listen(3000, () => {
console.log('Server running on port 3000');
console.log('Remember HPKP is deprecated and risky. Use with extreme caution.');
});