brakeman-lib 4.4.0 → 4.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +63 -0
  3. data/README.md +6 -7
  4. data/lib/brakeman.rb +7 -0
  5. data/lib/brakeman/app_tree.rb +34 -22
  6. data/lib/brakeman/call_index.rb +54 -15
  7. data/lib/brakeman/checks.rb +7 -7
  8. data/lib/brakeman/checks/base_check.rb +75 -56
  9. data/lib/brakeman/checks/check_content_tag.rb +12 -0
  10. data/lib/brakeman/checks/check_cookie_serialization.rb +22 -0
  11. data/lib/brakeman/checks/check_cross_site_scripting.rb +15 -10
  12. data/lib/brakeman/checks/check_default_routes.rb +5 -0
  13. data/lib/brakeman/checks/check_deserialize.rb +49 -0
  14. data/lib/brakeman/checks/check_dynamic_finders.rb +1 -1
  15. data/lib/brakeman/checks/check_evaluation.rb +0 -1
  16. data/lib/brakeman/checks/check_execute.rb +44 -1
  17. data/lib/brakeman/checks/check_file_access.rb +7 -1
  18. data/lib/brakeman/checks/check_force_ssl.rb +27 -0
  19. data/lib/brakeman/checks/check_header_dos.rb +2 -2
  20. data/lib/brakeman/checks/check_i18n_xss.rb +2 -2
  21. data/lib/brakeman/checks/check_jruby_xml.rb +2 -2
  22. data/lib/brakeman/checks/check_json_parsing.rb +7 -2
  23. data/lib/brakeman/checks/check_link_to_href.rb +6 -1
  24. data/lib/brakeman/checks/check_mail_to.rb +1 -1
  25. data/lib/brakeman/checks/check_mime_type_dos.rb +2 -2
  26. data/lib/brakeman/checks/check_model_attr_accessible.rb +1 -1
  27. data/lib/brakeman/checks/check_model_attributes.rb +12 -50
  28. data/lib/brakeman/checks/check_model_serialize.rb +1 -1
  29. data/lib/brakeman/checks/check_nested_attributes_bypass.rb +4 -4
  30. data/lib/brakeman/checks/check_reverse_tabnabbing.rb +54 -0
  31. data/lib/brakeman/checks/check_sanitize_methods.rb +2 -2
  32. data/lib/brakeman/checks/check_secrets.rb +1 -1
  33. data/lib/brakeman/checks/check_send.rb +0 -1
  34. data/lib/brakeman/checks/check_session_manipulation.rb +0 -1
  35. data/lib/brakeman/checks/check_session_settings.rb +15 -12
  36. data/lib/brakeman/checks/check_simple_format.rb +5 -0
  37. data/lib/brakeman/checks/check_skip_before_filter.rb +1 -1
  38. data/lib/brakeman/checks/check_sql.rb +27 -20
  39. data/lib/brakeman/checks/check_validation_regex.rb +1 -1
  40. data/lib/brakeman/checks/check_xml_dos.rb +2 -2
  41. data/lib/brakeman/checks/check_yaml_parsing.rb +10 -18
  42. data/lib/brakeman/differ.rb +16 -28
  43. data/lib/brakeman/file_parser.rb +6 -8
  44. data/lib/brakeman/file_path.rb +85 -0
  45. data/lib/brakeman/options.rb +7 -0
  46. data/lib/brakeman/parsers/haml_embedded.rb +44 -0
  47. data/lib/brakeman/parsers/slim_embedded.rb +44 -0
  48. data/lib/brakeman/parsers/template_parser.rb +8 -8
  49. data/lib/brakeman/processor.rb +4 -5
  50. data/lib/brakeman/processors/alias_processor.rb +49 -7
  51. data/lib/brakeman/processors/base_processor.rb +10 -7
  52. data/lib/brakeman/processors/controller_alias_processor.rb +10 -7
  53. data/lib/brakeman/processors/controller_processor.rb +9 -13
  54. data/lib/brakeman/processors/gem_processor.rb +10 -2
  55. data/lib/brakeman/processors/haml_template_processor.rb +92 -123
  56. data/lib/brakeman/processors/lib/call_conversion_helper.rb +4 -0
  57. data/lib/brakeman/processors/lib/find_all_calls.rb +27 -4
  58. data/lib/brakeman/processors/lib/find_call.rb +3 -64
  59. data/lib/brakeman/processors/lib/module_helper.rb +8 -8
  60. data/lib/brakeman/processors/lib/processor_helper.rb +3 -3
  61. data/lib/brakeman/processors/lib/rails2_config_processor.rb +4 -4
  62. data/lib/brakeman/processors/lib/rails2_route_processor.rb +2 -2
  63. data/lib/brakeman/processors/lib/rails3_config_processor.rb +3 -3
  64. data/lib/brakeman/processors/lib/rails3_route_processor.rb +2 -2
  65. data/lib/brakeman/processors/lib/render_helper.rb +2 -2
  66. data/lib/brakeman/processors/lib/render_path.rb +18 -1
  67. data/lib/brakeman/processors/library_processor.rb +5 -5
  68. data/lib/brakeman/processors/model_processor.rb +4 -5
  69. data/lib/brakeman/processors/output_processor.rb +5 -0
  70. data/lib/brakeman/processors/slim_template_processor.rb +16 -0
  71. data/lib/brakeman/processors/template_alias_processor.rb +32 -5
  72. data/lib/brakeman/processors/template_processor.rb +14 -10
  73. data/lib/brakeman/report.rb +3 -3
  74. data/lib/brakeman/report/ignore/config.rb +2 -3
  75. data/lib/brakeman/report/ignore/interactive.rb +2 -2
  76. data/lib/brakeman/report/pager.rb +1 -0
  77. data/lib/brakeman/report/report_base.rb +51 -6
  78. data/lib/brakeman/report/report_codeclimate.rb +3 -3
  79. data/lib/brakeman/report/report_hash.rb +1 -1
  80. data/lib/brakeman/report/report_html.rb +2 -2
  81. data/lib/brakeman/report/report_json.rb +1 -24
  82. data/lib/brakeman/report/report_table.rb +20 -4
  83. data/lib/brakeman/report/report_tabs.rb +1 -1
  84. data/lib/brakeman/report/report_text.rb +2 -2
  85. data/lib/brakeman/rescanner.rb +13 -12
  86. data/lib/brakeman/scanner.rb +24 -18
  87. data/lib/brakeman/tracker.rb +35 -7
  88. data/lib/brakeman/tracker/collection.rb +4 -3
  89. data/lib/brakeman/tracker/config.rb +44 -48
  90. data/lib/brakeman/tracker/constants.rb +2 -1
  91. data/lib/brakeman/util.rb +18 -147
  92. data/lib/brakeman/version.rb +1 -1
  93. data/lib/brakeman/warning.rb +27 -13
  94. data/lib/brakeman/warning_codes.rb +4 -0
  95. data/lib/ruby_parser/bm_sexp.rb +1 -1
  96. data/lib/ruby_parser/bm_sexp_processor.rb +1 -0
  97. metadata +58 -43
