brakeman 1.5.3 → 1.6.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/brakeman +20 -6
- data/lib/brakeman.rb +21 -1
- data/lib/brakeman/checks.rb +2 -7
- data/lib/brakeman/checks/base_check.rb +31 -26
- data/lib/brakeman/checks/check_basic_auth.rb +1 -7
- data/lib/brakeman/checks/check_cross_site_scripting.rb +38 -33
- data/lib/brakeman/checks/check_evaluation.rb +2 -1
- data/lib/brakeman/checks/check_execute.rb +5 -1
- data/lib/brakeman/checks/check_file_access.rb +6 -4
- data/lib/brakeman/checks/check_link_to.rb +8 -5
- data/lib/brakeman/checks/check_link_to_href.rb +6 -5
- data/lib/brakeman/checks/check_mail_to.rb +2 -4
- data/lib/brakeman/checks/check_mass_assignment.rb +12 -6
- data/lib/brakeman/checks/check_redirect.rb +17 -14
- data/lib/brakeman/checks/check_render.rb +4 -4
- data/lib/brakeman/checks/check_send.rb +4 -2
- data/lib/brakeman/checks/check_session_settings.rb +16 -21
- data/lib/brakeman/checks/check_skip_before_filter.rb +2 -4
- data/lib/brakeman/checks/check_sql.rb +8 -7
- data/lib/brakeman/checks/check_validation_regex.rb +2 -4
- data/lib/brakeman/checks/check_without_protection.rb +8 -9
- data/lib/brakeman/differ.rb +61 -0
- data/lib/brakeman/format/style.css +4 -0
- data/lib/brakeman/options.rb +8 -0
- data/lib/brakeman/processors/alias_processor.rb +5 -7
- data/lib/brakeman/processors/controller_alias_processor.rb +10 -3
- data/lib/brakeman/processors/erb_template_processor.rb +2 -0
- data/lib/brakeman/processors/erubis_template_processor.rb +2 -0
- data/lib/brakeman/processors/gem_processor.rb +8 -0
- data/lib/brakeman/processors/haml_template_processor.rb +2 -0
- data/lib/brakeman/processors/lib/rails2_route_processor.rb +2 -6
- data/lib/brakeman/processors/lib/rails3_route_processor.rb +2 -4
- data/lib/brakeman/processors/lib/render_helper.rb +3 -1
- data/lib/brakeman/processors/library_processor.rb +4 -6
- data/lib/brakeman/processors/template_alias_processor.rb +1 -1
- data/lib/brakeman/report.rb +257 -198
- data/lib/brakeman/rescanner.rb +112 -10
- data/lib/brakeman/scanner.rb +3 -4
- data/lib/brakeman/templates/controller_overview.html.erb +18 -0
- data/lib/brakeman/templates/controller_warnings.html.erb +17 -0
- data/lib/brakeman/templates/error_overview.html.erb +14 -0
- data/lib/brakeman/templates/header.html.erb +38 -0
- data/lib/brakeman/templates/model_warnings.html.erb +17 -0
- data/lib/brakeman/templates/overview.html.erb +28 -0
- data/lib/brakeman/templates/security_warnings.html.erb +28 -0
- data/lib/brakeman/templates/template_overview.html.erb +17 -0
- data/lib/brakeman/templates/view_warnings.html.erb +17 -0
- data/lib/brakeman/templates/warning_overview.html.erb +13 -0
- data/lib/brakeman/tracker.rb +1 -1
- data/lib/brakeman/util.rb +24 -4
- data/lib/brakeman/version.rb +1 -1
- data/lib/brakeman/warning.rb +11 -3
- data/lib/ruby_parser/bm_sexp.rb +5 -11
- metadata +84 -23
data/bin/brakeman
CHANGED
@@ -7,7 +7,13 @@ require 'brakeman/options'
|
|
7
7
|
require 'brakeman/version'
|
8
8
|
|
9
9
|
#Parse options
|
10
|
-
|
10
|
+
begin
|
11
|
+
options, parser = Brakeman::Options.parse! ARGV
|
12
|
+
rescue OptionParser::ParseError => e
|
13
|
+
$stderr.puts e.message.capitalize
|
14
|
+
$stderr.puts "Please see `brakeman --help` for valid options"
|
15
|
+
exit -1
|
16
|
+
end
|
11
17
|
|
12
18
|
#Exit early for these options
|
13
19
|
if options[:list_checks]
|
@@ -46,10 +52,18 @@ trap("INT") do
|
|
46
52
|
exit!
|
47
53
|
end
|
48
54
|
|
49
|
-
|
50
|
-
|
55
|
+
if options[:previous_results_json]
|
56
|
+
vulns = Brakeman.compare options
|
57
|
+
puts JSON.pretty_generate(vulns)
|
58
|
+
else
|
59
|
+
#Run scan and output a report
|
60
|
+
tracker = Brakeman.run options.merge(:print_report => true, :quiet => options[:quiet])
|
51
61
|
|
52
|
-
#Return error code if --exit-on-warn is used and warnings were found
|
53
|
-
if options[:exit_on_warn] and not tracker.checks.all_warnings.empty?
|
54
|
-
|
62
|
+
#Return error code if --exit-on-warn is used and warnings were found
|
63
|
+
if options[:exit_on_warn] and not tracker.checks.all_warnings.empty?
|
64
|
+
exit Brakeman::Warnings_Found_Exit_Code
|
65
|
+
end
|
55
66
|
end
|
67
|
+
|
68
|
+
|
69
|
+
|
data/lib/brakeman.rb
CHANGED
@@ -23,6 +23,7 @@ module Brakeman
|
|
23
23
|
# * :config_file - configuration file
|
24
24
|
# * :escape_html - escape HTML by default (automatic)
|
25
25
|
# * :exit_on_warn - return false if warnings found, true otherwise. Not recommended for library use (default: false)
|
26
|
+
# * :highlight_user_input - highlight user input in reported warnings (default: true)
|
26
27
|
# * :html_style - path to CSS file
|
27
28
|
# * :ignore_model_output - consider models safe (default: false)
|
28
29
|
# * :message_limit - limit length of messages
|
@@ -51,7 +52,6 @@ module Brakeman
|
|
51
52
|
if @quiet
|
52
53
|
options[:report_progress] = false
|
53
54
|
end
|
54
|
-
|
55
55
|
scan options
|
56
56
|
end
|
57
57
|
|
@@ -114,6 +114,7 @@ module Brakeman
|
|
114
114
|
:min_confidence => 2,
|
115
115
|
:combine_locations => true,
|
116
116
|
:collapse_mass_assignment => true,
|
117
|
+
:highlight_user_input => true,
|
117
118
|
:ignore_redirect_to_model => true,
|
118
119
|
:ignore_model_output => false,
|
119
120
|
:message_limit => 100,
|
@@ -310,4 +311,23 @@ module Brakeman
|
|
310
311
|
def self.debug message
|
311
312
|
$stderr.puts message if @debug
|
312
313
|
end
|
314
|
+
|
315
|
+
# Compare JSON ouptut from a previous scan and return the diff of the two scans
|
316
|
+
def self.compare options
|
317
|
+
require 'json'
|
318
|
+
require 'brakeman/differ'
|
319
|
+
raise ArgumentError.new("Comparison file doesn't exist") unless File.exists? options[:previous_results_json]
|
320
|
+
|
321
|
+
begin
|
322
|
+
previous_results = JSON.parse(File.read(options[:previous_results_json]), :symbolize_names =>true)[:warnings]
|
323
|
+
rescue JSON::ParserError
|
324
|
+
self.notify "Error parsing comparison file: #{options[:previous_results_json]}"
|
325
|
+
exit!
|
326
|
+
end
|
327
|
+
|
328
|
+
tracker = run(options)
|
329
|
+
new_results = JSON.parse(tracker.report.to_json, :symbolize_names =>true)[:warnings]
|
330
|
+
|
331
|
+
Brakeman::Differ.new(new_results, previous_results).diff
|
332
|
+
end
|
313
333
|
end
|
data/lib/brakeman/checks.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'thread'
|
2
|
+
require 'brakeman/differ'
|
2
3
|
|
3
4
|
#Collects up results from running different checks.
|
4
5
|
#
|
@@ -64,13 +65,7 @@ class Brakeman::Checks
|
|
64
65
|
def diff other_checks
|
65
66
|
my_warnings = self.all_warnings
|
66
67
|
other_warnings = other_checks.all_warnings
|
67
|
-
|
68
|
-
diff = {}
|
69
|
-
|
70
|
-
diff[:fixed] = other_warnings - my_warnings
|
71
|
-
diff[:new] = my_warnings - other_warnings
|
72
|
-
|
73
|
-
diff
|
68
|
+
Brakeman::Differ.new(my_warnings, other_warnings).diff
|
74
69
|
end
|
75
70
|
|
76
71
|
#Return an array of all warnings found.
|
@@ -12,6 +12,8 @@ class Brakeman::BaseCheck < SexpProcessor
|
|
12
12
|
|
13
13
|
CONFIDENCE = { :high => 0, :med => 1, :low => 2 }
|
14
14
|
|
15
|
+
Match = Struct.new(:type, :match)
|
16
|
+
|
15
17
|
#Initialize Check with Checks.
|
16
18
|
def initialize tracker
|
17
19
|
super()
|
@@ -66,13 +68,13 @@ class Brakeman::BaseCheck < SexpProcessor
|
|
66
68
|
process exp[3]
|
67
69
|
|
68
70
|
if params? exp[1]
|
69
|
-
@has_user_input = :params
|
71
|
+
@has_user_input = Match.new(:params, exp)
|
70
72
|
elsif cookies? exp[1]
|
71
|
-
@has_user_input = :cookies
|
73
|
+
@has_user_input = Match.new(:cookies, exp)
|
72
74
|
elsif request_env? exp[1]
|
73
|
-
@has_user_input = :request
|
75
|
+
@has_user_input = Match.new(:request, exp)
|
74
76
|
elsif sexp? exp[1] and model_name? exp[1][1]
|
75
|
-
@has_user_input = :model
|
77
|
+
@has_user_input = Match.new(:model, exp)
|
76
78
|
end
|
77
79
|
|
78
80
|
exp
|
@@ -92,13 +94,13 @@ class Brakeman::BaseCheck < SexpProcessor
|
|
92
94
|
|
93
95
|
#Note that params are included in current expression
|
94
96
|
def process_params exp
|
95
|
-
@has_user_input = :params
|
97
|
+
@has_user_input = Match.new(:params, exp)
|
96
98
|
exp
|
97
99
|
end
|
98
100
|
|
99
101
|
#Note that cookies are included in current expression
|
100
102
|
def process_cookies exp
|
101
|
-
@has_user_input = :cookies
|
103
|
+
@has_user_input = Match.new(:cookies, exp)
|
102
104
|
exp
|
103
105
|
end
|
104
106
|
|
@@ -206,19 +208,26 @@ class Brakeman::BaseCheck < SexpProcessor
|
|
206
208
|
|
207
209
|
#Does not actually process string interpolation, but notes that it occurred.
|
208
210
|
def process_string_interp exp
|
209
|
-
@string_interp =
|
211
|
+
@string_interp = Match.new(:interp, exp)
|
210
212
|
exp
|
211
213
|
end
|
212
214
|
|
213
215
|
#Checks if an expression contains string interpolation.
|
216
|
+
#
|
217
|
+
#Returns Match with :interp type if found.
|
214
218
|
def include_interp? exp
|
215
219
|
@string_interp = false
|
216
220
|
process exp
|
217
221
|
@string_interp
|
218
222
|
end
|
219
223
|
|
220
|
-
#Checks if _exp_ includes
|
221
|
-
#
|
224
|
+
#Checks if _exp_ includes user input in the form of cookies, parameters,
|
225
|
+
#request environment, or model attributes.
|
226
|
+
#
|
227
|
+
#If found, returns a struct containing a type (:cookies, :params, :request, :model) and
|
228
|
+
#the matching expression (Match#type and Match#match).
|
229
|
+
#
|
230
|
+
#Returns false otherwise.
|
222
231
|
def include_user_input? exp
|
223
232
|
@has_user_input = false
|
224
233
|
process exp
|
@@ -227,24 +236,24 @@ class Brakeman::BaseCheck < SexpProcessor
|
|
227
236
|
|
228
237
|
#This is used to check for user input being used directly.
|
229
238
|
#
|
230
|
-
|
231
|
-
#
|
232
|
-
#
|
233
|
-
#
|
239
|
+
##If found, returns a struct containing a type (:cookies, :params, :request) and
|
240
|
+
#the matching expression (Match#type and Match#match).
|
241
|
+
#
|
242
|
+
#Returns false otherwise.
|
234
243
|
def has_immediate_user_input? exp
|
235
244
|
if exp.nil?
|
236
245
|
false
|
237
246
|
elsif params? exp
|
238
|
-
return :params, exp
|
247
|
+
return Match.new(:params, exp)
|
239
248
|
elsif cookies? exp
|
240
|
-
return :cookies, exp
|
249
|
+
return Match.new(:cookies, exp)
|
241
250
|
elsif call? exp
|
242
251
|
if params? exp[1]
|
243
|
-
return :params, exp
|
252
|
+
return Match.new(:params, exp)
|
244
253
|
elsif cookies? exp[1]
|
245
|
-
return :cookies, exp
|
254
|
+
return Match.new(:cookies, exp)
|
246
255
|
elsif request_env? exp[1]
|
247
|
-
return :request, exp
|
256
|
+
return Match.new(:request, exp)
|
248
257
|
else
|
249
258
|
false
|
250
259
|
end
|
@@ -253,10 +262,8 @@ class Brakeman::BaseCheck < SexpProcessor
|
|
253
262
|
when :string_interp
|
254
263
|
exp.each do |e|
|
255
264
|
if sexp? e
|
256
|
-
|
257
|
-
if
|
258
|
-
return type, match
|
259
|
-
end
|
265
|
+
match = has_immediate_user_input?(e)
|
266
|
+
return match if match
|
260
267
|
end
|
261
268
|
end
|
262
269
|
false
|
@@ -265,10 +272,8 @@ class Brakeman::BaseCheck < SexpProcessor
|
|
265
272
|
if exp[1].node_type == :rlist
|
266
273
|
exp[1].each do |e|
|
267
274
|
if sexp? e
|
268
|
-
|
269
|
-
if
|
270
|
-
return type, match
|
271
|
-
end
|
275
|
+
match = has_immediate_user_input?(e)
|
276
|
+
return match if match
|
272
277
|
end
|
273
278
|
end
|
274
279
|
false
|
@@ -38,12 +38,6 @@ class Brakeman::CheckBasicAuth < Brakeman::BaseCheck
|
|
38
38
|
|
39
39
|
return false if args.nil? or not hash? args
|
40
40
|
|
41
|
-
|
42
|
-
if symbol? k and k[1] == :password
|
43
|
-
return v
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
nil
|
41
|
+
hash_access(args, :password)
|
48
42
|
end
|
49
43
|
end
|
@@ -83,11 +83,10 @@ class Brakeman::CheckCrossSiteScripting < Brakeman::BaseCheck
|
|
83
83
|
out = exp[1][3][1]
|
84
84
|
end
|
85
85
|
|
86
|
-
|
87
|
-
|
88
|
-
if type
|
86
|
+
if input = has_immediate_user_input?(out)
|
89
87
|
add_result exp
|
90
|
-
|
88
|
+
|
89
|
+
case input.type
|
91
90
|
when :params
|
92
91
|
message = "Unescaped parameter value"
|
93
92
|
when :cookies
|
@@ -101,8 +100,8 @@ class Brakeman::CheckCrossSiteScripting < Brakeman::BaseCheck
|
|
101
100
|
warn :template => @current_template,
|
102
101
|
:warning_type => "Cross Site Scripting",
|
103
102
|
:message => message,
|
104
|
-
:line => match.line,
|
105
|
-
:code => match,
|
103
|
+
:line => input.match.line,
|
104
|
+
:code => input.match,
|
106
105
|
:confidence => CONFIDENCE[:high]
|
107
106
|
|
108
107
|
elsif not tracker.options[:ignore_model_output] and match = has_immediate_model?(out)
|
@@ -161,29 +160,35 @@ class Brakeman::CheckCrossSiteScripting < Brakeman::BaseCheck
|
|
161
160
|
actually_process_call exp
|
162
161
|
message = nil
|
163
162
|
|
164
|
-
if @matched
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
if exp[1].nil? and @known_dangerous.include? exp[2]
|
176
|
-
confidence = CONFIDENCE[:high]
|
177
|
-
else
|
178
|
-
confidence = CONFIDENCE[:low]
|
163
|
+
if @matched
|
164
|
+
case @matched.type
|
165
|
+
when :model
|
166
|
+
unless tracker.options[:ignore_model_output]
|
167
|
+
message = "Unescaped model attribute"
|
168
|
+
end
|
169
|
+
when :params
|
170
|
+
message = "Unescaped parameter value"
|
171
|
+
when :cookies
|
172
|
+
message = "Unescaped cookie value"
|
179
173
|
end
|
180
174
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
175
|
+
if message and not duplicate? exp
|
176
|
+
add_result exp
|
177
|
+
|
178
|
+
if exp[1].nil? and @known_dangerous.include? exp[2]
|
179
|
+
confidence = CONFIDENCE[:high]
|
180
|
+
else
|
181
|
+
confidence = CONFIDENCE[:low]
|
182
|
+
end
|
183
|
+
|
184
|
+
warn :template => @current_template,
|
185
|
+
:warning_type => "Cross Site Scripting",
|
186
|
+
:message => message,
|
187
|
+
:line => exp.line,
|
188
|
+
:code => exp,
|
189
|
+
:user_input => @matched.match,
|
190
|
+
:confidence => confidence
|
191
|
+
end
|
187
192
|
end
|
188
193
|
|
189
194
|
@mark = @matched = false
|
@@ -204,7 +209,7 @@ class Brakeman::CheckCrossSiteScripting < Brakeman::BaseCheck
|
|
204
209
|
|
205
210
|
#Ignore safe items
|
206
211
|
if (target.nil? and (@ignore_methods.include? method or method.to_s =~ IGNORE_LIKE)) or
|
207
|
-
(@matched == :model and IGNORE_MODEL_METHODS.include? method) or
|
212
|
+
(@matched and @matched.type == :model and IGNORE_MODEL_METHODS.include? method) or
|
208
213
|
(target == HAML_HELPERS and method == :html_escape) or
|
209
214
|
((target == URI or target == CGI) and method == :escape) or
|
210
215
|
(target == XML_HELPER and method == :escape_xml) or
|
@@ -214,11 +219,11 @@ class Brakeman::CheckCrossSiteScripting < Brakeman::BaseCheck
|
|
214
219
|
#exp[0] = :ignore #should not be necessary
|
215
220
|
@matched = false
|
216
221
|
elsif sexp? exp[1] and model_name? exp[1][1]
|
217
|
-
@matched = :model
|
222
|
+
@matched = Match.new(:model, exp)
|
218
223
|
elsif cookies? exp
|
219
|
-
@matched = :cookies
|
224
|
+
@matched = Match.new(:cookies, exp)
|
220
225
|
elsif @inspect_arguments and params? exp
|
221
|
-
@matched = :params
|
226
|
+
@matched = Match.new(:params, exp)
|
222
227
|
elsif @inspect_arguments
|
223
228
|
process args
|
224
229
|
end
|
@@ -226,13 +231,13 @@ class Brakeman::CheckCrossSiteScripting < Brakeman::BaseCheck
|
|
226
231
|
|
227
232
|
#Note that params have been found
|
228
233
|
def process_params exp
|
229
|
-
@matched = :params
|
234
|
+
@matched = Match.new(:params, exp)
|
230
235
|
exp
|
231
236
|
end
|
232
237
|
|
233
238
|
#Note that cookies have been found
|
234
239
|
def process_cookies exp
|
235
|
-
@matched = :cookies
|
240
|
+
@matched = Match.new(:cookies, exp)
|
236
241
|
exp
|
237
242
|
end
|
238
243
|
|
@@ -20,11 +20,12 @@ class Brakeman::CheckEvaluation < Brakeman::BaseCheck
|
|
20
20
|
|
21
21
|
#Warns if eval includes user input
|
22
22
|
def process_result result
|
23
|
-
if include_user_input?
|
23
|
+
if input = include_user_input?(result[:call][-1])
|
24
24
|
warn :result => result,
|
25
25
|
:warning_type => "Dangerous Eval",
|
26
26
|
:message => "User input in eval",
|
27
27
|
:code => result[:call],
|
28
|
+
:user_input => input.match,
|
28
29
|
:confidence => CONFIDENCE[:high]
|
29
30
|
end
|
30
31
|
end
|
@@ -54,6 +54,7 @@ class Brakeman::CheckExecute < Brakeman::BaseCheck
|
|
54
54
|
:message => "Possible command injection",
|
55
55
|
:line => call.line,
|
56
56
|
:code => call,
|
57
|
+
:user_input => failure.match,
|
57
58
|
:confidence => confidence
|
58
59
|
end
|
59
60
|
end
|
@@ -75,16 +76,19 @@ class Brakeman::CheckExecute < Brakeman::BaseCheck
|
|
75
76
|
|
76
77
|
exp = result[:call]
|
77
78
|
|
78
|
-
if include_user_input?
|
79
|
+
if input = include_user_input?(exp)
|
79
80
|
confidence = CONFIDENCE[:high]
|
81
|
+
user_input = input.match
|
80
82
|
else
|
81
83
|
confidence = CONFIDENCE[:med]
|
84
|
+
user_input = nil
|
82
85
|
end
|
83
86
|
|
84
87
|
warning = { :warning_type => "Command Injection",
|
85
88
|
:message => "Possible command injection",
|
86
89
|
:line => exp.line,
|
87
90
|
:code => exp,
|
91
|
+
:user_input => user_input,
|
88
92
|
:confidence => confidence }
|
89
93
|
|
90
94
|
if result[:location][0] == :template
|
@@ -28,13 +28,14 @@ class Brakeman::CheckFileAccess < Brakeman::BaseCheck
|
|
28
28
|
|
29
29
|
file_name = call[3][1]
|
30
30
|
|
31
|
-
if
|
31
|
+
if input = include_user_input?(file_name)
|
32
32
|
unless duplicate? result
|
33
33
|
add_result result
|
34
34
|
|
35
|
-
|
35
|
+
case input.type
|
36
|
+
when :params
|
36
37
|
message = "Parameter"
|
37
|
-
|
38
|
+
when :cookies
|
38
39
|
message = "Cookie"
|
39
40
|
else
|
40
41
|
message = "User input"
|
@@ -47,7 +48,8 @@ class Brakeman::CheckFileAccess < Brakeman::BaseCheck
|
|
47
48
|
:message => message,
|
48
49
|
:confidence => CONFIDENCE[:high],
|
49
50
|
:line => call.line,
|
50
|
-
:code => call
|
51
|
+
:code => call,
|
52
|
+
:user_input => input.match
|
51
53
|
end
|
52
54
|
end
|
53
55
|
end
|
@@ -60,10 +60,9 @@ class Brakeman::CheckLinkTo < Brakeman::CheckCrossSiteScripting
|
|
60
60
|
|
61
61
|
def check_argument result, exp
|
62
62
|
arg = process exp
|
63
|
-
type, match = has_immediate_user_input? arg
|
64
63
|
|
65
|
-
if
|
66
|
-
case type
|
64
|
+
if input = has_immediate_user_input?(arg)
|
65
|
+
case input.type
|
67
66
|
when :params
|
68
67
|
message = "Unescaped parameter value in link_to"
|
69
68
|
when :cookies
|
@@ -76,7 +75,9 @@ class Brakeman::CheckLinkTo < Brakeman::CheckCrossSiteScripting
|
|
76
75
|
warn :result => result,
|
77
76
|
:warning_type => "Cross Site Scripting",
|
78
77
|
:message => message,
|
78
|
+
:user_input => input.match,
|
79
79
|
:confidence => CONFIDENCE[:high]
|
80
|
+
|
80
81
|
elsif not tracker.options[:ignore_model_output] and match = has_immediate_model?(arg)
|
81
82
|
method = match[2]
|
82
83
|
|
@@ -92,13 +93,14 @@ class Brakeman::CheckLinkTo < Brakeman::CheckCrossSiteScripting
|
|
92
93
|
warn :result => result,
|
93
94
|
:warning_type => "Cross Site Scripting",
|
94
95
|
:message => "Unescaped model attribute in link_to",
|
96
|
+
:user_input => match,
|
95
97
|
:confidence => confidence
|
96
98
|
end
|
97
99
|
|
98
100
|
elsif @matched
|
99
|
-
if @matched == :model and not tracker.options[:ignore_model_output]
|
101
|
+
if @matched.type == :model and not tracker.options[:ignore_model_output]
|
100
102
|
message = "Unescaped model attribute in link_to"
|
101
|
-
elsif @matched == :params
|
103
|
+
elsif @matched.type == :params
|
102
104
|
message = "Unescaped parameter value in link_to"
|
103
105
|
end
|
104
106
|
|
@@ -108,6 +110,7 @@ class Brakeman::CheckLinkTo < Brakeman::CheckCrossSiteScripting
|
|
108
110
|
warn :result => result,
|
109
111
|
:warning_type => "Cross Site Scripting",
|
110
112
|
:message => message,
|
113
|
+
:user_input => @matched.match,
|
111
114
|
:confidence => CONFIDENCE[:med]
|
112
115
|
end
|
113
116
|
end
|