brakeman 3.1.1 → 3.1.2
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.
- 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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4d7d20b349b33016522595eb63c5ef4cc0e257fa
|
4
|
+
data.tar.gz: 9dd081fae534c5ffb2f42f63178cdba9b912a27d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 889ad360ae4655bfff280157ca45ff548945fa8f3cf6f6d03333f0e04ac107d3489015cd0d837ecb0b0f8ea55fd985243f7d57e87d99d15c0ca76f8d0647ac81
|
7
|
+
data.tar.gz: a45beea309a50f727dc2a3d25628b89f5344126d8fc5231ca219fab4e4d601dbaee871bc8008aad006895a221415715ea5b5063bc00c01dedcb65ab012fb14b1
|
data/CHANGES
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
# 3.1.2
|
2
|
+
|
3
|
+
* Treat `current_user` like a model
|
4
|
+
* Set user input value for inline renders
|
5
|
+
* Avoid warning on inline renders with safe content types
|
6
|
+
* Handle empty interpolation in HAML filters
|
7
|
+
* Ignore filters that are not method names
|
8
|
+
* Avoid warning about model find/find_by* in hrefs
|
9
|
+
* Use SafeYAML to load configuration files
|
10
|
+
* Warn on SQL query keys, not values in hashes
|
11
|
+
* Allow inspection of recursive Sexps
|
12
|
+
* Add line numbers to class-level warnings
|
13
|
+
* Handle `private def ...`
|
14
|
+
* Catch divide-by-zero in alias processing
|
15
|
+
* Reduce string allocations in Warning#initialize
|
16
|
+
* Sortable tables in HTML report (David Lanner)
|
17
|
+
* Search for config file relative to application root
|
18
|
+
|
1
19
|
# 3.1.1
|
2
20
|
|
3
21
|
* Add optional check for use of MD5 and SHA1
|
data/lib/brakeman.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
require '
|
2
|
+
require 'safe_yaml/load'
|
3
3
|
require 'set'
|
4
4
|
|
5
5
|
module Brakeman
|
@@ -73,7 +73,7 @@ module Brakeman
|
|
73
73
|
options.delete :quiet
|
74
74
|
end
|
75
75
|
|
76
|
-
options = default_options.merge(load_options(options
|
76
|
+
options = default_options.merge(load_options(options)).merge(options)
|
77
77
|
|
78
78
|
if options[:quiet].nil? and not command_line
|
79
79
|
options[:quiet] = true
|
@@ -85,17 +85,15 @@ module Brakeman
|
|
85
85
|
options
|
86
86
|
end
|
87
87
|
|
88
|
-
CONFIG_FILES = [
|
89
|
-
File.expand_path("./config/brakeman.yml"),
|
90
|
-
File.expand_path("~/.brakeman/config.yml"),
|
91
|
-
File.expand_path("/etc/brakeman/config.yml")
|
92
|
-
]
|
93
|
-
|
94
88
|
#Load options from YAML file
|
95
|
-
def self.load_options
|
89
|
+
def self.load_options line_options
|
90
|
+
custom_location = line_options[:config_file]
|
91
|
+
quiet = line_options[:quiet]
|
92
|
+
app_path = line_options[:app_path]
|
93
|
+
|
96
94
|
#Load configuration file
|
97
|
-
if config = config_file(custom_location)
|
98
|
-
options =
|
95
|
+
if config = config_file(custom_location, app_path)
|
96
|
+
options = SafeYAML.load_file config, :deserialize_symbols => true
|
99
97
|
|
100
98
|
if options
|
101
99
|
options.each { |k, v| options[k] = Set.new v if v.is_a? Array }
|
@@ -115,8 +113,14 @@ module Brakeman
|
|
115
113
|
end
|
116
114
|
end
|
117
115
|
|
118
|
-
|
119
|
-
|
116
|
+
CONFIG_FILES = [
|
117
|
+
File.expand_path("~/.brakeman/config.yml"),
|
118
|
+
File.expand_path("/etc/brakeman/config.yml")
|
119
|
+
]
|
120
|
+
|
121
|
+
def self.config_file custom_location, app_path
|
122
|
+
app_config = File.expand_path(File.join(app_path, "config", "brakeman.yml"))
|
123
|
+
supported_locations = [File.expand_path(custom_location || ""), app_config] + CONFIG_FILES
|
120
124
|
supported_locations.detect {|f| File.file?(f) }
|
121
125
|
end
|
122
126
|
|
@@ -102,7 +102,7 @@ class Brakeman::CheckContentTag < Brakeman::CheckCrossSiteScripting
|
|
102
102
|
:warning_type => "Cross Site Scripting",
|
103
103
|
:warning_code => :xss_content_tag,
|
104
104
|
:message => message,
|
105
|
-
:user_input => input
|
105
|
+
:user_input => input,
|
106
106
|
:confidence => CONFIDENCE[:high],
|
107
107
|
:link_path => "content_tag"
|
108
108
|
|
@@ -136,7 +136,7 @@ class Brakeman::CheckContentTag < Brakeman::CheckCrossSiteScripting
|
|
136
136
|
:warning_type => "Cross Site Scripting",
|
137
137
|
:warning_code => :xss_content_tag,
|
138
138
|
:message => message,
|
139
|
-
:user_input => @matched
|
139
|
+
:user_input => @matched,
|
140
140
|
:confidence => CONFIDENCE[:med],
|
141
141
|
:link_path => "content_tag"
|
142
142
|
end
|
@@ -199,7 +199,7 @@ class Brakeman::CheckCrossSiteScripting < Brakeman::BaseCheck
|
|
199
199
|
:warning_code => warning_code,
|
200
200
|
:message => message,
|
201
201
|
:code => exp,
|
202
|
-
:user_input => @matched
|
202
|
+
:user_input => @matched,
|
203
203
|
:confidence => confidence,
|
204
204
|
:link_path => link_path
|
205
205
|
end
|
@@ -340,7 +340,7 @@ class Brakeman::CheckCrossSiteScripting < Brakeman::BaseCheck
|
|
340
340
|
def ignore_call? target, method
|
341
341
|
ignored_method?(target, method) or
|
342
342
|
safe_input_attribute?(target, method) or
|
343
|
-
ignored_model_method?(method) or
|
343
|
+
ignored_model_method?(target, method) or
|
344
344
|
form_builder_method?(target, method) or
|
345
345
|
haml_escaped?(target, method) or
|
346
346
|
boolean_method?(method) or
|
@@ -348,10 +348,10 @@ class Brakeman::CheckCrossSiteScripting < Brakeman::BaseCheck
|
|
348
348
|
xml_escaped?(target, method)
|
349
349
|
end
|
350
350
|
|
351
|
-
def ignored_model_method? method
|
352
|
-
@matched and
|
353
|
-
|
354
|
-
|
351
|
+
def ignored_model_method? target, method
|
352
|
+
((@matched and @matched.type == :model) or
|
353
|
+
model_name? target) and
|
354
|
+
IGNORE_MODEL_METHODS.include? method
|
355
355
|
end
|
356
356
|
|
357
357
|
def ignored_method? target, method
|
@@ -49,7 +49,7 @@ class Brakeman::CheckDeserialize < Brakeman::BaseCheck
|
|
49
49
|
:warning_type => "Remote Code Execution",
|
50
50
|
:warning_code => :unsafe_deserialize,
|
51
51
|
:message => message,
|
52
|
-
:user_input => input
|
52
|
+
:user_input => input,
|
53
53
|
:confidence => confidence,
|
54
54
|
:link_path => "unsafe_deserialization"
|
55
55
|
end
|
@@ -63,7 +63,7 @@ class Brakeman::CheckExecute < Brakeman::BaseCheck
|
|
63
63
|
:warning_code => :command_injection,
|
64
64
|
:message => "Possible command injection",
|
65
65
|
:code => call,
|
66
|
-
:user_input => failure
|
66
|
+
:user_input => failure,
|
67
67
|
:confidence => confidence
|
68
68
|
end
|
69
69
|
end
|
@@ -75,7 +75,7 @@ class Brakeman::CheckExecute < Brakeman::BaseCheck
|
|
75
75
|
:warning_type => "Command Injection",
|
76
76
|
:warning_code => :command_injection,
|
77
77
|
:message => "Possible command injection in open()",
|
78
|
-
:user_input => match
|
78
|
+
:user_input => match,
|
79
79
|
:confidence => CONFIDENCE[:high]
|
80
80
|
end
|
81
81
|
end
|
@@ -111,10 +111,8 @@ class Brakeman::CheckExecute < Brakeman::BaseCheck
|
|
111
111
|
|
112
112
|
if input = include_user_input?(exp)
|
113
113
|
confidence = CONFIDENCE[:high]
|
114
|
-
user_input = input.match
|
115
114
|
elsif input = dangerous?(exp)
|
116
115
|
confidence = CONFIDENCE[:med]
|
117
|
-
user_input = input
|
118
116
|
else
|
119
117
|
return
|
120
118
|
end
|
@@ -124,7 +122,7 @@ class Brakeman::CheckExecute < Brakeman::BaseCheck
|
|
124
122
|
:warning_code => :command_injection,
|
125
123
|
:message => "Possible command injection",
|
126
124
|
:code => exp,
|
127
|
-
:user_input =>
|
125
|
+
:user_input => input,
|
128
126
|
:confidence => confidence
|
129
127
|
end
|
130
128
|
|
@@ -28,7 +28,8 @@ class Brakeman::CheckForgerySetting < Brakeman::BaseCheck
|
|
28
28
|
:warning_code => :csrf_protection_missing,
|
29
29
|
:message => "'protect_from_forgery' should be called in ApplicationController",
|
30
30
|
:confidence => CONFIDENCE[:high],
|
31
|
-
:file => app_controller.file
|
31
|
+
:file => app_controller.file,
|
32
|
+
:line => app_controller.top_line
|
32
33
|
|
33
34
|
elsif version_between? "2.1.0", "2.3.10"
|
34
35
|
|
@@ -70,7 +70,7 @@ class Brakeman::CheckLinkTo < Brakeman::CheckCrossSiteScripting
|
|
70
70
|
|
71
71
|
message = "Unescaped #{friendly_type_of input} in link_to"
|
72
72
|
|
73
|
-
warn_xss(result, message, input
|
73
|
+
warn_xss(result, message, input, CONFIDENCE[:high])
|
74
74
|
end
|
75
75
|
|
76
76
|
# Check if we should warn about the specified method
|
@@ -93,7 +93,7 @@ class Brakeman::CheckLinkTo < Brakeman::CheckCrossSiteScripting
|
|
93
93
|
|
94
94
|
message = "Unescaped #{friendly_type_of matched} in link_to"
|
95
95
|
|
96
|
-
warn_xss(result, message, @matched
|
96
|
+
warn_xss(result, message, @matched, CONFIDENCE[:med])
|
97
97
|
end
|
98
98
|
|
99
99
|
# Create a warn for this xss
|
@@ -51,11 +51,11 @@ class Brakeman::CheckLinkToHref < Brakeman::CheckLinkTo
|
|
51
51
|
:warning_type => "Cross Site Scripting",
|
52
52
|
:warning_code => :xss_link_to_href,
|
53
53
|
:message => message,
|
54
|
-
:user_input => input
|
54
|
+
:user_input => input,
|
55
55
|
:confidence => CONFIDENCE[:high],
|
56
56
|
:link_path => "link_to_href"
|
57
57
|
end
|
58
|
-
elsif has_immediate_model? url_arg
|
58
|
+
elsif has_immediate_model? url_arg or model_find_call? url_arg
|
59
59
|
|
60
60
|
# Decided NOT warn on models. polymorphic_path is called it a model is
|
61
61
|
# passed to link_to (which passes it to url_for)
|
@@ -84,7 +84,7 @@ class Brakeman::CheckLinkToHref < Brakeman::CheckLinkTo
|
|
84
84
|
:warning_type => "Cross Site Scripting",
|
85
85
|
:warning_code => :xss_link_to_href,
|
86
86
|
:message => message,
|
87
|
-
:user_input => @matched
|
87
|
+
:user_input => @matched,
|
88
88
|
:confidence => CONFIDENCE[:med],
|
89
89
|
:link_path => "link_to_href"
|
90
90
|
end
|
@@ -105,4 +105,11 @@ class Brakeman::CheckLinkToHref < Brakeman::CheckLinkTo
|
|
105
105
|
method.to_s =~ /_path$/ or
|
106
106
|
(target.nil? and method.to_s =~ /_url$/)
|
107
107
|
end
|
108
|
+
|
109
|
+
def model_find_call? exp
|
110
|
+
return unless call? exp
|
111
|
+
|
112
|
+
MODEL_METHODS.include? exp.method or
|
113
|
+
exp.method.to_s =~ /^find_by_/
|
114
|
+
end
|
108
115
|
end
|
@@ -80,16 +80,14 @@ class Brakeman::CheckMassAssignment < Brakeman::BaseCheck
|
|
80
80
|
else
|
81
81
|
confidence = CONFIDENCE[:high]
|
82
82
|
end
|
83
|
-
user_input = input.match
|
84
83
|
else
|
85
84
|
confidence = CONFIDENCE[:low]
|
86
|
-
user_input = input.match
|
87
85
|
end
|
88
86
|
elsif node_type? call.first_arg, :lit, :str
|
89
87
|
return
|
90
88
|
else
|
91
89
|
confidence = CONFIDENCE[:low]
|
92
|
-
|
90
|
+
input = nil
|
93
91
|
end
|
94
92
|
|
95
93
|
warn :result => res,
|
@@ -97,7 +95,7 @@ class Brakeman::CheckMassAssignment < Brakeman::BaseCheck
|
|
97
95
|
:warning_code => :mass_assign_call,
|
98
96
|
:message => "Unprotected mass assignment",
|
99
97
|
:code => call,
|
100
|
-
:user_input =>
|
98
|
+
:user_input => input,
|
101
99
|
:confidence => confidence
|
102
100
|
end
|
103
101
|
|
@@ -56,6 +56,7 @@ class Brakeman::CheckModelAttributes < Brakeman::BaseCheck
|
|
56
56
|
if model.attr_protected.nil?
|
57
57
|
warn :model => name,
|
58
58
|
:file => model.file,
|
59
|
+
:line => model.top_line,
|
59
60
|
:warning_type => "Attribute Restriction",
|
60
61
|
:warning_code => :no_attr_accessible,
|
61
62
|
:message => "Mass assignment is not restricted using attr_accessible",
|
@@ -60,7 +60,8 @@ class Brakeman::CheckModelSerialize < Brakeman::BaseCheck
|
|
60
60
|
:message => "Serialized attributes are vulnerable in Rails #{rails_version}, upgrade to #{@upgrade_version} or patch.",
|
61
61
|
:confidence => confidence,
|
62
62
|
:link => "https://groups.google.com/d/topic/rubyonrails-security/KtmwSbEpzrU/discussion",
|
63
|
-
:file => model.file
|
63
|
+
:file => model.file,
|
64
|
+
:line => model.top_line
|
64
65
|
end
|
65
66
|
end
|
66
67
|
end
|
@@ -50,7 +50,6 @@ class Brakeman::CheckNumberToCurrency < Brakeman::BaseCheck
|
|
50
50
|
|
51
51
|
def check_helper_option result, exp
|
52
52
|
if match = (has_immediate_user_input? exp or has_immediate_model? exp)
|
53
|
-
match = match.match if match.is_a? Match
|
54
53
|
warn_on_number_helper result, match
|
55
54
|
@found_any = true
|
56
55
|
else
|
@@ -20,23 +20,35 @@ class Brakeman::CheckRenderInline < Brakeman::CheckCrossSiteScripting
|
|
20
20
|
if node_type? call, :render and
|
21
21
|
(call.render_type == :text or call.render_type == :inline)
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
:
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
:
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
23
|
+
unless call.render_type == :text and content_type_set? call[3]
|
24
|
+
render_value = call[2]
|
25
|
+
|
26
|
+
if input = has_immediate_user_input?(render_value)
|
27
|
+
warn :result => result,
|
28
|
+
:warning_type => "Cross Site Scripting",
|
29
|
+
:warning_code => :cross_site_scripting_inline,
|
30
|
+
:message => "Unescaped #{friendly_type_of input} rendered inline",
|
31
|
+
:user_input => input,
|
32
|
+
:confidence => CONFIDENCE[:high]
|
33
|
+
elsif input = has_immediate_model?(render_value)
|
34
|
+
warn :result => result,
|
35
|
+
:warning_type => "Cross Site Scripting",
|
36
|
+
:warning_code => :cross_site_scripting_inline,
|
37
|
+
:message => "Unescaped model attribute rendered inline",
|
38
|
+
:user_input => input,
|
39
|
+
:confidence => CONFIDENCE[:med]
|
40
|
+
end
|
39
41
|
end
|
40
42
|
end
|
41
43
|
end
|
44
|
+
|
45
|
+
CONTENT_TYPES = ["text/html", "text/javascript", "application/javascript"]
|
46
|
+
|
47
|
+
def content_type_set? opts
|
48
|
+
if hash? opts
|
49
|
+
content_type = hash_access(opts, :content_type)
|
50
|
+
|
51
|
+
string? content_type and not CONTENT_TYPES.include? content_type.value
|
52
|
+
end
|
53
|
+
end
|
42
54
|
end
|
@@ -52,7 +52,7 @@ class Brakeman::CheckSelectTag < Brakeman::BaseCheck
|
|
52
52
|
:result => result,
|
53
53
|
:message => @message,
|
54
54
|
:confidence => CONFIDENCE[:high],
|
55
|
-
:user_input => input
|
55
|
+
:user_input => input,
|
56
56
|
:link_path => "https://groups.google.com/d/topic/rubyonrails-security/fV3QUToSMSw/discussion"
|
57
57
|
end
|
58
58
|
end
|
@@ -30,7 +30,7 @@ class Brakeman::CheckSend < Brakeman::BaseCheck
|
|
30
30
|
:warning_code => :dangerous_send,
|
31
31
|
:message => "User controlled method execution",
|
32
32
|
:code => result[:call],
|
33
|
-
:user_input => input
|
33
|
+
:user_input => input,
|
34
34
|
:confidence => CONFIDENCE[:high]
|
35
35
|
end
|
36
36
|
end
|
@@ -29,7 +29,7 @@ class Brakeman::CheckSessionManipulation < Brakeman::BaseCheck
|
|
29
29
|
:warning_code => :session_key_manipulation,
|
30
30
|
:message => "#{friendly_type_of(input).capitalize} used as key in session hash",
|
31
31
|
:code => result[:call],
|
32
|
-
:user_input => input
|
32
|
+
:user_input => input,
|
33
33
|
:confidence => confidence
|
34
34
|
end
|
35
35
|
end
|