Class: Brakeman::Report::Table

Inherits:
Base
  • Object
show all
Defined in:
lib/brakeman/report/report_table.rb

Direct Known Subclasses

HTML, Markdown, Tabs

Constant Summary

Constants included from Util

Util::ALL_COOKIES, Util::ALL_PARAMETERS, Util::COOKIES, Util::COOKIES_SEXP, Util::DIR_CONST, Util::LITERALS, Util::PARAMETERS, Util::PARAMS_SEXP, Util::PATH_PARAMETERS, Util::QUERY_PARAMETERS, Util::REQUEST_COOKIES, Util::REQUEST_ENV, Util::REQUEST_PARAMETERS, Util::REQUEST_PARAMS, Util::REQUEST_REQUEST_PARAMETERS, Util::SAFE_LITERAL, Util::SESSION, Util::SESSION_SEXP, Util::SIMPLE_LITERALS

Instance Attribute Summary

Attributes inherited from Base

#checks, #tracker

Instance Method Summary collapse

Methods inherited from Base

#absolute_paths?, #all_warnings, #context_for, #controller_information, #controller_warnings, #filter_warnings, #generic_warnings, #github_url, #ignored_warnings, #model_warnings, #number_of_templates, #rails_version, #template_warnings, #warning_file, #warnings_summary

Methods included from Util

#all_literals?, #array?, #block?, #call?, #camelize, #class_name, #constant?, #contains_class?, #cookies?, #dir_glob?, #false?, #hash?, #hash_access, #hash_insert, #hash_iterate, #hash_values, #integer?, #kwsplat?, #literal?, #make_call, #node_type?, #number?, #params?, #pluralize, #rails_version, #recurse_check?, #regexp?, #remove_kwsplat, #request_headers?, #request_value?, #result?, #safe_literal, #safe_literal?, #safe_literal_target?, #set_env_defaults, #sexp?, #simple_literal?, #string?, #string_interp?, #symbol?, #template_path_to_name, #true?, #underscore

Constructor Details

#initialize(*args) ⇒ Table

Returns a new instance of Table.

[View source]

4
5
6
7
# File 'lib/brakeman/report/report_table.rb', line 4

def initialize *args
  super
  @table = Terminal::Table
end

Instance Method Details

#convert_ignored_warning(warning, original) ⇒ Object

[View source]

202
203
204
# File 'lib/brakeman/report/report_table.rb', line 202

def convert_ignored_warning warning, original
  convert_warning warning, original
end

#convert_template_warning(warning, original) ⇒ Object

[View source]

206
207
208
# File 'lib/brakeman/report/report_table.rb', line 206

def convert_template_warning warning, original
  convert_warning warning, original
end

#convert_to_rows(warnings, type = :warning) ⇒ Object

[View source]

185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/brakeman/report/report_table.rb', line 185

def convert_to_rows warnings, type = :warning
  warnings.map do |warning|
    w = warning.to_row type

    case type
    when :warning
      convert_warning w, warning
    when :ignored
      convert_ignored_warning w, warning
    when :template
      convert_template_warning w, warning
    else
      convert_warning w, warning
    end
  end
end

#convert_warning(warning, original) ⇒ Object

[View source]

227
228
229
230
231
# File 'lib/brakeman/report/report_table.rb', line 227

def convert_warning warning, original
  warning["Message"] = text_message original, warning["Message"]

  warning
end

#generate_controller_warningsObject

Generate table of controller warnings or nil if no warnings

[View source]

125
126
127
128
129
130
131
# File 'lib/brakeman/report/report_table.rb', line 125

def generate_controller_warnings
  render_warnings controller_warnings,
                  :controller,
                  'controller_warnings',
                  ['Confidence', 'Controller', 'Warning Type', "CWE ID", 'Message'],
                  'Controller'
end

#generate_controllersObject

Generate table of controllers and routes found for those controllers

[View source]

76
77
78
79
80
81
82
83
84
# File 'lib/brakeman/report/report_table.rb', line 76

def generate_controllers
  controller_rows = controller_information

  cols = ['Name', 'Parent', 'Includes', 'Routes']

  locals = {:controller_rows => controller_rows}
  values = controller_rows.collect{|row| row.values_at(*cols) }
  render_array('controller_overview', cols, values, locals)
end

#generate_errorsObject

Generate table of errors or return nil if no errors

