brakeman-lib 3.3.1

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.
Files changed (159) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES +872 -0
  3. data/FEATURES +16 -0
  4. data/README.md +169 -0
  5. data/WARNING_TYPES +95 -0
  6. data/bin/brakeman +89 -0
  7. data/lib/brakeman.rb +495 -0
  8. data/lib/brakeman/app_tree.rb +161 -0
  9. data/lib/brakeman/brakeman.rake +17 -0
  10. data/lib/brakeman/call_index.rb +219 -0
  11. data/lib/brakeman/checks.rb +191 -0
  12. data/lib/brakeman/checks/base_check.rb +518 -0
  13. data/lib/brakeman/checks/check_basic_auth.rb +88 -0
  14. data/lib/brakeman/checks/check_basic_auth_timing_attack.rb +33 -0
  15. data/lib/brakeman/checks/check_content_tag.rb +160 -0
  16. data/lib/brakeman/checks/check_create_with.rb +75 -0
  17. data/lib/brakeman/checks/check_cross_site_scripting.rb +385 -0
  18. data/lib/brakeman/checks/check_default_routes.rb +86 -0
  19. data/lib/brakeman/checks/check_deserialize.rb +57 -0
  20. data/lib/brakeman/checks/check_detailed_exceptions.rb +55 -0
  21. data/lib/brakeman/checks/check_digest_dos.rb +38 -0
  22. data/lib/brakeman/checks/check_dynamic_finders.rb +49 -0
  23. data/lib/brakeman/checks/check_escape_function.rb +21 -0
  24. data/lib/brakeman/checks/check_evaluation.rb +36 -0
  25. data/lib/brakeman/checks/check_execute.rb +167 -0
  26. data/lib/brakeman/checks/check_file_access.rb +63 -0
  27. data/lib/brakeman/checks/check_file_disclosure.rb +35 -0
  28. data/lib/brakeman/checks/check_filter_skipping.rb +31 -0
  29. data/lib/brakeman/checks/check_forgery_setting.rb +74 -0
  30. data/lib/brakeman/checks/check_header_dos.rb +31 -0
  31. data/lib/brakeman/checks/check_i18n_xss.rb +48 -0
  32. data/lib/brakeman/checks/check_jruby_xml.rb +38 -0
  33. data/lib/brakeman/checks/check_json_encoding.rb +47 -0
  34. data/lib/brakeman/checks/check_json_parsing.rb +107 -0
  35. data/lib/brakeman/checks/check_link_to.rb +132 -0
  36. data/lib/brakeman/checks/check_link_to_href.rb +115 -0
  37. data/lib/brakeman/checks/check_mail_to.rb +49 -0
  38. data/lib/brakeman/checks/check_mass_assignment.rb +198 -0
  39. data/lib/brakeman/checks/check_mime_type_dos.rb +39 -0
  40. data/lib/brakeman/checks/check_model_attr_accessible.rb +55 -0
  41. data/lib/brakeman/checks/check_model_attributes.rb +119 -0
  42. data/lib/brakeman/checks/check_model_serialize.rb +67 -0
  43. data/lib/brakeman/checks/check_nested_attributes.rb +38 -0
  44. data/lib/brakeman/checks/check_nested_attributes_bypass.rb +58 -0
  45. data/lib/brakeman/checks/check_number_to_currency.rb +74 -0
  46. data/lib/brakeman/checks/check_quote_table_name.rb +40 -0
  47. data/lib/brakeman/checks/check_redirect.rb +215 -0
  48. data/lib/brakeman/checks/check_regex_dos.rb +69 -0
  49. data/lib/brakeman/checks/check_render.rb +92 -0
  50. data/lib/brakeman/checks/check_render_dos.rb +37 -0
  51. data/lib/brakeman/checks/check_render_inline.rb +54 -0
  52. data/lib/brakeman/checks/check_response_splitting.rb +21 -0
  53. data/lib/brakeman/checks/check_route_dos.rb +42 -0
  54. data/lib/brakeman/checks/check_safe_buffer_manipulation.rb +31 -0
  55. data/lib/brakeman/checks/check_sanitize_methods.rb +79 -0
  56. data/lib/brakeman/checks/check_secrets.rb +40 -0
  57. data/lib/brakeman/checks/check_select_tag.rb +60 -0
  58. data/lib/brakeman/checks/check_select_vulnerability.rb +60 -0
  59. data/lib/brakeman/checks/check_send.rb +48 -0
  60. data/lib/brakeman/checks/check_send_file.rb +19 -0
  61. data/lib/brakeman/checks/check_session_manipulation.rb +36 -0
  62. data/lib/brakeman/checks/check_session_settings.rb +170 -0
  63. data/lib/brakeman/checks/check_simple_format.rb +59 -0
  64. data/lib/brakeman/checks/check_single_quotes.rb +101 -0
  65. data/lib/brakeman/checks/check_skip_before_filter.rb +60 -0
  66. data/lib/brakeman/checks/check_sql.rb +660 -0
  67. data/lib/brakeman/checks/check_sql_cves.rb +101 -0
  68. data/lib/brakeman/checks/check_ssl_verify.rb +49 -0
  69. data/lib/brakeman/checks/check_strip_tags.rb +89 -0
  70. data/lib/brakeman/checks/check_symbol_dos.rb +64 -0
  71. data/lib/brakeman/checks/check_symbol_dos_cve.rb +30 -0
  72. data/lib/brakeman/checks/check_translate_bug.rb +45 -0
  73. data/lib/brakeman/checks/check_unsafe_reflection.rb +51 -0
  74. data/lib/brakeman/checks/check_unscoped_find.rb +41 -0
  75. data/lib/brakeman/checks/check_validation_regex.rb +116 -0
  76. data/lib/brakeman/checks/check_weak_hash.rb +151 -0
  77. data/lib/brakeman/checks/check_without_protection.rb +80 -0
  78. data/lib/brakeman/checks/check_xml_dos.rb +51 -0
  79. data/lib/brakeman/checks/check_yaml_parsing.rb +121 -0
  80. data/lib/brakeman/differ.rb +66 -0
  81. data/lib/brakeman/file_parser.rb +50 -0
  82. data/lib/brakeman/format/style.css +133 -0
  83. data/lib/brakeman/options.rb +301 -0
  84. data/lib/brakeman/parsers/rails2_erubis.rb +6 -0
  85. data/lib/brakeman/parsers/rails2_xss_plugin_erubis.rb +48 -0
  86. data/lib/brakeman/parsers/rails3_erubis.rb +74 -0
  87. data/lib/brakeman/parsers/template_parser.rb +89 -0
  88. data/lib/brakeman/processor.rb +102 -0
  89. data/lib/brakeman/processors/alias_processor.rb +1013 -0
  90. data/lib/brakeman/processors/base_processor.rb +277 -0
  91. data/lib/brakeman/processors/config_processor.rb +14 -0
  92. data/lib/brakeman/processors/controller_alias_processor.rb +273 -0
  93. data/lib/brakeman/processors/controller_processor.rb +326 -0
  94. data/lib/brakeman/processors/erb_template_processor.rb +80 -0
  95. data/lib/brakeman/processors/erubis_template_processor.rb +104 -0
  96. data/lib/brakeman/processors/gem_processor.rb +57 -0
  97. data/lib/brakeman/processors/haml_template_processor.rb +190 -0
  98. data/lib/brakeman/processors/lib/basic_processor.rb +37 -0
  99. data/lib/brakeman/processors/lib/find_all_calls.rb +223 -0
  100. data/lib/brakeman/processors/lib/find_call.rb +183 -0
  101. data/lib/brakeman/processors/lib/find_return_value.rb +134 -0
  102. data/lib/brakeman/processors/lib/processor_helper.rb +75 -0
  103. data/lib/brakeman/processors/lib/rails2_config_processor.rb +145 -0
  104. data/lib/brakeman/processors/lib/rails2_route_processor.rb +313 -0
  105. data/lib/brakeman/processors/lib/rails3_config_processor.rb +132 -0
  106. data/lib/brakeman/processors/lib/rails3_route_processor.rb +308 -0
  107. data/lib/brakeman/processors/lib/render_helper.rb +181 -0
  108. data/lib/brakeman/processors/lib/render_path.rb +107 -0
  109. data/lib/brakeman/processors/lib/route_helper.rb +68 -0
  110. data/lib/brakeman/processors/lib/safe_call_helper.rb +16 -0
  111. data/lib/brakeman/processors/library_processor.rb +119 -0
  112. data/lib/brakeman/processors/model_processor.rb +191 -0
  113. data/lib/brakeman/processors/output_processor.rb +171 -0
  114. data/lib/brakeman/processors/route_processor.rb +17 -0
  115. data/lib/brakeman/processors/slim_template_processor.rb +107 -0
  116. data/lib/brakeman/processors/template_alias_processor.rb +116 -0
  117. data/lib/brakeman/processors/template_processor.rb +74 -0
  118. data/lib/brakeman/report.rb +78 -0
  119. data/lib/brakeman/report/config/remediation.yml +71 -0
  120. data/lib/brakeman/report/ignore/config.rb +135 -0
  121. data/lib/brakeman/report/ignore/interactive.rb +311 -0
  122. data/lib/brakeman/report/renderer.rb +24 -0
  123. data/lib/brakeman/report/report_base.rb +286 -0
  124. data/lib/brakeman/report/report_codeclimate.rb +70 -0
  125. data/lib/brakeman/report/report_csv.rb +55 -0
  126. data/lib/brakeman/report/report_hash.rb +23 -0
  127. data/lib/brakeman/report/report_html.rb +216 -0
  128. data/lib/brakeman/report/report_json.rb +42 -0
  129. data/lib/brakeman/report/report_markdown.rb +156 -0
  130. data/lib/brakeman/report/report_table.rb +107 -0
  131. data/lib/brakeman/report/report_tabs.rb +17 -0
  132. data/lib/brakeman/report/templates/controller_overview.html.erb +22 -0
  133. data/lib/brakeman/report/templates/controller_warnings.html.erb +21 -0
  134. data/lib/brakeman/report/templates/error_overview.html.erb +29 -0
  135. data/lib/brakeman/report/templates/header.html.erb +58 -0
  136. data/lib/brakeman/report/templates/ignored_warnings.html.erb +25 -0
  137. data/lib/brakeman/report/templates/model_warnings.html.erb +21 -0
  138. data/lib/brakeman/report/templates/overview.html.erb +38 -0
  139. data/lib/brakeman/report/templates/security_warnings.html.erb +23 -0
  140. data/lib/brakeman/report/templates/template_overview.html.erb +21 -0
  141. data/lib/brakeman/report/templates/view_warnings.html.erb +34 -0
  142. data/lib/brakeman/report/templates/warning_overview.html.erb +17 -0
  143. data/lib/brakeman/rescanner.rb +483 -0
  144. data/lib/brakeman/scanner.rb +317 -0
  145. data/lib/brakeman/tracker.rb +347 -0
  146. data/lib/brakeman/tracker/collection.rb +93 -0
  147. data/lib/brakeman/tracker/config.rb +101 -0
  148. data/lib/brakeman/tracker/constants.rb +101 -0
  149. data/lib/brakeman/tracker/controller.rb +161 -0
  150. data/lib/brakeman/tracker/library.rb +17 -0
  151. data/lib/brakeman/tracker/model.rb +90 -0
  152. data/lib/brakeman/tracker/template.rb +33 -0
  153. data/lib/brakeman/util.rb +481 -0
  154. data/lib/brakeman/version.rb +3 -0
  155. data/lib/brakeman/warning.rb +255 -0
  156. data/lib/brakeman/warning_codes.rb +111 -0
  157. data/lib/ruby_parser/bm_sexp.rb +610 -0
  158. data/lib/ruby_parser/bm_sexp_processor.rb +116 -0
  159. metadata +362 -0
