Skip to content

Commit 9c6a330

Browse files
authored
Merge pull request reidmorrison#247 from kennyevil/filter-bind-values
Ensure filtered params aren't revealed in sql
2 parents 0c09805 + c09d715 commit 9c6a330

File tree

4 files changed

+96
-2
lines changed

4 files changed

+96
-2
lines changed

lib/rails_semantic_logger/active_record/log_subscriber.rb

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,25 @@ def sql(event)
5454

5555
# When multiple values are received for a single bound field, it is converted into an array
5656
def add_bind_value(binds, key, value)
57-
key = key.downcase.to_sym unless key.nil?
58-
value = (Array(binds[key]) << value) if binds.key?(key)
57+
key = key.downcase.to_sym unless key.nil?
58+
59+
if rails_filter_params_include?(key)
60+
value = "[FILTERED]"
61+
elsif binds.key?(key)
62+
value = (Array(binds[key]) << value)
63+
end
64+
5965
binds[key] = value
6066
end
6167

68+
def rails_filter_params_include?(key)
69+
filter_parameters = Rails.configuration.filter_parameters
70+
71+
return filter_parameters.first.match? key if filter_parameters.first.is_a? Regexp
72+
73+
filter_parameters.include? key
74+
end
75+
6276
def logger
6377
self.class.logger
6478
end

test/active_record_test.rb

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,62 @@ class ActiveRecordTest < Minitest::Test
8787
assert_instance_of Integer, messages[0].payload[:allocations] if Rails.version.to_i >= 6
8888
end
8989

90+
it "filtered bind value" do
91+
filter_params_setting true, %i[name] do
92+
expected_sql =
93+
if Rails.version.to_f >= 5.2
94+
"SELECT #{extra_space}\"samples\".* FROM \"samples\" WHERE \"samples\".\"name\" = ? ORDER BY \"samples\".\"id\" ASC LIMIT ?"
95+
else
96+
"SELECT \"samples\".* FROM \"samples\" WHERE \"samples\".\"name\" = ? ORDER BY \"samples\".\"id\" ASC LIMIT ?"
97+
end
98+
99+
messages = semantic_logger_events do
100+
Sample.where(name: "Jack").first
101+
end
102+
assert_equal 1, messages.count, messages
103+
104+
assert_semantic_logger_event(
105+
messages[0],
106+
level: :debug,
107+
name: "ActiveRecord",
108+
message: "Sample Load",
109+
payload_includes: {
110+
sql: expected_sql,
111+
binds: {name: "[FILTERED]", limit: 1}
112+
}
113+
)
114+
assert_instance_of Integer, messages[0].payload[:allocations] if Rails.version.to_i >= 6
115+
end
116+
end
117+
118+
it "filtered bind value when filter_parameters set as regex" do
119+
filter_params_regex_setting true, %i[name] do
120+
expected_sql =
121+
if Rails.version.to_f >= 5.2
122+
"SELECT #{extra_space}\"samples\".* FROM \"samples\" WHERE \"samples\".\"name\" = ? ORDER BY \"samples\".\"id\" ASC LIMIT ?"
123+
else
124+
"SELECT \"samples\".* FROM \"samples\" WHERE \"samples\".\"name\" = ? ORDER BY \"samples\".\"id\" ASC LIMIT ?"
125+
end
126+
127+
messages = semantic_logger_events do
128+
Sample.where(name: "Jack").first
129+
end
130+
assert_equal 1, messages.count, messages
131+
132+
assert_semantic_logger_event(
133+
messages[0],
134+
level: :debug,
135+
name: "ActiveRecord",
136+
message: "Sample Load",
137+
payload_includes: {
138+
sql: expected_sql,
139+
binds: {name: "[FILTERED]", limit: 1}
140+
}
141+
)
142+
assert_instance_of Integer, messages[0].payload[:allocations] if Rails.version.to_i >= 6
143+
end
144+
end
145+
90146
it "multiple bind values" do
91147
skip "Not applicable to older rails" if Rails.version.to_f <= 5.1
92148

test/dummy/db/test.sqlite3

0 Bytes
Binary file not shown.

test/test_helper.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,27 @@
2323
Minitest::Test.include SemanticLogger::Test::Minitest
2424

2525
ActionMailer::Base.delivery_method = :test
26+
27+
def filter_params_setting(value, user_defined_params, &block)
28+
original_value = Rails.configuration.filter_parameters
29+
Rails.configuration.filter_parameters = user_defined_params
30+
block.call
31+
ensure
32+
Rails.configuration.filter_parameters = original_value
33+
end
34+
35+
def filter_params_regex_setting(value, user_defined_params, &block)
36+
original_value = Rails.configuration.filter_parameters
37+
38+
Rails.configuration.filter_parameters += user_defined_params
39+
40+
filter_params_regex = Rails.configuration.filter_parameters.map do |key|
41+
"(?i:#{key})"
42+
end.join("|")
43+
44+
Rails.configuration.filter_parameters = [/(?-mix:#{filter_params_regex})/]
45+
46+
block.call
47+
ensure
48+
Rails.configuration.filter_parameters = original_value
49+
end

0 commit comments

Comments
 (0)