brakeman 1.5.3 → 1.6.0.pre1
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 +20 -6
- data/lib/brakeman.rb +21 -1
- data/lib/brakeman/checks.rb +2 -7
- data/lib/brakeman/checks/base_check.rb +31 -26
- data/lib/brakeman/checks/check_basic_auth.rb +1 -7
- data/lib/brakeman/checks/check_cross_site_scripting.rb +38 -33
- data/lib/brakeman/checks/check_evaluation.rb +2 -1
- data/lib/brakeman/checks/check_execute.rb +5 -1
- data/lib/brakeman/checks/check_file_access.rb +6 -4
- data/lib/brakeman/checks/check_link_to.rb +8 -5
- data/lib/brakeman/checks/check_link_to_href.rb +6 -5
- data/lib/brakeman/checks/check_mail_to.rb +2 -4
- data/lib/brakeman/checks/check_mass_assignment.rb +12 -6
- data/lib/brakeman/checks/check_redirect.rb +17 -14
- data/lib/brakeman/checks/check_render.rb +4 -4
- data/lib/brakeman/checks/check_send.rb +4 -2
- data/lib/brakeman/checks/check_session_settings.rb +16 -21
- data/lib/brakeman/checks/check_skip_before_filter.rb +2 -4
- data/lib/brakeman/checks/check_sql.rb +8 -7
- data/lib/brakeman/checks/check_validation_regex.rb +2 -4
- data/lib/brakeman/checks/check_without_protection.rb +8 -9
- data/lib/brakeman/differ.rb +61 -0
- data/lib/brakeman/format/style.css +4 -0
- data/lib/brakeman/options.rb +8 -0
- data/lib/brakeman/processors/alias_processor.rb +5 -7
- data/lib/brakeman/processors/controller_alias_processor.rb +10 -3
- data/lib/brakeman/processors/erb_template_processor.rb +2 -0
- data/lib/brakeman/processors/erubis_template_processor.rb +2 -0
- data/lib/brakeman/processors/gem_processor.rb +8 -0
- data/lib/brakeman/processors/haml_template_processor.rb +2 -0
- data/lib/brakeman/processors/lib/rails2_route_processor.rb +2 -6
- data/lib/brakeman/processors/lib/rails3_route_processor.rb +2 -4
- data/lib/brakeman/processors/lib/render_helper.rb +3 -1
- data/lib/brakeman/processors/library_processor.rb +4 -6
- data/lib/brakeman/processors/template_alias_processor.rb +1 -1
- data/lib/brakeman/report.rb +257 -198
- data/lib/brakeman/rescanner.rb +112 -10
- data/lib/brakeman/scanner.rb +3 -4
- data/lib/brakeman/templates/controller_overview.html.erb +18 -0
- data/lib/brakeman/templates/controller_warnings.html.erb +17 -0
- data/lib/brakeman/templates/error_overview.html.erb +14 -0
- data/lib/brakeman/templates/header.html.erb +38 -0
- data/lib/brakeman/templates/model_warnings.html.erb +17 -0
- data/lib/brakeman/templates/overview.html.erb +28 -0
- data/lib/brakeman/templates/security_warnings.html.erb +28 -0
- data/lib/brakeman/templates/template_overview.html.erb +17 -0
- data/lib/brakeman/templates/view_warnings.html.erb +17 -0
- data/lib/brakeman/templates/warning_overview.html.erb +13 -0
- data/lib/brakeman/tracker.rb +1 -1
- data/lib/brakeman/util.rb +24 -4
- data/lib/brakeman/version.rb +1 -1
- data/lib/brakeman/warning.rb +11 -3
- data/lib/ruby_parser/bm_sexp.rb +5 -11
- metadata +84 -23
    
        data/lib/brakeman/rescanner.rb
    CHANGED
    
    | @@ -1,4 +1,6 @@ | |
| 1 1 | 
             
            require 'brakeman/scanner'
         | 
| 2 | 
            +
            require 'terminal-table'
         | 
| 3 | 
            +
            require 'brakeman/util'
         | 