@@ -0,0 +1,183 @@
1
+ require 'brakeman/processors/lib/basic_processor'
2
+
3
+ #Finds method calls matching the given target(s).
4
+ # #-- This should be deprecated --#
5
+ # #-- Do not use for new code --#
6
+ #
7
+ #Targets/methods can be:
8
+ #
9
+ # - nil: matches anything, including nothing
10
+ # - Empty array: matches nothing
11
+ # - Symbol: matches single target/method exactly
12
+ # - Array of symbols: matches against any of the symbols
13
+ # - Regular expression: matches the expression
14
+ # - Array of regular expressions: matches any of the expressions
15
+ #
16
+ #If a target is also the name of a class, methods called on instances
17
+ #of that class will also be matched, in a very limited way.
18
+ #(Any methods called on Klass.new, basically. More useful when used
19
+ #in conjunction with AliasProcessor.)
20
+ #
21
+ #Examples:
22
+ #
23
+ # #To find any uses of this class:
24
+ # FindCall.new :FindCall, nil
25
+ #
26
+ # #Find system calls without a target
27
+ # FindCall.new [], [:system, :exec, :syscall]
28
+ #
29
+ # #Find all calls to length(), no matter the target
30
+ # FindCall.new nil, :length
31
+ #
32
+ # #Find all calls to sub, sub!, gsub, or gsub!
33
+ # FindCall.new nil, /^g?sub!?$/
34
+ class Brakeman::FindCall < Brakeman::BasicProcessor
35
+
36
+ def initialize targets, methods, tracker, in_depth = false
37
+ super tracker
38
+ @calls = []
39
+ @find_targets = targets
40
+ @find_methods = methods
41
+ @current_class = nil
42
+ @current_method = nil
43
+ @in_depth = in_depth
44
+ end
45
+
46
+ #Returns a list of results.
47
+ #
48
+ #A result looks like:
49
+ #
50
+ # s(:result, :ClassName, :method_name, s(:call, ...))
51
+ #
52
+ #or
53
+ #
54
+ # s(:result, :template_name, s(:call, ...))
55
+ def matches
56
+ @calls
57
+ end
58
+
59
+ #Process the given source. Provide either class and method being searched
60
+ #or the template. These names are used when reporting results.
61
+ #
62
+ #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
67
+ process exp
68
+ end
69
+
70
+ #Process body of method
71
+ def process_defn exp
72
+ process_all exp.body
73
+ end
74
+
75
+ alias :process_defs :process_defn
76
+
77
+ #Process body of block
78
+ def process_rlist exp
79
+ process_all exp
80
+ end
81
+
82
+ #Look for matching calls and add them to results
83
+ def process_call exp
84
+ target = get_target exp.target
85
+ method = exp.method
86
+
87
+ process_call_args exp
88
+
89
+ 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
+
97
+ end
98
+
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
+ exp
110
+ end
111
+
112
+ #Process an assignment like a call
113
+ def process_attrasgn exp
114
+ process_call exp
115
+ end
116
+
117
+ private
118
+
119
+ #Gets the target of a call as a Symbol
120
+ #if possible
121
+ def get_target exp
122
+ if sexp? exp
123
+ case exp.node_type
124
+ when :ivar, :lvar, :const, :lit
125
+ exp.value
126
+ when :true, :false
127
+ exp.node_type
128
+ when :colon2
129
+ class_name exp
130
+ else
131
+ exp
132
+ end
133
+ else
134
+ exp
135
+ end
136
+ end
137
+
138
+ #Checks if the search terms match the given item
139
+ def match search_terms, item
140
+ case search_terms
141
+ when Symbol
142
+ if search_terms == item
143
+ true
144
+ elsif sexp? item
145
+ is_instance_of? item, search_terms
146
+ else
147
+ false
148
+ end
149
+ when Sexp
150
+ search_terms == item
151
+ when Enumerable
152
+ if search_terms.empty?
153
+ 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
+ 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
+ end
182
+ end
183
+ end
@@ -0,0 +1,134 @@
1
+ require 'brakeman/processors/alias_processor'
2
+
3
+ #Attempts to determine the return value of a method.
4
+ #
5
+ #Preferred usage:
6
+ #
7
+ # Brakeman::FindReturnValue.return_value exp
8
+ class Brakeman::FindReturnValue
9
+ include Brakeman::Util
10
+
11
+ #Returns a guess at the return value of a given method or other block of code.
12
+ #
13
+ #If multiple return values are possible, returns all values in an :or Sexp.
14
+ def self.return_value exp, env = nil
15
+ self.new.get_return_value exp, env
16
+ end
17
+
18
+ def initialize
19
+ @uses_ivars = false
20
+ @return_values = []
21
+ end
22
+
23
+ def uses_ivars?
24
+ @uses_ivars
25
+ end
26
+
27
+ #Find return value of Sexp. Takes an optional starting environment.
28
+ def get_return_value exp, env = nil
29
+ process_method exp, env
30
+ value = make_return_value
31
+ value.original_line = exp.line
32
+ value
33
+ end
34
+
35
+ #Process method (or, actually, any Sexp) for return value.
36
+ def process_method exp, env = nil
37
+ exp = Brakeman::AliasProcessor.new.process_safely exp, env
38
+
39
+ find_explicit_return_values exp
40
+
41
+ if node_type? exp, :defn, :defs
42
+ body = exp.body
43
+
44
+ unless body.empty?
45
+ @return_values << last_value(body)
46
+ else
47
+ Brakeman.debug "FindReturnValue: Empty method? #{exp.inspect}"
48
+ end
49
+ elsif exp
50
+ @return_values << last_value(exp)
51
+ else
52
+ Brakeman.debug "FindReturnValue: Given something strange? #{exp.inspect}"
53
+ end
54
+
55
+ exp
56
+ end
57
+
58
+ #Searches expression for return statements.
59
+ def find_explicit_return_values exp
60
+ todo = [exp]
61
+
62
+ until todo.empty?
63
+ current = todo.shift
64
+
65
+ @uses_ivars = true if node_type? current, :ivar
66
+
67
+ if node_type? current, :return
68
+ @return_values << current.value unless current.value.nil?
69
+ elsif sexp? current
70
+ todo = current[1..-1].concat todo
71
+ end
72
+ end
73
+ end
74
+
75
+ #Determines the "last value" of an expression.
76
+ def last_value exp
77
+ case exp.node_type
78
+ when :rlist, :block, :scope, Sexp
79
+ last_value exp.last
80
+ when :if
81
+ then_clause = exp.then_clause
82
+ else_clause = exp.else_clause
83
+
84
+ if then_clause.nil?
85
+ last_value else_clause
86
+ elsif else_clause.nil?
87
+ last_value then_clause
88
+ else
89
+ true_branch = last_value then_clause
90
+ false_branch = last_value else_clause
91
+
92
+ if true_branch and false_branch
93
+ value = make_or(true_branch, false_branch)
94
+ value.original_line = value.rhs.line
95
+ value
96
+ else #Unlikely?
97
+ true_branch or false_branch
98
+ end
99
+ end
100
+ when :lasgn, :iasgn
101
+ exp.rhs
102
+ when :return
103
+ exp.value
104
+ else
105
+ exp.original_line = exp.line unless exp.original_line
106
+ exp
107
+ end
108
+ end
109
+
110
+ def make_or lhs, rhs
111
+ #Better checks in future
112
+ if lhs == rhs
113
+ lhs
114
+ else
115
+ Sexp.new(:or, lhs, rhs)
116
+ end
117
+ end
118
+
119
+ #Turns the array of return values into an :or Sexp
120
+ def make_return_value
121
+ @return_values.compact!
122
+ @return_values.uniq!
123
+
124
+ if @return_values.empty?
125
+ Sexp.new(:nil)
126
+ elsif @return_values.length == 1
127
+ @return_values.first
128
+ else
129
+ @return_values.reduce do |value, sexp|
130
+ make_or value, sexp
131
+ end
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,75 @@
1
+ #Contains a couple shared methods for Processors.
2
+ module Brakeman::ProcessorHelper
3
+ def process_all exp
4
+ exp.each_sexp do |e|
5
+ process e
6
+ end
7
+ exp
8
+ end
9
+
10
+ def process_all! exp
11
+ exp.map! do |e|
12
+ if sexp? e
13
+ process e
14
+ else
15
+ e
16
+ end
17
+ end
18
+
19
+ exp
20
+ end
21
+
22
+ #Process the arguments of a method call. Does not store results.
23
+ #
24
+ #This method is used because Sexp#args and Sexp#arglist create new objects.
25
+ def process_call_args exp
26
+ exp.each_arg do |a|
27
+ process a if sexp? a
28
+ end
29
+
30
+ exp
31
+ end
32
+
33
+ def process_class exp
34
+ current_class = @current_class
35
+ @current_class = class_name exp[1]
36
+ process_all exp.body
37
+ @current_class = current_class
38
+ exp
39
+ end
40
+
41
+ #Sets the current module.
42
+ def process_module exp
43
+ module_name = class_name(exp.class_name).to_s
44
+ prev_module = @current_module
45
+
46
+ if prev_module
47
+ @current_module = "#{prev_module}::#{module_name}"
48
+ else
49
+ @current_module = module_name
50
+ end
51
+
52
+ if block_given?
53
+ yield
54
+ else
55
+ process_all exp.body
56
+ end
57
+
58
+ @current_module = prev_module
59
+
60
+ exp
61
+ end
62
+
63
+ # e.g. private defn
64
+ def process_call_defn? exp
65
+ if call? exp and exp.target.nil? and node_type? exp.first_arg, :defn, :defs and [:private, :public, :protected].include? exp.method
66
+ prev_visibility = @visibility
67
+ @visibility = exp.method
68
+ process exp.first_arg
69
+ @visibility = prev_visibility
70
+ exp
71
+ else
72
+ false
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,145 @@
1
+ require 'brakeman/processors/lib/basic_processor'
2
+
3
+ #Processes configuration. Results are put in tracker.config.
4
+ #
5
+ #Configuration of Rails via Rails::Initializer are stored in tracker.config.rails.
6
+ #For example:
7
+ #
8
+ # Rails::Initializer.run |config|
9
+ # config.action_controller.session_store = :cookie_store
10
+ # end
11
+ #
12
+ #will be stored in
13
+ #
14
+ # tracker.config[:rails][:action_controller][:session_store]
15
+ #
16
+ #Values for tracker.config.rails will still be Sexps.
17
+ class Brakeman::Rails2ConfigProcessor < Brakeman::BasicProcessor
18
+ #Replace block variable in
19
+ #
20
+ # Rails::Initializer.run |config|
21
+ #
22
+ #with this value so we can keep track of it.
23
+ RAILS_CONFIG = Sexp.new(:const, :"!BRAKEMAN_RAILS_CONFIG")
24
+
25
+ def initialize *args
26
+ super
27
+ end
28
+
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)
33
+ process res
34
+ end
35
+
36
+ #Check if config is set to use Erubis
37
+ def process_call exp
38
+ target = exp.target
39
+ target = process target if sexp? target
40
+
41
+ if exp.method == :gem and exp.first_arg.value == "erubis"
42
+ Brakeman.notify "[Notice] Using Erubis for ERB templates"
43
+ @tracker.config.erubis = true
44
+ end
45
+
46
+ exp
47
+ end
48
+
49
+ #Look for configuration settings
50
+ def process_attrasgn exp
51
+ if exp.target == RAILS_CONFIG
52
+ #Get rid of '=' at end
53
+ attribute = exp.method.to_s[0..-2].to_sym
54
+ if exp.args.length > 1
55
+ #Multiple arguments?...not sure if this will ever happen
56
+ @tracker.config.rails[attribute] = exp.args
57
+ else
58
+ @tracker.config.rails[attribute] = exp.first_arg
59
+ end
60
+ elsif include_rails_config? exp
61
+ options = get_rails_config exp
62
+ level = @tracker.config.rails
63
+ options[0..-2].each do |o|
64
+ level[o] ||= {}
65
+ level = level[o]
66
+ end
67
+
68
+ level[options.last] = exp.first_arg
69
+ end
70
+
71
+ exp
72
+ end
73
+
74
+ #Check for Rails version
75
+ def process_cdecl exp
76
+ #Set Rails version required
77
+ if exp.lhs == :RAILS_GEM_VERSION
78
+ @tracker.config.rails_version = exp.rhs.value
79
+ end
80
+
81
+ exp
82
+ end
83
+
84
+ #Check if an expression includes a call to set Rails config
85
+ def include_rails_config? exp
86
+ target = exp.target
87
+ if call? target
88
+ if target.target == RAILS_CONFIG
89
+ true
90
+ else
91
+ include_rails_config? target
92
+ end
93
+ elsif target == RAILS_CONFIG
94
+ true
95
+ else
96
+ false
97
+ end
98
+ end
99
+
100
+ #Returns an array of symbols for each 'level' in the config
101
+ #
102
+ # config.action_controller.session_store = :cookie
103
+ #
104
+ #becomes
105
+ #
106
+ # [:action_controller, :session_store]
107
+ def get_rails_config exp
108
+ if node_type? exp, :attrasgn
109
+ attribute = exp.method.to_s[0..-2].to_sym
110
+ get_rails_config(exp.target) << attribute
111
+ elsif call? exp
112
+ if exp.target == RAILS_CONFIG
113
+ [exp.method]
114
+ else
115
+ get_rails_config(exp.target) << exp.method
116
+ end
117
+ else
118
+ raise "WHAT"
119
+ end
120
+ end
121
+ end
122
+
123
+ #This is necessary to replace block variable so we can track config settings
124
+ class Brakeman::ConfigAliasProcessor < Brakeman::AliasProcessor
125
+
126
+ RAILS_INIT = Sexp.new(:colon2, Sexp.new(:const, :Rails), :Initializer)
127
+
128
+ #Look for a call to
129
+ #
130
+ # Rails::Initializer.run do |config|
131
+ # ...
132
+ # end
133
+ #
134
+ #and replace config with RAILS_CONFIG
135
+ def process_iter exp
136
+ target = exp.block_call.target
137
+ method = exp.block_call.method
138
+
139
+ if sexp? target and target == RAILS_INIT and method == :run
140
+ env[Sexp.new(:lvar, exp.block_args.value)] = Brakeman::Rails2ConfigProcessor::RAILS_CONFIG
141
+ end
142
+
143
+ process_default exp
144
+ end
145
+ end