← Back to Feed CACHED · 2026-05-17 09:42:19 · cache_key CVE-2025-29912
CVE-2026-46727 · CWE-362 · Disclosed 2026-05-22

Ruby 4 before 4

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
01 · The Real Story

This is less a wide-open front door and more a tripwire hidden in one hallway

CVE-2026-46727 is a race-condition-driven use-after-free in Ruby's pthread-based getaddrinfo timeout handler. In plain terms: if an application on Ruby 4.0.0 through 4.0.4 calls Addrinfo.getaddrinfo(..., timeout:) or Socket.tcp(..., resolv_timeout:), and an attacker can make DNS replies land right around the timeout boundary, the Ruby process can dereference freed memory and crash. Ruby upstream says Ruby 3.4 and earlier are not affected, and the fix lands in Ruby 4.0.5; 4.1.0-dev before the fix was also affected in development builds.

The vendor's HIGH 8.1 score prices in the worst-case memory-corruption potential, but that overshoots most real deployments. The decisive friction is that this is not generic unauthenticated internet-to-RCE: the attacker typically needs influence over DNS timing or a malicious resolver path, the target must actually use the vulnerable timeout-bearing APIs, and the currently documented outcome is a process crash, while code execution remains theoretical. For a 10,000-host estate, this is a selective reliability and availability issue, not an all-hands perimeter fire.

"This looks scary on paper, but the exploit chain is narrow: specific Ruby 4 code paths, timeout use, and DNS-path influence."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Gain DNS-path influence

The attacker needs to control or substantially influence name resolution timing for the victim application's outbound lookup path. In practice that means a crafted authoritative DNS server, a hostile recursive resolver, or a man-in-the-middle position able to delay DNS responses with tooling such as CoreDNS or dnsdist. This is the biggest reality check in the whole chain: most internet attackers do not control your resolver path.
Conditions required:
  • Unauthenticated remote position is not enough by itself; attacker must influence authoritative or recursive DNS behavior
  • Target application must resolve attacker-chosen or attacker-influenced hostnames
  • Victim network must permit DNS lookups through the affected path
Where this breaks in practice:
  • Most enterprises use fixed internal recursive resolvers, reducing direct attacker control
  • Applications often resolve stable internal or allowlisted names, not attacker-chosen domains
  • Egress filtering, split-horizon DNS, or private service discovery can remove the attacker from the lookup path
Detection/coverage: Traditional vuln scanners do not prove exploitability here. DNS telemetry, passive DNS, and resolver logs are more useful than banner scans.
STEP 02

Hit the vulnerable Ruby code path

The target process must be running Ruby 4.0.0–4.0.4 and must call Addrinfo.getaddrinfo(..., timeout:) or Socket.tcp(..., resolv_timeout:). An attacker would typically exercise this with application traffic that triggers outbound connection attempts or hostname resolution. Tooling is mundane here—just the app's own request flow plus a DNS server that can shape latency.
Conditions required:
  • Ruby runtime version in affected range
  • Application uses the affected APIs with explicit timeout options
  • Attacker can trigger the relevant application behavior remotely
Where this breaks in practice:
  • Many Ruby estates will still be on 3.x, which upstream marks unaffected
  • Not every app passes timeout: or resolv_timeout: at all
  • Some vulnerable hosts may be build tools or workers, not internet-reachable services
Detection/coverage: SBOM/package scans and local version inspection can find candidate hosts, but static detection usually cannot confirm whether the dangerous API options are actually used.
STEP 03

Win the race at the timeout boundary

The exploit primitive depends on a narrow race in the timeout-cancellation path of rb_getaddrinfo. The attacker delays the DNS response so it arrives near the configured timeout, attempting to force use-after-free behavior. A lab setup could use Scapy or a customized DNS server to tune response timing, but this is still high-complexity exploitation.
Conditions required:
  • Predictable enough timeout values and network timing
  • Repeated attempts against a stable target path
  • The process remains reachable long enough for race attempts
Where this breaks in practice:
  • Race windows are timing-sensitive and environment-dependent
  • Container scheduling, resolver caching, retries, and network jitter reduce reliability
  • Successful reproduction in one environment does not guarantee portability
Detection/coverage: You may see bursts of failed lookups, unusual timeout patterns, and application crashes, but there is no broadly reliable network signature for the race itself.
STEP 04

Crash the process; anything beyond that is speculative

Ruby upstream explicitly documents that an attacker may cause the process to dereference freed memory and crash. NVD notes that memory-corruption-based exploitation is theoretically possible, but there is no public evidence in the sources reviewed of weaponized RCE. For most defenders, the practical impact to plan around is availability loss of the targeted Ruby service.
Conditions required:
  • The race condition is triggered successfully
  • The vulnerable process handles the bad state without prior termination or recovery
