RubySec

Providing security resources for the Ruby community

CVE-2026-54904 (concurrent-ruby): Concurrent Ruby - `AtomicReference#update` livelocks when the stored value is `Float::NAN`

Concurrent Ruby - `AtomicReference#update` livelocks when the stored value is `Float::NAN`

Published: June 19, 2026

SECURITY IDENTIFIERS

GEM

concurrent-ruby

PATCHED VERSIONS

>= 1.3.7

DESCRIPTION

Summary

Concurrent::AtomicReference#update can enter a permanent busy retry loop when the current value is Float::NAN.

The issue is caused by the interaction between:

  • AtomicReference#update, which retries until compare_and_set(old_value, new_value) succeeds.
  • Numeric compare_and_set, which checks old == old_value before attempting the underlying atomic swap.
  • Ruby NaN semantics, where Float::NAN == Float::NAN is always false.

As a result, once an AtomicReference contains Float::NAN, calling #update repeatedly evaluates the caller's block and never returns. In services that store externally derived numeric values in an AtomicReference, this can cause CPU exhaustion or permanent request/job hangs.

Impact

This is an application-level denial of service issue. If an application stores externally derived numeric data in a Concurrent::AtomicReference, an attacker or faulty upstream data source may be able to cause the stored value to become Float::NAN. Any later call to AtomicReference#update on that reference will spin indefinitely, repeatedly executing the update block and consuming CPU.

Credit

Pranjali Thakur - depthfirst (depthfirst.com)

RELATED