From 29aca25218e4c82991400eb9b0c933626aefc98f Mon Sep 17 00:00:00 2001 From: Mikel Lindsaar Date: Wed, 14 Mar 2012 22:44:27 +1100 Subject: [PATCH] Preventing file system traversal in file_delivery method --- .../network/delivery_methods/file_delivery.rb | 4 ++-- .../delivery_methods/file_delivery_spec.rb | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/lib/mail/network/delivery_methods/file_delivery.rb b/lib/mail/network/delivery_methods/file_delivery.rb index fc3e3b2f9..fec750a0b 100644 --- a/lib/mail/network/delivery_methods/file_delivery.rb +++ b/lib/mail/network/delivery_methods/file_delivery.rb @@ -6,7 +6,7 @@ module Mail # So if you have an email going to fred@test, bob@test, joe@anothertest, and you # set your location path to /path/to/mails then FileDelivery will create the directory # if it does not exist, and put one copy of the email in three files, called - # "fred@test", "bob@test" and "joe@anothertest" + # by their message id # # Make sure the path you specify with :location is writable by the Ruby process # running Mail. @@ -32,7 +32,7 @@ def deliver!(mail) end mail.destinations.uniq.each do |to| - ::File.open(::File.join(settings[:location], to), 'a') { |f| "#{f.write(mail.encoded)}\r\n\r\n" } + ::File.open(::File.join(settings[:location], File.basename(to.to_s)), 'a') { |f| "#{f.write(mail.encoded)}\r\n\r\n" } end end diff --git a/spec/mail/network/delivery_methods/file_delivery_spec.rb b/spec/mail/network/delivery_methods/file_delivery_spec.rb index 10d16eb85..5aed80069 100644 --- a/spec/mail/network/delivery_methods/file_delivery_spec.rb +++ b/spec/mail/network/delivery_methods/file_delivery_spec.rb @@ -74,6 +74,21 @@ File.exists?(delivery).should be_true end + it "should use the base name of the file name to prevent file system traversal" do + Mail.defaults do + delivery_method :file, :location => tmpdir + end + + Mail.deliver do + from 'roger@moore.com' + to '../../../../../../../../../../../tmp/pwn' + subject 'evil hacker' + end + + delivery = File.join(Mail.delivery_method.settings[:location], 'pwn') + File.exists?(delivery).should be_true + end + end end