| 2 4 |  | 
| 3 5 | 
             
            #Class for rescanning changed files after an initial scan
         | 
| 4 6 | 
             
            class Brakeman::Rescanner < Brakeman::Scanner
         | 
| @@ -64,6 +66,10 @@ class Brakeman::Rescanner < Brakeman::Scanner | |
| 64 66 | 
             
              def rescan_file path, type = nil
         | 
| 65 67 | 
             
                type ||= file_type path
         | 
| 66 68 |  | 
| 69 | 
            +
                unless File.exist? path
         | 
| 70 | 
            +
                  return rescan_deleted_file path, type
         | 
| 71 | 
            +
                end
         | 
| 72 | 
            +
             | 
| 67 73 | 
             
                case type
         | 
| 68 74 | 
             
                when :controller
         | 
| 69 75 | 
             
                  rescan_controller path
         | 
| @@ -89,6 +95,10 @@ class Brakeman::Rescanner < Brakeman::Scanner | |
| 89 95 | 
             
                  process_controllers
         | 
| 90 96 | 
             
                  @reindex << :controllers << :templates
         | 
| 91 97 | 
             
                when :gemfile
         | 
| 98 | 
            +
                  if tracker.config[:gems][:rails_xss] and tracker.config[:escape_html]
         | 
| 99 | 
            +
                    tracker.config[:escape_html] = false
         | 
| 100 | 
            +
                  end
         | 
| 101 | 
            +
             | 
| 92 102 | 
             
                  process_gems
         | 
| 93 103 | 
             
                else
         | 
| 94 104 | 
             
                  return false #Nothing to do, file hopefully does not need to be rescanned
         | 
| @@ -111,7 +121,7 @@ class Brakeman::Rescanner < Brakeman::Scanner | |
| 111 121 | 
             
                      end
         | 
| 112 122 | 
             
                    end
         | 
| 113 123 |  | 
| 114 | 
            -
                    @processor.process_controller_alias controller[:src]
         | 
| 124 | 
            +
                    @processor.process_controller_alias controller[:name], controller[:src]
         | 
| 115 125 | 
             
                  end
         | 
| 116 126 | 
             
                end
         | 
| 117 127 | 
             
              end
         | 
| @@ -154,7 +164,7 @@ class Brakeman::Rescanner < Brakeman::Scanner | |
| 154 164 | 
             
                    controller = tracker.controllers[r[1]]
         | 
| 155 165 |  | 
| 156 166 | 
             
                    unless @paths.include? controller[:file]
         | 
| 157 | 
            -
                      @processor.process_controller_alias controller[:src], r[2]
         | 
| 167 | 
            +
                      @processor.process_controller_alias controller[:name], controller[:src], r[2]
         | 
| 158 168 | 
             
                    end
         | 
| 159 169 | 
             
                  elsif r[0] == :template
         | 
| 160 170 | 
             
                    template = tracker.templates[r[1]]
         | 
| @@ -179,6 +189,98 @@ class Brakeman::Rescanner < Brakeman::Scanner | |
| 179 189 | 
             
                @reindex << :models
         | 
| 180 190 | 
             
              end
         | 
| 181 191 |  | 
| 192 | 
            +
              #Handle rescanning when a file is deleted
         | 
| 193 | 
            +
              def rescan_deleted_file path, type
         | 
| 194 | 
            +
                case type
         | 
| 195 | 
            +
                when :controller
         | 
| 196 | 
            +
                  rescan_deleted_controller path
         | 
| 197 | 
            +
                when :template
         | 
| 198 | 
            +
                  rescan_deleted_template path
         | 
| 199 | 
            +
                when :model
         | 
| 200 | 
            +
                  rescan_model path
         | 
| 201 | 
            +
                when :lib
         | 
| 202 | 
            +
                  rescan_deleted_lib path
         | 
| 203 | 
            +
                when :initializer
         | 
| 204 | 
            +
                  rescan_deleted_initializer path
         | 
| 205 | 
            +
                else
         | 
| 206 | 
            +
                  if remove_deleted_file path
         | 
