From 825945e7d4bc46de381991909da1253ce5a7f942 Mon Sep 17 00:00:00 2001 From: Prem Sichanugrist Date: Sat, 1 Jan 2011 23:51:05 +0700 Subject: [PATCH] Filter sensitive `QUERY_STRING` parameters in the log This provides more safety to applications that appends secret information, such as API key or SSO token, as a `QUERY_STRING` in the request. Note that in Ruby 1.8 those `QUERY_STRING` might not be in the same order of original request as we reconstructed the `QUERY_STRING` from `request.GET` parameters and Ruby 1.8 doesn't honor the order of insertion. --- .../lib/action_dispatch/http/filter_parameters.rb | 14 ++++++++++---- actionpack/test/dispatch/request_test.rb | 12 ++++++++++++ railties/lib/rails/rack/logger.rb | 2 +- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/actionpack/lib/action_dispatch/http/filter_parameters.rb b/actionpack/lib/action_dispatch/http/filter_parameters.rb index 1ab48ae..c20920f 100644 --- a/actionpack/lib/action_dispatch/http/filter_parameters.rb +++ b/actionpack/lib/action_dispatch/http/filter_parameters.rb @@ -1,14 +1,15 @@ require 'active_support/core_ext/object/blank' require 'active_support/core_ext/hash/keys' require 'active_support/core_ext/object/duplicable' +require 'active_support/core_ext/object/to_query' module ActionDispatch module Http # Allows you to specify sensitive parameters which will be replaced from - # the request log by looking in all subhashes of the param hash for keys - # to filter. If a block is given, each key and value of the parameter - # hash and all subhashes is passed to it, the value or key can be replaced - # using String#replace or similar method. + # the request log by looking in the query string of the request and all + # subhashes of the param hash to filter. If a block is given, each key and + # value of the parameter hash and all subhashes is passed to it, the value + # or key can be replaced using String#replace or similar method. # # Examples: # @@ -38,6 +39,11 @@ module ActionDispatch @filtered_env ||= env_filter.filter(@env) end + # Reconstructed a path with all sensitive GET parameters replaced. + def filtered_path + @filtered_path ||= query_string.empty? ? path : "#{path}?#{parameter_filter.filter(self.GET).to_param.gsub(/%5BFILTERED%5D/,'[FILTERED]')}" + end + protected def parameter_filter diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb index 75b674e..149757c 100644 --- a/actionpack/test/dispatch/request_test.rb +++ b/actionpack/test/dispatch/request_test.rb @@ -518,6 +518,18 @@ class RequestTest < ActiveSupport::TestCase assert_equal "1", request.params["step"] end + test "filtered_path returns path with filtered query string" do + request = stub_request('QUERY_STRING' => "username=sikachu&secret=bd4f21f&api_key=b1bc3b3cd352f68d79d7", + 'PATH_INFO' => '/authenticate', + 'action_dispatch.parameter_filter' => [:secret, :api_key]) + + path = request.filtered_path + assert_match /^\/authenticate\?/, path + assert_match /username=sikachu/, path + assert_match /secret=\[FILTERED\]/, path + assert_match /api_key=\[FILTERED\]/, path + end + protected def stub_request(env = {}) diff --git a/railties/lib/rails/rack/logger.rb b/railties/lib/rails/rack/logger.rb index 32acc66..3be262d 100644 --- a/railties/lib/rails/rack/logger.rb +++ b/railties/lib/rails/rack/logger.rb @@ -19,7 +19,7 @@ module Rails def before_dispatch(env) request = ActionDispatch::Request.new(env) - path = request.fullpath + path = request.filtered_path info "\n\nStarted #{request.request_method} \"#{path}\" " \ "for #{request.ip} at #{Time.now.to_default_s}" -- 1.7.3.4