@@ -40,6 +40,10 @@ module Brakeman
40
40
  else
41
41
  original_exp
42
42
  end
43
+ rescue Encoding::CompatibilityError => e
44
+ # If the two strings are different encodings, we can't join them.
45
+ Brakeman.debug e.inspect
46
+ original_exp
43
47
  end
44
48
 
45
49
  def math_op op, lhs, rhs, original_exp = nil
@@ -5,9 +5,9 @@ class Brakeman::FindAllCalls < Brakeman::BasicProcessor
5
5
 
6
6
  def initialize tracker
7
7
  super
8
- @current_class = nil
9
- @current_method = nil
8
+
10
9
  @in_target = false
10
+ @processing_class = false
11
11
  @calls = []
12
12
  @cache = {}
13
13
  end
@@ -23,10 +23,33 @@ class Brakeman::FindAllCalls < Brakeman::BasicProcessor
23
23
  process exp
24
24
  end
25
25
 
26
+ #For whatever reason, originally the indexing of calls
27
+ #was performed on individual method bodies (see process_defn).
28
+ #This method explicitly indexes all calls everywhere given any
29
+ #source.
30
+ def process_all_source exp, opts
31
+ @processing_class = true
32
+ process_source exp, opts
33
+ ensure
34
+ @processing_class = false
35
+ end
36
+
26
37
  #Process body of method