| 207 | 
            +
                    return true
         | 
| 208 | 
            +
                  else
         | 
| 209 | 
            +
                    Brakeman.notify "Ignoring deleted file: #{path}"
         | 
| 210 | 
            +
                  end
         | 
| 211 | 
            +
                end
         | 
| 212 | 
            +
             | 
| 213 | 
            +
                true
         | 
| 214 | 
            +
              end
         | 
| 215 | 
            +
             | 
| 216 | 
            +
              def rescan_deleted_controller path
         | 
| 217 | 
            +
                #Remove from controller
         | 
| 218 | 
            +
                tracker.controllers.delete_if do |name, controller|
         | 
| 219 | 
            +
                  if controller[:file] == path
         | 
| 220 | 
            +
                    template_matcher = /(.+)\.#{name}#/
         | 
| 221 | 
            +
             | 
| 222 | 
            +
                    #Remove templates rendered from this controller
         | 
| 223 | 
            +
                    tracker.templates.keys.each do |template_name|
         | 
| 224 | 
            +
                      if template_name.to_s.match template_matcher
         | 
| 225 | 
            +
                        tracker.templates.delete template_name
         | 
| 226 | 
            +
                      end
         | 
| 227 | 
            +
                    end
         | 
| 228 | 
            +
             | 
| 229 | 
            +
                    true
         | 
| 230 | 
            +
                  end
         | 
| 231 | 
            +
                end
         | 
| 232 | 
            +
              end
         | 
| 233 | 
            +
             | 
| 234 | 
            +
              def rescan_deleted_template path
         | 
| 235 | 
            +
                return unless path.match KNOWN_TEMPLATE_EXTENSIONS
         | 
| 236 | 
            +
             | 
| 237 | 
            +
                template_name = template_path_to_name(path)
         | 
| 238 | 
            +
             | 
| 239 | 
            +
                #Remove template
         | 
| 240 | 
            +
                tracker.reset_template template_name
         | 
| 241 | 
            +
             | 
| 242 | 
            +
                rendered_from_controller = /^#{template_name}\.(.+Controller)#(.+)/
         | 
| 243 | 
            +
                rendered_from_view = /^#{template_name}\.Template:(.+)/
         | 
| 244 | 
            +
             | 
| 245 | 
            +
                #Remove any rendered versions, or partials rendered from it
         | 
| 246 | 
            +
                tracker.templates.delete_if do |name, template|
         | 
| 247 | 
            +
                  if template[:file] == path
         | 
| 248 | 
            +
                    true
         | 
| 249 | 
            +
                  elsif template[:file].nil?
         | 
| 250 | 
            +
                    name = name.to_s
         | 
| 251 | 
            +
             | 
| 252 | 
            +
                    name.match(rendered_from_controller) or name.match(rendered_from_view)
         | 
| 253 | 
            +
                  end
         | 
| 254 | 
            +
                end
         | 
| 255 | 
            +
              end
         | 
| 256 | 
            +
             | 
| 257 | 
            +
              def rescan_deleted_lib path
         | 
| 258 | 
            +
                tracker.libs.delete_if do |name, lib|
         | 
| 259 | 
            +
                  lib[:path] == path
         | 
| 260 | 
            +
                end
         | 
| 261 | 
            +
              end
         | 
| 262 | 
            +
             | 
| 263 | 
            +
              def rescan_deleted_initializer path
         | 
| 264 | 
            +
                tracker.initializers.delete Pathname.new(path).basename.to_s
         | 
| 265 | 
            +
              end
         | 
| 266 | 
            +
             | 
| 267 | 
            +
              #Check controllers, templates, models and libs for data from file
         | 
| 268 | 
            +
              #and delete it.
         | 
| 269 | 
            +
              def remove_deleted_file path
         | 
| 270 | 
            +
                deleted = false
         | 
| 271 | 
            +
             | 
| 272 | 
            +
                [:controllers, :templates, :models, :libs].each do |collection|
         | 
| 273 | 
            +
                  tracker.send(collection).delete_if do |name, data|
         | 