[View source]

87
88
89
90
# File 'lib/brakeman/report/report_table.rb', line 87

def generate_errors
  values = tracker.errors.collect{|error| [error[:error], error[:backtrace][0]]}
  render_array('error_overview', ['Error', 'Location'], values, {:tracker => tracker})
end

#generate_ignored_warningsObject

[View source]

133
134
135
136
137
138
139
# File 'lib/brakeman/report/report_table.rb', line 133

def generate_ignored_warnings
  render_warnings ignored_warnings,
                  :ignored,
                  'ignored_warnings',
                  ['Confidence', 'Warning Type', "CWE ID", 'File', 'Message'],
                  'Warning Type'
end

#generate_model_warningsObject

Generate table of model warnings or return nil if no warnings

[View source]

116
117
118
119
120
121
122
# File 'lib/brakeman/report/report_table.rb', line 116

def generate_model_warnings
  render_warnings model_warnings,
                  :model,
                  'model_warnings',
                  ['Confidence', 'Model', 'Warning Type', "CWE ID", 'Message'],
                  'Model'
end

#generate_obsoleteObject

[View source]

92
93
94
95
# File 'lib/brakeman/report/report_table.rb', line 92

def generate_obsolete
  values = tracker.unused_fingerprints.collect{|fingerprint| [fingerprint] }
  render_array('obsolete_ignore_entries', ['fingerprint'], values, {:tracker => tracker})
end

#generate_overviewObject

[View source]

52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/brakeman/report/report_table.rb', line 52

def generate_overview
  num_warnings = all_warnings.length

  @table.new(:headings => ['Scanned/Reported', 'Total']) do |t|
    t.add_row ['Controllers', tracker.controllers.length]
    t.add_row ['Models', tracker.models.length - 1]
    t.add_row ['Templates', number_of_templates(@tracker)]
    t.add_row ['Errors', tracker.errors.length]
    t.add_row ['Security Warnings', "#{num_warnings} (#{warnings_summary[:high_confidence]})"]
    t.add_row ['Ignored Warnings', ignored_warnings.length] unless ignored_warnings.empty?
  end
end

#generate_reportObject

[View source]

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/brakeman/report/report_table.rb', line 9

def generate_report
  summary_option = tracker.options[:summary_only]
  out = +""

  unless summary_option == :no_summary
    out << text_header <<
      "\n\n+SUMMARY+\n\n" <<
      truncate_table(generate_overview.to_s) << "\n\n" <<
      truncate_table(generate_warning_overview.to_s) << "\n"
  end

  #Return output early if only summarizing
  if summary_option == :summary_only or summary_option == true
    return out
  end

  if tracker.options[:report_routes] or tracker.options[:debug]
    out << "\n+CONTROLLERS+\n" <<
    truncate_table(generate_controllers.to_s) << "\n"
  end

  if tracker.options[:debug]
    out << "\n+TEMPLATES+\n\n" <<
    truncate_table(generate_templates.to_s) << "\n"
  end

  output_table("+Obsolete Ignore Entries+", generate_obsolete, out)
  output_table("+Errors+", generate_errors, out)
  output_table("+SECURITY WARNINGS+", generate_warnings, out)
  output_table("Controller Warnings:", generate_controller_warnings, out)
  output_table("Model Warnings:", generate_model_warnings, out)
  output_table("View Warnings:", generate_template_warnings, out)

  out << "\n"
  out
end

#generate_template_warningsObject

Generate table of template warnings or return nil if no warnings

[View source]

106
107
108
109
110
111
112
113
# File 'lib/brakeman/report/report_table.rb', line 106

def generate_template_warnings
  render_warnings template_warnings,
                  :template,
                  'view_warnings',
                  ['Confidence', 'Template', 'Warning Type', "CWE ID", 'Message'],
                  'Template'

end

#generate_templatesObject

Generate listings of templates and their output

[View source]

156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/brakeman/report/report_table.rb', line 156

def generate_templates
  out_processor = Brakeman::OutputProcessor.new
  template_rows = {}
  tracker.templates.each do |name, template|
    template.each_output do |out|
      out = out_processor.format out
      template_rows[name] ||= []
      template_rows[name] << out.gsub("\n", ";").gsub(/\s+/, " ")
    end
  end

  template_rows = template_rows.sort_by{|name, value| name.to_s}

  output = +''
  template_rows.each do |template|
    output << template.first.to_s << "\n\n"
    table = @table.new(:headings => ['Output']) do |t|
      # template[1] is an array of calls
      template[1].each do |v|
        t.add_row [v]
      end
    end

    output << table.to_s << "\n\n"
  end

  output
