From 7c57f0cb944b8b3fca70c6abbb2a83aa49581fdc Mon Sep 17 00:00:00 2001 From: Andrew White Date: Mon, 13 Nov 2017 15:29:02 +0000 Subject: [PATCH] Return a 400 Bad Request when path encoding is invalid Fixes #513. --- CHANGELOG.md | 2 ++ lib/sprockets/server.rb | 13 +++++++++++++ test/test_server.rb | 5 +++++ 3 files changed, 20 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c974312e..4eea26b6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ Get upgrade notes from Sprockets 3.x to 4.x at https://github.com/rails/sprocket ## Master +- Return a `400 Bad Request` when the path encoding is invalid. [#514] + ## 4.0.0.beta5 - Reduce string allocations diff --git a/lib/sprockets/server.rb b/lib/sprockets/server.rb index 2c7414356..8b8cc13a4 100644 --- a/lib/sprockets/server.rb +++ b/lib/sprockets/server.rb @@ -37,6 +37,10 @@ def call(env) # Extract the path from everything after the leading slash path = Rack::Utils.unescape(env['PATH_INFO'].to_s.sub(/^\//, '')) + unless path.valid_encoding? + return bad_request_response(env) + end + # Strip fingerprint if fingerprint = path_fingerprint(path) path = path.sub("-#{fingerprint}", '') @@ -131,6 +135,15 @@ def not_modified_response(env, etag) [ 304, cache_headers(env, etag), [] ] end + # Returns a 400 Forbidden response tuple + def bad_request_response(env) + if head_request?(env) + [ 400, { "Content-Type" => "text/plain", "Content-Length" => "0" }, [] ] + else + [ 400, { "Content-Type" => "text/plain", "Content-Length" => "11" }, [ "Bad Request" ] ] + end + end + # Returns a 403 Forbidden response tuple def forbidden_response(env) if head_request?(env) diff --git a/test/test_server.rb b/test/test_server.rb index a2f01c5df..d71bc9994 100644 --- a/test/test_server.rb +++ b/test/test_server.rb @@ -333,4 +333,9 @@ def app delete "/assets/foo.js" assert_equal 405, last_response.status end + + test "invalid URLs" do + get "/assets/%E2%EF%BF%BD%A6.js" + assert_equal 400, last_response.status + end end