| 274 | 
            +
                    if data[:file] == path
         | 
| 275 | 
            +
                      deleted = true
         | 
| 276 | 
            +
                      true
         | 
| 277 | 
            +
                    end
         | 
| 278 | 
            +
                  end
         | 
| 279 | 
            +
                end
         | 
| 280 | 
            +
             | 
| 281 | 
            +
                deleted
         | 
| 282 | 
            +
              end
         | 
| 283 | 
            +
             | 
| 182 284 | 
             
              #Guess at what kind of file the path contains
         | 
| 183 285 | 
             
              def file_type path
         | 
| 184 286 | 
             
                case path
         | 
| @@ -206,6 +308,7 @@ end | |
| 206 308 |  | 
| 207 309 | 
             
            #Class to make reporting of rescan results simpler to deal with
         | 
| 208 310 | 
             
            class Brakeman::RescanReport
         | 
| 311 | 
            +
              include Brakeman::Util
         | 
| 209 312 | 
             
              attr_reader :old_results, :new_results
         | 
| 210 313 |  | 
| 211 314 | 
             
              def initialize old_results, tracker
         | 
| @@ -271,17 +374,16 @@ New warnings: #{new_warnings.length} | |
| 271 374 | 
             
                    if warnings.length > 0
         | 
| 272 375 | 
             
                      out << "#{warning_type.to_s.titleize} warnings: #{warnings.length}\n"
         | 
| 273 376 |  | 
| 274 | 
            -
                      table =  | 
| 275 | 
            -
             | 
| 276 | 
            -
             | 
| 277 | 
            -
                        w = warning.to_row
         | 
| 377 | 
            +
                      table = Terminal::Table.new(:headings => ["Confidence", "Class", "Method", "Warning Type", "Message"]) do |t|
         | 
| 378 | 
            +
                        warnings.sort_by { |w| w.confidence}.each do |warning|
         | 
| 379 | 
            +
                          w = warning.to_row
         | 
| 278 380 |  | 
| 279 | 
            -
             | 
| 381 | 
            +
                          w["Confidence"] = Brakeman::Report::TEXT_CONFIDENCE[w["Confidence"]]
         | 
| 280 382 |  | 
| 281 | 
            -
             | 
| 383 | 
            +
                          t << [w["Confidence"], w["Class"], w["Method"], w["Warning Type"], w["Message"]]
         | 
| 384 | 
            +
                        end            
         | 
| 282 385 | 
             
                      end
         | 
| 283 | 
            -
             | 
| 284 | 
            -
                      out << table.to_s
         | 
| 386 | 
            +
                      out << truncate_table(table.to_s)
         | 
| 285 387 | 
             
                    end
         | 
| 286 388 | 
             
                  end
         | 
| 287 389 |  | 
    
        data/lib/brakeman/scanner.rb
    CHANGED
    
    | @@ -92,8 +92,7 @@ class Brakeman::Scanner | |
| 92 92 | 
             
                end
         | 
| 93 93 |  | 
| 94 94 | 
             
                if File.exists? "#@path/vendor/plugins/rails_xss" or
         | 
| 95 | 
            -
                  options[:rails3] or options[:escape_html] | 
| 96 | 
            -
                  (File.exists? "#@path/Gemfile" and File.read("#@path/Gemfile").include? "rails_xss")
         | 
| 95 | 
            +
                  options[:rails3] or options[:escape_html]
         | 
| 97 96 |  | 
| 98 97 | 
             
                  tracker.config[:escape_html] = true
         | 
| 99 98 | 
             
                  Brakeman.notify "[Notice] Escaping HTML by default"
         | 
| @@ -228,7 +227,7 @@ class Brakeman::Scanner | |
| 228 227 |  | 
| 229 228 | 
             
                Brakeman.notify "Processing data flow in controllers..."
         | 
| 230 229 |  | 
| 231 | 
            -
                tracker.controllers.each do |name, controller|
         | 
| 230 | 
            +
                tracker.controllers.sort_by{|name| name.to_s}.each do |name, controller|
         | 
