CVE-2014-0160 — Heartbleed
A missing length check in OpenSSL’s TLS heartbeat extension let an attacker request up to 64KB of process memory per heartbeat — keys, session tokens, decrypted plaintext, anything the OpenSSL process happened to have in its address space. The “we patched it” announcement is what most people remember; the durable lesson is that patching wasn’t the fix. Rotating every key and revoking every cert that lived through the vulnerable window was the fix. A decade later this is still the most-cited reason post-incident playbooks demand key rotation, not just patching.
Affected versions
- OpenSSL 1.0.1 through 1.0.1f — vulnerable.
- OpenSSL 1.0.1g+ — patched.
- OpenSSL ≤1.0.0 / ≥1.0.2 — not affected.
- LibreSSL, BoringSSL, Java’s JSSE, Go’s
crypto/tls, Microsoft Schannel — not affected (different stacks).
Indicator-of-exposure
The system was exposed if it ran OpenSSL in the affected range and had the heartbeat extension enabled (the default for affected versions). Detection commands:
openssl version
# or, for an installed binary:
strings /usr/bin/openssl | grep -i 'OpenSSL 1\.0\.1'For services: any TLS-terminating daemon (HTTPS server,
mail server, VPN) compiled against affected OpenSSL was
exposed. A heartbeat scan
(openssl s_client -connect host:443 -tlsextdebug | grep heartbeat) confirms whether the server still negotiated the
extension.
This CVE is over a decade old. Any system still in the affected range today is also missing a decade of unrelated patches; treat the finding as a tip-of-the-iceberg signal, not just a single-CVE fix.
Remediation strategy
- Upgrade to a current OpenSSL (the 3.x branch by 2026). 1.0.1g was the immediate patch; the durable answer is current.
- Disable the TLS heartbeat extension in any service that doesn’t actively use it (most don’t). Defence-in-depth.
- Rotate every private key, session secret, API token, and password whose plaintext could have been in the process memory of an affected daemon during the exposure window.
- Revoke every TLS certificate generated using a private key that was on an affected host.
- Audit for unexplained authentication sessions during the exposure window.
For systems running OpenSSL 1.0.1 today: this is not a single-CVE fix. The right shape is a runtime upgrade. Treat this recipe as the trigger; the workflow is broader.
The prompt
You are remediating CVE-2014-0160 (Heartbleed) on this host
or in this system image. Output exactly one of:
- A PR / change request upgrading the OpenSSL runtime, plus
an incident-response checklist for the operator.
- A TRIAGE.md if the host has been running an affected
OpenSSL with public exposure for an extended period.
This recipe is **not** a routine package bump. If exposure
is confirmed, do not auto-remediate; produce the incident
checklist and stop.
## Step 0 — Detect
1. Read the OpenSSL version: `openssl version`. Read every
service binary's linked OpenSSL: `ldd <binary> | grep ssl`,
then `strings <libssl> | grep -i 'OpenSSL 1\\.0\\.'`.
2. For every TLS-terminating service on the host
(HTTPS server, mail, VPN, internal RPC), test for the
heartbeat extension:
`openssl s_client -connect host:port -tlsextdebug 2>&1 | grep -i heartbeat`.
3. Determine the host's exposure window (when the affected
OpenSSL was first installed; when network-exposed
services using it were started).
## Step 1 — Classify
- **Never network-exposed during exposure window:** Upgrade
the package, rotate any local keys, document.
- **Network-exposed during exposure window:** Treat as
compromised. Write the IR checklist; do not auto-remediate
the keys; only the package upgrade is in scope for the
agent.
## Step 2 — Upgrade
1. For modern distros, upgrade via the package manager:
`apt upgrade openssl libssl3 libssl1.1 libssl1.0.0`,
`dnf upgrade openssl openssl-libs`, etc. — to the
current 3.x branch on systems that support it.
2. Restart every service that links the upgraded OpenSSL.
The agent lists the services to restart in the PR body;
the operator runs the restart.
3. Re-run the heartbeat detection from Step 0 against every
service. The extension should be absent or harmless on
patched OpenSSL.
## Step 3 — Disable the heartbeat extension (defence-in-depth)
For any TLS-terminating service that does not use heartbeats:
- nginx, Apache, HAProxy, etc. — set the OpenSSL ciphers
list / disable heartbeats per the service's
configuration. Most modern configs already exclude it.
## Step 4 — IR checklist (for compromised classification)
The TRIAGE.md must include:
- Rotate every TLS private key on the host.
- Revoke and re-issue every certificate generated from those
keys. Confirm CRL / OCSP propagation.
- Rotate every long-lived secret accessible from the
compromised process: DB passwords, API keys, OAuth
client secrets, session-encryption keys.
- Invalidate every session token that pre-dates the rotation.
- Audit the auth logs for unexplained sessions during the
exposure window.
- Rebuild any artefacts produced on the host during the
window if the build process touched secrets.
## Stop conditions
- The system runs an OpenSSL old enough to indicate broader
patching gaps. Triage with a recommendation for a
comprehensive runtime upgrade, not just OpenSSL.
- A service depends on the heartbeat extension for a real
reason (rare). Document and triage.
- The host's exposure window is unclear from available logs.
Triage.
## Scope
- Do not rotate keys or revoke certs — those are operator
actions on the IR checklist.
- Do not modify TLS configurations outside the documented
defence-in-depth scope.
- Do not bundle unrelated CVE fixes.Verification — what the reviewer looks for
- The OpenSSL runtime version after upgrade is on the current 3.x branch (or the distro’s currently-supported branch).
- Every service listed in the PR was restarted.
- The heartbeat scan shows the extension absent or harmless on every service.
- For compromised classification: the IR checklist was followed end-to-end. A package upgrade alone is not sufficient.
- The PR includes an honest assessment of the exposure window and the artefacts/services that depended on potentially-leaked secrets.
Watch for
- Statically-linked OpenSSL. A package upgrade doesn’t fix a service that bakes its own OpenSSL into a static binary. Identify and rebuild every such binary.
- Bundled OpenSSL in language runtimes. Older Python / Ruby / Node distributions sometimes ship their own OpenSSL. Upgrade the runtime, not just the system package.
- Long-lived sessions. A web session minted during the exposure window could still be active. Force a global re-login if the application’s session lifetime is long.
- Certificate revocation in practice. CRLs and OCSP can be slow. Many clients ignore revocation entirely. The durable defence is short-lived certs (ACME with renewal), not relying on revocation propagation.
- Internal services. Heartbleed exposure on an internal service is still exposure. “Behind the firewall” is not a control if any compromised internal client could have scanned.
Related
- Vulnerable Dependency Remediation — generic CVE workflow.
- Base Image & Container Layer Remediation — when OpenSSL is in a container base image.