Where this breaks in practice:
  • Observed and vendor-described impact is crash, not demonstrated code execution
  • Modern memory allocators and runtime behavior may make controlled exploitation much harder than simple process termination
Detection/coverage: EDR and crash telemetry can catch segfaults/abnormal exits after the fact. External scanners generally miss this unless they actively exercise the vulnerable path.
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo evidence found of active exploitation in the reviewed primary sources; not KEV-listed.
Proof-of-concept availabilityNo public PoC located in the reviewed sources. The underlying report is referenced via HackerOne report 3607434, but public exploit code was not confirmed.
EPSS0.00161 from the user-provided intel, which is extremely low in absolute probability terms; percentile was not independently confirmed from an authoritative EPSS query during this assessment.
KEV statusNo. The CISA KEV catalog did not show this CVE in the reviewed sources.
CVSS vectorCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H — the key flag is AC:H. That high complexity is not cosmetic here; timing control and DNS-path influence are real exploit friction.
Affected versionsUpstream lists Ruby 4.0.0 through 4.0.4 and Ruby 4.1.0-dev before the fix as affected; Ruby 3.4 and earlier are not affected.
Fixed versionsUpstream fix is Ruby 4.0.5 or later. Distros may eventually backport fixes without exposing the upstream version number, so package-level validation matters on managed Linux builds.
Scanning and exposure realityThere is no meaningful internet-banner census for this bug. Shodan/Censys-style exposure counts are poor proxies because this is a runtime/API-path issue inside Ruby applications, not a directly fingerprintable network service version.
Disclosure timelineRuby published the advisory on 2026-05-20; NVD shows the CVE published on 2026-05-22.
Reporter / patch creditDiscovery credited by Ruby to cantina-security; patch credit goes to shioimm.
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to MEDIUM (5.4/10)

The single most important downgrading factor is attacker position and path control: this is only reachable when the attacker can influence DNS timing against a very specific Ruby 4 code path. That sharply narrows the exposed population, and the documented real-world impact is a crash, not demonstrated remote code execution.

HIGH Affected-version range and fixed release
MEDIUM Practical exploitability in typical enterprise deployments
LOW Whether memory-corruption exploitation is achievable beyond denial of service

Why this verdict

  • Downgrade for attacker path control: vendor starts at 8.1, but real exploitation usually requires influence over authoritative/recursive DNS timing, which implies a narrower attacker position than plain internet reachability.
  • Downgrade for conditional code reachability: only Ruby 4.0.0–4.0.4 is affected, and only when applications call Addrinfo.getaddrinfo(..., timeout:) or Socket.tcp(..., resolv_timeout:); that is not the default shape of every Ruby deployment.
  • Downgrade for observed impact: upstream explicitly describes process crash, while NVD says memory-corruption exploitation is only *theoretically possible*; absent a public RCE chain or active exploitation, availability is the practical planning assumption.

Why not higher?

This is not a broad, low-friction perimeter bug. The exploit path compounds several prerequisites: affected Ruby 4 adoption, a timeout-bearing API call, attacker influence over DNS timing, and then winning a race. That combination is enough friction to keep it out of HIGH despite the scary memory-corruption label.

Why not lower?

It still deserves attention because the bug is remotely triggerable in the right application pattern and can take down a production Ruby process. For organizations running Ruby 4 services that make attacker-influenced outbound lookups with explicit resolver timeouts, the availability impact is real enough that calling it LOW would understate operational risk.

05 · Compensating Control

What to do — in priority order.

  1. Inventory Ruby 4 estates — Find hosts, containers, CI runners, and app images carrying Ruby 4.0.0–4.0.4 and map which services are internet-facing or process attacker-influenced hostnames. For a MEDIUM verdict there is no mitigation SLA, but do this during normal vulnerability hygiene and feed the actual patch plan into the 365-day remediation window.
  2. Remove vulnerable timeout usage where feasible — If you own the code and cannot upgrade immediately, stop passing timeout: to Addrinfo.getaddrinfo and resolv_timeout: to Socket.tcp, exactly as Ruby upstream recommends. There is no mitigation SLA for MEDIUM here, so treat this as a risk-reduction option rather than an emergency outage-control mandate.
  3. Constrain DNS trust paths — Force application egress through trusted internal recursive resolvers, block ad hoc resolver use, and review services that resolve attacker-supplied hostnames. This matters because the exploit chain becomes much less realistic when the attacker cannot shape DNS timing; implement as standard hardening within the same 365-day remediation window.
  4. Alert on crash patterns — Add monitoring for Ruby worker restarts, segfaults, lookup timeouts, and bursts of failed DNS resolution in affected services. This will not prevent exploitation, but it improves detection of attempted crash-inducing activity while you work through remediation.