| 232 231 | 
             
                  Brakeman.debug "Processing #{name}"
         | 
| 233 232 | 
             
                  if @report_progress
         | 
| 234 233 | 
             
                    $stderr.print " #{current}/#{total} controllers processed\r"
         | 
| @@ -281,7 +280,7 @@ class Brakeman::Scanner | |
| 281 280 |  | 
| 282 281 | 
             
                Brakeman.notify "Processing data flow in templates..."
         | 
| 283 282 |  | 
| 284 | 
            -
                tracker.templates.keys.dup.each do |name|
         | 
| 283 | 
            +
                tracker.templates.keys.dup.sort_by{|name| name.to_s}.each do |name|
         | 
| 285 284 | 
             
                  Brakeman.debug "Processing #{name}"
         | 
| 286 285 | 
             
                  if @report_progress
         | 
| 287 286 | 
             
                    count += 1
         | 
| @@ -0,0 +1,18 @@ | |
| 1 | 
            +
            <h2>Controllers</h2>
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            <table>
         | 
| 4 | 
            +
              <tr>
         | 
| 5 | 
            +
                <th>Name</th>
         | 
| 6 | 
            +
                <th>Parent</th>
         | 
| 7 | 
            +
                <th>Includes</th>
         | 
| 8 | 
            +
                <th>Routes</th>
         | 
| 9 | 
            +
              </tr>
         | 
| 10 | 
            +
            <% controller_rows.each do |row| %>
         | 
| 11 | 
            +
              <tr>
         | 
| 12 | 
            +
                <td><%= row['Name'] %></td>
         | 
| 13 | 
            +
                <td><%= row['Parent'] %></td>
         | 
| 14 | 
            +
                <td><%= row['Includes'] %></td>
         | 
| 15 | 
            +
                <td><%= row['Routes'] %></td>
         | 
| 16 | 
            +
              </tr>
         | 
| 17 | 
            +
            <% end %>
         | 
| 18 | 
            +
            </table>
         | 
| @@ -0,0 +1,17 @@ | |
| 1 | 
            +
            <p>Controller Warnings</p>
         | 
| 2 | 
            +
            <table>
         | 
| 3 | 
            +
              <tr>
         | 
| 4 | 
            +
                <th>Confidence</th>
         | 
| 5 | 
            +
                <th>Controller</th>
         | 
| 6 | 
            +
                <th>Warning Type</th>
         | 
| 7 | 
            +
                <th>Message</th>
         | 
| 8 | 
            +
              </tr>
         | 
| 9 | 
            +
            <% warnings.each do |warning| %>
         | 
| 10 | 
            +
              <tr>
         | 
| 11 | 
            +
                <td><%= warning['Confidence']%></td>
         | 
| 12 | 
            +
                <td><%= warning['Controller']%></td>
         | 
| 13 | 
            +
                <td><%= warning['Warning Type']%></td>
         | 
| 14 | 
            +
                <td><%= warning['Message']%></td>
         | 
| 15 | 
            +
              </tr>
         | 
| 16 | 
            +
            <% end %>
         | 
| 17 | 
            +
            </table>
         | 
| @@ -0,0 +1,14 @@ | |
| 1 | 
            +
            <div onClick="toggle('errors_table');">  <h2>Exceptions raised during the analysis (click to see them)</h2 ></div> <div id='errors_table' style='display:none'> 
         | 
| 2 | 
            +
            <table>
         | 
| 3 | 
            +
              <tr>
         | 
| 4 | 
            +
                <th>Error</th>
         | 
| 5 | 
            +
                <th>Location</th>
         | 
| 6 | 
            +
              </tr>
         | 
| 7 | 
            +
            <% tracker.errors.each do |warning| %>
         | 
| 8 | 
            +
              <tr>
         | 
| 9 | 
            +
                <td><%= CGI.escapeHTML warning[:error] %></td>
         | 
| 10 | 
            +
                <td><%= warning[:backtrace][0] %></td>
         | 
| 11 | 
            +
              </tr>
         | 
| 12 | 
            +
            <% end %>
         | 
