OpenSSL 4.0 is current: find the copies your services actually load
OpenSSL 4.0 shipped in April 2026 and 4.1 in October. A probe that finds the OpenSSL builds linked into running services, not the one on PATH.
By the Maborak engineering team · · 4 min read
The openssl command reports one build. A host usually runs several: the distribution copy, a vendored copy inside a container, a statically linked binary, and whatever a language runtime carries. Replacing the copy on PATH does not replace the library a running service has mapped.
Checked 29 October 2026. Timeline and versions from the project’s release and advisory timeline. The support status of each branch is on the same site; confirm it for the branch you run before planning.
Background
OpenSSL 3.6.0 landed on 1 October 2025. 4.0.0 followed on 14 April 2026, a major version rather than a point release. Security releases on 29 September 2026 shipped 3.6.5 and 4.0.3 together with 3.5.9 and 3.4.8; 4.1.0 arrived on 23 October 2026. The project still fixes several branches at once, which is why “the latest OpenSSL” is the wrong question. The right one is which branch a given binary loads and whether that branch is still receiving fixes.
Mechanics
libcrypto and libssl are shared objects with an ABI version. A binary records a dependency such as libssl.so.3; the dynamic loader resolves it through the library path. Three things break the assumption that one upgrade covers the host:
- Vendored copies. A container image, a Python wheel and a database package can each ship their own
libsslunder a private path. - Static links. A statically linked binary carries its own copy and ignores the system library entirely.
- Different TLS stacks. A Go service, or a Rust service using
rustls, does not call OpenSSL at all. Checkingopenssl versiontells you nothing about it.
The major version also changes the source interface. The OpenSSL migration guide documents removed and changed APIs in 4.0; a rebuild can fail at compile time even when the target ABI is present.
Impact
A host can report 4.0 on the command line while a long-running daemon still maps 3.0. Security fixes shipped on 29 September 2026 reach the branches listed in the timeline, so a service on an unfixed branch stays exposed regardless of the CLI. In containers, the running image digest is the fact that matters, not the tag.
Probe
This runs on Linux and needs no privileges for the first half. It prints the CLI build, every shared object on the filesystem, and the libraries mapped by running processes.
#!/bin/sh
# 1. The build on PATH.
openssl version -a | sed -n '1p'
# 2. Every libcrypto/libssl on the root filesystem.
find / -xdev \( -name 'libcrypto.so*' -o -name 'libssl.so*' \) 2>/dev/null | sort
# 3. Libraries mapped by running processes (needs read access to /proc).
for p in /proc/[0-9]*/maps; do
if grep -qE 'lib(crypto|ssl)\.so' "$p" 2>/dev/null; then
pid=${p#/proc/}; pid=${pid%/maps}
printf '\npid %s %s\n' "$pid" "$(tr -d '\0' < "/proc/$pid/comm")"
awk '/lib(crypto|ssl)\.so/{print $6}' "$p" | sort -u
fi
done
On macOS the third step becomes lsof -p <pid> | grep -E 'lib(crypto|ssl)', and the second uses find /usr /opt /Applications. On a container host, run step three inside each container, not on the host.
The output proves which libraries exist and which processes map them. It does not prove whether a service is affected by a specific CVE; that requires the advisory and the configuration.
Mitigation
Order: patch the distribution and rebuild containers, then handle statically linked binaries, then plan source changes.
- Rebuild containers from an updated base image. A
docker pullof a pinned digest does not change the digest. - For binaries that link the system library, follow the distribution’s backport. Distributions keep the ABI version and backport the fix, so the library name changes less often than the upstream version.
- For 4.0, read the migration guide and rebuild. Treat it as a source-compatibility project, not a library swap.
Verification
Confirm the binary resolves the library you think it does:
ldd "$(command -v openssl)" | grep -E 'lib(crypto|ssl)'
readlink -f /proc/"$(pgrep -n sshd)"/root 2>/dev/null || true
strings /usr/lib/x86_64-linux-gnu/libcrypto.so.3 | grep -m1 '^OpenSSL '
The last line prints the version string embedded in the shared object. Compare it with openssl version -a; when they differ, a second copy is in play.
On the machine used for this check, openssl version -a reports OpenSSL 4.1.0, built 23 October 2026. That is one binary. It says nothing about the libraries mapped by other processes, which is why step three exists. [reproduced]
Sources
- OpenSSL release and advisory timeline (checked 29 October 2026).
- OpenSSL migration guide.
- OpenSSL release strategy.