end

#generate_warning_overviewObject

Generate table of how many warnings of each warning type were reported

[View source]

66
67
68
69
70
71
72
73
# File 'lib/brakeman/report/report_table.rb', line 66

def generate_warning_overview
  types = warnings_summary.keys
  types.delete :high_confidence
  values = types.sort.collect{|warning_type| [warning_type, warnings_summary[warning_type]] }
  locals = {:types => types, :warnings_summary => warnings_summary}

  render_array('warning_overview', ['Warning Type', 'Total'], values, locals)
end

#generate_warningsObject

[View source]

97
98
99
100
101
102
103
# File 'lib/brakeman/report/report_table.rb', line 97

def generate_warnings
  render_warnings generic_warnings,
                  :warning,
                  'security_warnings',
                  ["Confidence", "Class", "Method", "Warning Type", "CWE ID", "Message"],
                  'Class'
end

#output_table(title, result, output) ⇒ Object

[View source]

46
47
48
49
50
# File 'lib/brakeman/report/report_table.rb', line 46

def output_table title, result, output
  return unless result

  output << "\n\n#{title}\n\n#{truncate_table(result.to_s)}"
end

#render_array(template, headings, value_array, locals) ⇒ Object

[View source]

219
220
221
222
223
224
225
# File 'lib/brakeman/report/report_table.rb', line 219

def render_array template, headings, value_array, locals
  return if value_array.empty?

  @table.new(:headings => headings) do |t|
    value_array.each { |value_row| t.add_row value_row }
  end
end

#render_warnings(warnings, type, template, cols, sort_col) ⇒ Object

[View source]

141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/brakeman/report/report_table.rb', line 141

def render_warnings warnings, type, template, cols, sort_col
  unless warnings.empty?
    rows = sort(convert_to_rows(warnings, type), sort_col)

    values = rows.collect { |row| row.values_at(*cols) }

    locals = { :warnings => rows }

    render_array(template, cols, values, locals)
  else
    nil
  end
end

#sort(rows, sort_col) ⇒ Object

[View source]

210
211
212
213
214
215
216
217
# File 'lib/brakeman/report/report_table.rb', line 210

def sort rows, sort_col
  stabilizer = 0
  rows.sort_by do |row|
    stabilizer += 1

    row.values_at("Confidence", "Warning Type", sort_col) << stabilizer
  end
end

#text_headerObject

Generate header for text output

[View source]

257
258
259
260
261
262
263
264
265
266
267
268
269
# File 'lib/brakeman/report/report_table.rb', line 257

def text_header
  <<-HEADER

+BRAKEMAN REPORT+

Application path: #{tracker.app_path}
Rails version: #{rails_version}
Brakeman version: #{Brakeman::Version}
Started at #{tracker.start_time}
Duration: #{tracker.duration} seconds
Checks run: #{checks.checks_run.sort.join(", ")}
HEADER
end

#text_message(warning, message) ⇒ Object

Escape warning message and highlight user input in text output

[View source]

234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
# File 'lib/brakeman/report/report_table.rb', line 234

def text_message warning, message
  message = message.to_s

  if warning.line
    message << " near line #{warning.line}"
  end

  if warning.code
    if @highlight_user_input and warning.user_input
      code = warning.format_with_user_input do |user_input, user_input_string|
        "+#{user_input_string}+"
      end
    else
      code = warning.format_code
    end

    message << ": #{code}"
  end

  message
end

#truncate_table(str) ⇒ Object

[View source]

271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
# File 'lib/brakeman/report/report_table.rb', line 271

def truncate_table str
  @terminal_width ||= if @tracker.options[:table_width]
                        @tracker.options[:table_width]
                      elsif $stdin && $stdin.tty?
                        Brakeman.load_brakeman_dependency 'highline'
                        ::HighLine.default_instance.terminal.terminal_size[0]
                      else
                        80
                      end
  lines = str.lines

  lines.map do |line|
    if line.chomp.length > @terminal_width
      line[0..(@terminal_width - 3)] + ">>\n"
    else
      line
    end
  end.join
end