| 13 | 
            +
            </table>
         | 
| 14 | 
            +
            </div>
         | 
| @@ -0,0 +1,38 @@ | |
| 1 | 
            +
            <!DOCTYPE HTML SYSTEM>
         | 
| 2 | 
            +
            <html>
         | 
| 3 | 
            +
            <head>
         | 
| 4 | 
            +
            <title>Brakeman Report</title>
         | 
| 5 | 
            +
              <script>
         | 
| 6 | 
            +
                function toggle(context) {
         | 
| 7 | 
            +
                  var elem = document.getElementById(context);
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  if (elem.style.display != "block")
         | 
| 10 | 
            +
                    elem.style.display = "block";
         | 
| 11 | 
            +
                  else
         | 
| 12 | 
            +
                    elem.style.display = "none";
         | 
| 13 | 
            +
                    
         | 
| 14 | 
            +
                  elem.parentNode.scrollIntoView();
         | 
| 15 | 
            +
                }
         | 
| 16 | 
            +
              </script>
         | 
| 17 | 
            +
              <style>
         | 
| 18 | 
            +
                <%= css %>
         | 
| 19 | 
            +
              </style>
         | 
| 20 | 
            +
            </head>
         | 
| 21 | 
            +
            <body>
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            <h1>Brakeman Report</h1>
         | 
| 24 | 
            +
            <table>
         | 
| 25 | 
            +
              <tr>
         | 
| 26 | 
            +
                <th>Application Path</th>
         | 
| 27 | 
            +
                <th>Rails Version</th>
         | 
| 28 | 
            +
                <th>Report Generation Time</th>
         | 
| 29 | 
            +
                <th>Checks Performed</th>
         | 
| 30 | 
            +
              </tr>
         | 
| 31 | 
            +
              <tr>
         | 
| 32 | 
            +
                <td><%= File.expand_path tracker.options[:app_path] %></td>
         | 
| 33 | 
            +
                <td><%= rails_version %></td>
         | 
| 34 | 
            +
                <td><%= Time.now %></td>
         | 
| 35 | 
            +
                <td><%= checks.checks_run.sort.join(", ") %></td>
         | 
| 36 | 
            +
              </tr>
         | 
| 37 | 
            +
            </table>
         | 
| 38 | 
            +
            <br>
         | 
| @@ -0,0 +1,17 @@ | |
| 1 | 
            +
            <p>Model Warnings</p>
         | 
| 2 | 
            +
            <table>
         | 
| 3 | 
            +
              <tr>
         | 
| 4 | 
            +
                <th>Confidence</th>
         | 
| 5 | 
            +
                <th>Model</th>
         | 
| 6 | 
            +
                <th>Warning Type</th>
         | 
| 7 | 
            +
                <th>Message</th>
         | 
| 8 | 
            +
              </tr>
         | 
| 9 | 
            +
            <% warnings.each do |warning| %>
         | 
| 10 | 
            +
              <tr>
         | 
| 11 | 
            +
                <td><%= warning['Confidence']%></td>
         | 
| 12 | 
            +
                <td><%= warning['Model']%></td>
         | 
| 13 | 
            +
                <td><%= warning['Warning Type']%></td>
         | 
| 14 | 
            +
                <td><%= warning['Message']%></td>
         | 
| 15 | 
            +
              </tr>
         | 
| 16 | 
            +
            <% end %>
         | 
| 17 | 
            +
            </table>
         | 
| @@ -0,0 +1,28 @@ | |
| 1 | 
            +
            <h2 id='summary'>Summary</h2> 
         | 
| 2 | 
            +
            <table>
         | 
| 3 | 
            +
              <tr>
         | 
| 4 | 
            +
                <th>Scanned/Reported</th>
         | 
| 5 | 
            +
                <th>Total</th>
         | 
| 6 | 
            +
              </tr>
         | 
| 7 | 
            +
              <tr>
         | 
| 8 | 
            +
                <td>Controllers</td>
         | 
| 9 | 
            +
                <td><%= tracker.controllers.length %></td>
         | 
