13 min read
High
By

OpenSSL security release: CVE-2026-45447 — how an empty ASN.1 set makes PKCS7_verify() free a buffer it does not own

12 June 2026. On 9 June the OpenSSL project shipped a batch security release — one High flaw and several Moderate findings across PKCS#7, CMS, QUIC and OCSP. The most serious, CVE-2026-45447, makes PKCS7_verify() wrongly free a caller-owned buffer as soon as a signed message carries an empty digestAlgorithms field — a use-after-free that, depending on the application, ranges from a crash to remote code execution. Fixed in OpenSSL 4.0.1, 3.6.3, 3.5.7, 3.4.6, 3.0.21 as well as 1.1.1zh and 1.0.2zq.

TL;DR — 90 seconds

Affected?

OpenSSL 4.0.0, 3.6.0–3.6.2, 3.5.0–3.5.6, 3.4.0–3.4.5, 3.0.0–3.0.20 as well as 1.1.1 before 1.1.1zh and 1.0.2 before 1.0.2zq — practically every current line. Actually exposed to the High finding is anyone who processes attacker-controlled PKCS#7/S-MIME signatures through the OpenSSL PKCS7 API (PKCS7_verify(), PHP: openssl_pkcs7_verify()). The CMS API is not affected by 45447.

Risk?

CVE-2026-45447: use-after-free → crash, heap corruption, in some contexts potentially RCE. Plus Moderate findings: CMS integrity/key oracle (34182), QUIC memory DoS (34183), OCSP-stapling double-free (35188).

Immediate action?

Raise OpenSSL to the patched line (4.0.1 / 3.6.3 / 3.5.7 / 3.4.6 / 3.0.21 or 1.1.1zh / 1.0.2zq), re-pull container base images, restart TLS-terminating services and PHP-FPM/workers.

Recommendation?

The German Mittelstand and enterprises alike: roll it in as a floor update within the running patch cycle; prioritise it if a service verifies signed email/documents via PKCS#7 or a QUIC/HTTP-3 endpoint is publicly reachable.

Criticality?

high (references the hero badge — RCE potential for 45447, but precondition-bound; no known mass exploitation).

 

What is the problem?

The 9 June batch release closes several independent flaws. We treat it as one piece because OpenSSL is not a single interchangeable library but the crypto floor under almost everything that speaks TLS in the German Mittelstand: PHP (ext/openssl), Node.js, nginx and Apache, PostgreSQL, Redis, curl and most container base images. An OpenSSL update is therefore rarely a point patch; it is a floor that moves under several services at once.

The most serious finding, CVE-2026-45447 (High), sits in PKCS7_verify(). When processing a PKCS#7 or S-MIME signed message, OpenSSL inspects the SignedData object. If its digestAlgorithms field is present as an empty ASN.1 SET, OpenSSL wrongly frees a caller-owned BIO during verification. The calling application then still holds a reference to exactly that buffer — this typically bites when it later calls BIO_free() on the BIO originally passed to PKCS7_verify(). From there it is a classic use-after-free: depending on allocator behaviour and the application’s BIO usage, the outcome ranges from a crash through heap corruption to — in some contexts — attacker-controlled code execution. Important for context: applications that solve the same task through the CMS API are not affected by 45447; the flaw hangs on the older PKCS7 path.

Three Moderate findings belong in the same view. CVE-2026-34182 lets CMS AuthEnvelopedData containers pass with forged parameters: an on-path attacker can rewrite a genuine AES-GCM message so the recipient decrypts it under an unauthenticated keystream mode (AES-256-OFB) and never checks the MAC — from which a key oracle or an integrity bypass can be built. CVE-2026-34183 is a QUIC memory hog: a malicious peer floods the local QUIC stack with PATH_CHALLENGE frames; a PATH_RESPONSE is allocated for each and only freed on an acknowledgement that never comes — unbounded growth, denial of service. CVE-2026-35188 is a double-free in the client when checking an OCSP-stapled response (only relevant if OCSP stapling is active on the client side — not a default). Plus low-severity findings in ASN.1 handling (34180, 7383) and a PKCS#12 PBMAC1 weakness (34181).

Who is affected?

StatusCondition
OpenSSL 4.0.0AffectedFix in 4.0.1
OpenSSL 3.6.0–3.6.2AffectedFix in 3.6.3
OpenSSL 3.5.0–3.5.6AffectedFix in 3.5.7
OpenSSL 3.4.0–3.4.5AffectedFix in 3.4.6
OpenSSL 3.0.0–3.0.20Affected (45447, 34180)Fix in 3.0.21
OpenSSL 1.1.1 < 1.1.1zh / 1.0.2 < 1.0.2zqAffected (45447, 34180)extended support only — fix 1.1.1zh / 1.0.2zq
OpenSSL FIPS modules (4.0/3.6/3.5/3.4/3.0)Not affectedaffected code lies outside the FIPS module boundary

