railroader 4.3.4

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 (165) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES.md +1091 -0
  3. data/FEATURES +16 -0
  4. data/README.md +174 -0
  5. data/bin/railroader +8 -0
  6. data/lib/railroader/app_tree.rb +191 -0
  7. data/lib/railroader/call_index.rb +219 -0
  8. data/lib/railroader/checks/base_check.rb +505 -0
  9. data/lib/railroader/checks/check_basic_auth.rb +88 -0
  10. data/lib/railroader/checks/check_basic_auth_timing_attack.rb +33 -0
  11. data/lib/railroader/checks/check_content_tag.rb +200 -0
  12. data/lib/railroader/checks/check_create_with.rb +74 -0
  13. data/lib/railroader/checks/check_cross_site_scripting.rb +381 -0
  14. data/lib/railroader/checks/check_default_routes.rb +86 -0
  15. data/lib/railroader/checks/check_deserialize.rb +56 -0
  16. data/lib/railroader/checks/check_detailed_exceptions.rb +55 -0
  17. data/lib/railroader/checks/check_digest_dos.rb +38 -0
  18. data/lib/railroader/checks/check_divide_by_zero.rb +42 -0
  19. data/lib/railroader/checks/check_dynamic_finders.rb +48 -0
  20. data/lib/railroader/checks/check_escape_function.rb +21 -0
  21. data/lib/railroader/checks/check_evaluation.rb +35 -0
  22. data/lib/railroader/checks/check_execute.rb +189 -0
  23. data/lib/railroader/checks/check_file_access.rb +71 -0
  24. data/lib/railroader/checks/check_file_disclosure.rb +35 -0
  25. data/lib/railroader/checks/check_filter_skipping.rb +31 -0
  26. data/lib/railroader/checks/check_forgery_setting.rb +81 -0
  27. data/lib/railroader/checks/check_header_dos.rb +31 -0
  28. data/lib/railroader/checks/check_i18n_xss.rb +48 -0
  29. data/lib/railroader/checks/check_jruby_xml.rb +36 -0
  30. data/lib/railroader/checks/check_json_encoding.rb +47 -0
  31. data/lib/railroader/checks/check_json_parsing.rb +107 -0
  32. data/lib/railroader/checks/check_link_to.rb +132 -0
  33. data/lib/railroader/checks/check_link_to_href.rb +146 -0
  34. data/lib/railroader/checks/check_mail_to.rb +49 -0
  35. data/lib/railroader/checks/check_mass_assignment.rb +196 -0
  36. data/lib/railroader/checks/check_mime_type_dos.rb +39 -0
  37. data/lib/railroader/checks/check_model_attr_accessible.rb +55 -0
  38. data/lib/railroader/checks/check_model_attributes.rb +119 -0
  39. data/lib/railroader/checks/check_model_serialize.rb +67 -0
  40. data/lib/railroader/checks/check_nested_attributes.rb +38 -0
  41. data/lib/railroader/checks/check_nested_attributes_bypass.rb +58 -0
  42. data/lib/railroader/checks/check_number_to_currency.rb +74 -0
  43. data/lib/railroader/checks/check_permit_attributes.rb +43 -0
  44. data/lib/railroader/checks/check_quote_table_name.rb +40 -0
  45. data/lib/railroader/checks/check_redirect.rb +256 -0
  46. data/lib/railroader/checks/check_regex_dos.rb +68 -0
  47. data/lib/railroader/checks/check_render.rb +97 -0
  48. data/lib/railroader/checks/check_render_dos.rb +37 -0
  49. data/lib/railroader/checks/check_render_inline.rb +53 -0
  50. data/lib/railroader/checks/check_response_splitting.rb +21 -0
  51. data/lib/railroader/checks/check_route_dos.rb +42 -0
  52. data/lib/railroader/checks/check_safe_buffer_manipulation.rb +31 -0
  53. data/lib/railroader/checks/check_sanitize_methods.rb +112 -0
  54. data/lib/railroader/checks/check_secrets.rb +40 -0
  55. data/lib/railroader/checks/check_select_tag.rb +59 -0
  56. data/lib/railroader/checks/check_select_vulnerability.rb +60 -0
  57. data/lib/railroader/checks/check_send.rb +47 -0
  58. data/lib/railroader/checks/check_send_file.rb +19 -0
  59. data/lib/railroader/checks/check_session_manipulation.rb +35 -0
  60. data/lib/railroader/checks/check_session_settings.rb +176 -0
  61. data/lib/railroader/checks/check_simple_format.rb +58 -0
  62. data/lib/railroader/checks/check_single_quotes.rb +101 -0
  63. data/lib/railroader/checks/check_skip_before_filter.rb +60 -0
  64. data/lib/railroader/checks/check_sql.rb +700 -0
  65. data/lib/railroader/checks/check_sql_cves.rb +106 -0
  66. data/lib/railroader/checks/check_ssl_verify.rb +48 -0
  67. data/lib/railroader/checks/check_strip_tags.rb +89 -0
  68. data/lib/railroader/checks/check_symbol_dos.rb +71 -0
  69. data/lib/railroader/checks/check_symbol_dos_cve.rb +30 -0
  70. data/lib/railroader/checks/check_translate_bug.rb +45 -0
  71. data/lib/railroader/checks/check_unsafe_reflection.rb +50 -0
  72. data/lib/railroader/checks/check_unscoped_find.rb +57 -0
  73. data/lib/railroader/checks/check_validation_regex.rb +116 -0
  74. data/lib/railroader/checks/check_weak_hash.rb +148 -0
  75. data/lib/railroader/checks/check_without_protection.rb +80 -0
  76. data/lib/railroader/checks/check_xml_dos.rb +45 -0
  77. data/lib/railroader/checks/check_yaml_parsing.rb +121 -0
  78. data/lib/railroader/checks.rb +209 -0
  79. data/lib/railroader/codeclimate/engine_configuration.rb +97 -0
  80. data/lib/railroader/commandline.rb +179 -0
  81. data/lib/railroader/differ.rb +66 -0
  82. data/lib/railroader/file_parser.rb +54 -0
  83. data/lib/railroader/format/style.css +133 -0
  84. data/lib/railroader/options.rb +339 -0
  85. data/lib/railroader/parsers/rails2_erubis.rb +6 -0
  86. data/lib/railroader/parsers/rails2_xss_plugin_erubis.rb +48 -0
  87. data/lib/railroader/parsers/rails3_erubis.rb +81 -0
  88. data/lib/railroader/parsers/template_parser.rb +108 -0
  89. data/lib/railroader/processor.rb +102 -0
  90. data/lib/railroader/processors/alias_processor.rb +1229 -0
  91. data/lib/railroader/processors/base_processor.rb +295 -0
  92. data/lib/railroader/processors/config_processor.rb +14 -0
  93. data/lib/railroader/processors/controller_alias_processor.rb +278 -0
  94. data/lib/railroader/processors/controller_processor.rb +249 -0
  95. data/lib/railroader/processors/erb_template_processor.rb +77 -0
  96. data/lib/railroader/processors/erubis_template_processor.rb +92 -0
  97. data/lib/railroader/processors/gem_processor.rb +64 -0
  98. data/lib/railroader/processors/haml_template_processor.rb +191 -0
  99. data/lib/railroader/processors/lib/basic_processor.rb +37 -0
  100. data/lib/railroader/processors/lib/call_conversion_helper.rb +90 -0
  101. data/lib/railroader/processors/lib/find_all_calls.rb +224 -0
  102. data/lib/railroader/processors/lib/find_call.rb +183 -0
  103. data/lib/railroader/processors/lib/find_return_value.rb +166 -0
  104. data/lib/railroader/processors/lib/module_helper.rb +111 -0
  105. data/lib/railroader/processors/lib/processor_helper.rb +88 -0
  106. data/lib/railroader/processors/lib/rails2_config_processor.rb +145 -0
  107. data/lib/railroader/processors/lib/rails2_route_processor.rb +313 -0
  108. data/lib/railroader/processors/lib/rails3_config_processor.rb +132 -0
  109. data/lib/railroader/processors/lib/rails3_route_processor.rb +308 -0
  110. data/lib/railroader/processors/lib/render_helper.rb +181 -0
  111. data/lib/railroader/processors/lib/render_path.rb +107 -0
  112. data/lib/railroader/processors/lib/route_helper.rb +68 -0
  113. data/lib/railroader/processors/lib/safe_call_helper.rb +16 -0
  114. data/lib/railroader/processors/library_processor.rb +74 -0
  115. data/lib/railroader/processors/model_processor.rb +91 -0
  116. data/lib/railroader/processors/output_processor.rb +144 -0
  117. data/lib/railroader/processors/route_processor.rb +17 -0
  118. data/lib/railroader/processors/slim_template_processor.rb +111 -0
  119. data/lib/railroader/processors/template_alias_processor.rb +118 -0
  120. data/lib/railroader/processors/template_processor.rb +85 -0
  121. data/lib/railroader/report/config/remediation.yml +71 -0
  122. data/lib/railroader/report/ignore/config.rb +153 -0
  123. data/lib/railroader/report/ignore/interactive.rb +362 -0
  124. data/lib/railroader/report/pager.rb +112 -0
  125. data/lib/railroader/report/renderer.rb +24 -0
  126. data/lib/railroader/report/report_base.rb +292 -0
  127. data/lib/railroader/report/report_codeclimate.rb +79 -0
  128. data/lib/railroader/report/report_csv.rb +55 -0
  129. data/lib/railroader/report/report_hash.rb +23 -0
  130. data/lib/railroader/report/report_html.rb +216 -0
  131. data/lib/railroader/report/report_json.rb +45 -0
  132. data/lib/railroader/report/report_markdown.rb +107 -0
  133. data/lib/railroader/report/report_table.rb +117 -0
  134. data/lib/railroader/report/report_tabs.rb +17 -0
  135. data/lib/railroader/report/report_text.rb +198 -0
  136. data/lib/railroader/report/templates/controller_overview.html.erb +22 -0
  137. data/lib/railroader/report/templates/controller_warnings.html.erb +21 -0
  138. data/lib/railroader/report/templates/error_overview.html.erb +29 -0
  139. data/lib/railroader/report/templates/header.html.erb +58 -0
  140. data/lib/railroader/report/templates/ignored_warnings.html.erb +25 -0
  141. data/lib/railroader/report/templates/model_warnings.html.erb +21 -0
  142. data/lib/railroader/report/templates/overview.html.erb +38 -0
  143. data/lib/railroader/report/templates/security_warnings.html.erb +23 -0
  144. data/lib/railroader/report/templates/template_overview.html.erb +21 -0
  145. data/lib/railroader/report/templates/view_warnings.html.erb +34 -0
  146. data/lib/railroader/report/templates/warning_overview.html.erb +17 -0
  147. data/lib/railroader/report.rb +88 -0
  148. data/lib/railroader/rescanner.rb +483 -0
  149. data/lib/railroader/scanner.rb +321 -0
  150. data/lib/railroader/tracker/collection.rb +93 -0
  151. data/lib/railroader/tracker/config.rb +154 -0
  152. data/lib/railroader/tracker/constants.rb +171 -0
  153. data/lib/railroader/tracker/controller.rb +161 -0
  154. data/lib/railroader/tracker/library.rb +17 -0
  155. data/lib/railroader/tracker/model.rb +90 -0
  156. data/lib/railroader/tracker/template.rb +33 -0
  157. data/lib/railroader/tracker.rb +362 -0
  158. data/lib/railroader/util.rb +503 -0
  159. data/lib/railroader/version.rb +3 -0
  160. data/lib/railroader/warning.rb +294 -0
  161. data/lib/railroader/warning_codes.rb +117 -0
  162. data/lib/railroader.rb +544 -0
  163. data/lib/ruby_parser/bm_sexp.rb +626 -0
  164. data/lib/ruby_parser/bm_sexp_processor.rb +116 -0
  165. metadata +386 -0