What doesn't work
  • A generic WAF does little here because the dangerous condition is in outbound DNS resolution timing inside the application, not a simple inbound HTTP signature.
  • Relying only on external vuln scanning will miss the real exposure question; scanners can spot Ruby versions, but they usually cannot prove that the app uses the vulnerable timeout-bearing APIs.
  • Assuming 'not internet-exposed' means safe is sloppy for worker tiers; background jobs and internal services may still resolve attacker-influenced hostnames and hit the vulnerable path.
06 · Verification

Crowdsourced verification payload.

Run this on the target Linux or macOS host that has the Ruby interpreter installed, or inside the affected container image. Invoke it as bash check_cve_2026_46727.sh /usr/bin/ruby or simply bash check_cve_2026_46727.sh to use ruby from PATH; no root is required, but package-manager metadata checks may return more detail when available.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check_cve_2026_46727.sh
# Determine likely exposure to CVE-2026-46727 based on local Ruby version.
# Outputs one of: VULNERABLE / PATCHED / UNKNOWN
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN

set -u

RUBY_BIN="${1:-ruby}"

have_cmd() {
  command -v "$1" >/dev/null 2>&1
}

version_ge() {
  # returns 0 if $1 >= $2
  [ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | tail -n1)" = "$1" ]
}

version_gt() {
  # returns 0 if $1 > $2
  [ "$1" != "$2" ] && version_ge "$1" "$2"
}

version_lt() {
  # returns 0 if $1 < $2
  ! version_ge "$1" "$2"
}

if ! have_cmd "$RUBY_BIN"; then
  echo "UNKNOWN - ruby binary not found: $RUBY_BIN"
  exit 2
fi

RAW_VER="$($RUBY_BIN -e 'print RUBY_VERSION' 2>/dev/null)"
if [ -z "$RAW_VER" ]; then
  echo "UNKNOWN - unable to read RUBY_VERSION from $RUBY_BIN"
  exit 2
fi

# Upstream advisory scope:
#   affected: 4.0.0 through 4.0.4
#   fixed:    4.0.5+
#   unaffected: 3.4 and earlier

if version_ge "$RAW_VER" "4.0.0" && version_lt "$RAW_VER" "4.0.5"; then
  PKG_HINT=""
  if have_cmd dpkg-query; then
    PKG_HINT="; distro package backports are possible, verify package changelog if this is vendor-managed"
  elif have_cmd rpm; then
    PKG_HINT="; distro package backports are possible, verify rpm changelog if this is vendor-managed"
  fi
  echo "VULNERABLE - Ruby version $RAW_VER is in upstream affected range 4.0.0-4.0.4$PKG_HINT"
  exit 1
fi

if version_ge "$RAW_VER" "4.0.5"; then
  echo "PATCHED - Ruby version $RAW_VER is at or above upstream fixed version 4.0.5"
  exit 0
fi

if version_lt "$RAW_VER" "4.0.0"; then
  echo "PATCHED - Ruby version $RAW_VER is below Ruby 4 and outside upstream affected range"
  exit 0
fi

# Catch development/pre-release or unusual builds that don't compare cleanly to stable semantics.
echo "UNKNOWN - Ruby version $RAW_VER could not be mapped cleanly to the upstream advisory; verify whether this is a 4.1.0-dev build before the fix"
exit 2
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning, do not treat this like an emergency perimeter RCE. First, inventory where Ruby 4.0.0–4.0.4 actually exists and which apps use the timeout-bearing resolver calls; for a MEDIUM verdict there is no noisgate mitigation SLA — go straight to the 365-day remediation window unless your own exposure review shows attacker-influenced DNS resolution on production-facing services. Then patch those confirmed instances to Ruby 4.0.5+ within the noisgate remediation SLA of ≤ 365 days, and, where upgrade lag exists, remove the vulnerable timeout arguments or lock DNS to trusted internal resolvers as sensible hardening rather than as an incident response drill.

Sources

  1. Ruby security advisory for CVE-2026-46727
  2. Ruby 4.0.5 release announcement
  3. NVD entry for CVE-2026-46727
  4. CVE Record page
  5. CISA Known Exploited Vulnerabilities catalog
  6. FIRST EPSS overview
  7. FIRST EPSS API documentation
  8. Ubuntu CVE tracker search result for CVE-2026-46727
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.