| 10 | 
            +
              </tr>
         | 
| 11 | 
            +
              <tr>
         | 
| 12 | 
            +
                <td>Models</td>
         | 
| 13 | 
            +
                <td><%= tracker.models.length - 1 %></td>
         | 
| 14 | 
            +
              </tr>
         | 
| 15 | 
            +
              <tr>
         | 
| 16 | 
            +
                <td>Templates</td>
         | 
| 17 | 
            +
                <td><%= number_of_templates(@tracker) %></td>
         | 
| 18 | 
            +
              </tr>
         | 
| 19 | 
            +
              <tr>
         | 
| 20 | 
            +
                <td>Errors</td>
         | 
| 21 | 
            +
                <td><%= tracker.errors.length %></td>
         | 
| 22 | 
            +
              </tr>
         | 
| 23 | 
            +
              <tr>
         | 
| 24 | 
            +
                <td>Security Warnings</td>
         | 
| 25 | 
            +
                <td><%= warnings %> <span class='high-confidence'>(<%= warnings_summary[:high_confidence] %>)</span></td>
         | 
| 26 | 
            +
              </tr>
         | 
| 27 | 
            +
            </table>
         | 
| 28 | 
            +
            <br>
         | 
| @@ -0,0 +1,28 @@ | |
| 1 | 
            +
            <h2>Security Warnings</h2>  
         | 
| 2 | 
            +
            <table>
         | 
| 3 | 
            +
            <% if warning_messages.any? %>
         | 
| 4 | 
            +
              <tr>
         | 
| 5 | 
            +
                <th>Confidence</th>
         | 
| 6 | 
            +
                <th>Class</th>
         | 
| 7 | 
            +
                <th>Method</th>
         | 
| 8 | 
            +
                <th>Warning Type</th>
         | 
| 9 | 
            +
                <th>Message</th>
         | 
| 10 | 
            +
              </tr>
         | 
| 11 | 
            +
              <% warning_messages.each do |warning| %>
         | 
| 12 | 
            +
              <tr>
         | 
| 13 | 
            +
                <td><%= warning['Confidence']%></td>
         | 
| 14 | 
            +
                <td><%= warning['Class']%></td>
         | 
| 15 | 
            +
                <td><%= warning['Method']%></td>
         | 
| 16 | 
            +
                <td><%= warning['Warning Type']%></td>
         | 
| 17 | 
            +
                <td><%= warning['Message']%></td>
         | 
| 18 | 
            +
              </tr>
         | 
| 19 | 
            +
              <% end %>
         | 
| 20 | 
            +
            <% else %>
         | 
| 21 | 
            +
              <tr>
         | 
| 22 | 
            +
                <th>General Warnings</th>
         | 
| 23 | 
            +
              </tr>
         | 
| 24 | 
            +
              <tr>
         | 
| 25 | 
            +
                <td>[NONE]</td>
         | 
| 26 | 
            +
              </tr>
         | 
| 27 | 
            +
            <% end %>
         | 
| 28 | 
            +
            </table>
         | 
| @@ -0,0 +1,17 @@ | |
| 1 | 
            +
            <h2>Templates</h2>
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            <% template_rows.each do |template| %>
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            <p><%= template[0] %></p>
         | 
| 6 | 
            +
            <table>
         | 
| 7 | 
            +
              <tr>
         | 
| 8 | 
            +
                <th>Output</th>
         | 
| 9 | 
            +
              </tr>
         | 
| 10 | 
            +
              <% template[1].each do |call| %>
         | 
| 11 | 
            +
              <tr>
         | 
| 12 | 
            +
                <td><%= call %></td>
         | 
| 13 | 
            +
              </tr>
         | 
| 14 | 
            +
              <% end %>
         | 
| 15 | 
            +
            </table>
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            <% end %>
         | 
| @@ -0,0 +1,17 @@ | |
| 1 | 
            +
            <p>View Warnings</p>
         | 
| 2 | 
            +
            <table>
         | 
| 3 | 
            +
              <tr>
         | 