@@ -0,0 +1,362 @@
1
+ require 'set'
2
+ require 'railroader/call_index'
3
+ require 'railroader/checks'
4
+ require 'railroader/report'
5
+ require 'railroader/processors/lib/find_call'
6
+ require 'railroader/processors/lib/find_all_calls'
7
+ require 'railroader/tracker/config'
8
+ require 'railroader/tracker/constants'
9
+
10
+ #The Tracker keeps track of all the processed information.
11
+ class Railroader::Tracker
12
+ attr_accessor :controllers, :constants, :templates, :models, :errors,
13
+ :checks, :initializers, :config, :routes, :processor, :libs,
14
+ :template_cache, :options, :filter_cache, :start_time, :end_time,
15
+ :duration, :ignored_filter
16
+
17
+ #Place holder when there should be a model, but it is not
18
+ #clear what model it will be.
19
+ UNKNOWN_MODEL = :RailroaderUnresolvedModel
20
+
21
+ #Creates a new Tracker.
22
+ #
23
+ #The Processor argument is only used by other Processors
24
+ #that might need to access it.
25
+ def initialize(app_tree, processor = nil, options = {})
26
+ @app_tree = app_tree
27
+ @processor = processor
28
+ @options = options
29
+
30
+ @config = Railroader::Config.new(self)
31
+ @templates = {}
32
+ @controllers = {}
33
+ #Initialize models with the unknown model so
34
+ #we can match models later without knowing precisely what
35
+ #class they are.
36
+ @models = {}
37
+ @models[UNKNOWN_MODEL] = Railroader::Model.new(UNKNOWN_MODEL, nil, nil, nil, self)
38
+ @routes = {}
39
+ @initializers = {}
40
+ @errors = []
41
+ @libs = {}
42
+ @constants = Railroader::Constants.new
43
+ @checks = nil
44
+ @processed = nil
45
+ @template_cache = Set.new
46
+ @filter_cache = {}
47
+ @call_index = nil
48
+ @start_time = Time.now
49
+ @end_time = nil
50
+ @duration = nil
51
+ end
52
+
53
+ #Add an error to the list. If no backtrace is given,
54
+ #the one from the exception will be used.
55
+ def error exception, backtrace = nil
56
+ backtrace ||= exception.backtrace
57
+ unless backtrace.is_a? Array
58
+ backtrace = [ backtrace ]
59
+ end
60
+
61
+ Railroader.debug exception
62
+ Railroader.debug backtrace
63
+
64
+ @errors << { :error => exception.to_s.gsub("\n", " "), :backtrace => backtrace }
65
+ end
66
+
67
+ #Run a set of checks on the current information. Results will be stored
68
+ #in Tracker#checks.
69
+ def run_checks
70
+ @checks = Railroader::Checks.run_checks(@app_tree, self)
71
+
72
+ @end_time = Time.now
73
+ @duration = @end_time - @start_time
74
+ @checks
75
+ end
76
+
77
+ def app_path
78
+ @app_path ||= File.expand_path @options[:app_path]
79
+ end
80
+
81
+ #Iterate over all methods in controllers and models.
82
+ def each_method
83
+ classes = [self.controllers, self.models]
84
+
85
+ if @options[:index_libs]
86
+ classes << self.libs
87
+ end
88
+
89
+ classes.each do |set|
90
+ set.each do |set_name, collection|
91
+ collection.each_method do |method_name, definition|
92
+ src = definition[:src]
93
+ yield src, set_name, method_name, definition[:file]
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+ #Iterates over each template, yielding the name and the template.
100
+ #Prioritizes templates which have been rendered.
101
+ def each_template
102
+ if @processed.nil?
103
+ @processed, @rest = templates.keys.sort_by{|template| template.to_s}.partition { |k| k.to_s.include? "." }
104
+ end
105
+
106
+ @processed.each do |k|
107
+ yield k, templates[k]
108
+ end
109
+
110
+ @rest.each do |k|
111
+ yield k, templates[k]
112
+ end
113
+ end
114
+
115
+
116
+ def each_class
117
+ classes = [self.controllers, self.models]
118
+
119
+ if @options[:index_libs]
120
+ classes << self.libs
121
+ end
122
+
123
+ classes.each do |set|
124
+ set.each do |set_name, collection|
125
+ collection.src.each do |file, src|
126
+ yield src, set_name, file
127
+ end
128
+ end
129
+ end
130
+ end
131
+
132
+ #Find a method call.
133
+ #
134
+ #Options:
135
+ # * :target => target name(s)
136
+ # * :method => method name(s)
137
+ # * :chained => search in method chains
138
+ #
139
+ #If :target => false or :target => nil, searches for methods without a target.
140
+ #Targets and methods can be specified as a symbol, an array of symbols,
141
+ #or a regular expression.
142
+ #
143
+ #If :chained => true, matches target at head of method chain and method at end.
144
+ #
145
+ #For example:
146
+ #
147
+ # find_call :target => User, :method => :all, :chained => true
148
+ #
149
+ #could match
150
+ #
151
+ # User.human.active.all(...)
152
+ #
153
+ def find_call options
154
+ index_call_sites unless @call_index
155
+ @call_index.find_calls options
156
+ end
157
+
158
+ #Searches the initializers for a method call
159
+ def check_initializers target, method
160
+ finder = Railroader::FindCall.new target, method, self
161
+
162
+ initializers.sort.each do |name, initializer|
163
+ finder.process_source initializer
164
+ end
165
+
166
+ finder.matches
167
+ end
168
+
169
+ #Returns a Report with this Tracker's information
170
+ def report
171
+ Railroader::Report.new(@app_tree, self)
172
+ end
173
+
174
+ def warnings
175
+ self.checks.all_warnings
176
+ end
177
+
178
+ def filtered_warnings
179
+ if self.ignored_filter
180
+ self.warnings.reject do |w|
181
+ self.ignored_filter.ignored? w
182
+ end
183
+ else
184
+ self.warnings
185
+ end
186
+ end
187
+
188
+ def unused_fingerprints
189
+ return [] unless self.ignored_filter
190
+ self.ignored_filter.obsolete_fingerprints
191
+ end
192
+
193
+ def add_constant name, value, context = nil
194
+ @constants.add name, value, context unless @options[:disable_constant_tracking]
195
+ end
196
+
197
+ def constant_lookup name
198
+ @constants.get_literal name unless @options[:disable_constant_tracking]
199
+ end
200
+
201
+ def find_class name
202
+ [@controllers, @models, @libs].each do |collection|
203
+ if c = collection[name]
204
+ return c
205
+ end
206
+ end
207
+
208
+ nil
209
+ end
210
+
211
+ def index_call_sites
212
+ finder = Railroader::FindAllCalls.new self
213
+
214
+ self.each_method do |definition, set_name, method_name, file|
215
+ finder.process_source definition, :class => set_name, :method => method_name, :file => file
216
+ end
217
+
218
+ self.each_class do |definition, set_name, file|
219
+ finder.process_source definition, :class => set_name, :file => file
220
+ end
221
+
222
+ self.each_template do |_name, template|
223
+ finder.process_source template.src, :template => template, :file => template.file
224
+ end
225
+
226
+ @call_index = Railroader::CallIndex.new finder.calls
227
+ end
228
+
229
+ #Reindex call sites
230
+ #
231
+ #Takes a set of symbols which can include :templates, :models,
232
+ #or :controllers
233
+ #
234
+ #This will limit reindexing to the given sets
235
+ def reindex_call_sites locations
236
+ #If reindexing templates, models, and controllers, just redo
237
+ #everything
238
+ if locations.length == 3
239
+ return index_call_sites
240
+ end
241
+
242
+ if locations.include? :templates
243
+ @call_index.remove_template_indexes
244
+ end
245
+
246
+ classes_to_reindex = Set.new
247
+ method_sets = []
248
+
249
+ if locations.include? :models
250
+ classes_to_reindex.merge self.models.keys
251
+ method_sets << self.models
252
+ end
253
+
254
+ if locations.include? :controllers
255
+ classes_to_reindex.merge self.controllers.keys
256
+ method_sets << self.controllers
257
+ end
258
+
259
+ @call_index.remove_indexes_by_class classes_to_reindex
260
+
261
+ finder = Railroader::FindAllCalls.new self
262
+
263
+ method_sets.each do |set|
264
+ set.each do |set_name, info|
265
+ info.each_method do |method_name, definition|
266
+ src = definition[:src]
267
+ finder.process_source src, :class => set_name, :method => method_name, :file => definition[:file]
268
+ end
269
+ end
270
+ end
271
+
272
+ if locations.include? :templates
273
+ self.each_template do |_name, template|
274
+ finder.process_source template.src, :template => template, :file => template.file
275
+ end
276
+ end
277
+
278
+ @call_index.index_calls finder.calls
279
+ end
280
+
281
+ #Clear information related to templates.
282
+ #If :only_rendered => true, will delete templates rendered from
283
+ #controllers (but not those rendered from other templates)
284
+ def reset_templates options = { :only_rendered => false }
285
+ if options[:only_rendered]
286
+ @templates.delete_if do |_name, template|
287
+ template.rendered_from_controller?
288
+ end
289
+ else
290
+ @templates = {}
291
+ end
292
+ @processed = nil
293
+ @rest = nil
294
+ @template_cache.clear
295
+ end
296
+
297
+ #Clear information related to template
298
+ def reset_template name
299
+ name = name.to_sym
300
+ @templates.delete name
301
+ @processed = nil
302
+ @rest = nil
303
+ @template_cache.clear
304
+ end
305
+
306
+ #Clear information related to model
307
+ def reset_model path
308
+ model_name = nil
309
+
310
+ @models.each do |name, model|
311
+ if model.files.include?(path)
312
+ model_name = name
313
+ break
314
+ end
315
+ end
316
+
317
+ @models.delete model_name
318
+ end
319
+
320
+ #Clear information related to model
321
+ def reset_lib path
322
+ lib_name = nil
323
+
324
+ @libs.each do |name, lib|
325
+ if lib.files.include?(path)
326
+ lib_name = name
327
+ break
328
+ end
329
+ end
330
+
331
+ @libs.delete lib_name
332
+ end
333
+
334
+ def reset_controller path
335
+ controller_name = nil
336
+
337
+ #Remove from controller
338
+ @controllers.each do |name, controller|
339
+ if controller.files.include?(path)
340
+ controller_name = name
341
+
342
+ #Remove templates rendered from this controller
343
+ @templates.each do |template_name, template|
344
+ if template.render_path and template.render_path.include_controller? name
345
+ reset_template template_name
346
+ @call_index.remove_template_indexes template_name
347
+ end
348
+ end
349
+
350
+ #Remove calls indexed from this controller
351
+ @call_index.remove_indexes_by_class [name]
352
+ break
353
+ end
354
+ end
355
+ @controllers.delete controller_name
356
+ end
357
+
358
+ #Clear information about routes
359
+ def reset_routes
360
+ @routes = {}
361
+ end
362
+ end