27
38
  def process_defn exp
28
- return exp unless @current_method
29
- process_all exp.body
39
+ return exp unless @current_method or @processing_class
40
+
41
+ # 'Normal' processing assumes the method name was given
42
+ # as an option to `process_source` but for `process_all_source`
43
+ # we don't want to do that.
44
+ if @current_method.nil?
45
+ @current_method = exp.method_name
46
+ process_all exp.body
47
+ @current_method = nil
48
+ else
49
+ process_all exp.body
50
+ end
51
+
52
+ exp
30
53
  end
31
54
 
32
55
  alias process_defs process_defn
@@ -33,14 +33,13 @@ require 'brakeman/processors/lib/basic_processor'
33
33
  # FindCall.new nil, /^g?sub!?$/
34
34
  class Brakeman::FindCall < Brakeman::BasicProcessor
35
35
 
36
- def initialize targets, methods, tracker, in_depth = false
36
+ def initialize targets, methods, tracker
37
37
  super tracker
38
38
  @calls = []
39
39
  @find_targets = targets
40
40
  @find_methods = methods
41
41
  @current_class = nil
42
42
  @current_method = nil
43
- @in_depth = in_depth
44
43
  end
45
44
 
46
45
  #Returns a list of results.
@@ -48,10 +47,6 @@ class Brakeman::FindCall < Brakeman::BasicProcessor
48
47
  #A result looks like:
49
48
  #
50
49
  # s(:result, :ClassName, :method_name, s(:call, ...))
51
- #
52
- #or
53
- #
54
- # s(:result, :template_name, s(:call, ...))
55
50
  def matches
56
51
  @calls
57
52
  end
@@ -60,10 +55,7 @@ class Brakeman::FindCall < Brakeman::BasicProcessor
60
55
  #or the template. These names are used when reporting results.
61
56
  #
62
57
  #Use FindCall#matches to retrieve results.
63
- def process_source exp, klass = nil, method = nil, template = nil
64
- @current_class = klass
65
- @current_method = method
66
- @current_template = template
58
+ def process_source exp
67
59
  process exp
68
60
  end
69
61
 
@@ -74,11 +66,6 @@ class Brakeman::FindCall < Brakeman::BasicProcessor
74
66
 
75
67
  alias :process_defs :process_defn
76
68
 
77
- #Process body of block
78
- def process_rlist exp
79
- process_all exp
80
- end
81
-
82
69
  #Look for matching calls and add them to results
83
70
  def process_call exp
84
71
  target = get_target exp.target
@@ -87,25 +74,9 @@ class Brakeman::FindCall < Brakeman::BasicProcessor
87
74
  process_call_args exp
88
75
 
89
76
  if match(@find_targets, target) and match(@find_methods, method)
90
-
91
- if @current_template
92
- @calls << Sexp.new(:result, @current_template, exp).line(exp.line)
93
- else
94
- @calls << Sexp.new(:result, @current_module, @current_class, @current_method, exp).line(exp.line)
95
- end
96
-
77
+ @calls << Sexp.new(:result, @current_module, @current_class, @current_method, exp).line(exp.line)
97
78
  end
98
79
 
99
- #Normally FindCall won't match a method invocation that is the target of
100
- #another call, such as:
101
- #
102
- # User.find(:first, :conditions => "user = '#{params['user']}').name
103
- #
104
- #A search for User.find will not match this unless @in_depth is true.
105
- if @in_depth and call? exp.target
106
- process exp.target
107
- end
108
-
109
80
  exp