The version exposure is near-universal — almost every running OpenSSL install. The risk exposure is narrower per flaw: 45447 only bites those who verify PKCS#7/S-MIME signatures from an attackable source through the legacy PKCS7 API (signed inbound mail, AS2/EDI, signed document uploads, licence/token validation). 34183 bites anyone running a publicly reachable QUIC/HTTP-3 endpoint. 34182 needs an on-path position and CMS decryption with a success/failure signal. 35188 needs client-side OCSP stapling to be active. Mitigating throughout: using the CMS API instead of PKCS7, not exposing QUIC, and updating OpenSSL centrally through pinned base images anyway.

Impact

OpenSSL rates CVE-2026-45447 as High. The mechanism is a use-after-free on a caller-owned BIO: at scale, the reliably reachable effect is a crash (denial of service), in unfavourable constellations heap corruption, and “in some application contexts this may potentially be exploitable for remote code execution” (OpenSSL advisory). Reliable code execution through a UAF is technically demanding and strongly environment-dependent — the honest read is: serious pressure to act where attacker-controlled PKCS#7/S-MIME data runs through PKCS7_verify(), otherwise a regular but prompt floor update.

The Moderate findings do not push the picture into the dramatic, but are relevant depending on setup: 34182 is a genuine crypto integrity flaw (a Bleichenbacher-style oracle / integrity bypass on the CMS path) and so matters to anyone processing CMS-encrypted messages; 34183 is an unauthenticated, network-based QUIC DoS that hits HTTP/3 edges and load balancers whose QUIC layer increasingly uses OpenSSL. In architectural terms: the most dangerous flaw hangs on an old API that many houses never migrated to CMS — the patch closes the specific spot, the migration closes the class.

Mitigation / immediate steps

Now: raise OpenSSL to the patched line

 

# Check the installed version per host
openssl version -a          # target per line: 4.0.1 / 3.6.3 / 3.5.7 / 3.4.6 / 3.0.21

# Debian/Ubuntu
apt update && apt install --only-upgrade openssl libssl3 libssl3t64
# RHEL/Alma/Rocky
dnf update openssl openssl-libs
# Alpine / Wolfi (container base)
apk upgrade --no-cache openssl libcrypto3 libssl3

# Restart services linked against OpenSSL (the library is loaded at start)
systemctl restart nginx php-fpm postgresql redis-server

 

Containers: rebuild base images, do not patch in place

 

# Check the image inventory for the OpenSSL version
docker run --rm <image> openssl version 2>/dev/null || \
docker run --rm <image> sh -c 'apk info openssl 2>/dev/null || dpkg -l | grep -i libssl'

# Re-pull the patched base image and rebuild the app image
docker pull <base-image>:<patched-tag>
docker build --no-cache -t <app-image>:<new-tag> .
# Force the rollout by digest (not by a mutable tag)

 

If an update is not immediately possible (stopgaps, no substitute for the patch)

 

# 45447: do not route attacker-controlled PKCS#7/S-MIME data through PKCS7_verify();
#        where possible switch to the CMS API (CMS_verify).
# 34183: expose QUIC/HTTP-3 only where needed; otherwise disable the QUIC listener
#        or run it behind a QUIC-capable edge with rate limiting / address validation.
# 35188: verify OCSP-stapled responses client-side only against trusted servers.

 

Important: the OpenSSL library is loaded at process start. An apt upgrade without a subsequent restart of the linked services leaves the old, unpatched code running in memory — the most common mistake with OpenSSL updates.

Detection / verification

Establish the inventory: who links which OpenSSL version?

 

# Running processes that have loaded libcrypto/libssl (not just package state)
for pid in $(pgrep -d' ' -f '.'); do
  maps=/proc/$pid/maps
  [ -r "$maps" ] && grep -qE 'libssl|libcrypto' "$maps" 2>/dev/null && \
    printf '%s\t%s\n' "$pid" "$(grep -oE 'libcrypto[^ ]*' "$maps" | head -1)"
done | sort -u

# Container fleet
docker ps --format '{{.Names}}' | while read c; do
  printf '%s: ' "$c"; docker exec "$c" openssl version 2>/dev/null || echo "n/a"
done

 

PHP applications: does the code use the vulnerable PKCS7 API?

 

# Search for legacy PKCS7 calls on attackable input
grep -rnE 'openssl_pkcs7_(verify|read)|PKCS7_verify' \
  --include='*.php' --include='*.c' --include='*.go' path/to/app

# Cross-check: CMS API (not affected by 45447)
grep -rnE 'openssl_cms_(verify|read)|CMS_verify' --include='*.php' path/to/app

 

Acceptance check after the patch

 

# Confirm the version per service after restart
openssl version            # expected: patched line
# QUIC endpoint: observe memory behaviour under PATH_CHALLENGE load (test environment only)
# PKCS7 path: regression test with a message whose digestAlgorithms is empty —
#             no UAF on patched OpenSSL (verify with an ASAN build).

Operator recommendation

Operational decision block:

Mittelstand

Re-pull base images and rebuild containers, then restart TLS-terminating services and PHP-FPM. Then settle the one question this flaw really poses: does any code in the house verify signed email or documents through the old PKCS7 API? If so, the durable hardening is the move to the CMS API, not just the patch.

Enterprise / multi-stage fleets

