brakeman-min 3.1.1 → 3.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES +18 -0
- data/lib/brakeman.rb +17 -13
- data/lib/brakeman/checks/base_check.rb +2 -0
- data/lib/brakeman/checks/check_content_tag.rb +2 -2
- data/lib/brakeman/checks/check_cross_site_scripting.rb +6 -6
- data/lib/brakeman/checks/check_deserialize.rb +1 -1
- data/lib/brakeman/checks/check_evaluation.rb +1 -1
- data/lib/brakeman/checks/check_execute.rb +3 -5
- data/lib/brakeman/checks/check_file_access.rb +1 -1
- data/lib/brakeman/checks/check_forgery_setting.rb +2 -1
- data/lib/brakeman/checks/check_link_to.rb +2 -2
- data/lib/brakeman/checks/check_link_to_href.rb +10 -3
- data/lib/brakeman/checks/check_mass_assignment.rb +2 -4
- data/lib/brakeman/checks/check_model_attributes.rb +1 -0
- data/lib/brakeman/checks/check_model_serialize.rb +2 -1
- data/lib/brakeman/checks/check_number_to_currency.rb +0 -1
- data/lib/brakeman/checks/check_redirect.rb +1 -1
- data/lib/brakeman/checks/check_regex_dos.rb +1 -1
- data/lib/brakeman/checks/check_render.rb +1 -1
- data/lib/brakeman/checks/check_render_inline.rb +28 -16
- data/lib/brakeman/checks/check_select_tag.rb +1 -1
- data/lib/brakeman/checks/check_send.rb +1 -1
- data/lib/brakeman/checks/check_session_manipulation.rb +1 -1
- data/lib/brakeman/checks/check_simple_format.rb +1 -1
- data/lib/brakeman/checks/check_sql.rb +2 -2
- data/lib/brakeman/checks/check_symbol_dos.rb +1 -1
- data/lib/brakeman/checks/check_unsafe_reflection.rb +1 -1
- data/lib/brakeman/checks/check_unscoped_find.rb +1 -1
- data/lib/brakeman/checks/check_weak_hash.rb +0 -1
- data/lib/brakeman/checks/check_without_protection.rb +1 -3
- data/lib/brakeman/processors/alias_processor.rb +11 -1
- data/lib/brakeman/processors/base_processor.rb +4 -1
- data/lib/brakeman/processors/controller_processor.rb +2 -0
- data/lib/brakeman/processors/haml_template_processor.rb +1 -1
- data/lib/brakeman/processors/lib/processor_helper.rb +13 -0
- data/lib/brakeman/processors/library_processor.rb +8 -0
- data/lib/brakeman/processors/model_processor.rb +2 -0
- data/lib/brakeman/report/report_html.rb +11 -1
- data/lib/brakeman/report/templates/controller_overview.html.erb +18 -14
- data/lib/brakeman/report/templates/controller_warnings.html.erb +18 -14
- data/lib/brakeman/report/templates/error_overview.html.erb +8 -4
- data/lib/brakeman/report/templates/header.html.erb +32 -18
- data/lib/brakeman/report/templates/ignored_warnings.html.erb +11 -7
- data/lib/brakeman/report/templates/model_warnings.html.erb +18 -14
- data/lib/brakeman/report/templates/overview.html.erb +32 -28
- data/lib/brakeman/report/templates/security_warnings.html.erb +18 -14
- data/lib/brakeman/report/templates/template_overview.html.erb +10 -6
- data/lib/brakeman/report/templates/view_warnings.html.erb +30 -26
- data/lib/brakeman/report/templates/warning_overview.html.erb +12 -8
- data/lib/brakeman/tracker/collection.rb +12 -0
- data/lib/brakeman/tracker/controller.rb +2 -2
- data/lib/brakeman/version.rb +1 -1
- data/lib/brakeman/warning.rb +29 -6
- data/lib/ruby_parser/bm_sexp.rb +18 -0
- metadata +16 -2
@@ -54,6 +54,6 @@ class Brakeman::CheckSimpleFormat < Brakeman::CheckCrossSiteScripting
|
|
54
54
|
:message => "Values passed to simple_format are not safe in Rails #{rails_version}",
|
55
55
|
:confidence => CONFIDENCE[:high],
|
56
56
|
:link_path => "https://groups.google.com/d/msg/ruby-security-ann/5ZI1-H5OoIM/ZNq4FoR2GnIJ",
|
57
|
-
:user_input => match
|
57
|
+
:user_input => match
|
58
58
|
end
|
59
59
|
end
|
@@ -197,7 +197,7 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
|
|
197
197
|
input = include_user_input? dangerous_value
|
198
198
|
if input
|
199
199
|
confidence = CONFIDENCE[:high]
|
200
|
-
user_input = input
|
200
|
+
user_input = input
|
201
201
|
else
|
202
202
|
confidence = CONFIDENCE[:med]
|
203
203
|
user_input = dangerous_value
|
@@ -342,7 +342,7 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
|
|
342
342
|
def check_hash_keys exp
|
343
343
|
hash_iterate(exp) do |key, value|
|
344
344
|
unless symbol?(key)
|
345
|
-
unsafe_key = unsafe_sql?
|
345
|
+
unsafe_key = unsafe_sql? key
|
346
346
|
return unsafe_key if unsafe_key
|
347
347
|
end
|
348
348
|
end
|
@@ -41,7 +41,7 @@ class Brakeman::CheckSymbolDoS < Brakeman::BaseCheck
|
|
41
41
|
:warning_type => "Denial of Service",
|
42
42
|
:warning_code => :unsafe_symbol_creation,
|
43
43
|
:message => message,
|
44
|
-
:user_input => input
|
44
|
+
:user_input => input,
|
45
45
|
:confidence => confidence
|
46
46
|
end
|
47
47
|
end
|
@@ -44,7 +44,7 @@ class Brakeman::CheckUnsafeReflection < Brakeman::BaseCheck
|
|
44
44
|
:warning_type => "Remote Code Execution",
|
45
45
|
:warning_code => :unsafe_constantize,
|
46
46
|
:message => message,
|
47
|
-
:user_input => input
|
47
|
+
:user_input => input,
|
48
48
|
:confidence => confidence
|
49
49
|
end
|
50
50
|
end
|
@@ -30,7 +30,6 @@ class Brakeman::CheckWeakHash < Brakeman::BaseCheck
|
|
30
30
|
|
31
31
|
if DIGEST_CALLS.include? call.method
|
32
32
|
if input = user_input_as_arg?(call)
|
33
|
-
input = input.match
|
34
33
|
confidence = CONFIDENCE[:high]
|
35
34
|
elsif input = hashing_password?(call)
|
36
35
|
confidence = CONFIDENCE[:high]
|
@@ -43,10 +43,8 @@ class Brakeman::CheckWithoutProtection < Brakeman::BaseCheck
|
|
43
43
|
|
44
44
|
if input = include_user_input?(call.arglist)
|
45
45
|
confidence = CONFIDENCE[:high]
|
46
|
-
user_input = input.match
|
47
46
|
else
|
48
47
|
confidence = CONFIDENCE[:med]
|
49
|
-
user_input = nil
|
50
48
|
end
|
51
49
|
|
52
50
|
warn :result => res,
|
@@ -54,7 +52,7 @@ class Brakeman::CheckWithoutProtection < Brakeman::BaseCheck
|
|
54
52
|
:warning_code => :mass_assign_without_protection,
|
55
53
|
:message => "Unprotected mass assignment",
|
56
54
|
:code => call,
|
57
|
-
:user_input =>
|
55
|
+
:user_input => input,
|
58
56
|
:confidence => confidence
|
59
57
|
|
60
58
|
end
|
@@ -79,6 +79,7 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
|
|
79
79
|
|
80
80
|
#Process a method call.
|
81
81
|
def process_call exp
|
82
|
+
return exp if process_call_defn? exp
|
82
83
|
target_var = exp.target
|
83
84
|
target_var &&= target_var.deep_clone
|
84
85
|
exp = process_default exp
|
@@ -142,7 +143,16 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
|
|
142
143
|
end
|
143
144
|
when :/
|
144
145
|
if number? target and number? first_arg
|
145
|
-
|
146
|
+
if first_arg.value == 0 and not target.value.is_a? Float
|
147
|
+
if @tracker
|
148
|
+
location = [@current_class, @current_method, "line #{first_arg.line}"].compact.join(' ')
|
149
|
+
require 'brakeman/processors/output_processor'
|
150
|
+
code = Brakeman::OutputProcessor.new.format(exp)
|
151
|
+
@tracker.error Exception.new("Potential divide by zero: #{code} (#{location})")
|
152
|
+
end
|
153
|
+
else
|
154
|
+
exp = Sexp.new(:lit, target.value / first_arg.value)
|
155
|
+
end
|
146
156
|
end
|
147
157
|
when :[]
|
148
158
|
if array? target
|
@@ -103,7 +103,10 @@ class Brakeman::BaseProcessor < Brakeman::SexpProcessor
|
|
103
103
|
#Processes the inside of an interpolated String.
|
104
104
|
def process_evstr exp
|
105
105
|
exp = exp.dup
|
106
|
-
|
106
|
+
if exp[1]
|
107
|
+
exp[1] = process exp[1]
|
108
|
+
end
|
109
|
+
|
107
110
|
exp
|
108
111
|
end
|
109
112
|
|
@@ -109,6 +109,8 @@ class Brakeman::ControllerProcessor < Brakeman::BaseProcessor
|
|
109
109
|
|
110
110
|
#Look for specific calls inside the controller
|
111
111
|
def process_call exp
|
112
|
+
return exp if process_call_defn? exp
|
113
|
+
|
112
114
|
target = exp.target
|
113
115
|
if sexp? target
|
114
116
|
target = process target
|
@@ -59,4 +59,17 @@ module Brakeman::ProcessorHelper
|
|
59
59
|
|
60
60
|
exp
|
61
61
|
end
|
62
|
+
|
63
|
+
# e.g. private defn
|
64
|
+
def process_call_defn? exp
|
65
|
+
if call? exp and exp.target.nil? and node_type? exp.first_arg, :defn, :defs and [:private, :public, :protected].include? exp.method
|
66
|
+
prev_visibility = @visibility
|
67
|
+
@visibility = exp.method
|
68
|
+
process exp.first_arg
|
69
|
+
@visibility = prev_visibility
|
70
|
+
exp
|
71
|
+
else
|
72
|
+
false
|
73
|
+
end
|
74
|
+
end
|
62
75
|
end
|
@@ -94,6 +94,8 @@ class Brakeman::ModelProcessor < Brakeman::BaseProcessor
|
|
94
94
|
#such as include, attr_accessible, private, etc.
|
95
95
|
def process_call exp
|
96
96
|
return exp unless @current_class
|
97
|
+
return exp if process_call_defn? exp
|
98
|
+
|
97
99
|
target = exp.target
|
98
100
|
if sexp? target
|
99
101
|
target = process target
|
@@ -139,6 +139,16 @@ class Brakeman::Report::HTML < Brakeman::Report::Base
|
|
139
139
|
"<table id='#{code_id}' class='context' style='display:none'>" <<
|
140
140
|
"<caption>#{CGI.escapeHTML warning_file(warning) || ''}</caption>"
|
141
141
|
|
142
|
+
output << <<-HTML
|
143
|
+
<thead style='display:none'>
|
144
|
+
<tr>
|
145
|
+
<th>line number</th>
|
146
|
+
<th>line content</th>
|
147
|
+
</tr>
|
148
|
+
</thead>
|
149
|
+
<tbody>
|
150
|
+
HTML
|
151
|
+
|
142
152
|
unless context.empty?
|
143
153
|
if warning.line - 1 == 1 or warning.line + 1 == 1
|
144
154
|
error = " near_error"
|
@@ -184,7 +194,7 @@ class Brakeman::Report::HTML < Brakeman::Report::Base
|
|
184
194
|
end
|
185
195
|
end
|
186
196
|
|
187
|
-
output << "</table></div>"
|
197
|
+
output << "</tbody></table></div>"
|
188
198
|
end
|
189
199
|
|
190
200
|
#Escape warning message and highlight user input in HTML output
|
@@ -1,18 +1,22 @@
|
|
1
1
|
<h2>Controllers</h2>
|
2
2
|
|
3
3
|
<table>
|
4
|
-
<
|
5
|
-
<
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
<
|
15
|
-
|
16
|
-
|
17
|
-
|
4
|
+
<thead>
|
5
|
+
<tr>
|
6
|
+
<th>Name</th>
|
7
|
+
<th>Parent</th>
|
8
|
+
<th>Includes</th>
|
9
|
+
<th>Routes</th>
|
10
|
+
</tr>
|
11
|
+
</thead>
|
12
|
+
<tbody>
|
13
|
+
<% controller_rows.each do |row| %>
|
14
|
+
<tr>
|
15
|
+
<td><%= row['Name'] %></td>
|
16
|
+
<td><%= row['Parent'] %></td>
|
17
|
+
<td><%= row['Includes'] %></td>
|
18
|
+
<td><%= row['Routes'] %></td>
|
19
|
+
</tr>
|
20
|
+
<% end %>
|
21
|
+
</tbody>
|
18
22
|
</table>
|
@@ -1,17 +1,21 @@
|
|
1
1
|
<p>Controller Warnings</p>
|
2
2
|
<table>
|
3
|
-
<
|
4
|
-
<
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
<
|
14
|
-
|
15
|
-
|
16
|
-
|
3
|
+
<thead>
|
4
|
+
<tr>
|
5
|
+
<th>Confidence</th>
|
6
|
+
<th>Controller</th>
|
7
|
+
<th>Warning Type</th>
|
8
|
+
<th>Message</th>
|
9
|
+
</tr>
|
10
|
+
</thead>
|
11
|
+
<tbody>
|
12
|
+
<% warnings.each do |warning| %>
|
13
|
+
<tr>
|
14
|
+
<td><%= warning['Confidence']%></td>
|
15
|
+
<td><%= warning['Controller']%></td>
|
16
|
+
<td><%= warning['Warning Type']%></td>
|
17
|
+
<td><%= warning['Message']%></td>
|
18
|
+
</tr>
|
19
|
+
<% end %>
|
20
|
+
</tbody>
|
17
21
|
</table>
|
@@ -2,10 +2,13 @@
|
|
2
2
|
<div>
|
3
3
|
<div id='errors_table' style='display:none'>
|
4
4
|
<table>
|
5
|
-
<
|
6
|
-
<
|
7
|
-
|
8
|
-
|
5
|
+
<thead>
|
6
|
+
<tr>
|
7
|
+
<th>Error</th>
|
8
|
+
<th>Location</th>
|
9
|
+
</tr>
|
10
|
+
</thead>
|
11
|
+
<tbody>
|
9
12
|
<% tracker.errors.each do |warning| %>
|
10
13
|
<tr>
|
11
14
|
<td><%= CGI.escapeHTML warning[:error] %></td>
|
@@ -20,6 +23,7 @@
|
|
20
23
|
</td>
|
21
24
|
</tr>
|
22
25
|
<% end %>
|
26
|
+
</tbody>
|
23
27
|
</table>
|
24
28
|
</div>
|
25
29
|
</div>
|
@@ -3,7 +3,9 @@
|
|
3
3
|
<head>
|
4
4
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
5
5
|
<title>Brakeman Report</title>
|
6
|
-
<script>
|
6
|
+
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
|
7
|
+
<script type="text/javascript" src="https://cdn.datatables.net/1.10.9/js/jquery.dataTables.min.js"></script>
|
8
|
+
<script type="text/javascript">
|
7
9
|
function toggle(context) {
|
8
10
|
var elem = document.getElementById(context);
|
9
11
|
|
@@ -14,6 +16,14 @@
|
|
14
16
|
|
15
17
|
elem.parentNode.scrollIntoView();
|
16
18
|
}
|
19
|
+
|
20
|
+
$(document).ready(function() {
|
21
|
+
$('table').DataTable({
|
22
|
+
searching: false,
|
23
|
+
paging: false,
|
24
|
+
info: false
|
25
|
+
});
|
26
|
+
});
|
17
27
|
</script>
|
18
28
|
<style>
|
19
29
|
<%= css %>
|
@@ -23,22 +33,26 @@
|
|
23
33
|
|
24
34
|
<h1>Brakeman Report</h1>
|
25
35
|
<table>
|
26
|
-
<
|
27
|
-
<
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
<
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
36
|
+
<thead>
|
37
|
+
<tr>
|
38
|
+
<th>Application Path</th>
|
39
|
+
<th>Rails Version</th>
|
40
|
+
<th>Brakeman Version</th>
|
41
|
+
<th>Report Time</th>
|
42
|
+
<th>Checks Performed</th>
|
43
|
+
</tr>
|
44
|
+
</thead>
|
45
|
+
<tbody>
|
46
|
+
<tr>
|
47
|
+
<td><%= tracker.app_path %></td>
|
48
|
+
<td><%= rails_version %></td>
|
49
|
+
<td><%= brakeman_version %>
|
50
|
+
<td>
|
51
|
+
<%= tracker.start_time %><br><br>
|
52
|
+
<%= tracker.duration %> seconds
|
53
|
+
</td>
|
54
|
+
<td><%= checks.checks_run.sort.join(", ") %></td>
|
55
|
+
</tr>
|
56
|
+
</tbody>
|
43
57
|
</table>
|
44
58
|
<br>
|
@@ -1,13 +1,16 @@
|
|
1
1
|
<div onClick="toggle('ignored_table');"> <h2><%= warnings.length %> Ignored Warnings (click to see them)</h2 ></div>
|
2
2
|
<div>
|
3
3
|
<table style="display:none" id="ignored_table">
|
4
|
-
<
|
5
|
-
<
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
4
|
+
<thead>
|
5
|
+
<tr>
|
6
|
+
<th>Confidence</th>
|
7
|
+
<th>File</th>
|
8
|
+
<th>Warning Type</th>
|
9
|
+
<th>Message</th>
|
10
|
+
<th>Note</th>
|
11
|
+
</tr>
|
12
|
+
</thead>
|
13
|
+
<tbody>
|
11
14
|
<% warnings.each do |warning| %>
|
12
15
|
<tr>
|
13
16
|
<td><%= warning['Confidence']%></td>
|
@@ -17,5 +20,6 @@
|
|
17
20
|
<td><%= warning['Note']%></td>
|
18
21
|
</tr>
|
19
22
|
<% end %>
|
23
|
+
</tbody>
|
20
24
|
</table>
|
21
25
|
</div>
|
@@ -1,17 +1,21 @@
|
|
1
1
|
<p>Model Warnings</p>
|
2
2
|
<table>
|
3
|
-
<
|
4
|
-
<
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
<
|
14
|
-
|
15
|
-
|
16
|
-
|
3
|
+
<thead>
|
4
|
+
<tr>
|
5
|
+
<th>Confidence</th>
|
6
|
+
<th>Model</th>
|
7
|
+
<th>Warning Type</th>
|
8
|
+
<th>Message</th>
|
9
|
+
</tr>
|
10
|
+
</thead>
|
11
|
+
<tbody>
|
12
|
+
<% warnings.each do |warning| %>
|
13
|
+
<tr>
|
14
|
+
<td><%= warning['Confidence']%></td>
|
15
|
+
<td><%= warning['Model']%></td>
|
16
|
+
<td><%= warning['Warning Type']%></td>
|
17
|
+
<td><%= warning['Message']%></td>
|
18
|
+
</tr>
|
19
|
+
<% end %>
|
20
|
+
</tbody>
|
17
21
|
</table>
|