Cloudanix VulnDB

CVE-2026-54904

High · 7.5

CVSS

7.5

EPSS

0.7%

Published

Jun 24, 2026

CISA due date

—

Cloudanix analysis

Next patch cycle SSVC: Track

A flaw in a common Ruby concurrency library can let malformed numeric input make affected applications hang or consume excessive CPU until they become unavailable.

Exploitation
Remote Unauthenticated
Attacker needs
None
Complexity
Moderate
Impact
Denial Of Service
Component
Library
Class
Denial of service
Remediation
Upgrade
Effort
Medium
Patch risk
Low

What it actually does

concurrent-ruby versions prior to 1.3.7 can enter an infinite busy retry loop in Concurrent::AtomicReference#update when the stored value is Float::NAN. The update method repeatedly evaluates the caller-provided block until compare_and_set succeeds, but Ruby NaN equality semantics make Float::NAN == Float::NAN false, so the expected value check never matches and the atomic update never completes. In affected applications, this can pin CPU, hang request handlers or background jobs, and exhaust worker capacity when externally influenced numeric input can become NaN and is stored in an AtomicReference.

Why it matters to the business

Applications that depend on affected concurrent-ruby versions may become slow or unavailable if a crafted or malformed numeric value causes workers to spin indefinitely. The practical consequence is denial of service: elevated CPU usage, stuck jobs, exhausted web/application worker pools, missed processing deadlines, and possible cascading degradation in Ruby services. Although this is not listed in CISA KEV and the current EPSS score is low, the flaw is low-complexity where an application accepts or derives NaN values from external input, so internet-facing or high-throughput services using concurrent-ruby should still prioritize remediation.

How an attack unfolds

An attacker first identifies an application path where externally supplied numeric data is parsed or transformed into a Ruby Float and may become Float::NAN, such as permissive parsing of the string "NaN", non-finite numeric values from data feeds, or calculations that produce NaN. If that value is stored in a Concurrent::AtomicReference, the attacker then triggers functionality that calls AtomicReference#update on that reference. In vulnerable concurrent-ruby versions, the update operation repeatedly calls the update block and retries compare_and_set forever because NaN is not equal to itself under Ruby semantics. Repeated requests or jobs can cause many threads to enter the same busy loop, consuming CPU and preventing normal request or job completion. No authentication is required by the library-level flaw itself, but real-world exploitability depends on whether the host application exposes a reachable path for untrusted input to become NaN inside an AtomicReference.

How to fix it

Upgrade concurrent-ruby to version 1.3.7 or later wherever it is used, including direct and transitive Ruby gem dependencies. Regenerate and redeploy lockfiles such as Gemfile.lock so production artifacts actually resolve to the fixed version. If immediate upgrade is not possible, reduce exposure by rejecting or normalizing non-finite numeric values before they can reach Concurrent::AtomicReference, including NaN, Infinity, and -Infinity; add application-level validation around numeric parsing; and avoid calling AtomicReference#update on references that may contain Float::NAN. Operational mitigations such as request rate limiting, worker timeouts, job execution time limits, and CPU-based autoscaling can reduce blast radius but do not fix the underlying bug.

How to confirm the fix worked

Confirm the deployed dependency version with software composition analysis, gem inventory, or lockfile review and verify concurrent-ruby resolves to 1.3.7 or later in every built artifact. In Ruby projects, review Gemfile.lock or equivalent package manifests for the concurrent-ruby gem version, then confirm the runtime image or deployment package contains the same fixed version. As a controlled functional check in a non-production environment, attempt an AtomicReference update where the current value is Float::NAN and verify the operation returns rather than hanging. Also test application input validation to ensure externally supplied or calculated NaN values are rejected, normalized, or safely handled before reaching shared atomic state. Monitor after deployment for reduced CPU spikes, fewer long-running Ruby threads, and disappearance of request or job hangs associated with non-finite numeric values.

Typical attack path

  1. Find a Ruby application or service that uses concurrent-ruby before version 1.3.7.
  2. Identify an externally reachable input path that accepts numeric values or data that can be parsed or calculated into Float::NAN.
  3. Submit crafted input such as a non-finite numeric value where the application accepts it and stores or propagates it into a Concurrent::AtomicReference.
  4. Trigger application logic that calls Concurrent::AtomicReference#update on the reference containing Float::NAN.
  5. Repeat the request or workload to create multiple permanently spinning update calls, increasing CPU consumption and tying up worker threads.
  6. Sustain the traffic until the service becomes degraded or unavailable due to CPU exhaustion, request timeouts, or stuck background jobs.

How to detect it

There are no universal network indicators for this library-level denial-of-service issue because exploitation depends on application-specific input paths and logging. To assess possible prior exploitation, review application logs, API gateway logs, job processor logs, APM traces, and host/container metrics for time-correlated patterns of requests or jobs containing non-finite numeric values such as NaN followed by sustained CPU spikes, request timeouts, thread starvation, or stuck background jobs. Inspect Ruby thread dumps, profiler output, or crash diagnostics captured during incidents for threads repeatedly executing concurrent-ruby AtomicReference update logic. Look for high CPU utilization with low request throughput, worker processes that do not complete jobs, repeated client retries against numeric-processing endpoints, and error logs showing parsing or propagation of NaN values shortly before service degradation. Because the current public exploit maturity is reported as none and the EPSS score is low, absence of these behavioral signs reduces but does not eliminate concern.

  • Concurrent::AtomicReference#update
  • Concurrent::AtomicReference
  • Float::NAN
  • NaN
  • concurrent-ruby

What your security team should do

  • Inventory Ruby applications, containers, and build artifacts for concurrent-ruby versions earlier than 1.3.7.
  • Prioritize upgrades for internet-facing services, APIs processing user-supplied numeric data, data ingestion pipelines, and high-volume background job systems.
  • Upgrade concurrent-ruby to 1.3.7 or later and redeploy affected applications with refreshed lockfiles and images.
  • Add validation to reject or normalize NaN and other non-finite numeric values at trust boundaries, especially before storing them in shared state or concurrency primitives.
  • Set or verify request, job, and worker execution time limits so a single hung operation cannot permanently consume capacity.
  • Review recent incidents of unexplained CPU saturation, Ruby worker hangs, request timeouts, or job queue backlogs for possible abuse.
  • Create monitoring alerts for sustained high CPU with low throughput, increased timeout rates, and unusually long-running Ruby threads after numeric input handling paths are exercised.

The record

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.

Affected packages

Ecosystem Package Introduced Fixed

Related vulnerabilities