110
81
  end
111
82
 
@@ -123,8 +94,6 @@ class Brakeman::FindCall < Brakeman::BasicProcessor
123
94
  case exp.node_type
124
95
  when :ivar, :lvar, :const, :lit
125
96
  exp.value
126
- when :true, :false
127
- exp.node_type
128
97
  when :colon2
129
98
  class_name exp
130
99
  else
@@ -141,43 +110,13 @@ class Brakeman::FindCall < Brakeman::BasicProcessor
141
110
  when Symbol
142
111
  if search_terms == item
143
112
  true
144
- elsif sexp? item
145
- is_instance_of? item, search_terms
146
113
  else
147
114
  false
148
115
  end
149
- when Sexp
150
- search_terms == item
151
116
  when Enumerable
152
117
  if search_terms.empty?
153
118
  item == nil
154
- else
155
- search_terms.each do|term|
156
- if match(term, item)
157
- return true
158
- end
159
- end
160
- false
161
119
  end
162
- when Regexp
163
- search_terms.match item.to_s
164
- when nil
165
- true
166
- else
167
- raise "Cannot match #{search_terms} and #{item}"
168
- end
169
- end
170
-
171
- #Checks if +item+ is an instance of +klass+ by looking for Klass.new
172
- def is_instance_of? item, klass
173
- if call? item
174
- if sexp? item.target
175
- item.method == :new and item.target.node_type == :const and item.target.value == klass
176
- else
177
- item.method == :new and item.target == klass
178
- end
179
- else
180
- false
181
120
  end
182
121
  end
183
122
  end
@@ -13,9 +13,9 @@ module Brakeman::ModuleHelper
13
13
 
14
14
  if @tracker.libs[name]
15
15
  @current_module = @tracker.libs[name]
16
- @current_module.add_file @file_name, exp
16
+ @current_module.add_file @current_file, exp
17
17
  else
18
- @current_module = tracker_class.new name, parent, @file_name, exp, @tracker
18
+ @current_module = tracker_class.new name, parent, @current_file, exp, @tracker
19
19
  @tracker.libs[name] = @current_module
20
20
  end
21
21
 
@@ -45,9 +45,9 @@ module Brakeman::ModuleHelper
45
45
 
46
46
  if collection[name]
47
47
  @current_class = collection[name]
48
- @current_class.add_file @file_name, exp
48
+ @current_class.add_file @current_file, exp
49
49
  else
50
- @current_class = tracker_class.new name, parent, @file_name, exp, @tracker
50
+ @current_class = tracker_class.new name, parent, @current_file, exp, @tracker
51
51
  collection[name] = @current_class
52
52
  end
53
53
 
@@ -85,9 +85,9 @@ module Brakeman::ModuleHelper
85
85
  @current_method = nil
86
86
 
87
87
  if @current_class
88
- @current_class.add_method @visibility, name, res, @file_name
88
+ @current_class.add_method @visibility, name, res, @current_file
89
89
  elsif @current_module
90
- @current_module.add_method @visibility, name, res, @file_name
90
+ @current_module.add_method @visibility, name, res, @current_file
91
91
  end
92
92
  res
93
93
  end
@@ -101,9 +101,9 @@ module Brakeman::ModuleHelper
101
101
  @current_method = nil
102
102
 
103
103
  if @current_class
104
- @current_class.add_method @visibility, name, res, @file_name
104
+ @current_class.add_method @visibility, name, res, @current_file
105
105
  elsif @current_module
106
- @current_module.add_method @visibility, name, res, @file_name
106
+ @current_module.add_method @visibility, name, res, @current_file
107
107
  end
108
108
 
109
109
  res
@@ -73,10 +73,10 @@ module Brakeman::ProcessorHelper
73
73
  end
74
74
  end
75
75
 
76
- def current_file_name
76
+ def current_file
77
77
  case
78
- when @file_name
79
- @file_name
78
+ when @current_file
79
+ @current_file
80
80
  when @current_class.is_a?(Brakeman::Collection)
