Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-53510

CVE-2026-53510: Savon Ruby SOAP Client RCE Vulnerability

CVE-2026-53510 is a remote code execution vulnerability in Savon Ruby SOAP client affecting versions 0.9.8 to 2.17.1. Attackers can execute arbitrary Ruby code via WSDL operation name injection. This article covers technical details, affected versions, impact, and mitigation steps.

Published:

CVE-2026-53510 Overview

CVE-2026-53510 is a code injection vulnerability [CWE-94] in Savon, a widely used Ruby SOAP client library. The flaw exists in Savon::Model.all_operations, which interpolates attacker-controlled Web Services Description Language (WSDL) operation names directly into Ruby source code passed to module_eval. This allows arbitrary Ruby code execution within the host application process. Versions from 0.9.8 up to but not including 2.17.2 are affected. The maintainers released a fix in Savon 2.17.2.

Critical Impact

An attacker who controls or tampers with a WSDL document consumed by a Savon client can execute arbitrary Ruby code in the application process, leading to full application compromise.

Affected Products

  • Savon Ruby SOAP client versions 0.9.8 through 2.17.1
  • Ruby applications using Savon::Model.all_operations with untrusted or attacker-influenced WSDL sources
  • Fixed in Savon 2.17.2

Discovery Timeline

  • 2026-07-31 - CVE-2026-53510 published to NVD
  • 2026-07-31 - Last updated in NVD database

Technical Details for CVE-2026-53510

Vulnerability Analysis

Savon is a Ruby client library for consuming Simple Object Access Protocol (SOAP) services. When an application calls Savon::Model.all_operations, Savon iterates through the operations advertised by the target service's WSDL document and dynamically defines Ruby methods that map to each SOAP operation. In the vulnerable implementation, operation names extracted from the WSDL are string-interpolated into a Ruby source snippet passed to module_eval. Because module_eval compiles and executes the resulting string as Ruby code, any Ruby syntax embedded in the operation name is executed in the context of the application process. An attacker who controls the WSDL, or can perform a machine-in-the-middle attack against WSDL retrieval over insecure transport, can therefore achieve remote code execution against the consuming service.

Root Cause

The root cause is unsafe use of module_eval with a string constructed via Ruby's %{ ... } interpolation. Both define_class_operation and define_instance_operation inlined the SOAP operation name into the evaluated source without sanitization or escaping. Operation names are supplied by the WSDL, which is external input, violating the security boundary between data and code.

Attack Vector

Exploitation requires the target Ruby application to load a WSDL that an attacker can influence. This can occur when a Savon client fetches a WSDL from an attacker-controlled host, from a compromised partner endpoint, or over an insecure channel susceptible to interception. An attacker crafts a malicious WSDL containing an operation name that closes the surrounding Ruby method definition and appends arbitrary Ruby statements. When the application invokes Savon::Model.all_operations, the malicious string is compiled and executed.

ruby
# Vulnerable pattern (pre-2.17.2) vs. fixed pattern in lib/savon/model.rb
# Source: https://github.com/savonrb/savon/commit/8f22eb543e7436f6247172c9be47e22792d375e9

    # Defines a class-level SOAP operation.
    def define_class_operation(operation)
-     class_operation_module.module_eval %{
-       def #{StringUtils.snakecase(operation.to_s)}(locals = {})
-         client.call #{operation.inspect}, locals
-       end
-     }, __FILE__, __LINE__ - 4
+     method_name = operation_method_name(operation)
+
+     class_operation_module.define_method(method_name) do |locals = {}|
+       client.call operation, locals
+     end
    end

    # Defines an instance-level SOAP operation.
    def define_instance_operation(operation)
-     instance_operation_module.module_eval %{
-       def #{StringUtils.snakecase(operation.to_s)}(locals = {})
-         self.class.#{StringUtils.snakecase(operation.to_s)} locals
-       end
-     }, __FILE__, __LINE__ - 4
+     method_name = operation_method_name(operation)
+
+     instance_operation_module.define_method(method_name) do |locals = {}|
+       self.class.public_send(method_name, locals)
+     end
    end

The patch replaces string-based module_eval with define_method, which accepts the operation name as a bound variable rather than compiling it as source code. See the GitHub commit for the full diff.

Detection Methods for CVE-2026-53510

Indicators of Compromise

  • Unexpected Ruby child processes or shell commands spawned by a Rails or Rack worker that consumes SOAP services
  • Outbound network connections from Ruby application hosts to unknown WSDL endpoints or attacker-controlled hosts
  • Anomalous file writes, credential access, or new cron entries originating from the Ruby application user
  • Stack traces or exceptions referencing Savon::Model, module_eval, or malformed operation names in application logs

Detection Strategies

  • Inventory Ruby applications and Gemfile.lock entries to identify Savon versions earlier than 2.17.2
  • Run software composition analysis against source repositories and container images to flag vulnerable gem versions
  • Instrument application logs to record the source URL of every WSDL fetched by Savon and alert on non-allowlisted destinations
  • Hunt in endpoint telemetry for Ruby processes executing interpreter, shell, or networking utilities not typical of the workload

Monitoring Recommendations

  • Monitor process lineage where the Ruby interpreter is the parent of unexpected binaries such as sh, bash, curl, or wget
  • Alert on egress traffic from application servers to WSDL hosts outside a defined allowlist
  • Track filesystem changes to application directories, SSH configurations, and scheduled task locations
  • Correlate SOAP integration errors with subsequent unusual host behavior to identify exploitation attempts

How to Mitigate CVE-2026-53510

Immediate Actions Required

  • Upgrade Savon to version 2.17.2 or later in all Ruby applications and rebuild affected container images
  • Audit code paths that call Savon::Model.all_operations and restrict them to WSDLs from trusted, authenticated sources
  • Force WSDL retrieval over HTTPS with certificate validation to prevent machine-in-the-middle tampering
  • Rotate credentials, tokens, and secrets accessible to any Ruby process that may have loaded an untrusted WSDL

Patch Information

The fix ships in Savon 2.17.2, published in the v2.17.2 release. The patch, tracked in GHSA-mx5j-mp4f-g8jg, replaces string interpolation into module_eval with define_method, eliminating the code injection sink. Update the Gemfile constraint to gem 'savon', '>= 2.17.2' and run bundle update savon.

Workarounds

  • Avoid calling Savon::Model.all_operations against WSDLs that are not fully controlled by your organization
  • Pre-fetch and pin trusted WSDL documents, then load them from a read-only local path instead of a remote URL
  • Wrap Savon initialization to validate that operation names match a strict pattern such as /\A[A-Za-z_][A-Za-z0-9_]*\z/ before use
bash
# Pin Savon to the patched version and verify the resolved gem
bundle update savon --conservative
bundle list | grep savon
# Expected output: savon (2.17.2) or later

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.