Vulnerable Library - jekyll-github-metadata-2.15.0.gem
Path to dependency file: /Gemfile.lock
Path to vulnerable library: /home/wss-scanner/.gem/ruby/2.7.0/cache/faraday-2.5.2.gem
Vulnerabilities
| Vulnerability |
Severity |
CVSS |
Dependency |
Type |
Fixed in (jekyll-github-metadata version) |
Remediation Possible** |
| CVE-2026-54904 |
High |
7.5 |
concurrent-ruby-1.1.10.gem |
Transitive |
N/A* |
❌ |
| CVE-2026-54297 |
High |
7.5 |
faraday-2.5.2.gem |
Transitive |
N/A* |
❌ |
| CVE-2026-35611 |
High |
7.5 |
addressable-2.8.1.gem |
Transitive |
N/A* |
❌ |
| CVE-2024-49761 |
High |
7.5 |
rexml-3.2.5.gem |
Transitive |
N/A* |
❌ |
| CVE-2024-43398 |
Medium |
5.9 |
rexml-3.2.5.gem |
Transitive |
N/A* |
❌ |
| CVE-2026-25765 |
Medium |
5.8 |
faraday-2.5.2.gem |
Transitive |
N/A* |
❌ |
| CVE-2026-54905 |
Medium |
5.3 |
concurrent-ruby-1.1.10.gem |
Transitive |
N/A* |
❌ |
| CVE-2024-41946 |
Medium |
5.3 |
rexml-3.2.5.gem |
Transitive |
N/A* |
❌ |
| CVE-2024-41123 |
Medium |
5.3 |
rexml-3.2.5.gem |
Transitive |
N/A* |
❌ |
| CVE-2024-35176 |
Medium |
5.3 |
rexml-3.2.5.gem |
Transitive |
N/A* |
❌ |
| CVE-2024-39908 |
Medium |
4.3 |
rexml-3.2.5.gem |
Transitive |
N/A* |
❌ |
| CVE-2026-54906 |
Medium |
4.0 |
concurrent-ruby-1.1.10.gem |
Transitive |
N/A* |
❌ |
| CVE-2026-33637 |
Low |
0.0 |
faraday-2.5.2.gem |
Transitive |
N/A* |
❌ |
*For some transitive vulnerabilities, there is no version of direct dependency with a fix. Check the "Details" section below to see if there is a version of transitive dependency where vulnerability is fixed.
**In some cases, Remediation PR cannot be created automatically for a vulnerability despite the availability of remediation
Details
CVE-2026-54904
Vulnerable Library - concurrent-ruby-1.1.10.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.1.10.gem
Path to dependency file: /Gemfile.lock
Path to vulnerable library: /home/wss-scanner/.gem/ruby/2.7.0/cache/concurrent-ruby-1.1.10.gem
Dependency Hierarchy:
- jekyll-github-metadata-2.15.0.gem (Root Library)
- jekyll-4.2.2.gem
- i18n-1.12.0.gem
- ❌ concurrent-ruby-1.1.10.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: 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
CVE-2026-54297
Vulnerable Library - faraday-2.5.2.gem
Library home page: https://rubygems.org/gems/faraday-2.5.2.gem
Path to dependency file: /Gemfile.lock
Path to vulnerable library: /home/wss-scanner/.gem/ruby/2.7.0/cache/faraday-2.5.2.gem
Dependency Hierarchy:
- jekyll-github-metadata-2.15.0.gem (Root Library)
- octokit-4.25.1.gem
- ❌ faraday-2.5.2.gem (Vulnerable Library)
Found in base branch: master
Vulnerability Details
Uncontrolled Recursion in NestedParamsEncoder Allows Stack Exhaustion DoS via Deeply Nested Query Parameters Summary "Faraday::NestedParamsEncoder", the default nested query parameter encoder/decoder in Faraday, decodes nested query strings without enforcing a maximum nesting depth. A crafted query string such as: a[x][x][x][x]...[x]=1 causes Faraday to build a deeply nested Ruby "Hash" structure. The internal "dehash" routine then recursively walks this attacker-controlled structure without a depth limit. At sufficient depth, Ruby raises an uncaught "SystemStackError" ("stack level too deep"), crashing the calling thread or worker. This can lead to denial of service in applications that pass attacker-controlled query strings to Faraday's nested query parsing or URL-building paths. Affected Product - Product: Faraday - Repository: https://github.com/lostisland/faraday - Tested version: "v2.14.2-2-g59334e0" - Tested commit: "59334e0e9b19" - Ruby version: "ruby 3.2.3" - Tested component: "Faraday::NestedParamsEncoder" / "Faraday::Utils.parse_nested_query" - Date tested: "2026-05-24" Vulnerability Type - Denial of Service - Uncontrolled Recursion - Stack Exhaustion Preconditions An application must pass attacker-controlled or attacker-influenced query strings to one of Faraday's nested parameter parsing/building paths. Confirmed reachable paths include: 1. Direct use of the public utility: Faraday::Utils.parse_nested_query(untrusted_query_string) 2. Normal Faraday request URL building: conn = Faraday.new('https://api.example.com') conn.build_url("/search?#{untrusted_query_string}") In the second case, the crash occurs during URL construction before any network request is sent. Impact A relatively small query string can trigger a "SystemStackError" and crash the calling Ruby thread or worker. In my local test environment, a payload of approximately 9.4 KB was sufficient: depth=3119 bytes=9360 result=SystemStackError message="stack level too deep" Repeated requests with such payloads may cause a denial of service against applications whose request path forwards, parses, or rebuilds attacker-controlled query strings through Faraday. This issue does not provide remote code execution, authentication bypass, or data disclosure. The confirmed impact is availability loss. Technical Details Faraday supports nested query parameters such as: user[name]=alice&user[roles][]=admin which are decoded into nested Ruby structures. However, Faraday also accepts arbitrarily deep nesting such as: a[x][x][x][x][x][x]...[x]=1 This creates a deeply nested structure similar to: { "a" => { "x" => { "x" => { "x" => { "x" => ... } } } } } The recursive "dehash" routine then walks the structure without a maximum depth check. Affected file: lib/faraday/encoders/nested_params_encoder.rb Relevant logic: def dehash(hash, depth) hash.each do |key, value| hash[key] = dehash(value, depth + 1) if value.is_a?(Hash) end ... end Although the function accepts a "depth" argument, the value is not used to enforce a maximum depth. Therefore, recursion depth is fully controlled by the input query string. Proof of Concept PoC 1: Direct parser crash require 'faraday' payload = "a#{'[x]' * 3119}=1" Faraday::Utils.parse_nested_query(payload) Observed result: SystemStackError: stack level too deep PoC 2: Normal URL-building crash require 'faraday' conn = Faraday.new('https://api.example.com') payload = "/search?a#{'[x]' * 3500}=1" conn.build_url(payload) Observed result: SystemStackError No network request is required; the crash occurs during URL construction. Local Reproduction Results The issue was reproduced locally against Faraday commit "59334e0e9b19". Environment: ruby 3.2.3 faraday v2.14.2-2-g59334e0 commit 59334e0e9b19 Full PoC result == (A) DEEP nesting -> dehash recursion / stack exhaustion == depth=100 parse=0.0003s OK depth=1000 parse=0.0034s OK depth=5000 SystemStackError (stack overflow DoS): SystemStackError depth=20000 SystemStackError (stack overflow DoS): SystemStackError depth=100000 SystemStackError (stack overflow DoS): SystemStackError == (B) WIDE numeric keys -> dehash sort + numeric-key scan per level == N=1000 parse=0.0093s N=10000 parse=0.1053s N=50000 parse=0.4992s N=100000 parse=1.1242s == (C) MANY array pushes a[]&a[]&... == N=1000 parse=0.0048s N=10000 parse=0.0614s N=50000 parse=0.2915s N=100000 parse=0.5403s Minimal depth test depth=100 bytes=303 result=OK depth=1000 bytes=3003 result=OK depth=2500 bytes=7503 result=OK depth=3000 bytes=9003 result=OK depth=3119 bytes=9360 result=SystemStackError message="stack level too deep" depth=3500 bytes=10503 result=SystemStackError message="stack level too deep" depth=5000 bytes=15003 result=SystemStackError message="stack level too deep" URL-building test build_url depth=100 bytes=311 result=OK build_url depth=1000 bytes=3011 result=OK build_url depth=3500 bytes=10511 result=SystemStackError build_url depth=8000 bytes=24011 result=SystemStackError These results confirm that both direct parsing and normal Faraday URL construction can trigger the stack exhaustion condition. Expected Behavior Faraday should reject excessively deep nested query parameters with a controlled and rescuable exception. For example, behavior similar to Rack's parameter depth limit would prevent stack exhaustion: Faraday::Error: Exceeded the maximum allowed nested parameter depth Actual Behavior Faraday recursively processes attacker-controlled nesting depth and eventually raises: SystemStackError: stack level too deep This exception indicates stack exhaustion and can crash the calling worker/thread. Suggested Fix Add a configurable maximum nesting depth to "Faraday::NestedParamsEncoder", similar to Rack's "param_depth_limit". Suggested behavior: - Set a default maximum depth, for example "100". - Reject keys whose subkey chain exceeds the maximum depth. - Raise a normal "Faraday::Error" or another controlled exception rather than allowing Ruby stack exhaustion. Example patch concept: module Faraday module NestedParamsEncoder class << self attr_accessor :sort_params, :array_indices, :param_depth_limit end @param_depth_limit = 100 end end Then in "decode_pair": subkeys = key.scan(SUBKEYS_REGEX) if param_depth_limit && subkeys.length > param_depth_limit raise Faraday::Error, "Exceeded the maximum allowed nested parameter depth of #{param_depth_limit}" end A local patch implementing this approach was tested. With the patch applied: - The crash payloads raise a controlled "Faraday::Error" instead of "SystemStackError". - Normal nested query parsing still works. - Existing encoder/utils tests passed in the local test set: 42 examples, 0 failures Security Policy Fit Faraday's "SECURITY.md" states that the "2.x" branch is supported for security updates and that vulnerabilities should be reported privately. This issue was reproduced on the current tested "2.x" codebase: v2.14.2-2-g59334e0 commit 59334e0e9b19 The report is intended for private disclosure through GitHub Security Advisories and should not be opened as a public issue before maintainer triage. Related Public Discussions / Duplicate Check I searched the public issue tracker, pull requests, changelog, and GitHub Advisory Database for similar reports using terms including: NestedParamsEncoder parse_nested_query SystemStackError stack level too deep param_depth_limit nested parameter depth Uncontrolled recursion CWE-674 dehash depth parse_nested_query depth I did not find a public report or fix for this specific "NestedParamsEncoder" depth-limit / "SystemStackError" denial-of-service issue. The closest unrelated public items I found were: - "lostisland/faraday#1107" — "Infinite recursion (SystemStackError) on load when running with -rdebug with breakpoints" - This appears unrelated to nested query parameter parsing and "Faraday::NestedParamsEncoder". - "GHSA-33mh-2634-fwr2" / "CVE-2026-25765" - This concerns a protocol-relative URL / host override issue and does not address nested query parameter recursion or depth limiting. Repo-local checks also found no existing "param_depth_limit" or equivalent mitigation in "lib/faraday/encoders/nested_params_encoder.rb". Severity Suggested severity: Medium Rationale: - The attack can be triggered over the network in applications that pass attacker-controlled query strings into Faraday's parsing/building paths. - The payload is small enough to be practical, approximately 9.4 KB in the local reproduction. - No authentication or user interaction is required in affected application patterns. - The confirmed impact is availability only. Because Faraday is a library, the exact severity depends on how an application exposes the affected parsing/building path to attacker-controlled input. If the maintainers prefer conservative scoring for library reachability, the availability impact could be adjusted accordingly. Notes This report does not claim remote code execution, authentication bypass, or information disclosure. The confirmed issue is an uncontrolled-recursion denial of service condition caused by missing nesting-depth enforcement in Faraday's nested parameter decoder. No third-party live services were tested. Reproduction was performed only in a local lab environment. Reporter Reported by: Emre Koca Please let me know if you need additional reproduction details, logs, or a patch proposal.
Publish Date: 2026-06-19
URL: CVE-2026-54297
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: GHSA-98m9-hrrm-r99r
Release Date: 2026-06-19
Fix Resolution: faraday - 2.14.3
Step up your Open Source Security Game with Mend here
CVE-2026-35611
Vulnerable Library - addressable-2.8.1.gem
Addressable is an alternative implementation to the URI implementation that is
part of Ruby's standard library. It is flexible, offers heuristic parsing, and
additionally provides extensive support for IRIs and URI templates.
Library home page: https://rubygems.org/gems/addressable-2.8.1.gem
Path to dependency file: /Gemfile.lock
Path to vulnerable library: /home/wss-scanner/.gem/ruby/2.7.0/cache/addressable-2.8.1.gem
Dependency Hierarchy:
- jekyll-github-metadata-2.15.0.gem (Root Library)
- jekyll-4.2.2.gem
- ❌ addressable-2.8.1.gem (Vulnerable Library)
Found in base branch: master
Vulnerability Details
Addressable is an alternative implementation to the URI implementation that is part of Ruby's standard library. From 2.3.0 to before 2.9.0, within the URI template implementation in Addressable, two classes of URI template generate regular expressions vulnerable to catastrophic backtracking. Templates using the * (explode) modifier with any expansion operator (e.g., {foo*}, {+var*}, {#var*}, {/var*}, {.var*}, {;var*}, {?var*}, {&var*}) generate patterns with nested unbounded quantifiers that are O(2^n) when matched against a maliciously crafted URI. Templates using multiple variables with the + or # operators (e.g., {+v1,v2,v3}) generate patterns with O(n^k) complexity due to the comma separator being within the matched character class, causing ambiguous backtracking across k variables. When matched against a maliciously crafted URI, this can result in catastrophic backtracking and uncontrolled resource consumption, leading to denial of service. This vulnerability is fixed in 2.9.0.
Publish Date: 2026-04-07
URL: CVE-2026-35611
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
Release Date: 2026-04-07
Fix Resolution: https://github.com/sporkmonger/addressable.git - addressable-2.9.0
Step up your Open Source Security Game with Mend here
CVE-2024-49761
Vulnerable Library - rexml-3.2.5.gem
An XML toolkit for Ruby
Library home page: https://rubygems.org/gems/rexml-3.2.5.gem
Path to dependency file: /Gemfile.lock
Path to vulnerable library: /home/wss-scanner/.gem/ruby/2.7.0/cache/rexml-3.2.5.gem
Dependency Hierarchy:
- jekyll-github-metadata-2.15.0.gem (Root Library)
- jekyll-4.2.2.gem
- kramdown-2.4.0.gem
- ❌ rexml-3.2.5.gem (Vulnerable Library)
Found in base branch: master
Vulnerability Details
REXML is an XML toolkit for Ruby. The REXML gem before 3.3.9 has a ReDoS vulnerability when it parses an XML that has many digits between &# and x...; in a hex numeric character reference (&#x...;). This does not happen with Ruby 3.2 or later. Ruby 3.1 is the only affected maintained Ruby. The REXML gem 3.3.9 or later include the patch to fix the vulnerability.
Publish Date: 2024-10-28
URL: CVE-2024-49761
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://www.cve.org/CVERecord?id=CVE-2024-49761
Release Date: 2024-10-28
Fix Resolution: rexml - 3.3.9
Step up your Open Source Security Game with Mend here
CVE-2024-43398
Vulnerable Library - rexml-3.2.5.gem
An XML toolkit for Ruby
Library home page: https://rubygems.org/gems/rexml-3.2.5.gem
Path to dependency file: /Gemfile.lock
Path to vulnerable library: /home/wss-scanner/.gem/ruby/2.7.0/cache/rexml-3.2.5.gem
Dependency Hierarchy:
- jekyll-github-metadata-2.15.0.gem (Root Library)
- jekyll-4.2.2.gem
- kramdown-2.4.0.gem
- ❌ rexml-3.2.5.gem (Vulnerable Library)
Found in base branch: master
Vulnerability Details
REXML is an XML toolkit for Ruby. The REXML gem before 3.3.6 has a DoS vulnerability when it parses an XML that has many deep elements that have same local name attributes. If you need to parse untrusted XMLs with tree parser API like REXML::Document.new, you may be impacted to this vulnerability. If you use other parser APIs such as stream parser API and SAX2 parser API, this vulnerability is not affected. The REXML gem 3.3.6 or later include the patch to fix the vulnerability.
Publish Date: 2024-08-22
URL: CVE-2024-43398
CVSS 3 Score Details (5.9)
Base Score Metrics:
- Exploitability Metrics:
- Attack Vector: Network
- Attack Complexity: High
- 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: GHSA-vmwr-mc7x-5vc3
Release Date: 2024-08-22
Fix Resolution: rexml - 3.3.6
Step up your Open Source Security Game with Mend here
CVE-2026-25765
Vulnerable Library - faraday-2.5.2.gem
Library home page: https://rubygems.org/gems/faraday-2.5.2.gem
Path to dependency file: /Gemfile.lock
Path to vulnerable library: /home/wss-scanner/.gem/ruby/2.7.0/cache/faraday-2.5.2.gem
Dependency Hierarchy:
- jekyll-github-metadata-2.15.0.gem (Root Library)
- octokit-4.25.1.gem
- ❌ faraday-2.5.2.gem (Vulnerable Library)
Found in base branch: master
Vulnerability Details
Faraday is an HTTP client library abstraction layer that provides a common interface over many adapters. Prior to 2.14.1, Faraday's build_exclusive_url method (in lib/faraday/connection.rb) uses Ruby's URI#merge to combine the connection's base URL with a user-supplied path. Per RFC 3986, protocol-relative URLs (e.g. //evil.com/path) are treated as network-path references that override the base URL's host/authority component. This means that if any application passes user-controlled input to Faraday's get(), post(), build_url(), or other request methods, an attacker can supply a protocol-relative URL like //attacker.com/endpoint to redirect the request to an arbitrary host, enabling Server-Side Request Forgery (SSRF). This vulnerability is fixed in 2.14.1.
Publish Date: 2026-02-09
URL: CVE-2026-25765
CVSS 3 Score Details (5.8)
Base Score Metrics:
- Exploitability Metrics:
- Attack Vector: Network
- Attack Complexity: Low
- Privileges Required: None
- User Interaction: None
- Scope: Changed
- Impact Metrics:
- Confidentiality Impact: Low
- Integrity Impact: None
- Availability Impact: None
For more information on CVSS3 Scores, click here.
Suggested Fix
Type: Upgrade version
Origin: GHSA-33mh-2634-fwr2
Release Date: 2026-02-09
Fix Resolution: https://github.com/lostisland/faraday.git - v2.14.1,faraday - 2.14.1
Step up your Open Source Security Game with Mend here
CVE-2026-54905
Vulnerable Library - concurrent-ruby-1.1.10.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.1.10.gem
Path to dependency file: /Gemfile.lock
Path to vulnerable library: /home/wss-scanner/.gem/ruby/2.7.0/cache/concurrent-ruby-1.1.10.gem
Dependency Hierarchy:
- jekyll-github-metadata-2.15.0.gem (Root Library)
- jekyll-4.2.2.gem
- i18n-1.12.0.gem
- ❌ concurrent-ruby-1.1.10.gem (Vulnerable Library)
Found in base branch: master
Vulnerability Details
Summary "Concurrent::ReentrantReadWriteLock" can incorrectly grant a write lock after one thread acquires the read lock 32,768 times. The lock stores a thread's local read and write hold counts in one integer. The low 15 bits are used for the read hold count, and bit 15 is used as "WRITE_LOCK_HELD". After 32,768 reentrant read acquisitions, the local read count crosses into the write-lock bit. "try_write_lock" then treats the thread as already holding a write lock and returns "true" without setting the global "RUNNING_WRITER" bit. This breaks the core mutual-exclusion guarantee: the caller is told it has a write lock, but other threads can still hold or acquire read locks at the same time. Version Software: concurrent-ruby Version: 1.3.6 Commit: 7a1b78941c081106c20a9ca0144ac73a48d254ab Details The implementation uses a shared counter to track global readers/writers and a per-thread local counter to support reentrancy: READER_BITS = 15 WRITER_BITS = 14 WAITING_WRITER = 1 << READER_BITS RUNNING_WRITER = 1 << (READER_BITS + WRITER_BITS) MAX_READERS = WAITING_WRITER - 1 MAX_WRITERS = RUNNING_WRITER - MAX_READERS - 1 WRITE_LOCK_HELD = 1 << READER_BITS READ_LOCK_MASK = WRITE_LOCK_HELD - 1 WRITE_LOCK_MASK = MAX_WRITERS When a thread already holds a lock, "acquire_read_lock" increments "@HeldCount": if (held = @HeldCount.value) > 0 if held & READ_LOCK_MASK == 0 @Counter.update { |c| c + 1 } end @HeldCount.value = held + 1 return true end After 32,768 read acquisitions, the per-thread held count becomes "32768", which is equal to "WRITE_LOCK_HELD". Then "try_write_lock" returns success through its "already have a write lock" branch: def try_write_lock if (held = @HeldCount.value) >= WRITE_LOCK_HELD @HeldCount.value = held + WRITE_LOCK_HELD return true else # normal global writer acquisition path end end This branch does not set the global "RUNNING_WRITER" bit. Other threads therefore do not observe an active writer and can continue holding or acquiring read locks while the caller believes it owns the write lock. PoC #!/usr/bin/env ruby frozen_string_literal: true require 'concurrent/atomic/reentrant_read_write_lock' require 'concurrent/version' require 'thread' def wait_for_queue(queue, timeout_seconds) deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + timeout_seconds loop do return queue.pop(true) rescue ThreadError return nil if Process.clock_gettime(Process::CLOCK_MONOTONIC) >= deadline sleep 0.001 end end puts "ruby=#{RUBY_DESCRIPTION}" puts "concurrent_ruby_version=#{Concurrent::VERSION}" puts "poc=ReentrantReadWriteLock read-depth overflow grants write lock without exclusivity" lock = Concurrent::ReentrantReadWriteLock.new other_reader_ready = Queue.new other_reader_stop = Queue.new other_reader = Thread.new do lock.acquire_read_lock other_reader_ready << :held other_reader_stop.pop end wait_for_queue(other_reader_ready, 1) puts "other_thread_holds_read_lock=true" depth = Concurrent::ReentrantReadWriteLock::WRITE_LOCK_HELD depth.times { lock.acquire_read_lock } held_count = lock.instance_eval { @HeldCount.value } counter_before = lock.instance_eval { @Counter.value } puts "main_thread_read_acquisitions=#{depth}" puts "main_thread_held_count=#{held_count}" puts "counter_before_try_write=#{counter_before}" puts "running_writer_bit_before=#{(counter_before & Concurrent::ReentrantReadWriteLock::RUNNING_WRITER) != 0}" write_granted = lock.try_write_lock counter_after = lock.instance_eval { @Counter.value } puts "try_write_lock_returned=#{write_granted}" puts "counter_after_try_write=#{counter_after}" puts "running_writer_bit_after=#{(counter_after & Concurrent::ReentrantReadWriteLock::RUNNING_WRITER) != 0}" third_reader_ready = Queue.new third_reader = Thread.new do lock.acquire_read_lock third_reader_ready << :acquired end third_reader_acquired = wait_for_queue(third_reader_ready, 0.25) == :acquired puts "new_reader_acquired_while_write_claimed=#{third_reader_acquired}" if write_granted && third_reader_acquired && (counter_after & Concurrent::ReentrantReadWriteLock::RUNNING_WRITER).zero? puts 'result=REPRODUCED write lock granted without setting global writer state' else puts 'result=NOT_REPRODUCED' end third_reader.kill other_reader_stop << :stop other_reader.kill Log evidence ruby=ruby 2.6.10p210 (2022-04-12 revision 67958) [universal.arm64e-darwin25] concurrent_ruby_version=1.3.6 poc=ReentrantReadWriteLock read-depth overflow grants write lock without exclusivity other_thread_holds_read_lock=true main_thread_read_acquisitions=32768 main_thread_held_count=32768 counter_before_try_write=2 running_writer_bit_before=false try_write_lock_returned=true counter_after_try_write=2 running_writer_bit_after=false new_reader_acquired_while_write_claimed=true result=REPRODUCED write lock granted without setting global writer state Impact This breaks the write-lock exclusivity guarantee. After the overflow, a thread can be told it has acquired the write lock while other threads can still hold or acquire read locks, allowing races and inconsistent reads of protected mutable state. Credit Pranjali Thakur - depthfirst ("depthfirst.com" (http://depthfirst.com))
Publish Date: 2026-06-19
URL: CVE-2026-54905
CVSS 3 Score Details (5.3)
Base Score Metrics:
- Exploitability Metrics:
- Attack Vector: Local
- Attack Complexity: Low
- Privileges Required: Low
- User Interaction: None
- Scope: Unchanged
- Impact Metrics:
- Confidentiality Impact: Low
- Integrity Impact: Low
- Availability Impact: Low
For more information on CVSS3 Scores, click here.
Suggested Fix
Type: Upgrade version
Origin: GHSA-wv3x-4vxv-whpp
Release Date: 2026-06-19
Fix Resolution: concurrent-ruby - 1.3.7
Step up your Open Source Security Game with Mend here
CVE-2024-41946
Vulnerable Library - rexml-3.2.5.gem
An XML toolkit for Ruby
Library home page: https://rubygems.org/gems/rexml-3.2.5.gem
Path to dependency file: /Gemfile.lock
Path to vulnerable library: /home/wss-scanner/.gem/ruby/2.7.0/cache/rexml-3.2.5.gem
Dependency Hierarchy:
- jekyll-github-metadata-2.15.0.gem (Root Library)
- jekyll-4.2.2.gem
- kramdown-2.4.0.gem
- ❌ rexml-3.2.5.gem (Vulnerable Library)
Found in base branch: master
Vulnerability Details
REXML is an XML toolkit for Ruby. The REXML gem 3.3.2 has a DoS vulnerability when it parses an XML that has many entity expansions with SAX2 or pull parser API. The REXML gem 3.3.3 or later include the patch to fix the vulnerability.
Publish Date: 2024-08-01
URL: CVE-2024-41946
CVSS 3 Score Details (5.3)
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: Low
For more information on CVSS3 Scores, click here.
Suggested Fix
Type: Upgrade version
Origin: GHSA-5866-49gr-22v4
Release Date: 2024-08-01
Fix Resolution: rexml - 3.3.3
Step up your Open Source Security Game with Mend here
CVE-2024-41123
Vulnerable Library - rexml-3.2.5.gem
An XML toolkit for Ruby
Library home page: https://rubygems.org/gems/rexml-3.2.5.gem
Path to dependency file: /Gemfile.lock
Path to vulnerable library: /home/wss-scanner/.gem/ruby/2.7.0/cache/rexml-3.2.5.gem
Dependency Hierarchy:
- jekyll-github-metadata-2.15.0.gem (Root Library)
- jekyll-4.2.2.gem
- kramdown-2.4.0.gem
- ❌ rexml-3.2.5.gem (Vulnerable Library)
Found in base branch: master
Vulnerability Details
REXML is an XML toolkit for Ruby. The REXML gem before 3.3.2 has some DoS vulnerabilities when it parses an XML that has many specific characters such as whitespace character, >] and ]>. The REXML gem 3.3.3 or later include the patches to fix these vulnerabilities.
Publish Date: 2024-08-01
URL: CVE-2024-41123
CVSS 3 Score Details (5.3)
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: Low
For more information on CVSS3 Scores, click here.
Suggested Fix
Type: Upgrade version
Origin: GHSA-r55c-59qm-vjw6
Release Date: 2024-08-01
Fix Resolution: rexml - 3.3.3
Step up your Open Source Security Game with Mend here
CVE-2024-35176
Vulnerable Library - rexml-3.2.5.gem
An XML toolkit for Ruby
Library home page: https://rubygems.org/gems/rexml-3.2.5.gem
Path to dependency file: /Gemfile.lock
Path to vulnerable library: /home/wss-scanner/.gem/ruby/2.7.0/cache/rexml-3.2.5.gem
Dependency Hierarchy:
- jekyll-github-metadata-2.15.0.gem (Root Library)
- jekyll-4.2.2.gem
- kramdown-2.4.0.gem
- ❌ rexml-3.2.5.gem (Vulnerable Library)
Found in base branch: master
Vulnerability Details
REXML is an XML toolkit for Ruby. The REXML gem before 3.2.6 has a denial of service vulnerability when it parses an XML that has many "<"s in an attribute value. Those who need to parse untrusted XMLs may be impacted to this vulnerability. The REXML gem 3.2.7 or later include the patch to fix this vulnerability. As a workaround, don't parse untrusted XMLs.
Publish Date: 2024-05-16
URL: CVE-2024-35176
CVSS 3 Score Details (5.3)
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: Low
For more information on CVSS3 Scores, click here.
Suggested Fix
Type: Upgrade version
Origin: GHSA-vg3r-rm7w-2xgh
Release Date: 2024-05-16
Fix Resolution: rexml - 3.2.7
Step up your Open Source Security Game with Mend here
CVE-2024-39908
Vulnerable Library - rexml-3.2.5.gem
An XML toolkit for Ruby
Library home page: https://rubygems.org/gems/rexml-3.2.5.gem
Path to dependency file: /Gemfile.lock
Path to vulnerable library: /home/wss-scanner/.gem/ruby/2.7.0/cache/rexml-3.2.5.gem
Dependency Hierarchy:
- jekyll-github-metadata-2.15.0.gem (Root Library)
- jekyll-4.2.2.gem
- kramdown-2.4.0.gem
- ❌ rexml-3.2.5.gem (Vulnerable Library)
Found in base branch: master
Vulnerability Details
REXML is an XML toolkit for Ruby. The REXML gem before 3.3.1 has some DoS vulnerabilities when it parses an XML that has many specific characters such as <, 0 and %>. If you need to parse untrusted XMLs, you many be impacted to these vulnerabilities. The REXML gem 3.3.2 or later include the patches to fix these vulnerabilities. Users are advised to upgrade. Users unable to upgrade should avoid parsing untrusted XML strings.
Publish Date: 2024-07-16
URL: CVE-2024-39908
CVSS 3 Score Details (4.3)
Base Score Metrics:
- Exploitability Metrics:
- Attack Vector: Network
- Attack Complexity: Low
- Privileges Required: None
- User Interaction: Required
- Scope: Unchanged
- Impact Metrics:
- Confidentiality Impact: None
- Integrity Impact: None
- Availability Impact: Low
For more information on CVSS3 Scores, click here.
Suggested Fix
Type: Upgrade version
Origin: GHSA-4xqq-m2hx-25v8
Release Date: 2024-07-16
Fix Resolution: rexml - 3.3.2
Step up your Open Source Security Game with Mend here
CVE-2026-54906
Vulnerable Library - concurrent-ruby-1.1.10.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.1.10.gem
Path to dependency file: /Gemfile.lock
Path to vulnerable library: /home/wss-scanner/.gem/ruby/2.7.0/cache/concurrent-ruby-1.1.10.gem
Dependency Hierarchy:
- jekyll-github-metadata-2.15.0.gem (Root Library)
- jekyll-4.2.2.gem
- i18n-1.12.0.gem
- ❌ concurrent-ruby-1.1.10.gem (Vulnerable Library)
Found in base branch: master
Vulnerability Details
Summary "Concurrent::ReadWriteLock#release_write_lock" does not verify that the calling thread acquired the write lock. Any thread with access to the lock object can release an active write lock held by another thread. A second writer can then enter its critical section while the first writer is still running. "Concurrent::ReadWriteLock#release_read_lock" also decrements the shared counter even when no read lock is held. Calling it on a fresh lock changes the counter from "0" to "-1", after which normal read acquisition raises "Concurrent::ResourceLimitError". This is a synchronization correctness issue in the public "Concurrent::ReadWriteLock" API. It should not be framed as an authorization bypass; the lock is an in-process concurrency primitive, not an access-control boundary. Version Software: concurrent-ruby Version: 1.3.6 Commit: 7a1b78941c081106c20a9ca0144ac73a48d254ab Details "release_write_lock" checks only whether the global counter indicates that a writer is running. It does not track or verify ownership: def release_write_lock return true unless running_writer? c = @Counter.update { |counter| counter - RUNNING_WRITER } @ReadLock.broadcast @WriteLock.signal if waiting_writers(c) > 0 true end Because ownership is not checked, a different thread can clear the "RUNNING_WRITER" bit while the original writer is still inside its critical section. Another writer can then acquire the write lock and run concurrently with the first writer. "release_read_lock" unconditionally decrements the shared counter: def release_read_lock while true c = @Counter.value if @Counter.compare_and_set(c, c-1) if waiting_writer?(c) && running_readers(c) == 1 @WriteLock.signal end break end end true end On a fresh lock, this changes the counter from "0" to "-1". A later "acquire_read_lock" raises "Concurrent::ResourceLimitError" because the maximum-reader check masks the negative counter as saturated. Reproduce From the root of a "concurrent-ruby" checkout, run: ruby -Ilib/concurrent-ruby - <<'RUBY' require 'concurrent/atomic/read_write_lock' require 'concurrent/version' require 'thread' puts "ruby=#{RUBY_DESCRIPTION}" puts "concurrent_ruby_version=#{Concurrent::VERSION}" puts "poc=ReadWriteLock release methods corrupt or bypass lock state" lock = Concurrent::ReadWriteLock.new events = Queue.new writer1_inside = false writer1 = Thread.new do lock.acquire_write_lock writer1_inside = true events << :writer1_acquired sleep 0.5 writer1_inside = false lock.release_write_lock events << :writer1_finished end events.pop puts 'writer1_acquired=true' intruder_result = nil intruder = Thread.new do intruder_result = lock.release_write_lock end intruder.join puts "wrong_thread_release_write_lock_returned=#{intruder_result}" writer2_entered_while_writer1_inside = nil writer2 = Thread.new do lock.acquire_write_lock writer2_entered_while_writer1_inside = writer1_inside lock.release_write_lock end writer2.join(0.25) puts "writer2_acquired_while_writer1_inside=#{writer2_entered_while_writer1_inside}" writer1.join lock2 = Concurrent::ReadWriteLock.new stray_read_release_result = lock2.release_read_lock counter_after_stray_read_release = lock2.instance_eval { @Counter.value } read_after_stray_release = begin lock2.acquire_read_lock 'acquired' rescue => error "#{error.class}: #{error.message}" end puts "stray_release_read_lock_returned=#{stray_read_release_result}" puts "counter_after_stray_read_release=#{counter_after_stray_read_release}" puts "acquire_read_after_stray_release=#{read_after_stray_release}" if intruder_result && writer2_entered_while_writer1_inside && counter_after_stray_read_release == -1 puts 'result=REPRODUCED wrong-thread write release and stray read-release corruption' else puts 'result=NOT_REPRODUCED' end Expected result: - A second thread successfully calls "release_write_lock" while the first writer still holds the lock. - A second writer enters while the first writer is still inside the write critical section. - Calling "release_read_lock" on a fresh lock changes the counter to "-1". - A subsequent read acquisition fails with "Concurrent::ResourceLimitError". Log evidence Local reproduction output: ruby=ruby 2.6.10p210 (2022-04-12 revision 67958) [universal.arm64e-darwin25] concurrent_ruby_version=1.3.6 poc=ReadWriteLock release methods corrupt or bypass lock state writer1_acquired=true wrong_thread_release_write_lock_returned=true writer2_acquired_while_writer1_inside=true stray_release_read_lock_returned=true counter_after_stray_read_release=-1 acquire_read_after_stray_release=Concurrent::ResourceLimitError: Too many reader threads result=REPRODUCED wrong-thread write release and stray read-release corruption Impact This can break the write-lock mutual exclusion guarantee and can also leave a lock unusable after a stray read release. The impact is local to applications that expose or misuse the manual "acquire_" / "release_" APIs. If the lock protects integrity-sensitive mutable state, wrong-thread write release can allow concurrent writers and data races. The stray read-release path can cause denial of service by corrupting the lock counter. Credit Pranjali Thakur - depthfirst ("depthfirst.com" (http://depthfirst.com))
Publish Date: 2026-06-19
URL: CVE-2026-54906
CVSS 3 Score Details (4.0)
Base Score Metrics:
- Exploitability Metrics:
- Attack Vector: Local
- Attack Complexity: High
- Privileges Required: None
- User Interaction: None
- Scope: Unchanged
- Impact Metrics:
- Confidentiality Impact: None
- Integrity Impact: Low
- Availability Impact: Low
For more information on CVSS3 Scores, click here.
Suggested Fix
Type: Upgrade version
Origin: GHSA-6wx8-w4f5-wwcr
Release Date: 2026-06-19
Fix Resolution: concurrent-ruby - 1.3.7
Step up your Open Source Security Game with Mend here
CVE-2026-33637
Vulnerable Library - faraday-2.5.2.gem
Library home page: https://rubygems.org/gems/faraday-2.5.2.gem
Path to dependency file: /Gemfile.lock
Path to vulnerable library: /home/wss-scanner/.gem/ruby/2.7.0/cache/faraday-2.5.2.gem
Dependency Hierarchy:
- jekyll-github-metadata-2.15.0.gem (Root Library)
- octokit-4.25.1.gem
- ❌ faraday-2.5.2.gem (Vulnerable Library)
Found in base branch: master
Vulnerability Details
Faraday is an HTTP client library abstraction layer that provides a common interface over many adapters. Versions 2.0.0 through 2.14.1 still allow protocol-relative host override when the request target is passed as a URI object (rather than a String) to Faraday::Connection#build_exclusive_url. This bypasses the February 2026 fix for GHSA-33mh-2634-fwr2 and enables off-host request forgery: a request built from a fixed-base Faraday::Connection can be redirected to an attacker-controlled host, forwarding connection-scoped values such as Authorization headers and default query parameters. This issue has been fixed in version 2.14.3.
Publish Date: 2026-05-19
URL: CVE-2026-33637
CVSS 3 Score Details (0.0)
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: None
For more information on CVSS3 Scores, click here.
Suggested Fix
Type: Upgrade version
Origin: GHSA-5rv5-xj5j-3484
Release Date: 2026-05-18
Fix Resolution: faraday - 2.14.2
Step up your Open Source Security Game with Mend here
Path to dependency file: /Gemfile.lock
Path to vulnerable library: /home/wss-scanner/.gem/ruby/2.7.0/cache/faraday-2.5.2.gem
Vulnerabilities
*For some transitive vulnerabilities, there is no version of direct dependency with a fix. Check the "Details" section below to see if there is a version of transitive dependency where vulnerability is fixed.
**In some cases, Remediation PR cannot be created automatically for a vulnerability despite the availability of remediation
Details
Vulnerable Library - concurrent-ruby-1.1.10.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.1.10.gem
Path to dependency file: /Gemfile.lock
Path to vulnerable library: /home/wss-scanner/.gem/ruby/2.7.0/cache/concurrent-ruby-1.1.10.gem
Dependency Hierarchy:
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: 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
Vulnerable Library - faraday-2.5.2.gem
Library home page: https://rubygems.org/gems/faraday-2.5.2.gem
Path to dependency file: /Gemfile.lock
Path to vulnerable library: /home/wss-scanner/.gem/ruby/2.7.0/cache/faraday-2.5.2.gem
Dependency Hierarchy:
Found in base branch: master
Vulnerability Details
Uncontrolled Recursion in NestedParamsEncoder Allows Stack Exhaustion DoS via Deeply Nested Query Parameters Summary "Faraday::NestedParamsEncoder", the default nested query parameter encoder/decoder in Faraday, decodes nested query strings without enforcing a maximum nesting depth. A crafted query string such as: a[x][x][x][x]...[x]=1 causes Faraday to build a deeply nested Ruby "Hash" structure. The internal "dehash" routine then recursively walks this attacker-controlled structure without a depth limit. At sufficient depth, Ruby raises an uncaught "SystemStackError" ("stack level too deep"), crashing the calling thread or worker. This can lead to denial of service in applications that pass attacker-controlled query strings to Faraday's nested query parsing or URL-building paths. Affected Product - Product: Faraday - Repository: https://github.com/lostisland/faraday - Tested version: "v2.14.2-2-g59334e0" - Tested commit: "59334e0e9b19" - Ruby version: "ruby 3.2.3" - Tested component: "Faraday::NestedParamsEncoder" / "Faraday::Utils.parse_nested_query" - Date tested: "2026-05-24" Vulnerability Type - Denial of Service - Uncontrolled Recursion - Stack Exhaustion Preconditions An application must pass attacker-controlled or attacker-influenced query strings to one of Faraday's nested parameter parsing/building paths. Confirmed reachable paths include: 1. Direct use of the public utility: Faraday::Utils.parse_nested_query(untrusted_query_string) 2. Normal Faraday request URL building: conn = Faraday.new('https://api.example.com') conn.build_url("/search?#{untrusted_query_string}") In the second case, the crash occurs during URL construction before any network request is sent. Impact A relatively small query string can trigger a "SystemStackError" and crash the calling Ruby thread or worker. In my local test environment, a payload of approximately 9.4 KB was sufficient: depth=3119 bytes=9360 result=SystemStackError message="stack level too deep" Repeated requests with such payloads may cause a denial of service against applications whose request path forwards, parses, or rebuilds attacker-controlled query strings through Faraday. This issue does not provide remote code execution, authentication bypass, or data disclosure. The confirmed impact is availability loss. Technical Details Faraday supports nested query parameters such as: user[name]=alice&user[roles][]=admin which are decoded into nested Ruby structures. However, Faraday also accepts arbitrarily deep nesting such as: a[x][x][x][x][x][x]...[x]=1 This creates a deeply nested structure similar to: { "a" => { "x" => { "x" => { "x" => { "x" => ... } } } } } The recursive "dehash" routine then walks the structure without a maximum depth check. Affected file: lib/faraday/encoders/nested_params_encoder.rb Relevant logic: def dehash(hash, depth) hash.each do |key, value| hash[key] = dehash(value, depth + 1) if value.is_a?(Hash) end ... end Although the function accepts a "depth" argument, the value is not used to enforce a maximum depth. Therefore, recursion depth is fully controlled by the input query string. Proof of Concept PoC 1: Direct parser crash require 'faraday' payload = "a#{'[x]' * 3119}=1" Faraday::Utils.parse_nested_query(payload) Observed result: SystemStackError: stack level too deep PoC 2: Normal URL-building crash require 'faraday' conn = Faraday.new('https://api.example.com') payload = "/search?a#{'[x]' * 3500}=1" conn.build_url(payload) Observed result: SystemStackError No network request is required; the crash occurs during URL construction. Local Reproduction Results The issue was reproduced locally against Faraday commit "59334e0e9b19". Environment: ruby 3.2.3 faraday v2.14.2-2-g59334e0 commit 59334e0e9b19 Full PoC result == (A) DEEP nesting -> dehash recursion / stack exhaustion == depth=100 parse=0.0003s OK depth=1000 parse=0.0034s OK depth=5000 SystemStackError (stack overflow DoS): SystemStackError depth=20000 SystemStackError (stack overflow DoS): SystemStackError depth=100000 SystemStackError (stack overflow DoS): SystemStackError == (B) WIDE numeric keys -> dehash sort + numeric-key scan per level == N=1000 parse=0.0093s N=10000 parse=0.1053s N=50000 parse=0.4992s N=100000 parse=1.1242s == (C) MANY array pushes a[]&a[]&... == N=1000 parse=0.0048s N=10000 parse=0.0614s N=50000 parse=0.2915s N=100000 parse=0.5403s Minimal depth test depth=100 bytes=303 result=OK depth=1000 bytes=3003 result=OK depth=2500 bytes=7503 result=OK depth=3000 bytes=9003 result=OK depth=3119 bytes=9360 result=SystemStackError message="stack level too deep" depth=3500 bytes=10503 result=SystemStackError message="stack level too deep" depth=5000 bytes=15003 result=SystemStackError message="stack level too deep" URL-building test build_url depth=100 bytes=311 result=OK build_url depth=1000 bytes=3011 result=OK build_url depth=3500 bytes=10511 result=SystemStackError build_url depth=8000 bytes=24011 result=SystemStackError These results confirm that both direct parsing and normal Faraday URL construction can trigger the stack exhaustion condition. Expected Behavior Faraday should reject excessively deep nested query parameters with a controlled and rescuable exception. For example, behavior similar to Rack's parameter depth limit would prevent stack exhaustion: Faraday::Error: Exceeded the maximum allowed nested parameter depth Actual Behavior Faraday recursively processes attacker-controlled nesting depth and eventually raises: SystemStackError: stack level too deep This exception indicates stack exhaustion and can crash the calling worker/thread. Suggested Fix Add a configurable maximum nesting depth to "Faraday::NestedParamsEncoder", similar to Rack's "param_depth_limit". Suggested behavior: - Set a default maximum depth, for example "100". - Reject keys whose subkey chain exceeds the maximum depth. - Raise a normal "Faraday::Error" or another controlled exception rather than allowing Ruby stack exhaustion. Example patch concept: module Faraday module NestedParamsEncoder class << self attr_accessor :sort_params, :array_indices, :param_depth_limit end @param_depth_limit = 100 end end Then in "decode_pair": subkeys = key.scan(SUBKEYS_REGEX) if param_depth_limit && subkeys.length > param_depth_limit raise Faraday::Error, "Exceeded the maximum allowed nested parameter depth of #{param_depth_limit}" end A local patch implementing this approach was tested. With the patch applied: - The crash payloads raise a controlled "Faraday::Error" instead of "SystemStackError". - Normal nested query parsing still works. - Existing encoder/utils tests passed in the local test set: 42 examples, 0 failures Security Policy Fit Faraday's "SECURITY.md" states that the "2.x" branch is supported for security updates and that vulnerabilities should be reported privately. This issue was reproduced on the current tested "2.x" codebase: v2.14.2-2-g59334e0 commit 59334e0e9b19 The report is intended for private disclosure through GitHub Security Advisories and should not be opened as a public issue before maintainer triage. Related Public Discussions / Duplicate Check I searched the public issue tracker, pull requests, changelog, and GitHub Advisory Database for similar reports using terms including: NestedParamsEncoder parse_nested_query SystemStackError stack level too deep param_depth_limit nested parameter depth Uncontrolled recursion CWE-674 dehash depth parse_nested_query depth I did not find a public report or fix for this specific "NestedParamsEncoder" depth-limit / "SystemStackError" denial-of-service issue. The closest unrelated public items I found were: - "lostisland/faraday#1107" — "Infinite recursion (SystemStackError) on load when running with -rdebug with breakpoints" - This appears unrelated to nested query parameter parsing and "Faraday::NestedParamsEncoder". - "GHSA-33mh-2634-fwr2" / "CVE-2026-25765" - This concerns a protocol-relative URL / host override issue and does not address nested query parameter recursion or depth limiting. Repo-local checks also found no existing "param_depth_limit" or equivalent mitigation in "lib/faraday/encoders/nested_params_encoder.rb". Severity Suggested severity: Medium Rationale: - The attack can be triggered over the network in applications that pass attacker-controlled query strings into Faraday's parsing/building paths. - The payload is small enough to be practical, approximately 9.4 KB in the local reproduction. - No authentication or user interaction is required in affected application patterns. - The confirmed impact is availability only. Because Faraday is a library, the exact severity depends on how an application exposes the affected parsing/building path to attacker-controlled input. If the maintainers prefer conservative scoring for library reachability, the availability impact could be adjusted accordingly. Notes This report does not claim remote code execution, authentication bypass, or information disclosure. The confirmed issue is an uncontrolled-recursion denial of service condition caused by missing nesting-depth enforcement in Faraday's nested parameter decoder. No third-party live services were tested. Reproduction was performed only in a local lab environment. Reporter Reported by: Emre Koca Please let me know if you need additional reproduction details, logs, or a patch proposal.
Publish Date: 2026-06-19
URL: CVE-2026-54297
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: GHSA-98m9-hrrm-r99r
Release Date: 2026-06-19
Fix Resolution: faraday - 2.14.3
Step up your Open Source Security Game with Mend here
Vulnerable Library - addressable-2.8.1.gem
Addressable is an alternative implementation to the URI implementation that is part of Ruby's standard library. It is flexible, offers heuristic parsing, and additionally provides extensive support for IRIs and URI templates.
Library home page: https://rubygems.org/gems/addressable-2.8.1.gem
Path to dependency file: /Gemfile.lock
Path to vulnerable library: /home/wss-scanner/.gem/ruby/2.7.0/cache/addressable-2.8.1.gem
Dependency Hierarchy:
Found in base branch: master
Vulnerability Details
Addressable is an alternative implementation to the URI implementation that is part of Ruby's standard library. From 2.3.0 to before 2.9.0, within the URI template implementation in Addressable, two classes of URI template generate regular expressions vulnerable to catastrophic backtracking. Templates using the * (explode) modifier with any expansion operator (e.g., {foo*}, {+var*}, {#var*}, {/var*}, {.var*}, {;var*}, {?var*}, {&var*}) generate patterns with nested unbounded quantifiers that are O(2^n) when matched against a maliciously crafted URI. Templates using multiple variables with the + or # operators (e.g., {+v1,v2,v3}) generate patterns with O(n^k) complexity due to the comma separator being within the matched character class, causing ambiguous backtracking across k variables. When matched against a maliciously crafted URI, this can result in catastrophic backtracking and uncontrolled resource consumption, leading to denial of service. This vulnerability is fixed in 2.9.0.
Publish Date: 2026-04-07
URL: CVE-2026-35611
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
Release Date: 2026-04-07
Fix Resolution: https://github.com/sporkmonger/addressable.git - addressable-2.9.0
Step up your Open Source Security Game with Mend here
Vulnerable Library - rexml-3.2.5.gem
An XML toolkit for Ruby
Library home page: https://rubygems.org/gems/rexml-3.2.5.gem
Path to dependency file: /Gemfile.lock
Path to vulnerable library: /home/wss-scanner/.gem/ruby/2.7.0/cache/rexml-3.2.5.gem
Dependency Hierarchy:
Found in base branch: master
Vulnerability Details
REXML is an XML toolkit for Ruby. The REXML gem before 3.3.9 has a ReDoS vulnerability when it parses an XML that has many digits between &# and x...; in a hex numeric character reference (&#x...;). This does not happen with Ruby 3.2 or later. Ruby 3.1 is the only affected maintained Ruby. The REXML gem 3.3.9 or later include the patch to fix the vulnerability.
Publish Date: 2024-10-28
URL: CVE-2024-49761
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://www.cve.org/CVERecord?id=CVE-2024-49761
Release Date: 2024-10-28
Fix Resolution: rexml - 3.3.9
Step up your Open Source Security Game with Mend here
Vulnerable Library - rexml-3.2.5.gem
An XML toolkit for Ruby
Library home page: https://rubygems.org/gems/rexml-3.2.5.gem
Path to dependency file: /Gemfile.lock
Path to vulnerable library: /home/wss-scanner/.gem/ruby/2.7.0/cache/rexml-3.2.5.gem
Dependency Hierarchy:
Found in base branch: master
Vulnerability Details
REXML is an XML toolkit for Ruby. The REXML gem before 3.3.6 has a DoS vulnerability when it parses an XML that has many deep elements that have same local name attributes. If you need to parse untrusted XMLs with tree parser API like REXML::Document.new, you may be impacted to this vulnerability. If you use other parser APIs such as stream parser API and SAX2 parser API, this vulnerability is not affected. The REXML gem 3.3.6 or later include the patch to fix the vulnerability.
Publish Date: 2024-08-22
URL: CVE-2024-43398
CVSS 3 Score Details (5.9)
Base Score Metrics:
- Exploitability Metrics:
- Attack Vector: Network
- Attack Complexity: High
- 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: GHSA-vmwr-mc7x-5vc3
Release Date: 2024-08-22
Fix Resolution: rexml - 3.3.6
Step up your Open Source Security Game with Mend here
Vulnerable Library - faraday-2.5.2.gem
Library home page: https://rubygems.org/gems/faraday-2.5.2.gem
Path to dependency file: /Gemfile.lock
Path to vulnerable library: /home/wss-scanner/.gem/ruby/2.7.0/cache/faraday-2.5.2.gem
Dependency Hierarchy:
Found in base branch: master
Vulnerability Details
Faraday is an HTTP client library abstraction layer that provides a common interface over many adapters. Prior to 2.14.1, Faraday's build_exclusive_url method (in lib/faraday/connection.rb) uses Ruby's URI#merge to combine the connection's base URL with a user-supplied path. Per RFC 3986, protocol-relative URLs (e.g. //evil.com/path) are treated as network-path references that override the base URL's host/authority component. This means that if any application passes user-controlled input to Faraday's get(), post(), build_url(), or other request methods, an attacker can supply a protocol-relative URL like //attacker.com/endpoint to redirect the request to an arbitrary host, enabling Server-Side Request Forgery (SSRF). This vulnerability is fixed in 2.14.1.
Publish Date: 2026-02-09
URL: CVE-2026-25765
CVSS 3 Score Details (5.8)
Base Score Metrics:
- Exploitability Metrics:
- Attack Vector: Network
- Attack Complexity: Low
- Privileges Required: None
- User Interaction: None
- Scope: Changed
- Impact Metrics:
- Confidentiality Impact: Low
- Integrity Impact: None
- Availability Impact: None
For more information on CVSS3 Scores, click here.Suggested Fix
Type: Upgrade version
Origin: GHSA-33mh-2634-fwr2
Release Date: 2026-02-09
Fix Resolution: https://github.com/lostisland/faraday.git - v2.14.1,faraday - 2.14.1
Step up your Open Source Security Game with Mend here
Vulnerable Library - concurrent-ruby-1.1.10.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.1.10.gem
Path to dependency file: /Gemfile.lock
Path to vulnerable library: /home/wss-scanner/.gem/ruby/2.7.0/cache/concurrent-ruby-1.1.10.gem
Dependency Hierarchy:
Found in base branch: master
Vulnerability Details
Summary "Concurrent::ReentrantReadWriteLock" can incorrectly grant a write lock after one thread acquires the read lock 32,768 times. The lock stores a thread's local read and write hold counts in one integer. The low 15 bits are used for the read hold count, and bit 15 is used as "WRITE_LOCK_HELD". After 32,768 reentrant read acquisitions, the local read count crosses into the write-lock bit. "try_write_lock" then treats the thread as already holding a write lock and returns "true" without setting the global "RUNNING_WRITER" bit. This breaks the core mutual-exclusion guarantee: the caller is told it has a write lock, but other threads can still hold or acquire read locks at the same time. Version Software: concurrent-ruby Version: 1.3.6 Commit: 7a1b78941c081106c20a9ca0144ac73a48d254ab Details The implementation uses a shared counter to track global readers/writers and a per-thread local counter to support reentrancy: READER_BITS = 15 WRITER_BITS = 14 WAITING_WRITER = 1 << READER_BITS RUNNING_WRITER = 1 << (READER_BITS + WRITER_BITS) MAX_READERS = WAITING_WRITER - 1 MAX_WRITERS = RUNNING_WRITER - MAX_READERS - 1 WRITE_LOCK_HELD = 1 << READER_BITS READ_LOCK_MASK = WRITE_LOCK_HELD - 1 WRITE_LOCK_MASK = MAX_WRITERS When a thread already holds a lock, "acquire_read_lock" increments "@HeldCount": if (held = @HeldCount.value) > 0 if held & READ_LOCK_MASK == 0 @Counter.update { |c| c + 1 } end @HeldCount.value = held + 1 return true end After 32,768 read acquisitions, the per-thread held count becomes "32768", which is equal to "WRITE_LOCK_HELD". Then "try_write_lock" returns success through its "already have a write lock" branch: def try_write_lock if (held = @HeldCount.value) >= WRITE_LOCK_HELD @HeldCount.value = held + WRITE_LOCK_HELD return true else # normal global writer acquisition path end end This branch does not set the global "RUNNING_WRITER" bit. Other threads therefore do not observe an active writer and can continue holding or acquiring read locks while the caller believes it owns the write lock. PoC #!/usr/bin/env ruby frozen_string_literal: true require 'concurrent/atomic/reentrant_read_write_lock' require 'concurrent/version' require 'thread' def wait_for_queue(queue, timeout_seconds) deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + timeout_seconds loop do return queue.pop(true) rescue ThreadError return nil if Process.clock_gettime(Process::CLOCK_MONOTONIC) >= deadline sleep 0.001 end end puts "ruby=#{RUBY_DESCRIPTION}" puts "concurrent_ruby_version=#{Concurrent::VERSION}" puts "poc=ReentrantReadWriteLock read-depth overflow grants write lock without exclusivity" lock = Concurrent::ReentrantReadWriteLock.new other_reader_ready = Queue.new other_reader_stop = Queue.new other_reader = Thread.new do lock.acquire_read_lock other_reader_ready << :held other_reader_stop.pop end wait_for_queue(other_reader_ready, 1) puts "other_thread_holds_read_lock=true" depth = Concurrent::ReentrantReadWriteLock::WRITE_LOCK_HELD depth.times { lock.acquire_read_lock } held_count = lock.instance_eval { @HeldCount.value } counter_before = lock.instance_eval { @Counter.value } puts "main_thread_read_acquisitions=#{depth}" puts "main_thread_held_count=#{held_count}" puts "counter_before_try_write=#{counter_before}" puts "running_writer_bit_before=#{(counter_before & Concurrent::ReentrantReadWriteLock::RUNNING_WRITER) != 0}" write_granted = lock.try_write_lock counter_after = lock.instance_eval { @Counter.value } puts "try_write_lock_returned=#{write_granted}" puts "counter_after_try_write=#{counter_after}" puts "running_writer_bit_after=#{(counter_after & Concurrent::ReentrantReadWriteLock::RUNNING_WRITER) != 0}" third_reader_ready = Queue.new third_reader = Thread.new do lock.acquire_read_lock third_reader_ready << :acquired end third_reader_acquired = wait_for_queue(third_reader_ready, 0.25) == :acquired puts "new_reader_acquired_while_write_claimed=#{third_reader_acquired}" if write_granted && third_reader_acquired && (counter_after & Concurrent::ReentrantReadWriteLock::RUNNING_WRITER).zero? puts 'result=REPRODUCED write lock granted without setting global writer state' else puts 'result=NOT_REPRODUCED' end third_reader.kill other_reader_stop << :stop other_reader.kill Log evidence ruby=ruby 2.6.10p210 (2022-04-12 revision 67958) [universal.arm64e-darwin25] concurrent_ruby_version=1.3.6 poc=ReentrantReadWriteLock read-depth overflow grants write lock without exclusivity other_thread_holds_read_lock=true main_thread_read_acquisitions=32768 main_thread_held_count=32768 counter_before_try_write=2 running_writer_bit_before=false try_write_lock_returned=true counter_after_try_write=2 running_writer_bit_after=false new_reader_acquired_while_write_claimed=true result=REPRODUCED write lock granted without setting global writer state Impact This breaks the write-lock exclusivity guarantee. After the overflow, a thread can be told it has acquired the write lock while other threads can still hold or acquire read locks, allowing races and inconsistent reads of protected mutable state. Credit Pranjali Thakur - depthfirst ("depthfirst.com" (http://depthfirst.com))
Publish Date: 2026-06-19
URL: CVE-2026-54905
CVSS 3 Score Details (5.3)
Base Score Metrics:
- Exploitability Metrics:
- Attack Vector: Local
- Attack Complexity: Low
- Privileges Required: Low
- User Interaction: None
- Scope: Unchanged
- Impact Metrics:
- Confidentiality Impact: Low
- Integrity Impact: Low
- Availability Impact: Low
For more information on CVSS3 Scores, click here.Suggested Fix
Type: Upgrade version
Origin: GHSA-wv3x-4vxv-whpp
Release Date: 2026-06-19
Fix Resolution: concurrent-ruby - 1.3.7
Step up your Open Source Security Game with Mend here
Vulnerable Library - rexml-3.2.5.gem
An XML toolkit for Ruby
Library home page: https://rubygems.org/gems/rexml-3.2.5.gem
Path to dependency file: /Gemfile.lock
Path to vulnerable library: /home/wss-scanner/.gem/ruby/2.7.0/cache/rexml-3.2.5.gem
Dependency Hierarchy:
Found in base branch: master
Vulnerability Details
REXML is an XML toolkit for Ruby. The REXML gem 3.3.2 has a DoS vulnerability when it parses an XML that has many entity expansions with SAX2 or pull parser API. The REXML gem 3.3.3 or later include the patch to fix the vulnerability.
Publish Date: 2024-08-01
URL: CVE-2024-41946
CVSS 3 Score Details (5.3)
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: Low
For more information on CVSS3 Scores, click here.Suggested Fix
Type: Upgrade version
Origin: GHSA-5866-49gr-22v4
Release Date: 2024-08-01
Fix Resolution: rexml - 3.3.3
Step up your Open Source Security Game with Mend here
Vulnerable Library - rexml-3.2.5.gem
An XML toolkit for Ruby
Library home page: https://rubygems.org/gems/rexml-3.2.5.gem
Path to dependency file: /Gemfile.lock
Path to vulnerable library: /home/wss-scanner/.gem/ruby/2.7.0/cache/rexml-3.2.5.gem
Dependency Hierarchy:
Found in base branch: master
Vulnerability Details
REXML is an XML toolkit for Ruby. The REXML gem before 3.3.2 has some DoS vulnerabilities when it parses an XML that has many specific characters such as whitespace character,
>]and]>. The REXML gem 3.3.3 or later include the patches to fix these vulnerabilities.Publish Date: 2024-08-01
URL: CVE-2024-41123
CVSS 3 Score Details (5.3)
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: Low
For more information on CVSS3 Scores, click here.Suggested Fix
Type: Upgrade version
Origin: GHSA-r55c-59qm-vjw6
Release Date: 2024-08-01
Fix Resolution: rexml - 3.3.3
Step up your Open Source Security Game with Mend here
Vulnerable Library - rexml-3.2.5.gem
An XML toolkit for Ruby
Library home page: https://rubygems.org/gems/rexml-3.2.5.gem
Path to dependency file: /Gemfile.lock
Path to vulnerable library: /home/wss-scanner/.gem/ruby/2.7.0/cache/rexml-3.2.5.gem
Dependency Hierarchy:
Found in base branch: master
Vulnerability Details
REXML is an XML toolkit for Ruby. The REXML gem before 3.2.6 has a denial of service vulnerability when it parses an XML that has many "<"s in an attribute value. Those who need to parse untrusted XMLs may be impacted to this vulnerability. The REXML gem 3.2.7 or later include the patch to fix this vulnerability. As a workaround, don't parse untrusted XMLs.
Publish Date: 2024-05-16
URL: CVE-2024-35176
CVSS 3 Score Details (5.3)
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: Low
For more information on CVSS3 Scores, click here.Suggested Fix
Type: Upgrade version
Origin: GHSA-vg3r-rm7w-2xgh
Release Date: 2024-05-16
Fix Resolution: rexml - 3.2.7
Step up your Open Source Security Game with Mend here
Vulnerable Library - rexml-3.2.5.gem
An XML toolkit for Ruby
Library home page: https://rubygems.org/gems/rexml-3.2.5.gem
Path to dependency file: /Gemfile.lock
Path to vulnerable library: /home/wss-scanner/.gem/ruby/2.7.0/cache/rexml-3.2.5.gem
Dependency Hierarchy:
Found in base branch: master
Vulnerability Details
REXML is an XML toolkit for Ruby. The REXML gem before 3.3.1 has some DoS vulnerabilities when it parses an XML that has many specific characters such as
<,0and%>. If you need to parse untrusted XMLs, you many be impacted to these vulnerabilities. The REXML gem 3.3.2 or later include the patches to fix these vulnerabilities. Users are advised to upgrade. Users unable to upgrade should avoid parsing untrusted XML strings.Publish Date: 2024-07-16
URL: CVE-2024-39908
CVSS 3 Score Details (4.3)
Base Score Metrics:
- Exploitability Metrics:
- Attack Vector: Network
- Attack Complexity: Low
- Privileges Required: None
- User Interaction: Required
- Scope: Unchanged
- Impact Metrics:
- Confidentiality Impact: None
- Integrity Impact: None
- Availability Impact: Low
For more information on CVSS3 Scores, click here.Suggested Fix
Type: Upgrade version
Origin: GHSA-4xqq-m2hx-25v8
Release Date: 2024-07-16
Fix Resolution: rexml - 3.3.2
Step up your Open Source Security Game with Mend here
Vulnerable Library - concurrent-ruby-1.1.10.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.1.10.gem
Path to dependency file: /Gemfile.lock
Path to vulnerable library: /home/wss-scanner/.gem/ruby/2.7.0/cache/concurrent-ruby-1.1.10.gem
Dependency Hierarchy:
Found in base branch: master
Vulnerability Details
Summary "Concurrent::ReadWriteLock#release_write_lock" does not verify that the calling thread acquired the write lock. Any thread with access to the lock object can release an active write lock held by another thread. A second writer can then enter its critical section while the first writer is still running. "Concurrent::ReadWriteLock#release_read_lock" also decrements the shared counter even when no read lock is held. Calling it on a fresh lock changes the counter from "0" to "-1", after which normal read acquisition raises "Concurrent::ResourceLimitError". This is a synchronization correctness issue in the public "Concurrent::ReadWriteLock" API. It should not be framed as an authorization bypass; the lock is an in-process concurrency primitive, not an access-control boundary. Version Software: concurrent-ruby Version: 1.3.6 Commit: 7a1b78941c081106c20a9ca0144ac73a48d254ab Details "release_write_lock" checks only whether the global counter indicates that a writer is running. It does not track or verify ownership: def release_write_lock return true unless running_writer? c = @Counter.update { |counter| counter - RUNNING_WRITER } @ReadLock.broadcast @WriteLock.signal if waiting_writers(c) > 0 true end Because ownership is not checked, a different thread can clear the "RUNNING_WRITER" bit while the original writer is still inside its critical section. Another writer can then acquire the write lock and run concurrently with the first writer. "release_read_lock" unconditionally decrements the shared counter: def release_read_lock while true c = @Counter.value if @Counter.compare_and_set(c, c-1) if waiting_writer?(c) && running_readers(c) == 1 @WriteLock.signal end break end end true end On a fresh lock, this changes the counter from "0" to "-1". A later "acquire_read_lock" raises "Concurrent::ResourceLimitError" because the maximum-reader check masks the negative counter as saturated. Reproduce From the root of a "concurrent-ruby" checkout, run: ruby -Ilib/concurrent-ruby - <<'RUBY' require 'concurrent/atomic/read_write_lock' require 'concurrent/version' require 'thread' puts "ruby=#{RUBY_DESCRIPTION}" puts "concurrent_ruby_version=#{Concurrent::VERSION}" puts "poc=ReadWriteLock release methods corrupt or bypass lock state" lock = Concurrent::ReadWriteLock.new events = Queue.new writer1_inside = false writer1 = Thread.new do lock.acquire_write_lock writer1_inside = true events << :writer1_acquired sleep 0.5 writer1_inside = false lock.release_write_lock events << :writer1_finished end events.pop puts 'writer1_acquired=true' intruder_result = nil intruder = Thread.new do intruder_result = lock.release_write_lock end intruder.join puts "wrong_thread_release_write_lock_returned=#{intruder_result}" writer2_entered_while_writer1_inside = nil writer2 = Thread.new do lock.acquire_write_lock writer2_entered_while_writer1_inside = writer1_inside lock.release_write_lock end writer2.join(0.25) puts "writer2_acquired_while_writer1_inside=#{writer2_entered_while_writer1_inside}" writer1.join lock2 = Concurrent::ReadWriteLock.new stray_read_release_result = lock2.release_read_lock counter_after_stray_read_release = lock2.instance_eval { @Counter.value } read_after_stray_release = begin lock2.acquire_read_lock 'acquired' rescue => error "#{error.class}: #{error.message}" end puts "stray_release_read_lock_returned=#{stray_read_release_result}" puts "counter_after_stray_read_release=#{counter_after_stray_read_release}" puts "acquire_read_after_stray_release=#{read_after_stray_release}" if intruder_result && writer2_entered_while_writer1_inside && counter_after_stray_read_release == -1 puts 'result=REPRODUCED wrong-thread write release and stray read-release corruption' else puts 'result=NOT_REPRODUCED' end Expected result: - A second thread successfully calls "release_write_lock" while the first writer still holds the lock. - A second writer enters while the first writer is still inside the write critical section. - Calling "release_read_lock" on a fresh lock changes the counter to "-1". - A subsequent read acquisition fails with "Concurrent::ResourceLimitError". Log evidence Local reproduction output: ruby=ruby 2.6.10p210 (2022-04-12 revision 67958) [universal.arm64e-darwin25] concurrent_ruby_version=1.3.6 poc=ReadWriteLock release methods corrupt or bypass lock state writer1_acquired=true wrong_thread_release_write_lock_returned=true writer2_acquired_while_writer1_inside=true stray_release_read_lock_returned=true counter_after_stray_read_release=-1 acquire_read_after_stray_release=Concurrent::ResourceLimitError: Too many reader threads result=REPRODUCED wrong-thread write release and stray read-release corruption Impact This can break the write-lock mutual exclusion guarantee and can also leave a lock unusable after a stray read release. The impact is local to applications that expose or misuse the manual "acquire_" / "release_" APIs. If the lock protects integrity-sensitive mutable state, wrong-thread write release can allow concurrent writers and data races. The stray read-release path can cause denial of service by corrupting the lock counter. Credit Pranjali Thakur - depthfirst ("depthfirst.com" (http://depthfirst.com))
Publish Date: 2026-06-19
URL: CVE-2026-54906
CVSS 3 Score Details (4.0)
Base Score Metrics:
- Exploitability Metrics:
- Attack Vector: Local
- Attack Complexity: High
- Privileges Required: None
- User Interaction: None
- Scope: Unchanged
- Impact Metrics:
- Confidentiality Impact: None
- Integrity Impact: Low
- Availability Impact: Low
For more information on CVSS3 Scores, click here.Suggested Fix
Type: Upgrade version
Origin: GHSA-6wx8-w4f5-wwcr
Release Date: 2026-06-19
Fix Resolution: concurrent-ruby - 1.3.7
Step up your Open Source Security Game with Mend here
Vulnerable Library - faraday-2.5.2.gem
Library home page: https://rubygems.org/gems/faraday-2.5.2.gem
Path to dependency file: /Gemfile.lock
Path to vulnerable library: /home/wss-scanner/.gem/ruby/2.7.0/cache/faraday-2.5.2.gem
Dependency Hierarchy:
Found in base branch: master
Vulnerability Details
Faraday is an HTTP client library abstraction layer that provides a common interface over many adapters. Versions 2.0.0 through 2.14.1 still allow protocol-relative host override when the request target is passed as a URI object (rather than a String) to Faraday::Connection#build_exclusive_url. This bypasses the February 2026 fix for GHSA-33mh-2634-fwr2 and enables off-host request forgery: a request built from a fixed-base Faraday::Connection can be redirected to an attacker-controlled host, forwarding connection-scoped values such as Authorization headers and default query parameters. This issue has been fixed in version 2.14.3.
Publish Date: 2026-05-19
URL: CVE-2026-33637
CVSS 3 Score Details (0.0)
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: None
For more information on CVSS3 Scores, click here.Suggested Fix
Type: Upgrade version
Origin: GHSA-5rv5-xj5j-3484
Release Date: 2026-05-18
Fix Resolution: faraday - 2.14.2
Step up your Open Source Security Game with Mend here