From 446c192ac35d561372d2e862a6be63572f8e0e16 Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Tue, 15 Sep 2020 16:24:38 -0400 Subject: [PATCH] Validate content-type of internal calls --- lib/better_errors/middleware.rb | 9 +++++++++ spec/better_errors/middleware_spec.rb | 29 ++++++++++++++++++++++----- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/lib/better_errors/middleware.rb b/lib/better_errors/middleware.rb index 11036128..da7bf361 100644 --- a/lib/better_errors/middleware.rb +++ b/lib/better_errors/middleware.rb @@ -156,6 +156,8 @@ def internal_call(env, opts) body = JSON.parse(request.body.read) return invalid_csrf_token_json_response unless request.cookies[CSRF_TOKEN_COOKIE_NAME] == body['csrfToken'] + return not_acceptable_json_response unless request.content_type == 'application/json' + response = @error_page.send("do_#{opts[:method]}", body) [200, { "Content-Type" => "application/json; charset=utf-8" }, [JSON.dump(response)]] end @@ -200,5 +202,12 @@ def invalid_csrf_token_json_response "or something went wrong.", )]] end + + def not_acceptable_json_response + [406, { "Content-Type" => "application/json; charset=utf-8" }, [JSON.dump( + error: "Request not acceptable", + explanation: "The internal request did not match an acceptable content type.", + )]] + end end end diff --git a/spec/better_errors/middleware_spec.rb b/spec/better_errors/middleware_spec.rb index 44b38fd1..b35b7da2 100644 --- a/spec/better_errors/middleware_spec.rb +++ b/spec/better_errors/middleware_spec.rb @@ -356,11 +356,30 @@ def initialize(message, original_exception = nil) request_env["HTTP_COOKIE"] = "BetterErrors-CSRF-Token=csrfToken123" end - it 'returns the HTML content' do - expect(error_page).to receive(:do_variables).and_return(html: "") - expect(json_body).to match( - 'html' => '', - ) + context 'when the Content-Type of the request is application/json' do + before do + request_env['CONTENT_TYPE'] = 'application/json' + end + + it 'returns JSON containing the HTML content' do + expect(error_page).to receive(:do_variables).and_return(html: "") + expect(json_body).to match( + 'html' => '', + ) + end + end + + context 'when the Content-Type of the request is application/json' do + before do + request_env['HTTP_CONTENT_TYPE'] = 'application/json' + end + + it 'returns a JSON error' do + expect(json_body).to match( + 'error' => 'Request not acceptable', + 'explanation' => /did not match an acceptable content type/, + ) + end end end