twilio / twilio-ruby

A Ruby gem for communicating with the Twilio API and generating TwiML
MIT License
1.36k stars 464 forks source link

When there is an apostrophe in the body the validation of the webhook fails #528

Open theghall opened 4 years ago

theghall commented 4 years ago

Issue Summary

An apostrophe in the body of a text message causes validation of Twilio webhook to fail

Steps to Reproduce

  1. Send a text message with an apostrophe in it
  2. try to validate the incoming webhook

Code Snippet

    twilio_signature = env["HTTP_X_TWILIO_SIGNATURE"]
        url = "#{rack_request.scheme}://" + env["HTTP_HOST"] + env["REQUEST_URI"]
        unless validator.validate(url, {}, twilio_signature)
          raise "Twilio request validation failed."
        end

Technical details:

theghall commented 4 years ago

Debugging a little it appears as if the gem encodes the ' as %27 via URI, whereas the signature generated by Twilio did not encode the ' as %27. Because if I do the calculation to generate the signature keeping the ' as ', I get the signatures to match.

eshanholtz commented 4 years ago

This issue has been added to our internal backlog to be prioritized. Pull requests and +1s on the issue summary will help it move up the backlog.

theghall commented 4 years ago

Twilio support gave me the workaround of making the Webhook a POST instead of a GET. My code is now as follows:

      # Need this because env['rack.url_scheme'] is only for the last leg of the journey,
      # Rack::Request#scheme gets us the scheme of the real request
      rack_request = Rack::Request.new(env)

     validator = Twilio::Security::RequestValidator.new(ENV["MEMBERS_TWILIO_SECRET"])
     twilio_signature = env["HTTP_X_TWILIO_SIGNATURE"]
     url = "#{rack_request.scheme}://" + env["HTTP_HOST"] + env["REQUEST_URI"]
     # params arg: Use rack_request.params for POST request.  Use {} for GET request
     unless validator.validate(url, rack_request.params, twilio_signature)
        raise "Twilio request validation failed."
    end
ramonrovirosa commented 2 years ago

Same issue described above was happening to me. It was happening because the url contained a query parameter that had an apostraphe in the value e.g. the url had an apostraphe that was encoded with %27 https://www.example.com?name=O%27Malley

The fix for me was to double encode the query parameters before sending the request to twilio. e.g. https://www.example.com?name=O%2527Malley And then make sure to do an extra decoding on the callback query params on my backend

If the signature generated by Twilio decodes special charecters including those in the url as query parameter values, the library should do decoding along with parsing on validate https://github.com/twilio/twilio-ruby/blob/main/lib/twilio-ruby/security/request_validator.rb#L27