Verify the patch level across the fleet by inventory (SBOM / image digest) rather than by spot check, because OpenSSL sits in countless transitive image layers. Additionally secure QUIC edges with address validation and rate limiting against 34183.

Kubernetes / declarative stacks

Roll out patched base images through the registry, pin the image digest, force the rollout across all replicas. Add an admission policy that rejects images with OpenSSL below the patched line. Remember: a rolling restart is needed so pods load the new library.

What we did concretely

We checked the advisory against our estate on release day. Because our containers are centrally pinned by digest and rebuilt nightly from hardened base images, the version question was answered in minutes rather than by host spot check — exactly the value a maintained image inventory pays out on a day like this. The patched base images are in, the TLS-terminating services and PHP workers were restarted on a rolling basis so the new libcrypto actually sits in memory and not just on disk.

More operationally relevant than the patch itself was the second question: does a PKCS#7/S-MIME verification on foreign input run anywhere in our house through the old API? We searched the code for it (openssl_pkcs7_verify, PKCS7_verify) and reconciled the few hits against the CMS variant. The lesson learned is an architectural statement, not a single measure: the most dangerous of the ten flaws hangs not on “OpenSSL is old” but on “we call a deprecated API on foreign data”. The patch closes CVE-2026-45447; the migration from PKCS7 to CMS closes the whole class of follow-on errors on that path. We also treat the OpenSSL floor deliberately as an inventory question: not “is OpenSSL patched?” but “which running processes still have the old libcrypto in their address space?”

Frequently asked questions about the OpenSSL release and CVE-2026-45447

Am I affected by CVE-2026-45447 if I “only” do TLS with OpenSSL and do not process S/MIME mail?+

For the High finding itself, probably not — it needs a PKCS#7/S-MIME verification through the legacy PKCS7 API on attackable input. Patch anyway: the release also contains a QUIC DoS (CVE-2026-34183), a CMS integrity flaw (CVE-2026-34182) and an OCSP double-free (CVE-2026-35188), and OpenSSL is your TLS floor under several services.

Is apt upgrade openssl enough, or do I have to restart services?+

The update alone is not enough. libcrypto/libssl are loaded at process start — nginx, Apache, PHP-FPM, PostgreSQL and the like otherwise keep running with the old library in memory. After the upgrade, restart the linked services (or restart pods on a rolling basis).

Does the CMS API protect me from CVE-2026-45447?+

For 45447, yes — the flaw sits on the PKCS7 path, and the CMS API (CMS_verify / PHP openssl_cms_verify) is not affected. But note CVE-2026-34182: that is a separate CMS AuthEnvelopedData flaw, against which only the patch helps. So a CMS migration does not replace the update.

Which OpenSSL version do I need to close all flaws from the 9 June release?+

4.0.1, 3.6.3, 3.5.7, 3.4.6 or 3.0.21 — depending on the line you run. On the extended-support lines 1.1.1zh and 1.0.2zq (relevant only for 45447 and 34180, since QUIC/CMS AuthEnvelopedData do not exist there).

Are my FIPS-validated OpenSSL modules affected?+

No. The affected code (PKCS7, CMS, QUIC, OCSP, ASN.1 decoder) lies outside the FIPS module boundary. You still have to update the application library — the FIPS statement only concerns the validated crypto core, not the rest of the library.

Does this also affect Node.js, since Node bundles OpenSSL?+

Node bundles its own OpenSSL variant; what matters is the version baked into your Node release. The regular route here is the Node security release (for June 2026 announced for the 17th), not a system apt update. Until then the same risk question applies: do you process PKCS#7/S-MIME signatures or expose QUIC?

Conclusion

The 9 June OpenSSL release is not a fire alarm, but it is a mandatory appointment. The version exposure is near-universal, yet the most dangerous finding (CVE-2026-45447, use-after-free with RCE potential) is bound to a concrete precondition: processing attacker-controlled PKCS#7/S-MIME signatures through the legacy API. Whoever has that acts within the 48-hour window; whoever runs OpenSSL “only” as a TLS floor rolls the update in within the running cycle — and does not forget the restart of the linked services. The durable lesson sits one level below the patch: the most serious flaw hangs on a deprecated API that many never migrated. Patching closes the spot, migrating to CMS closes the class.

Sources

Before the next crypto floor moves — let us talk about inventory instead of spot checks.

We inventory, patch and validate your OpenSSL floor against the 9 June release — and check where the legacy PKCS7 API still runs on foreign data.

We take the version inventory across running processes and image digests (not just package states), pull in the patched base images, restart the linked services on a rolling basis and validate the state. We then locate the PKCS#7/S-MIME paths in the code and plan, where it makes sense, the migration to the CMS API.

Platform operations instead of advice-on-paper: we check, mitigate and validate production stacks — from the OpenSSL inventory through the service restart to the API migration.

Book an appointment directly

About the author

[Translate to English:] Foto von Kai Ole Hartwig.

Kai Ole Hartwig

Founder · Moselwal Digitalagentur · OnlyOle

Programming since 2002 – self-taught, set up my own business with KO-Web in 2012, now Moselwal. Over 100 projects, with a focus on security, performance, automation and quality.