ManageIQ / ManageIQ/dbus_api_service

CVE-2026-54904 (High) detected in concurrent-ruby-1.3.1.gem

Open Beginner friendly
#93 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Mend: dependency security vulnerability
Dominant language
Ruby
Stars
1
Forks
12
PR merge metrics
No merged PRs in 30d

Description

CVE-2026-54904 - High Severity Vulnerability

Vulnerable Library - concurrent-ruby-1.3.1.gem

Modern concurrency tools including agents, futures, promises, thread pools, actors, supervisors, and more. Inspired by Erlang, Clojure, Go, JavaScript, actors, and classic concurrency patterns.

Library home page: https://rubygems.org/gems/concurrent-ruby-1.3.1.gem

Path to dependency file: /Gemfile.lock

Path to vulnerable library: /home/wss-scanner/.gem/ruby/3.2.0/cache/concurrent-ruby-1.3.1.gem

Dependency Hierarchy:

  • manageiq-style-1.5.1.gem (Root Library)
    • rubocop-rails-2.25.0.gem
      • activesupport-7.1.3.4.gem
        • concurrent-ruby-1.3.1.gem (Vulnerable Library)

Found in base branch: master

Vulnerability Details

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))

Publish Date: 2026-06-19

URL: CVE-2026-54904

CVSS 3 Score Details (7.5)

Base Score Metrics:

  • Exploitability Metrics:
    • Attack Vector: Network
    • Attack Complexity: Low
    • Privileges Required: None
    • User Interaction: None
    • Scope: Unchanged
  • Impact Metrics:
    • Confidentiality Impact: None
    • Integrity Impact: None
    • Availability Impact: High

For more information on CVSS3 Scores, click here.

Suggested Fix

Type: Upgrade version

Origin: https://github.com/advisories/GHSA-h8w8-99g7-qmvj

Release Date: 2026-06-19

Fix Resolution: concurrent-ruby - 1.3.7


Step up your Open Source Security Game with Mend here

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with /Gemfile.lock and inspect the dependency chain through rubocop-rails and activesupport to concurrent-ruby 1.3.1. Update the resolved concurrent-ruby version to 1.3.7, then run the repository's available bundle checks or tests. Done means the lockfile no longer contains the vulnerable version and the project still passes its checks.

Written by the indexing model from the issue text.

Assessment

Tech stack
ruby
Domain
security
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.