January 26, 2011

Security Issue in Mail Gem

This is an important one for anyone using Rails 3 in a production environment who hasn’t yet updated the Mail gem to version 2.2.15 or later.

A project I’m working on at the moment sends transactional e-mails via the sendmail delivery method. Some of the recipients’ e-mail addresses contain the ampersand (&) character in the local part (the bit before the @ symbol).

We started being notified of strange exceptions when the application was sending to these addresses. A quick test in the console revealed this:

ruby-1.9.2-p0 > mail.to = 'test.&.test@stevelorek.com'
 => "test.&.test@stevelorek.com" 
ruby-1.9.2-p0 > mail.deliver
sh: .test@stevelorek.com: command not found

Clearly, at some point the e-mail address is being output to the shell directly, without any escaping. We can see that the ampersand is acting as a command splitter, so everything after the ampersand is treated as a new command.

It’s good practise to sanitise and validate any user input anyway – indeed, many validations will erroneously reject an ampersand in the local part anyway. However, this still represents a serious security risk to Rails 3 applications.

The culprit was the Mail gem which Rails depends on to handle e-mail delivery. The lines responsible for this error are in lib/mail/network/delivery_methods/sendmail.rb of version 2.2.14:

def Sendmail.call(path, arguments, destinations, mail)
  IO.popen("#{path} #{arguments} #{destinations}", "w+") do |io|
    io.puts mail.encoded.to_lf
    io.flush
  end
end

After discussing this with Andy Lindeman we reported the bug to the gem’s author, Mikel Lindsaar, who quickly applied Andy’s patch and issued an announcement which was copied to the Ruby on Rails security group.

The patch also had the nice effect of making my application work with all valid e-mail addresses.

I would advise that everyone in a production environment update the Mail gem to version 2.2.15 immediately:

$ bundle update mail