class Brakeman::Rescanner
Class for rescanning changed files after an initial scan
Constants
- KNOWN_TEMPLATE_EXTENSIONS
- SCAN_ORDER
Public Class Methods
new(options, processor, changed_files)
click to toggle source
Create new Rescanner
to scan changed files
Calls superclass method
Brakeman::Scanner::new
# File lib/brakeman/rescanner.rb, line 13 def initialize options, processor, changed_files super(options, processor) @paths = changed_files.map {|f| tracker.app_tree.file_path(f) } @old_results = tracker.filtered_warnings #Old warnings from previous scan @changes = nil #True if files had to be rescanned @reindex = Set.new end
Public Instance Methods
file_type(path)
click to toggle source
Guess at what kind of file the path contains
# File lib/brakeman/rescanner.rb, line 319 def file_type path case path when /\/app\/controllers/ :controller when /\/app\/views/ :template when /\/app\/models/ :model when /\/lib/ :lib when /\/config\/initializers/ :initializer when /config\/routes\.rb/ :routes when /\/config\/.+\.(rb|yml)/ :config when /\.ruby-version/ :config when /Gemfile|gems\./ :gemfile else :unknown end end
parse_ruby_files(list)
click to toggle source
# File lib/brakeman/rescanner.rb, line 394 def parse_ruby_files list paths = list.select(&:exists?) file_parser = Brakeman::FileParser.new(tracker.app_tree, tracker.options[:parser_timeout], tracker.options[:parallel_checks]) file_parser.parse_files paths tracker.add_errors(file_parser.errors) file_parser.file_list end
recheck()
click to toggle source
Runs checks. Will rescan files if they have not already been scanned
# File lib/brakeman/rescanner.rb, line 24 def recheck rescan if @changes.nil? tracker.run_checks if @changes Brakeman::RescanReport.new @old_results, tracker end
remove_deleted_file(path)
click to toggle source
Check controllers, templates, models and libs for data from file and delete it.
# File lib/brakeman/rescanner.rb, line 296 def remove_deleted_file path deleted = false [:controllers, :models, :libs].each do |collection| tracker.send(collection).delete_if do |_name, data| if data.files.include?(path) deleted = true true end end end tracker.templates.delete_if do |_name, data| if data.file == path deleted = true true end end deleted end
rescan()
click to toggle source
Rescans changed files
# File lib/brakeman/rescanner.rb, line 33 def rescan tracker.template_cache.clear paths_by_type = {} SCAN_ORDER.each do |type| paths_by_type[type] = [] end @paths.each do |path| type = file_type(path) paths_by_type[type] << path unless type == :unknown end @changes = false SCAN_ORDER.each do |type| paths_by_type[type].each do |path| Brakeman.debug "Rescanning #{path} as #{type}" if rescan_file path, type @changes = true end end end if @changes and not @reindex.empty? tracker.reindex_call_sites @reindex end self end
rescan_controller(path)
click to toggle source
# File lib/brakeman/rescanner.rb, line 102 def rescan_controller path controller = tracker.reset_controller path paths = controller.nil? ? [path] : controller.files parse_ruby_files(paths).each do |astfile| process_controller astfile end #Process data flow and template rendering #from the controller tracker.controllers.each do |name, controller| if controller.files.include?(path) tracker.templates.each do |template_name, template| next unless template.render_path if template.render_path.include_controller? name tracker.reset_template template_name end end controller.src.each do |file, src| @processor.process_controller_alias controller.name, src, nil, file end end end @reindex << :templates << :controllers end
rescan_deleted_file(path, type)
click to toggle source
Handle rescanning when a file is deleted
# File lib/brakeman/rescanner.rb, line 240 def rescan_deleted_file path, type case type when :controller rescan_controller path when :template rescan_deleted_template path when :model rescan_model path when :lib rescan_deleted_lib path when :initializer rescan_deleted_initializer path else if remove_deleted_file path return true else Brakeman.notify "Ignoring deleted file: #{path}" end end true end
rescan_deleted_initializer(path)
click to toggle source
# File lib/brakeman/rescanner.rb, line 290 def rescan_deleted_initializer path tracker.initializers.delete Pathname.new(path).basename.to_s end
rescan_deleted_lib(path)
click to toggle source
# File lib/brakeman/rescanner.rb, line 277 def rescan_deleted_lib path deleted_lib = nil tracker.libs.delete_if do |_name, lib| if lib.files.include?(path) deleted_lib = lib true end end rescan_mixin deleted_lib if deleted_lib end
rescan_deleted_template(path)
click to toggle source
# File lib/brakeman/rescanner.rb, line 263 def rescan_deleted_template path return unless path.relative.match KNOWN_TEMPLATE_EXTENSIONS template_name = template_path_to_name(path) #Remove template tracker.reset_template template_name #Remove any rendered versions, or partials rendered from it tracker.templates.delete_if do |_name, template| template.file == path or template.name.to_sym == template_name.to_sym end end
rescan_file(path, type = nil)
click to toggle source
Rescans a single file
# File lib/brakeman/rescanner.rb, line 67 def rescan_file path, type = nil type ||= file_type path unless path.exists? return rescan_deleted_file path, type end case type when :controller rescan_controller path when :template rescan_template path when :model rescan_model path when :lib rescan_lib path when :config process_config when :initializer rescan_initializer path when :routes rescan_routes when :gemfile if tracker.config.has_gem? :rails_xss and tracker.config.escape_html? tracker.config.escape_html = false end process_gems else return false #Nothing to do, file hopefully does not need to be rescanned end true end
rescan_initializer(path)
click to toggle source
# File lib/brakeman/rescanner.rb, line 229 def rescan_initializer path tracker.reset_initializer path parse_ruby_files([path]).each do |astfile| process_initializer astfile end @reindex << :initializers end
rescan_lib(path)
click to toggle source
# File lib/brakeman/rescanner.rb, line 199 def rescan_lib path lib = tracker.reset_lib path paths = lib.nil? ? [path] : lib.files parse_ruby_files(paths).each do |astfile| process_lib astfile end lib = nil tracker.libs.each do |_name, library| if library.files.include?(path) lib = library break end end rescan_mixin lib if lib end
rescan_mixin(lib)
click to toggle source
# File lib/brakeman/rescanner.rb, line 344 def rescan_mixin lib method_names = [] lib.each_method do |name, _meth| method_names << name end to_rescan = [] #Rescan controllers that mixed in library tracker.controllers.each do |_name, controller| if controller.includes.include? lib.name controller.files.each do |path| unless @paths.include? path to_rescan << path end end end end to_rescan.each do |controller| tracker.reset_controller controller rescan_file controller end to_rescan = [] #Check if a method from this mixin was used to render a template. #This is not precise, because a different controller might have the #same method... tracker.templates.each do |name, template| next unless template.render_path if template.render_path.include_any_method? method_names name.to_s.match(/^([^.]+)/) original = tracker.templates[$1.to_sym] if original to_rescan << [name, original.file] end end end to_rescan.each do |template| tracker.reset_template template[0] rescan_file template[1] end end
rescan_model(path)
click to toggle source
# File lib/brakeman/rescanner.rb, line 181 def rescan_model path num_models = tracker.models.length model = tracker.reset_model path paths = model.nil? ? [path] : model.files parse_ruby_files(paths).each do |astfile| process_model astfile.path, astfile.ast end #Only need to rescan other things if a model is added or removed if num_models != tracker.models.length process_template_data_flows process_controller_data_flows @reindex << :templates << :controllers end @reindex << :models end
rescan_routes()
click to toggle source
# File lib/brakeman/rescanner.rb, line 218 def rescan_routes # Routes affect which controller methods are treated as actions # which affects which templates are rendered, so routes, controllers, # and templates rendered from controllers must be rescanned tracker.reset_routes tracker.reset_templates :only_rendered => true process_routes process_controller_data_flows @reindex << :controllers << :templates end
rescan_template(path)
click to toggle source
# File lib/brakeman/rescanner.rb, line 129 def rescan_template path return unless path.relative.match KNOWN_TEMPLATE_EXTENSIONS and path.exists? template_name = template_path_to_name(path) tracker.reset_template template_name fp = Brakeman::FileParser.new(tracker.app_tree, tracker.options[:parser_timeout]) template_parser = Brakeman::TemplateParser.new(tracker, fp) template_parser.parse_template path, path.read tracker.add_errors(fp.errors) process_template fp.file_list.first @processor.process_template_alias tracker.templates[template_name] rescan = Set.new #Search for processed template and process it. #Search for rendered versions of template and re-render (if necessary) tracker.templates.each do |_name, template| if template.file == path or template.file.nil? next unless template.render_path and template.name.to_sym == template_name.to_sym template.render_path.each do |from| case from[:type] when :template rescan << [:template, from[:name]] when :controller rescan << [:controller, from[:class], from[:method]] end end end end rescan.each do |r| if r[0] == :controller controller = tracker.controllers[r[1]] controller.src.each do |file, src| unless @paths.include? file @processor.process_controller_alias controller.name, src, r[2], file end end elsif r[0] == :template template = tracker.templates[r[1]] rescan_template template.file end end @reindex << :templates end