twilio / twilio-ruby

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

[BUG] NoMethodError: undefined method `ascii_only?' for nil:NilClass #613

Closed wjlroe closed 2 years ago

wjlroe commented 2 years ago

Issue Summary

The RequestValidator can raise an exception when it tries to validate requests that don't have any query parameters in the url and pass a non-enumerable (e.g. the POST body as a string) value as the params.

This happens because internally it uses parsed_url = URI(url) and then URI.decode_www_form(parsed_url.query) - without checking whether parsed_url.query is nil.

We haven't seen this occur very frequently and we didn't have enough logging last time it occured to be specific as to the arguments passed to validate when it happened to us. But since this method should be able to validate whether a request originated from Twilio or not, it should be resilient to issues such as this.

In our specific code, we call it like this (simplified):

validator = ::Twilio::Security::RequestValidator.new(twilio_auth_token)
validator.validate(request.url, env['rack.request.form_hash'], env['HTTP_X_TWILIO_SIGNATURE'])

The above code is part of a Sinatra extension so env and request should be understood within that context.

And in order to trigger the NoMethodError, request.url would have no query parameters at all and env['rack.request.form_hash'] would need to not be enumerable after being interogated by RequestValidator#body_or_hash. That method has documentation indicating its use relative to versions of Rails, however we are using this code in the context of Sinatra and Rack, not Rails.

Steps to Reproduce

The code snippet shows a working example of this bug in action

Code Snippet

require 'twilio-ruby'
validator = ::Twilio::Security::RequestValidator.new('twilio-auth-token')
validator.validate('http://example.com', '', 'signature')

Exception/Log

Exception: NoMethodError: undefined method `ascii_only?' for nil:NilClass
--
0: ~/.rubies/ruby-2.7.3/lib/ruby/2.7.0/uri/common.rb:455:in `decode_www_form'
1: ~/.gem/ruby/2.7.3/gems/twilio-ruby-5.67.0/lib/twilio-ruby/security/request_validator.rb:35:in `validate'

Technical details:

childish-sambino commented 2 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 (ref: DI-2242).