It's like finding a flaw in the ejection seat of a car that was never fitted with one
CVE-2025-9230 is an out-of-bounds read and write in OpenSSL's RFC 3211 KEK (Key Encryption Key) unwrap routine, triggered when an application decrypts CMS (Cryptographic Message Syntax) messages protected by password-based encryption (PWRI). The OOB write can corrupt heap memory, theoretically reaching code execution; the OOB read can crash the process for a denial-of-service. It affects every active OpenSSL branch: 1.0.2 before 1.0.2zm, 1.1.1 before 1.1.1zd, 3.0 before 3.0.18, 3.2 before 3.2.6, 3.3 before 3.3.5, 3.4 before 3.4.3, and 3.5 before 3.5.4. FIPS provider modules are not affected because CMS sits outside the FIPS boundary.
Tenable's plugin flags this as High (7.5) using the cve.org CVSS:3.1 vector AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H, but that vector only captures the availability impact and assumes unauthenticated network access — which is technically true yet wildly misleading. The OpenSSL project itself rated the flaw Moderate, and Red Hat scored it with AC:H (high attack complexity) at a much lower base. The decisive reality: CMS password-based encryption (RFC 3211 PWRI) is an obscure feature almost nobody uses. The vast majority of OpenSSL deployments — TLS termination, HTTPS, VPN tunnels — never invoke this code path. Tenable's own VPR (Vulnerability Priority Rating) agrees, placing it at 5.0 / Medium in the 94th percentile, well below the base CVSS. This is a textbook case where the CVSS vector's AC:L misrepresents the real-world attack surface.
4 steps from start to impact.
Identify a CMS PWRI consumer
CMS_decrypt() or equivalent on CMS enveloped-data using password-based recipient info (PWRI). This is the critical gate — the entire chain fails without it. Typical OpenSSL consumers (nginx, Apache, HAProxy, curl, stunnel) do not process CMS PWRI messages.- Target application must use OpenSSL CMS PWRI decryption
- Target must accept externally-supplied CMS messages
- CMS password-based encryption is extremely rare in production — S/MIME with PWRI is a niche use case
- Most OpenSSL consumers use TLS only, never touching the CMS API
- Identifying a PWRI consumer from the outside is nearly impossible without source code review
Craft a malicious CMS message
- Knowledge of the RFC 3211 KEK unwrap internals
- Ability to deliver the crafted CMS blob to the target application
- Weaponizing the OOB write for RCE requires heap grooming specific to the target's allocator and binary layout — not a generic exploit
- PoCs available largely demonstrate the DoS/crash, not reliable code execution
Deliver the crafted message to the target
CMS_decrypt(). The delivery mechanism is entirely application-specific.- Network or local access to the application's CMS input channel
- The application must not reject the malformed structure before reaching the vulnerable code
- Email gateways typically strip or quarantine malformed S/MIME
- Custom applications may validate CMS structure before decryption
- Firewalls and WAFs do not inspect CMS payloads, but the delivery path itself may be restricted
Trigger OOB read/write → crash or RCE
- Successful delivery of the crafted CMS message
- No ASLR/stack canary bypass needed for DoS; full bypass needed for RCE
- Modern OS hardening (ASLR, stack canaries, NX) makes heap-based RCE significantly harder
- OpenSSL is typically compiled with hardening flags on modern distros
- The crash itself may be caught by a supervisor process (systemd restart, container orchestrator)
The supporting signals.
| In-the-Wild Exploitation | No evidence. Not observed by GreyNoise, no CISA alerts, no vendor incident reports. No active campaigns documented as of 2026-09-17. |
|---|---|
| CISA KEV Status | Not listed in the Known Exploited Vulnerabilities catalog. |
| Proof-of-Concept | 14 GitHub repositories tagged with CVE-2025-9230 PoCs. Most demonstrate the crash/DoS path only. No public RCE exploit confirmed. |
| EPSS | Not yet scored in FIRST EPSS feed at time of assessment. Given the niche attack surface, expect a low percentile once scored. |
| CVSS Vectors | cve.org: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H → 7.5. Red Hat: CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L → 5.6. OpenSSL project: Moderate. Tenable VPR: 5.0 (Medium, 94th percentile). |
| Affected Versions | OpenSSL 1.1.1 < 1.1.1zd, 1.0.2 < 1.0.2zm, 3.0 < 3.0.18, 3.2 < 3.2.6, 3.3 < 3.3.5, 3.4 < 3.4.3, 3.5 < 3.5.4 |
| Fixed Versions | 1.1.1zd, 1.0.2zm, 3.0.18, 3.2.6, 3.3.5, 3.4.3, 3.5.4 — note 1.1.1 and 1.0.2 are premium support only (EOL for public). |
| Scanning / Exposure | OpenSSL is ubiquitous (~70% of internet-facing TLS endpoints), but the vulnerable CMS PWRI code path is exercised by a negligible fraction. Shodan/Censys can identify OpenSSL versions but cannot determine CMS PWRI usage. |
| Disclosure Date | 2025-09-30 (OpenSSL security advisory) |
| Reporter | Not publicly credited in the OpenSSL advisory. Multiple vendor bulletins (IBM, Siemens, SUSE, Red Hat, Debian) issued downstream advisories. |
noisgate verdict.
The single most decisive factor driving this downgrade is the extremely narrow affected code path: CMS password-based encryption (RFC 3211 PWRI) is used by a negligible fraction of OpenSSL deployments, meaning the vast majority of hosts flagged by version-detection scanners are not actually exploitable. The OpenSSL project's own Moderate rating and Tenable's VPR of 5.0 both confirm the real-world risk is far below the CVSS 7.5 base score.
Why this verdict
- Niche code path: The vulnerability is in CMS PWRI decryption, a feature almost no production application exercises. TLS, the dominant OpenSSL use case, is entirely unaffected. This alone invalidates the
AC:Lin the CVSS vector for real-world scoring. - No active exploitation or KEV listing: Zero in-the-wild exploitation evidence, no CISA KEV entry, no GreyNoise scanning activity. The 14 GitHub PoCs demonstrate crashes, not weaponized RCE.
- Vendor consensus on Moderate: OpenSSL project rates it Moderate. Red Hat scored it 5.6 with
AC:H. Tenable's own VPR is 5.0. Three independent severity assessments agree this is not High in practice. - Role multiplier: OpenSSL is a canonical high-value component present on network edge appliances, identity providers, hypervisors, and CI/CD systems. However, the vulnerable code path (CMS PWRI) is not invoked by any of these high-value roles in their standard configurations — none of them process password-based CMS messages. The blast radius is limited to the rare application that explicitly uses
CMS_decrypt()with PWRI recipients, which represents well under 1% of the OpenSSL installed base. The high-value role floor does not apply because the chain does not succeed in those roles. - RCE is theoretical, DoS is the realistic ceiling: Public PoCs achieve crashes only. Heap-based RCE against hardened binaries with ASLR requires target-specific exploitation not demonstrated publicly.
Why not higher?
Promoting to HIGH would require either active exploitation, a realistic RCE chain, or a code path that impacts a significant share of deployments. None of these conditions are met. The CMS PWRI feature is so niche that even OpenSSL's own team rated this Moderate, and no attacker has demonstrated interest in weaponizing it. The 7.5 CVSS reflects a theoretical network-accessible DoS that almost no real application exposes.
Why not lower?
Dropping to LOW or IGNORE would undercount the theoretical RCE potential of the OOB write and the fact that OpenSSL 1.1.1 is past public EOL — any host still running it has a broader hygiene problem. The 14 public PoCs lower the bar for a motivated attacker to at least achieve process crashes against the rare vulnerable consumer. Additionally, downstream embedded or IoT devices may use CMS in ways not visible to enterprise scanning.
What to do — in priority order.
- Audit for CMS PWRI usage in your codebase — Search your source code and third-party dependencies for calls to
CMS_decrypt(),CMS_RecipientInfo_kekri_*, or RFC 3211 references. If none are found, this CVE has zero exploitable surface in your environment. Complete this audit within the noisgate remediation SLA of 365 days. - Prioritize OpenSSL 1.1.1 migration to 3.x — OpenSSL 1.1.1 reached public EOL on 2023-09-11. Hosts still running it are accumulating CVEs without free patches. 1.1.1zd requires a premium support contract. Plan migration to OpenSSL 3.3+ as part of your 365-day remediation window.
- Restrict CMS message ingestion at application boundaries — If you do have CMS-processing applications, validate CMS structure and reject messages with PWRI recipient info types before passing to OpenSSL decryption. This can be done at the application layer.
- Enable process restart supervision — Ensure services using OpenSSL are supervised by systemd, Kubernetes liveness probes, or equivalent. This limits DoS impact to a brief restart window rather than a sustained outage.
- WAF rules — CMS messages are not HTTP-layer constructs; WAFs cannot inspect or block malicious CMS blobs inside application payloads.
- TLS version pinning / cipher suite hardening — This vulnerability is in the CMS API, not in TLS handshake or record processing. Hardening your TLS config has zero effect.
- FIPS mode — While the FIPS provider module is not affected, enabling FIPS mode on OpenSSL 1.1.1 does not disable the vulnerable CMS code path (CMS is outside the FIPS boundary but still callable).
Crowdsourced verification payload.
Run this script on each target host as any user with read access to the OpenSSL binary. Example: bash check_cve_2025_9230.sh /usr/bin/openssl. No root required.
#!/usr/bin/env bash
# check_cve_2025_9230.sh — Detect CVE-2025-9230 (OpenSSL CMS PWRI OOB)
# Usage: bash check_cve_2025_9230.sh [/path/to/openssl]
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
set -euo pipefail
OPENSSL_BIN="${1:-openssl}"
if ! command -v "$OPENSSL_BIN" &>/dev/null; then
echo "UNKNOWN — '$OPENSSL_BIN' not found in PATH"
exit 2
fi
VERSION_STRING=$($OPENSSL_BIN version 2>&1) || { echo "UNKNOWN — could not execute openssl version"; exit 2; }
echo "Detected: $VERSION_STRING"
# Extract version number
VER=$(echo "$VERSION_STRING" | grep -oP 'OpenSSL \K[0-9]+\.[0-9]+\.[0-9]+[a-z]*')
if [[ -z "$VER" ]]; then
echo "UNKNOWN — could not parse version from: $VERSION_STRING"
exit 2
fi
# Parse major.minor.patch and letter suffix
MAJOR=$(echo "$VER" | cut -d. -f1)
MINOR=$(echo "$VER" | cut -d. -f2)
PATCH_RAW=$(echo "$VER" | cut -d. -f3)
PATCH_NUM=$(echo "$PATCH_RAW" | grep -oP '^[0-9]+')
SUFFIX=$(echo "$PATCH_RAW" | grep -oP '[a-z]+$' || true)
# Function to compare letter suffixes (zd = fixed for 1.1.1)
letter_ge() {
# Returns 0 if $1 >= $2 lexicographically
[[ "$(printf '%s\n%s' "$2" "$1" | sort | head -1)" == "$2" ]]
}
if [[ "$MAJOR" -eq 1 && "$MINOR" -eq 1 && "$PATCH_NUM" -eq 1 ]]; then
# OpenSSL 1.1.1 branch — fixed in 1.1.1zd
if [[ -z "$SUFFIX" ]]; then
echo "VULNERABLE — OpenSSL 1.1.1 (no patch letter) is affected"
exit 1
elif letter_ge "$SUFFIX" "zd"; then
echo "PATCHED — OpenSSL 1.1.1$SUFFIX >= 1.1.1zd"
exit 0
else
echo "VULNERABLE — OpenSSL 1.1.1$SUFFIX < 1.1.1zd"
exit 1
fi
elif [[ "$MAJOR" -eq 1 && "$MINOR" -eq 0 && "$PATCH_NUM" -eq 2 ]]; then
echo "VULNERABLE — OpenSSL 1.0.2 branch detected; fixed in 1.0.2zm (premium support). Upgrade to 3.x recommended."
exit 1
elif [[ "$MAJOR" -eq 3 ]]; then
# 3.0.x fixed in 3.0.18, 3.2.x in 3.2.6, 3.3.x in 3.3.5, 3.4.x in 3.4.3, 3.5.x in 3.5.4
case "$MINOR" in
0) FIXED=18 ;;
2) FIXED=6 ;;
3) FIXED=5 ;;
4) FIXED=3 ;;
5) FIXED=4 ;;
*) echo "UNKNOWN — OpenSSL 3.$MINOR not in known affected range"; exit 2 ;;
esac
if [[ "$PATCH_NUM" -ge "$FIXED" ]]; then
echo "PATCHED — OpenSSL $VER >= 3.$MINOR.$FIXED"
exit 0
else
echo "VULNERABLE — OpenSSL $VER < 3.$MINOR.$FIXED"
exit 1
fi
else
echo "UNKNOWN — OpenSSL $VER not in a known affected branch"
exit 2
fiIf you remember one thing.
Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.