mirror of https://github.com/rails/rails
Filter sensitive query string parameters in the log [#6244 state:committed]
This provides more safety to applications that put secret information in the query string, such as API keys or SSO tokens. Signed-off-by: Xavier Noria <fxn@hashref.com>
This commit is contained in:
parent
51a269b228
commit
68802d0fbe
|
@ -1,5 +1,7 @@
|
|||
*Rails 3.1.0 (unreleased)*
|
||||
|
||||
* Sensitive query string parameters (specified in config.filter_parameters) will now be filtered out from the request paths in the log file. [Prem Sichanugrist, fxn]
|
||||
|
||||
* URL parameters which return false for to_param now appear in the query string (previously they were removed) [Andrew White]
|
||||
|
||||
* URL parameters which return nil for to_param are now removed from the query string [Andrew White]
|
||||
|
|
|
@ -5,10 +5,10 @@ require 'active_support/core_ext/object/duplicable'
|
|||
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 params hash to filter. If a block is given, each key and
|
||||
# value of the params hash and all subhashes is passed to it, the value
|
||||
# or key can be replaced using String#replace or similar method.
|
||||
#
|
||||
# Examples:
|
||||
#
|
||||
|
@ -38,6 +38,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}?#{filtered_query_string}"
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def parameter_filter
|
||||
|
@ -52,6 +57,14 @@ module ActionDispatch
|
|||
@@parameter_filter_for[filters] ||= ParameterFilter.new(filters)
|
||||
end
|
||||
|
||||
KV_RE = '[^&;=]+'
|
||||
PAIR_RE = %r{(#{KV_RE})=(#{KV_RE})}
|
||||
def filtered_query_string
|
||||
query_string.gsub(PAIR_RE) do |_|
|
||||
parameter_filter.filter([[$1, $2]]).first.join("=")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -518,6 +518,44 @@ class RequestTest < ActiveSupport::TestCase
|
|||
assert_equal "1", request.params["step"]
|
||||
end
|
||||
|
||||
test "filtered_path returns path with filtered query string" do
|
||||
%w(; &).each do |sep|
|
||||
request = stub_request('QUERY_STRING' => %w(username=sikachu secret=bd4f21f api_key=b1bc3b3cd352f68d79d7).join(sep),
|
||||
'PATH_INFO' => '/authenticate',
|
||||
'action_dispatch.parameter_filter' => [:secret, :api_key])
|
||||
|
||||
path = request.filtered_path
|
||||
assert_equal %w(/authenticate?username=sikachu secret=[FILTERED] api_key=[FILTERED]).join(sep), path
|
||||
end
|
||||
end
|
||||
|
||||
test "filtered_path should not unescape a genuine '[FILTERED]' value" do
|
||||
request = stub_request('QUERY_STRING' => "secret=bd4f21f&genuine=%5BFILTERED%5D",
|
||||
'PATH_INFO' => '/authenticate',
|
||||
'action_dispatch.parameter_filter' => [:secret])
|
||||
|
||||
path = request.filtered_path
|
||||
assert_equal "/authenticate?secret=[FILTERED]&genuine=%5BFILTERED%5D", path
|
||||
end
|
||||
|
||||
test "filtered_path should preserve duplication of keys in query string" do
|
||||
request = stub_request('QUERY_STRING' => "username=sikachu&secret=bd4f21f&username=fxn",
|
||||
'PATH_INFO' => '/authenticate',
|
||||
'action_dispatch.parameter_filter' => [:secret])
|
||||
|
||||
path = request.filtered_path
|
||||
assert_equal "/authenticate?username=sikachu&secret=[FILTERED]&username=fxn", path
|
||||
end
|
||||
|
||||
test "filtered_path should ignore searchparts" do
|
||||
request = stub_request('QUERY_STRING' => "secret",
|
||||
'PATH_INFO' => '/authenticate',
|
||||
'action_dispatch.parameter_filter' => [:secret])
|
||||
|
||||
path = request.filtered_path
|
||||
assert_equal "/authenticate?secret", path
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def stub_request(env = {})
|
||||
|
|
|
@ -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}"
|
||||
|
|
Loading…
Reference in New Issue