81
81
  @current_class.file
82
82
  when @current_module.is_a?(Brakeman::Collection)
@@ -27,9 +27,9 @@ class Brakeman::Rails2ConfigProcessor < Brakeman::BasicProcessor
27
27
  end
28
28
 
29
29
  #Use this method to process configuration file
30
- def process_config src, file_name
31
- @file_name = file_name
32
- res = Brakeman::ConfigAliasProcessor.new.process_safely(src, nil, file_name)
30
+ def process_config src, current_file
31
+ @current_file = current_file
32
+ res = Brakeman::ConfigAliasProcessor.new.process_safely(src, nil, current_file)
33
33
  process res
34
34
  end
35
35
 
@@ -75,7 +75,7 @@ class Brakeman::Rails2ConfigProcessor < Brakeman::BasicProcessor
75
75
  def process_cdecl exp
76
76
  #Set Rails version required
77
77
  if exp.lhs == :RAILS_GEM_VERSION
78
- @tracker.config.rails_version = exp.rhs.value
78
+ @tracker.config.set_rails_version exp.rhs.value
79
79
  end
80
80
 
81
81
  exp
@@ -16,7 +16,7 @@ class Brakeman::Rails2RoutesProcessor < Brakeman::BasicProcessor
16
16
  @prefix = [] #Controller name prefix (a module name, usually)
17
17
  @current_controller = nil
18
18
  @with_options = nil #For use inside map.with_options
19
- @file_name = "config/routes.rb"
19
+ @current_file = "config/routes.rb"
20
20
  end
21
21
 
22
22
  #Call this with parsed route file information.
@@ -24,7 +24,7 @@ class Brakeman::Rails2RoutesProcessor < Brakeman::BasicProcessor
24
24
  #This method first calls RouteAliasProcessor#process_safely on the +exp+,
25
25
  #so it does not modify the +exp+.
26
26
  def process_routes exp
27
- process Brakeman::RouteAliasProcessor.new.process_safely(exp, nil, @file_name)
27
+ process Brakeman::RouteAliasProcessor.new.process_safely(exp, nil, @current_file)
28
28
  end
29
29
 
30
30
  #Looking for mapping of routes
@@ -24,9 +24,9 @@ class Brakeman::Rails3ConfigProcessor < Brakeman::BasicProcessor
24
24
  end
25
25
 
26
26
  #Use this method to process configuration file
27
- def process_config src, file_name
28
- @file_name = file_name
29
- res = Brakeman::AliasProcessor.new(@tracker).process_safely(src, nil, @file_name)
27
+ def process_config src, current_file
28
+ @current_file = current_file
29
+ res = Brakeman::AliasProcessor.new(@tracker).process_safely(src, nil, @current_file)
30
30
  process res
31
31
  end
32
32
 
@@ -17,11 +17,11 @@ class Brakeman::Rails3RoutesProcessor < Brakeman::BasicProcessor
17
17
  @current_controller = nil
18
18
  @with_options = nil #For use inside map.with_options
19
19
  @controller_block = false
20
- @file_name = "config/routes.rb"
20
+ @current_file = "config/routes.rb"
21
21
  end
22
22
 
23
23
  def process_routes exp
24
- process Brakeman::AliasProcessor.new.process_safely(exp, nil, @file_name)
24
+ process Brakeman::AliasProcessor.new.process_safely(exp, nil, @current_file)
25
25
  end
26
26
 
27
27
  def process_call exp
@@ -36,7 +36,7 @@ module Brakeman::RenderHelper
36
36
 
37
37
  #Determines file name for partial and then processes it
38
38
  def process_partial name, args, line
39
- if name == "" or !(string? name or symbol? name)
39
+ if !(string? name or symbol? name) or name.value == ""
40
40
  return
41
41
  end
42
42
 
@@ -148,7 +148,7 @@ module Brakeman::RenderHelper
148
148
  #This information will be stored in tracker.templates, but with a name
149
149
  #specifying this particular route. The original source should remain
150
150
  #pristine (so it can be processed within other environments).
