RubySec

Providing security resources for the Ruby community

GHSA-w39f-xq2m-4g8x (dalli): Forking can resend buffered memcached requests and desynchronize the parent's connection

Forking can resend buffered memcached requests and desynchronize the parent's connection

Published: October 05, 2026

SECURITY IDENTIFIERS

GEM

dalli

PATCHED VERSIONS

~> 3.2.13 ~> 4.3.7 ~> 5.0.9 ~> 5.1.3 >= 5.2.1

DESCRIPTION

Dalli buffered request bytes in Ruby's IO write buffer, and quiet (multi) blocks don't flush until they end. When the process forks, the child inherits the buffer, and Ruby flushes it when the child closes or finalizes the socket, even if the child never uses Dalli, so the request is sent twice: a buffered write is applied twice, or a buffered non-quiet request leaves the parent's connection off by one reply, so later reads return the previous key's value. Affects 4.2.0 and later.

With TLS, the child's close sends close_notify on the shared connection and tears down the parent's session. Affects all versions with TLS.

Applications that fork while threads use a shared client are affected (pre-forking servers, job runners).

The first fix was incomplete on 4.3.6 and 3.2.12: when another library's fork hook (such as connection_pool's, loaded before Dalli) ran first in the child, the parent's TLS session could still be ended, and 4.3.6's write buffer kept a reference to the caller's value string with the meta protocol. Both are fixed in 4.3.7 and 3.2.13.

Workarounds

Call close on Dalli clients before forking, outside any quiet block.

RELATED