Path traversal middleware stops sinatra route from matching
Closed this issue · 2 comments
In our sinatra app, we have a route like this:
get "/links-to/:site_root" do
# ...
end
Where :site_root
can be a simple domain name (e.g. /links-to/foo.com
) or a domain + path (e.g. /links-to/foo.com%2Fblog
). The route matched both of these examples just fine until we upgraded to rack-protection 1.5.3 -- then we started getting 404s. It looks like we're getting 404s because of 7875ec5 (from #54) -- in it, it changed the unescaping from path.gsub('%2e', '.').gsub('%2f', '/')
, which would not match against capitals to path.gsub(/%2e/i, '.').gsub(/%2f/i, '/')
which does map against capitals. So I guess we've actually been lucky that the client (which we control) encodes /
as %2F
rather than %2f
.
It appears this is all by design. Given how the path traversal middleware works, is there a way to make the sinatra match a request like /links-to/foo.com%2Fblog
? I'm going to look into disabling the path traversal middleware (which will likely fix the problem), but it would be nice to not have to do that. It seems like a pretty big gotcha of the middleware that it affects what sinatra routes match.
Yes, this is by design, it is actually extremely close to the main use case as to why path traversal was introduced.
Quite a few Sinatra apps do the following:
get '/page/:name' do
erb params[:name].to_sym
end
The assumption that it wouldn't match a slash is obviously wrong. If you don't use captures in file paths, you can disable the path traversal middleware:
set :protection, except: :path_traversal
Thanks, the set
line works perfectly.