151
- @tracker.processor.process_template name, src, template.type, called_from
151
+ @tracker.processor.process_template name, src, template.type, called_from, template.file
152
152
  end
153
153
  end
154
154
 
@@ -83,7 +83,7 @@ module Brakeman
83
83
  end
84
84
 
85
85
  def map &block
86
- @path.map &block
86
+ @path.map(&block)
87
87
  end
88
88
 
89
89
  def to_a
@@ -114,6 +114,23 @@ module Brakeman
114
114
  JSON.generate(@path)
115
115
  end
116
116
 
117
+ def with_relative_paths
118
+ @path.map do |loc|
119
+ r = loc.dup
120
+
121
+ if r[:file]
122
+ r[:file] = r[:file].relative
123
+ end
124
+
125
+ if r[:rendered] and r[:rendered][:file]
126
+ r[:rendered] = r[:rendered].dup
127
+ r[:rendered][:file] = r[:rendered][:file].relative
128
+ end
129
+
130
+ r
131
+ end
132
+ end
133
+
117
134
  def initialize_copy original
118
135
  @path = original.path.dup
119
136
  self
@@ -9,15 +9,15 @@ class Brakeman::LibraryProcessor < Brakeman::BaseProcessor
9
9
 
10
10
  def initialize tracker
11
11
  super
12
- @file_name = nil
12
+ @current_file = nil
13
13
  @alias_processor = Brakeman::AliasProcessor.new tracker
14
14
  @current_module = nil
15
15
  @current_class = nil
16
16
  @initializer_env = nil
17
17
  end
18
18
 
19
- def process_library src, file_name = nil
20
- @file_name = file_name
19
+ def process_library src, current_file = @current_file
20
+ @current_file = current_file
21
21
  process src
22
22
  end
23
23
 
@@ -41,10 +41,10 @@ class Brakeman::LibraryProcessor < Brakeman::BaseProcessor
41
41
 
42
42
  if @current_class
43
43
  exp.body = process_all! exp.body
44
- @current_class.add_method :public, exp.method_name, exp, @file_name
44
+ @current_class.add_method :public, exp.method_name, exp, @current_file
45
45
  elsif @current_module
46
46
  exp.body = process_all! exp.body
47
- @current_module.add_method :public, exp.method_name, exp, @file_name
47
+ @current_module.add_method :public, exp.method_name, exp, @current_file
48
48
  end
49
49
 
50
50
  exp
@@ -12,24 +12,23 @@ class Brakeman::ModelProcessor < Brakeman::BaseProcessor
12
12
  @current_method = nil
13
13
  @current_module = nil
14
14
  @visibility = :public
15
- @file_name = nil
15
+ @current_file = nil
16
16
  end
17
17
 
18
18
  #Process model source
19
- def process_model src, file_name = nil
20
- @file_name = file_name
19
+ def process_model src, current_file = @current_file
20
+ @current_file = current_file
21
21
  process src
22
22
  end
23
23
 
24
24
  #s(:class, NAME, PARENT, BODY)
25
25
  def process_class exp
26
26
  name = class_name(exp.class_name)
27
- parent = class_name(exp.parent_name)
28
27
 
29
28
  #If inside an inner class we treat it as a library.
30
29
  if @current_class
31
30
  Brakeman.debug "[Notice] Treating inner class as library: #{name}"
32
- Brakeman::LibraryProcessor.new(@tracker).process_library exp, @file_name
31
+ Brakeman::LibraryProcessor.new(@tracker).process_library exp, @current_file
33
32
  return exp
34
33
  end
35
34
 
@@ -8,6 +8,11 @@ require 'brakeman/util'
8
8
  class Brakeman::OutputProcessor < Ruby2Ruby
9
9
  include Brakeman::Util
10
10
 
11
+ def initialize *args
12
+ super
13
+ @user_input = nil
14
+ end
15
+
11
16
  #Copies +exp+ and then formats it.
12
17
  def format exp, user_input = nil, &block
13
18
  @user_input = user_input