brakeman 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/bin/brakeman +32 -173
- data/lib/brakeman.rb +47 -25
- data/lib/brakeman/call_index.rb +37 -1
- data/lib/brakeman/checks.rb +17 -0
- data/lib/brakeman/checks/base_check.rb +5 -1
- data/lib/brakeman/checks/check_cross_site_scripting.rb +18 -22
- data/lib/brakeman/checks/check_execute.rb +11 -24
- data/lib/brakeman/checks/check_render.rb +15 -26
- data/lib/brakeman/checks/check_sql.rb +48 -3
- data/lib/brakeman/options.rb +204 -0
- data/lib/brakeman/processor.rb +2 -2
- data/lib/brakeman/processors/controller_alias_processor.rb +9 -1
- data/lib/brakeman/processors/lib/find_all_calls.rb +36 -0
- data/lib/brakeman/processors/lib/rails3_route_processor.rb +1 -0
- data/lib/brakeman/processors/model_processor.rb +1 -1
- data/lib/brakeman/report.rb +36 -122
- data/lib/brakeman/rescanner.rb +247 -0
- data/lib/brakeman/scanner.rb +94 -76
- data/lib/brakeman/tracker.rb +103 -2
- data/lib/brakeman/util.rb +106 -0
- data/lib/brakeman/version.rb +1 -1
- data/lib/brakeman/warning.rb +26 -11
- metadata +5 -3
data/bin/brakeman
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'set'
|
4
|
-
|
2
|
+
#Adjust path in case called directly and not through gem
|
5
3
|
$:.unshift "#{File.expand_path(File.dirname(__FILE__))}/../lib"
|
6
4
|
|
7
5
|
require 'brakeman'
|
6
|
+
require 'brakeman/options'
|
8
7
|
require 'brakeman/version'
|
9
8
|
|
10
9
|
trap("INT") do
|
@@ -12,180 +11,40 @@ trap("INT") do
|
|
12
11
|
exit!
|
13
12
|
end
|
14
13
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
opts.on "-q", "--quiet", "Suppress informational messages" do
|
36
|
-
options[:quiet] = true
|
37
|
-
end
|
38
|
-
|
39
|
-
opts.on( "-z", "--exit-on-warn", "Exit code is non-zero if warnings found") do |s|
|
40
|
-
options[:exit_on_warn] = s
|
41
|
-
end
|
42
|
-
|
43
|
-
opts.on "-3", "--rails3", "Force Rails 3 mode" do
|
44
|
-
options[:rails3] = true
|
45
|
-
end
|
46
|
-
|
47
|
-
opts.separator ""
|
48
|
-
opts.separator "Scanning options:"
|
49
|
-
|
50
|
-
opts.on "-a", "--assume-routes", "Assume all controller methods are actions" do
|
51
|
-
options[:assume_all_routes] = true
|
52
|
-
end
|
53
|
-
|
54
|
-
opts.on "--ignore-model-output", "Consider model attributes XSS-safe" do
|
55
|
-
options[:ignore_model_output] = true
|
56
|
-
end
|
57
|
-
|
58
|
-
opts.on "-e", "--escape-html", "Escape HTML by default" do
|
59
|
-
options[:escape_html] = true
|
60
|
-
end
|
61
|
-
|
62
|
-
opts.on "--faster", "Faster, but less accurate scan" do
|
63
|
-
options[:ignore_ifs] = true
|
64
|
-
options[:skip_libs] = true
|
65
|
-
end
|
66
|
-
|
67
|
-
opts.on "--no-branching", "Disable flow sensitivity on conditionals" do
|
68
|
-
options[:ignore_ifs] = true
|
69
|
-
end
|
70
|
-
|
71
|
-
opts.on "-r", "--report-direct", "Only report direct use of untrusted data" do |option|
|
72
|
-
options[:check_arguments] = !option
|
73
|
-
end
|
74
|
-
|
75
|
-
opts.on "-s", "--safe-methods meth1,meth2,etc", Array, "Consider the specified methods safe" do |methods|
|
76
|
-
options[:safe_methods] ||= Set.new
|
77
|
-
options[:safe_methods].merge methods.map {|e| e.to_sym }
|
78
|
-
end
|
79
|
-
|
80
|
-
opts.on "--skip-libs", "Skip processing lib directory" do
|
81
|
-
options[:skip_libs] = true
|
82
|
-
end
|
83
|
-
|
84
|
-
opts.on "-t", "--test Check1,Check2,etc", Array, "Only run the specified checks" do |checks|
|
85
|
-
checks.each_with_index do |s, index|
|
86
|
-
if s[0,5] != "Check"
|
87
|
-
checks[index] = "Check" << s
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
options[:run_checks] ||= Set.new
|
92
|
-
options[:run_checks].merge checks
|
93
|
-
end
|
94
|
-
|
95
|
-
opts.on "-x", "--except Check1,Check2,etc", Array, "Skip the specified checks" do |skip|
|
96
|
-
skip.each do |s|
|
97
|
-
if s[0,5] != "Check"
|
98
|
-
s = "Check" << s
|
99
|
-
end
|
100
|
-
|
101
|
-
options[:skip_checks] ||= Set.new
|
102
|
-
options[:skip_checks] << s
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
opts.separator ""
|
107
|
-
opts.separator "Output options:"
|
108
|
-
|
109
|
-
opts.on "-d", "--debug", "Lots of output" do
|
110
|
-
options[:debug] = true
|
111
|
-
end
|
112
|
-
|
113
|
-
opts.on "-f",
|
114
|
-
"--format TYPE",
|
115
|
-
[:pdf, :text, :html, :csv, :tabs],
|
116
|
-
"Specify output format. Default is text" do |type|
|
117
|
-
|
118
|
-
type = "s" if type == :text
|
119
|
-
options[:output_format] = ("to_" << type.to_s).to_sym
|
120
|
-
end
|
121
|
-
|
122
|
-
opts.on "--css-file CSSFile", "Specify CSS to use for HTML output" do |file|
|
123
|
-
options[:html_style] = File.expand_path file
|
124
|
-
end
|
125
|
-
|
126
|
-
opts.on "-l", "--[no]-combine-locations", "Combine warning locations (Default)" do |combine|
|
127
|
-
options[:combine_locations] = combine
|
128
|
-
end
|
129
|
-
|
130
|
-
opts.on "-m", "--routes", "Report controller information" do
|
131
|
-
options[:report_routes] = true
|
132
|
-
end
|
133
|
-
|
134
|
-
opts.on "--message-limit LENGTH", "Limit message length in HTML report" do |limit|
|
135
|
-
options[:message_limit] = limit.to_i
|
136
|
-
end
|
137
|
-
|
138
|
-
opts.on "-o", "--output FILE", "Specify file for output. Defaults to stdout" do |file|
|
139
|
-
options[:output_file] = file
|
140
|
-
end
|
141
|
-
|
142
|
-
opts.on "--separate-models", "Warn on each model without attr_accessible" do
|
143
|
-
options[:collapse_mass_assignment] = false
|
144
|
-
end
|
145
|
-
|
146
|
-
opts.on "-w",
|
147
|
-
"--confidence-level LEVEL",
|
148
|
-
["1", "2", "3"],
|
149
|
-
"Set minimal confidence level (1 - 3)" do |level|
|
150
|
-
|
151
|
-
options[:min_confidence] = 3 - level.to_i
|
152
|
-
end
|
153
|
-
|
154
|
-
opts.separator ""
|
155
|
-
opts.separator "Configuration files:"
|
156
|
-
|
157
|
-
opts.on "-c", "--config-file FILE", "Use specified configuration file" do |file|
|
158
|
-
options[:config_file] = File.expand_path(file)
|
159
|
-
end
|
160
|
-
|
161
|
-
opts.on "-C", "--create-config [FILE]", "Output configuration file based on options" do |file|
|
162
|
-
if file
|
163
|
-
options[:create_config] = file
|
164
|
-
else
|
165
|
-
options[:create_config] = true
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
|
-
opts.separator ""
|
170
|
-
|
171
|
-
opts.on "-k", "--checks", "List all available vulnerability checks" do
|
172
|
-
options[:list_checks] = true
|
173
|
-
end
|
174
|
-
|
175
|
-
opts.on "-v", "--version", "Show Brakeman version" do
|
176
|
-
puts "brakeman #{Brakeman::Version}"
|
177
|
-
exit
|
178
|
-
end
|
14
|
+
#Parse options
|
15
|
+
options, parser = Brakeman::Options.parse! ARGV
|
16
|
+
|
17
|
+
#Exit early for these options
|
18
|
+
if options[:list_checks]
|
19
|
+
Brakeman.list_checks
|
20
|
+
exit
|
21
|
+
elsif options[:create_config]
|
22
|
+
Brakeman.dump_config options
|
23
|
+
exit
|
24
|
+
elsif options[:show_help]
|
25
|
+
puts parser
|
26
|
+
exit
|
27
|
+
elsif options[:show_version]
|
28
|
+
puts "brakeman #{Brakeman::Version}"
|
29
|
+
exit
|
30
|
+
elsif options[:install_rake_task]
|
31
|
+
Brakeman.install_rake_task
|
32
|
+
exit
|
33
|
+
end
|
179
34
|
|
180
|
-
|
181
|
-
|
182
|
-
|
35
|
+
#Set application path according to the commandline arguments
|
36
|
+
unless options[:app_path]
|
37
|
+
if ARGV[-1].nil?
|
38
|
+
options[:app_path] = File.expand_path "."
|
39
|
+
else
|
40
|
+
options[:app_path] = File.expand_path ARGV[-1]
|
183
41
|
end
|
184
|
-
end
|
42
|
+
end
|
185
43
|
|
44
|
+
#Run scan and output a report
|
186
45
|
clean = Brakeman.run options.merge(:print_report => true, :quiet => options[:quiet])
|
187
46
|
|
188
|
-
if
|
47
|
+
#Return error code if --exit-on-warn is used and warnings were found
|
48
|
+
if options[:exit_on_warn] and not clean
|
189
49
|
exit Brakeman::Warnings_Found_Exit_Code
|
190
50
|
end
|
191
|
-
|
data/lib/brakeman.rb
CHANGED
@@ -4,6 +4,10 @@ require 'set'
|
|
4
4
|
|
5
5
|
module Brakeman
|
6
6
|
|
7
|
+
#This exit code is used when warnings are found and the --exit-on-warn
|
8
|
+
#option is set
|
9
|
+
Warnings_Found_Exit_Code = 3
|
10
|
+
|
7
11
|
#Run Brakeman scan. Returns Tracker object.
|
8
12
|
#
|
9
13
|
#Options:
|
@@ -14,12 +18,10 @@ module Brakeman
|
|
14
18
|
# * :collapse_mass_assignment - report unprotected models in single warning (default: true)
|
15
19
|
# * :combine_locations - combine warning locations (default: true)
|
16
20
|
# * :config_file - configuration file
|
17
|
-
# * :create_config - output configuration file
|
18
21
|
# * :escape_html - escape HTML by default (automatic)
|
19
22
|
# * :exit_on_warn - return false if warnings found, true otherwise. Not recommended for library use (default: false)
|
20
23
|
# * :html_style - path to CSS file
|
21
24
|
# * :ignore_model_output - consider models safe (default: false)
|
22
|
-
# * :list_checks - list all checks (does not run scan)
|
23
25
|
# * :message_limit - limit length of messages
|
24
26
|
# * :min_confidence - minimum confidence (0-2, 0 is highest)
|
25
27
|
# * :output_file - file for output
|
@@ -33,18 +35,11 @@ module Brakeman
|
|
33
35
|
# * :safe_methods - array of methods to consider safe
|
34
36
|
# * :skip_libs - do not process lib/ directory (default: false)
|
35
37
|
# * :skip_checks - checks not to run (run all if not specified)
|
38
|
+
# * :summary_only - only output summary section of report
|
39
|
+
# (does not apply to tabs format)
|
36
40
|
#
|
41
|
+
#Alternatively, just supply a path as a string.
|
37
42
|
def self.run options
|
38
|
-
if options[:list_checks]
|
39
|
-
list_checks
|
40
|
-
exit
|
41
|
-
end
|
42
|
-
|
43
|
-
if options[:create_config]
|
44
|
-
dump_config options
|
45
|
-
exit
|
46
|
-
end
|
47
|
-
|
48
43
|
options = set_options options
|
49
44
|
|
50
45
|
if options[:quiet]
|
@@ -55,22 +50,17 @@ module Brakeman
|
|
55
50
|
scan options
|
56
51
|
end
|
57
52
|
|
58
|
-
private
|
59
|
-
|
60
53
|
def self.set_options options
|
54
|
+
if options.is_a? String
|
55
|
+
options = { :app_path => options }
|
56
|
+
end
|
57
|
+
|
58
|
+
options[:app_path] = File.expand_path(options[:app_path])
|
59
|
+
|
61
60
|
options = load_options(options[:config_file]).merge! options
|
62
61
|
options = get_defaults.merge! options
|
63
62
|
options[:output_format] = get_output_format options
|
64
63
|
|
65
|
-
#Check application path
|
66
|
-
unless options[:app_path]
|
67
|
-
if ARGV[-1].nil?
|
68
|
-
options[:app_path] = File.expand_path "."
|
69
|
-
else
|
70
|
-
options[:app_path] = File.expand_path ARGV[-1]
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
64
|
app_path = options[:app_path]
|
75
65
|
|
76
66
|
abort("Please supply the path to a Rails application.") unless app_path and File.exist? app_path + "/app"
|
@@ -86,7 +76,7 @@ module Brakeman
|
|
86
76
|
def self.load_options config_file
|
87
77
|
config_file ||= ""
|
88
78
|
|
89
|
-
#Load
|
79
|
+
#Load configuration file
|
90
80
|
[File.expand_path(config_file),
|
91
81
|
File.expand_path("./config.yaml"),
|
92
82
|
File.expand_path("~/.brakeman/config.yaml"),
|
@@ -161,7 +151,33 @@ module Brakeman
|
|
161
151
|
require 'brakeman/scanner'
|
162
152
|
$stderr.puts "Available Checks:"
|
163
153
|
$stderr.puts "-" * 30
|
164
|
-
$stderr.puts Checks.checks.map { |c| c.to_s }.sort.join "\n"
|
154
|
+
$stderr.puts Checks.checks.map { |c| c.to_s.match(/^Brakeman::(.*)$/)[1] }.sort.join "\n"
|
155
|
+
end
|
156
|
+
|
157
|
+
def self.install_rake_task
|
158
|
+
if not File.exists? "Rakefile"
|
159
|
+
abort "No Rakefile detected"
|
160
|
+
elsif File.exists? "lib/tasks/brakeman.rake"
|
161
|
+
abort "Task already exists"
|
162
|
+
end
|
163
|
+
|
164
|
+
require 'fileutils'
|
165
|
+
|
166
|
+
if not File.exists? "lib/tasks"
|
167
|
+
warn "Creating lib/tasks"
|
168
|
+
FileUtils.mkdir_p "lib/tasks"
|
169
|
+
end
|
170
|
+
|
171
|
+
path = File.expand_path(File.dirname(__FILE__))
|
172
|
+
|
173
|
+
FileUtils.cp "#{path}/brakeman/brakeman.rake", "lib/tasks/brakeman.rake"
|
174
|
+
|
175
|
+
if File.exists? "lib/tasks/brakeman.rake"
|
176
|
+
warn "Task created in lib/tasks/brakeman.rake"
|
177
|
+
warn "Usage: rake brakeman:run[output_file]"
|
178
|
+
else
|
179
|
+
warn "Could not create task"
|
180
|
+
end
|
165
181
|
end
|
166
182
|
|
167
183
|
def self.dump_config options
|
@@ -239,4 +255,10 @@ module Brakeman
|
|
239
255
|
|
240
256
|
tracker
|
241
257
|
end
|
258
|
+
|
259
|
+
def self.rescan tracker, files
|
260
|
+
require 'brakeman/rescanner'
|
261
|
+
|
262
|
+
Rescanner.new(tracker.options, tracker.processor, files).recheck
|
263
|
+
end
|
242
264
|
end
|
data/lib/brakeman/call_index.rb
CHANGED
@@ -67,7 +67,41 @@ class Brakeman::CallIndex
|
|
67
67
|
calls
|
68
68
|
end
|
69
69
|
|
70
|
-
|
70
|
+
def remove_template_indexes
|
71
|
+
@calls_by_method.each do |name, calls|
|
72
|
+
calls.delete_if do |call|
|
73
|
+
call[:location][0] == :template
|
74
|
+
end
|
75
|
+
|
76
|
+
@methods.delete name.to_s if calls.empty?
|
77
|
+
end
|
78
|
+
|
79
|
+
@calls_by_target.each do |name, calls|
|
80
|
+
calls.delete_if do |call|
|
81
|
+
call[:location][0] == :template
|
82
|
+
end
|
83
|
+
|
84
|
+
@targets.delete name.to_s if calls.empty?
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def remove_indexes_by_class classes
|
89
|
+
@calls_by_method.each do |name, calls|
|
90
|
+
calls.delete_if do |call|
|
91
|
+
call[:location][0] == :class and classes.include? call[:location][1]
|
92
|
+
end
|
93
|
+
|
94
|
+
@methods.delete name.to_s if calls.empty?
|
95
|
+
end
|
96
|
+
|
97
|
+
@calls_by_target.each do |name, calls|
|
98
|
+
calls.delete_if do |call|
|
99
|
+
call[:location][0] == :class and classes.include? call[:location][1]
|
100
|
+
end
|
101
|
+
|
102
|
+
@targets.delete name.to_s if calls.empty?
|
103
|
+
end
|
104
|
+
end
|
71
105
|
|
72
106
|
def index_calls calls
|
73
107
|
calls.each do |call|
|
@@ -78,6 +112,8 @@ class Brakeman::CallIndex
|
|
78
112
|
end
|
79
113
|
end
|
80
114
|
|
115
|
+
private
|
116
|
+
|
81
117
|
def find_chain options
|
82
118
|
target = options[:target] || options[:targets]
|
83
119
|
method = options[:method] || options[:methods]
|
data/lib/brakeman/checks.rb
CHANGED
@@ -46,6 +46,23 @@ class Brakeman::Checks
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
+
#Return a hash of arrays of new and fixed warnings
|
50
|
+
#
|
51
|
+
# diff = checks.diff old_checks
|
52
|
+
# diff[:fixed] # [...]
|
53
|
+
# diff[:new] # [...]
|
54
|
+
def diff other_checks
|
55
|
+
my_warnings = self.all_warnings
|
56
|
+
other_warnings = other_checks.all_warnings
|
57
|
+
|
58
|
+
diff = {}
|
59
|
+
|
60
|
+
diff[:fixed] = other_warnings - my_warnings
|
61
|
+
diff[:new] = my_warnings - other_warnings
|
62
|
+
|
63
|
+
diff
|
64
|
+
end
|
65
|
+
|
49
66
|
#Return an array of all warnings found.
|
50
67
|
def all_warnings
|
51
68
|
@warnings + @template_warnings + @controller_warnings + @model_warnings
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'sexp_processor'
|
2
2
|
require 'brakeman/processors/output_processor'
|
3
|
+
require 'brakeman/processors/lib/processor_helper'
|
3
4
|
require 'brakeman/warning'
|
4
5
|
require 'brakeman/util'
|
5
6
|
|
@@ -91,7 +92,10 @@ class Brakeman::BaseCheck < SexpProcessor
|
|
91
92
|
|
92
93
|
#Report a warning
|
93
94
|
def warn options
|
94
|
-
|
95
|
+
warning = Brakeman::Warning.new(options.merge({ :check => self.class.to_s }))
|
96
|
+
warning.file = file_for warning
|
97
|
+
|
98
|
+
@warnings << warning
|
95
99
|
end
|
96
100
|
|
97
101
|
#Run _exp_ through OutputProcessor to get a nice String.
|
@@ -14,22 +14,9 @@ require 'set'
|
|
14
14
|
class Brakeman::CheckCrossSiteScripting < Brakeman::BaseCheck
|
15
15
|
Brakeman::Checks.add self
|
16
16
|
|
17
|
-
#Ignore these methods and their arguments.
|
18
|
-
#It is assumed they will take care of escaping their output.
|
19
|
-
IGNORE_METHODS = Set.new([:button_to, :check_box, :escapeHTML, :escape_once,
|
20
|
-
:field_field, :fields_for, :h, :hidden_field,
|
21
|
-
:hidden_field, :hidden_field_tag, :image_tag, :label,
|
22
|
-
:link_to, :mail_to, :radio_button, :select,
|
23
|
-
:submit_tag, :text_area, :text_field,
|
24
|
-
:text_field_tag, :url_encode, :url_for,
|
25
|
-
:will_paginate] )
|
26
|
-
|
27
17
|
#Model methods which are known to be harmless
|
28
18
|
IGNORE_MODEL_METHODS = Set.new([:average, :count, :maximum, :minimum, :sum])
|
29
19
|
|
30
|
-
#Methods known to not escape their input
|
31
|
-
KNOWN_DANGEROUS = Set.new([:truncate, :concat])
|
32
|
-
|
33
20
|
MODEL_METHODS = Set.new([:all, :find, :first, :last, :new])
|
34
21
|
|
35
22
|
IGNORE_LIKE = /^link_to_|(_path|_tag|_url)$/
|
@@ -46,7 +33,14 @@ class Brakeman::CheckCrossSiteScripting < Brakeman::BaseCheck
|
|
46
33
|
|
47
34
|
#Run check
|
48
35
|
def run_check
|
49
|
-
|
36
|
+
@ignore_methods = Set.new([:button_to, :check_box, :escapeHTML, :escape_once,
|
37
|
+
:field_field, :fields_for, :h, :hidden_field,
|
38
|
+
:hidden_field, :hidden_field_tag, :image_tag, :label,
|
39
|
+
:link_to, :mail_to, :radio_button, :select,
|
40
|
+
:submit_tag, :text_area, :text_field,
|
41
|
+
:text_field_tag, :url_encode, :url_for,
|
42
|
+
:will_paginate] ).merge tracker.options[:safe_methods]
|
43
|
+
|
50
44
|
@models = tracker.models.keys
|
51
45
|
@inspect_arguments = tracker.options[:check_arguments]
|
52
46
|
|
@@ -54,10 +48,12 @@ class Brakeman::CheckCrossSiteScripting < Brakeman::BaseCheck
|
|
54
48
|
link_to_check.run_check
|
55
49
|
warnings.concat link_to_check.warnings unless link_to_check.warnings.empty?
|
56
50
|
|
51
|
+
@known_dangerous = Set.new([:truncate, :concat])
|
52
|
+
|
57
53
|
if version_between? "2.0.0", "3.0.5"
|
58
|
-
|
54
|
+
@known_dangerous << :auto_link
|
59
55
|
elsif version_between? "3.0.6", "3.0.99"
|
60
|
-
|
56
|
+
@ignore_methods << :auto_link
|
61
57
|
end
|
62
58
|
|
63
59
|
tracker.each_template do |name, template|
|
@@ -170,7 +166,7 @@ class Brakeman::CheckCrossSiteScripting < Brakeman::BaseCheck
|
|
170
166
|
if message and not duplicate? exp
|
171
167
|
add_result exp
|
172
168
|
|
173
|
-
if exp[1].nil? and
|
169
|
+
if exp[1].nil? and @known_dangerous.include? exp[2]
|
174
170
|
confidence = CONFIDENCE[:high]
|
175
171
|
else
|
176
172
|
confidence = CONFIDENCE[:low]
|
@@ -201,15 +197,15 @@ class Brakeman::CheckCrossSiteScripting < Brakeman::BaseCheck
|
|
201
197
|
args = exp[3]
|
202
198
|
|
203
199
|
#Ignore safe items
|
204
|
-
if (target.nil? and (
|
200
|
+
if (target.nil? and (@ignore_methods.include? method or method.to_s =~ IGNORE_LIKE)) or
|
205
201
|
(@matched == :model and IGNORE_MODEL_METHODS.include? method) or
|
206
202
|
(target == HAML_HELPERS and method == :html_escape) or
|
207
203
|
((target == URI or target == CGI) and method == :escape) or
|
208
204
|
(target == XML_HELPER and method == :escape_xml) or
|
209
|
-
(target == FORM_BUILDER and
|
205
|
+
(target == FORM_BUILDER and @ignore_methods.include? method) or
|
210
206
|
(method.to_s[-1,1] == "?")
|
211
207
|
|
212
|
-
exp[0] = :ignore
|
208
|
+
#exp[0] = :ignore #should not be necessary
|
213
209
|
@matched = false
|
214
210
|
elsif sexp? exp[1] and model_name? exp[1][1]
|
215
211
|
@matched = :model
|
@@ -269,9 +265,9 @@ end
|
|
269
265
|
|
270
266
|
#This _only_ checks calls to link_to
|
271
267
|
class Brakeman::CheckLinkTo < Brakeman::CheckCrossSiteScripting
|
272
|
-
IGNORE_METHODS = IGNORE_METHODS - [:link_to]
|
273
|
-
|
274
268
|
def run_check
|
269
|
+
@ignore_methods = []
|
270
|
+
@known_dangerous = []
|
275
271
|
#Ideally, I think this should also check to see if people are setting
|
276
272
|
#:escape => false
|
277
273
|
methods = tracker.find_call :target => false, :method => :link_to
|