| 4 | 
            +
                <th>Confidence</th>
         | 
| 5 | 
            +
                <th>Template</th>
         | 
| 6 | 
            +
                <th>Warning Type</th>
         | 
| 7 | 
            +
                <th>Message</th>
         | 
| 8 | 
            +
              </tr>
         | 
| 9 | 
            +
            <% warnings.each do |warning| %>
         | 
| 10 | 
            +
              <tr>
         | 
| 11 | 
            +
                <td><%= warning['Confidence']%></td>
         | 
| 12 | 
            +
                <td><%= warning['Template']%></td>
         | 
| 13 | 
            +
                <td><%= warning['Warning Type']%></td>
         | 
| 14 | 
            +
                <td><%= warning['Message']%></td>
         | 
| 15 | 
            +
              </tr>
         | 
| 16 | 
            +
            <% end %>
         | 
| 17 | 
            +
            </table>
         | 
    
        data/lib/brakeman/tracker.rb
    CHANGED
    
    | @@ -85,7 +85,7 @@ class Brakeman::Tracker | |
| 85 85 | 
             
              #Prioritizes templates which have been rendered.
         | 
| 86 86 | 
             
              def each_template
         | 
| 87 87 | 
             
                if @processed.nil?
         | 
| 88 | 
            -
                  @processed, @rest = templates.keys.partition { |k| k.to_s.include? "." }
         | 
| 88 | 
            +
                  @processed, @rest = templates.keys.sort_by{|template| template.to_s}.partition { |k| k.to_s.include? "." }
         | 
| 89 89 | 
             
                end
         | 
| 90 90 |  | 
| 91 91 | 
             
                @processed.each do |k|
         | 
    
        data/lib/brakeman/util.rb
    CHANGED
    
    | @@ -88,10 +88,8 @@ module Brakeman::Util | |
| 88 88 | 
             
                  key = Sexp.new(:lit, key)
         | 
| 89 89 | 
             
                end
         | 
| 90 90 |  | 
| 91 | 
            -
                 | 
| 92 | 
            -
                   | 
| 93 | 
            -
                    return v
         | 
| 94 | 
            -
                  end
         | 
| 91 | 
            +
                if index = hash.find_index(key) and index > 0
         | 
| 92 | 
            +
                  return hash[index + 1]
         | 
| 95 93 | 
             
                end
         | 
| 96 94 |  | 
| 97 95 | 
             
                nil
         | 
| @@ -326,4 +324,26 @@ module Brakeman::Util | |
| 326 324 |  | 
| 327 325 | 
             
                context
         | 
| 328 326 | 
             
              end
         | 
| 327 | 
            +
             | 
| 328 | 
            +
              def truncate_table str
         | 
| 329 | 
            +
                @terminal_width ||= ::HighLine::SystemExtensions::terminal_size[0]
         | 
| 330 | 
            +
                lines = str.lines
         | 
| 331 | 
            +
             | 
| 332 | 
            +
                lines.map do |line|
         | 
| 333 | 
            +
                  if line.chomp.length > @terminal_width
         | 
| 334 | 
            +
                    line[0..(@terminal_width - 3)] + ">>"
         | 
| 335 | 
            +
                  else
         | 
| 336 | 
            +
                    line
         | 
| 337 | 
            +
                  end
         | 
| 338 | 
            +
                end.join
         | 
| 339 | 
            +
              end
         | 
| 340 | 
            +
             | 
| 341 | 
            +
              # rely on Terminal::Table to build the structure, extract the data out in CSV format
         | 
| 342 | 
            +
              def table_to_csv table
         | 
| 343 | 
            +
                output = CSV.generate_line(table.headings.cells.map{|cell| cell.to_s.strip})
         | 
| 344 | 
            +
                table.rows.each do |row|
         | 
| 345 | 
            +
                  output << CSV.generate_line(row.cells.map{|cell| cell.to_s.strip})
         | 
| 346 | 
            +
                end
         | 
| 347 | 
            +
                output
         | 
| 348 | 
            +
              end  
         | 
| 329 349 | 
             
            end
         |