-
Notifications
You must be signed in to change notification settings - Fork 715
/
report_text.rb
213 lines (175 loc) · 5.37 KB
/
report_text.rb
1
2
3
4
5
6
7
8
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
Brakeman.load_brakeman_dependency 'highline'
class Brakeman::Report::Text < Brakeman::Report::Base
def generate_report
HighLine.use_color = !!tracker.options[:output_color]
summary_option = tracker.options[:summary_only]
@output_string = "\n"
unless summary_option == :no_summary
add_chunk generate_header
add_chunk generate_overview
add_chunk generate_warning_overview
end
if summary_option == :summary_only or summary_option == true
return @output_string
end
add_chunk generate_controllers if tracker.options[:debug] or tracker.options[:report_routes]
add_chunk generate_templates if tracker.options[:debug]
add_chunk generate_obsolete
add_chunk generate_errors
add_chunk generate_warnings
end
def add_chunk chunk, out = @output_string
if chunk and not chunk.empty?
if chunk.is_a? Array
chunk = chunk.join("\n")
end
out << chunk << "\n\n"
end
end
def generate_controllers
double_space "Controller Overview", controller_information.map { |ci|
controller = [
label("Controller", ci["Name"]),
label("Parent", ci["Parent"]),
label("Routes", ci["Routes"])
]
if ci["Includes"] and not ci["Includes"].empty?
controller.insert(2, label("Includes", ci["Includes"]))
end
controller
}
end
def generate_header
[
header("Brakeman Report"),
label("Application Path", tracker.app_path),
label("Rails Version", rails_version),
label("Brakeman Version", Brakeman::Version),
label("Scan Date", tracker.start_time),
label("Duration", "#{tracker.duration} seconds"),
label("Checks Run", checks.checks_run.sort.join(", "))
]
end
def generate_overview
overview = [
header("Overview"),
label('Controllers', tracker.controllers.length),
label('Models', tracker.models.length - 1),
label('Templates', number_of_templates(@tracker)),
label('Errors', tracker.errors.length),
label('Security Warnings', all_warnings.length)
]
unless ignored_warnings.empty?
overview << label('Ignored Warnings', ignored_warnings.length)
end
overview
end
def generate_warning_overview
warning_types = warnings_summary
warning_types.delete :high_confidence
warning_types.sort_by { |t, c| t }.map do |type, count|
label(type, count)
end.unshift(header('Warning Types'))
end
def generate_warnings
if tracker.filtered_warnings.empty?
HighLine.color("No warnings found", :bold, :green)
else
warnings = tracker.filtered_warnings.sort_by do |w|
[w.confidence, w.warning_type, w.file, w.line, w.fingerprint]
end.map do |w|
output_warning w
end
double_space "Warnings", warnings
end
end
def generate_errors
return if tracker.errors.empty?
full_trace = tracker.options[:debug]
errors = tracker.errors.map do |e|
trace = if full_trace
e[:backtrace].join("\n")
else
e[:backtrace][0]
end
[
label("Error", e[:error]),
label("Location", trace)
]
end
double_space "Errors", errors
end
def generate_obsolete
return if tracker.unused_fingerprints.empty?
[header("Obsolete Ignore Entries")] + tracker.unused_fingerprints
end
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
double_space "Template Output", template_rows.sort_by { |name, value| name.to_s }.map { |template|
[HighLine.new.color("#{template.first}\n", :cyan)] + template[1]
}.compact
end
def output_warning w
out = [
label('Confidence', confidence(w.confidence)),
label('Category', w.warning_type.to_s),
label('Check', w.check.gsub(/^Brakeman::Check/, '')),
label('Message', w.message)
]
if w.code
out << label('Code', format_code(w))
end
out << label('File', warning_file(w))
if w.line
out << label('Line', w.line)
end
out
end
def double_space title, values
values = values.map { |v| v.join("\n") }.join("\n\n")
[header(title), values]
end
def format_code w
if @highlight_user_input and w.user_input
w.format_with_user_input do |exp, text|
HighLine.new.color(text, :yellow)
end
else
w.format_code
end
end
def confidence c
case c
when 0
HighLine.new.color("High", :red)
when 1
HighLine.new.color("Medium", :yellow)
when 2
HighLine.new.color("Weak", :none)
end
end
def label l, value, color = :green
"#{HighLine.new.color(l, color)}: #{value}"
end
def header text
HighLine.new.color("== #{text} ==\n", :bold, :magenta)
end
# ONLY used for generate_controllers to avoid duplication
def render_array name, cols, values, locals
controllers = values.map do |controller_name, parent, includes, routes|
c = [ label("Controller", controller_name) ]
c << label("Parent", parent) unless parent.empty?
c << label("Includes", includes) unless includes.empty?
c << label("Routes", routes)
end
double_space "Controller Overview", controllers
end
end