diff --git a/lib/sinatra/base.rb b/lib/sinatra/base.rb index 56150f30c7..f5175916bc 100644 --- a/lib/sinatra/base.rb +++ b/lib/sinatra/base.rb @@ -884,7 +884,9 @@ def metadef(message, &block) # static files route get(/.*[^\/]$/) do pass unless options.static? && options.public? - path = options.public + unescape(request.path_info) + public_dir = File.expand_path(options.public) + path = File.expand_path(public_dir + unescape(request.path_info)) + pass if path[0, public_dir.length] != public_dir pass unless File.file?(path) send_file path, :disposition => nil end diff --git a/test/static_test.rb b/test/static_test.rb index b79d5f9238..2fde797f5b 100644 --- a/test/static_test.rb +++ b/test/static_test.rb @@ -62,4 +62,19 @@ get "/foobarbaz.txt" assert not_found? end + + it 'serves files when .. path traverses within public directory' do + get "/data/../#{File.basename(__FILE__)}" + assert ok? + assert_equal File.read(__FILE__), body + end + + it '404s when .. path traverses outside of public directory' do + mock_app { + set :static, true + set :public, File.dirname(__FILE__) + '/data' + } + get "/../#{File.basename(__FILE__)}" + assert not_found? + end end