brakeman 1.2.2 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +2 -2
- data/lib/brakeman.rb +3 -1
- data/lib/brakeman/checks/base_check.rb +10 -2
- data/lib/brakeman/checks/check_basic_auth.rb +2 -0
- data/lib/brakeman/checks/check_cross_site_scripting.rb +4 -0
- data/lib/brakeman/checks/check_default_routes.rb +2 -0
- data/lib/brakeman/checks/check_escape_function.rb +2 -0
- data/lib/brakeman/checks/check_evaluation.rb +2 -0
- data/lib/brakeman/checks/check_execute.rb +2 -0
- data/lib/brakeman/checks/check_file_access.rb +2 -0
- data/lib/brakeman/checks/check_filter_skipping.rb +2 -0
- data/lib/brakeman/checks/check_forgery_setting.rb +2 -0
- data/lib/brakeman/checks/check_link_to.rb +2 -0
- data/lib/brakeman/checks/check_mail_to.rb +2 -0
- data/lib/brakeman/checks/check_mass_assignment.rb +10 -2
- data/lib/brakeman/checks/check_model_attributes.rb +47 -13
- data/lib/brakeman/checks/check_nested_attributes.rb +2 -0
- data/lib/brakeman/checks/check_quote_table_name.rb +2 -0
- data/lib/brakeman/checks/check_redirect.rb +2 -0
- data/lib/brakeman/checks/check_render.rb +2 -0
- data/lib/brakeman/checks/check_response_splitting.rb +2 -0
- data/lib/brakeman/checks/check_send_file.rb +2 -0
- data/lib/brakeman/checks/check_session_settings.rb +2 -0
- data/lib/brakeman/checks/check_sql.rb +42 -3
- data/lib/brakeman/checks/check_strip_tags.rb +2 -0
- data/lib/brakeman/checks/check_translate_bug.rb +2 -0
- data/lib/brakeman/checks/check_validation_regex.rb +2 -0
- data/lib/brakeman/checks/check_without_protection.rb +3 -1
- data/lib/brakeman/format/style.css +5 -0
- data/lib/brakeman/options.rb +13 -4
- data/lib/brakeman/processor.rb +2 -2
- data/lib/brakeman/processors/alias_processor.rb +65 -21
- data/lib/brakeman/processors/controller_alias_processor.rb +26 -8
- data/lib/brakeman/processors/lib/find_all_calls.rb +7 -1
- data/lib/brakeman/processors/lib/processor_helper.rb +2 -0
- data/lib/brakeman/processors/lib/rails3_config_processor.rb +1 -1
- data/lib/brakeman/processors/library_processor.rb +1 -1
- data/lib/brakeman/processors/output_processor.rb +3 -1
- data/lib/brakeman/report.rb +2 -1
- data/lib/brakeman/rescanner.rb +27 -4
- data/lib/brakeman/scanner.rb +21 -1
- data/lib/brakeman/tracker.rb +2 -1
- data/lib/brakeman/util.rb +5 -0
- data/lib/brakeman/version.rb +1 -1
- metadata +16 -8
data/README.md
CHANGED
@@ -12,7 +12,7 @@ For even more continuous testing, try the [Guard plugin](https://github.com/oreo
|
|
12
12
|
|
13
13
|
Website: http://brakemanscanner.org/
|
14
14
|
|
15
|
-
Twitter: http://twitter.com/
|
15
|
+
Twitter: http://twitter.com/brakeman
|
16
16
|
|
17
17
|
Mailing list: brakeman@librelist.com
|
18
18
|
|
@@ -89,7 +89,7 @@ If Brakeman is running a bit slow, try
|
|
89
89
|
|
90
90
|
This will disable some features, but will probably be much faster (currently it is the same as `--skip-libs --no-branching`). *WARNING*: This may cause Brakeman to miss some vulnerabilities.
|
91
91
|
|
92
|
-
By default, Brakeman will return 0 as an exit code unless something
|
92
|
+
By default, Brakeman will return 0 as an exit code unless something went very wrong. To return an error code when warnings were found:
|
93
93
|
|
94
94
|
brakeman -z
|
95
95
|
|
data/lib/brakeman.rb
CHANGED
@@ -162,7 +162,9 @@ module Brakeman
|
|
162
162
|
require 'brakeman/scanner'
|
163
163
|
$stderr.puts "Available Checks:"
|
164
164
|
$stderr.puts "-" * 30
|
165
|
-
$stderr.puts Checks.checks.map { |c|
|
165
|
+
$stderr.puts Checks.checks.map { |c|
|
166
|
+
c.to_s.match(/^Brakeman::(.*)$/)[1].ljust(27) << c.description
|
167
|
+
}.sort.join "\n"
|
166
168
|
end
|
167
169
|
|
168
170
|
#Installs Rake task for running Brakeman,
|
@@ -68,6 +68,8 @@ class Brakeman::BaseCheck < SexpProcessor
|
|
68
68
|
@has_user_input = :params
|
69
69
|
elsif cookies? exp[1]
|
70
70
|
@has_user_input = :cookies
|
71
|
+
elsif request_env? exp[1]
|
72
|
+
@has_user_input = :request
|
71
73
|
elsif sexp? exp[1] and model_name? exp[1][1]
|
72
74
|
@has_user_input = :model
|
73
75
|
end
|
@@ -103,13 +105,13 @@ class Brakeman::BaseCheck < SexpProcessor
|
|
103
105
|
end
|
104
106
|
|
105
107
|
#Checks if the model inherits from parent,
|
106
|
-
def parent?
|
108
|
+
def parent? model, parent
|
107
109
|
if model == nil
|
108
110
|
false
|
109
111
|
elsif model[:parent] == parent
|
110
112
|
true
|
111
113
|
elsif model[:parent]
|
112
|
-
parent? tracker
|
114
|
+
parent? tracker.models[model[:parent]], parent
|
113
115
|
else
|
114
116
|
false
|
115
117
|
end
|
@@ -209,6 +211,8 @@ class Brakeman::BaseCheck < SexpProcessor
|
|
209
211
|
return :params, exp
|
210
212
|
elsif cookies? exp[1]
|
211
213
|
return :cookies, exp
|
214
|
+
elsif request_env? exp[1]
|
215
|
+
return :request, exp
|
212
216
|
else
|
213
217
|
false
|
214
218
|
end
|
@@ -396,4 +400,8 @@ class Brakeman::BaseCheck < SexpProcessor
|
|
396
400
|
"config/environment.rb"
|
397
401
|
end
|
398
402
|
end
|
403
|
+
|
404
|
+
def self.description
|
405
|
+
@description
|
406
|
+
end
|
399
407
|
end
|
@@ -14,6 +14,8 @@ require 'set'
|
|
14
14
|
class Brakeman::CheckCrossSiteScripting < Brakeman::BaseCheck
|
15
15
|
Brakeman::Checks.add self
|
16
16
|
|
17
|
+
@description = "Checks for unescaped output in views"
|
18
|
+
|
17
19
|
#Model methods which are known to be harmless
|
18
20
|
IGNORE_MODEL_METHODS = Set.new([:average, :count, :maximum, :minimum, :sum])
|
19
21
|
|
@@ -84,6 +86,8 @@ class Brakeman::CheckCrossSiteScripting < Brakeman::BaseCheck
|
|
84
86
|
message = "Unescaped parameter value"
|
85
87
|
when :cookies
|
86
88
|
message = "Unescaped cookie value"
|
89
|
+
when :request
|
90
|
+
message = "Unescaped request value"
|
87
91
|
else
|
88
92
|
message = "Unescaped user input value"
|
89
93
|
end
|
@@ -4,6 +4,8 @@ require 'brakeman/checks/base_check'
|
|
4
4
|
class Brakeman::CheckDefaultRoutes < Brakeman::BaseCheck
|
5
5
|
Brakeman::Checks.add self
|
6
6
|
|
7
|
+
@description = "Checks for default routes"
|
8
|
+
|
7
9
|
#Checks for :allow_all_actions globally and for individual routes
|
8
10
|
#if it is not enabled globally.
|
9
11
|
def run_check
|
@@ -5,6 +5,8 @@ require 'brakeman/checks/base_check'
|
|
5
5
|
class Brakeman::CheckEscapeFunction < Brakeman::BaseCheck
|
6
6
|
Brakeman::Checks.add self
|
7
7
|
|
8
|
+
@description = "Checks for versions before 2.3.14 which have a vulnerable escape method"
|
9
|
+
|
8
10
|
def run_check
|
9
11
|
if version_between?('2.0.0', '2.3.13') and RUBY_VERSION < '1.9.0'
|
10
12
|
|
@@ -11,6 +11,8 @@ require 'brakeman/checks/base_check'
|
|
11
11
|
class Brakeman::CheckExecute < Brakeman::BaseCheck
|
12
12
|
Brakeman::Checks.add self
|
13
13
|
|
14
|
+
@description = "Finds instances of possible command injection"
|
15
|
+
|
14
16
|
#Check models, controllers, and views for command injection.
|
15
17
|
def run_check
|
16
18
|
Brakeman.debug "Finding system calls using ``"
|
@@ -5,6 +5,8 @@ require 'brakeman/processors/lib/processor_helper'
|
|
5
5
|
class Brakeman::CheckFileAccess < Brakeman::BaseCheck
|
6
6
|
Brakeman::Checks.add self
|
7
7
|
|
8
|
+
@description = "Finds possible file access using user input"
|
9
|
+
|
8
10
|
def run_check
|
9
11
|
Brakeman.debug "Finding possible file access"
|
10
12
|
methods = tracker.find_call :targets => [:Dir, :File, :IO, :Kernel, :"Net::FTP", :"Net::HTTP", :PStore, :Pathname, :Shell, :YAML], :methods => [:[], :chdir, :chroot, :delete, :entries, :foreach, :glob, :install, :lchmod, :lchown, :link, :load, :load_file, :makedirs, :move, :new, :open, :read, :read_lines, :rename, :rmdir, :safe_unlink, :symlink, :syscopy, :sysopen, :truncate, :unlink]
|
@@ -5,6 +5,8 @@ require 'brakeman/checks/base_check'
|
|
5
5
|
class Brakeman::CheckFilterSkipping < Brakeman::BaseCheck
|
6
6
|
Brakeman::Checks.add self
|
7
7
|
|
8
|
+
@description = "Checks for versions 3.0-3.0.9 which had a vulnerability in filters"
|
9
|
+
|
8
10
|
def run_check
|
9
11
|
if version_between?('3.0.0', '3.0.9') and uses_arbitrary_actions?
|
10
12
|
|
@@ -7,6 +7,8 @@ require 'brakeman/checks/base_check'
|
|
7
7
|
class Brakeman::CheckForgerySetting < Brakeman::BaseCheck
|
8
8
|
Brakeman::Checks.add self
|
9
9
|
|
10
|
+
@description = "Verifies that protect_from_forgery is enabled in ApplicationController"
|
11
|
+
|
10
12
|
def run_check
|
11
13
|
app_controller = tracker.controllers[:ApplicationController]
|
12
14
|
if tracker.config[:rails][:action_controller] and
|
@@ -7,6 +7,8 @@ require 'brakeman/checks/check_cross_site_scripting'
|
|
7
7
|
class Brakeman::CheckLinkTo < Brakeman::CheckCrossSiteScripting
|
8
8
|
Brakeman::Checks.add self
|
9
9
|
|
10
|
+
@description = "Checks for XSS in link_to in versions before 3.0"
|
11
|
+
|
10
12
|
def run_check
|
11
13
|
return unless version_between?("2.0.0", "2.9.9") and not tracker.config[:escape_html]
|
12
14
|
|
@@ -7,6 +7,8 @@ require 'brakeman/checks/base_check'
|
|
7
7
|
class Brakeman::CheckMailTo < Brakeman::BaseCheck
|
8
8
|
Brakeman::Checks.add self
|
9
9
|
|
10
|
+
@description = "Checks for mail_to XSS vulnerability in certain versions"
|
11
|
+
|
10
12
|
def run_check
|
11
13
|
if (version_between? "2.3.0", "2.3.10" or version_between? "3.0.0", "3.0.3") and result = mail_to_javascript?
|
12
14
|
message = "Vulnerability in mail_to using javascript encoding (CVE-2011-0446). Upgrade to Rails version "
|
@@ -7,12 +7,14 @@ require 'set'
|
|
7
7
|
class Brakeman::CheckMassAssignment < Brakeman::BaseCheck
|
8
8
|
Brakeman::Checks.add self
|
9
9
|
|
10
|
+
@description = "Finds instances of mass assignment"
|
11
|
+
|
10
12
|
def run_check
|
11
13
|
return if mass_assign_disabled?
|
12
14
|
|
13
15
|
models = []
|
14
16
|
tracker.models.each do |name, m|
|
15
|
-
if parent?(
|
17
|
+
if parent?(m, :"ActiveRecord::Base") and m[:attr_accessible].nil?
|
16
18
|
models << name
|
17
19
|
end
|
18
20
|
end
|
@@ -45,7 +47,13 @@ class Brakeman::CheckMassAssignment < Brakeman::BaseCheck
|
|
45
47
|
if check and not @results.include? call
|
46
48
|
@results << call
|
47
49
|
|
48
|
-
|
50
|
+
model = tracker.models[res[:chain].first]
|
51
|
+
|
52
|
+
attr_protected = (model and model[:options][:attr_protected])
|
53
|
+
|
54
|
+
if attr_protected and tracker.options[:ignore_attr_protected]
|
55
|
+
return
|
56
|
+
elsif include_user_input? call[3] and not hash? call[3][1] and not attr_protected
|
49
57
|
confidence = CONFIDENCE[:high]
|
50
58
|
else
|
51
59
|
confidence = CONFIDENCE[:low]
|
@@ -8,29 +8,63 @@ require 'brakeman/checks/base_check'
|
|
8
8
|
class Brakeman::CheckModelAttributes < Brakeman::BaseCheck
|
9
9
|
Brakeman::Checks.add self
|
10
10
|
|
11
|
+
@description = "Reports models which do not use attr_restricted and warns on models that use attr_protected"
|
12
|
+
|
11
13
|
def run_check
|
12
14
|
return if mass_assign_disabled?
|
13
15
|
|
14
|
-
|
16
|
+
#Roll warnings into one warning for all models
|
17
|
+
if tracker.options[:collapse_mass_assignment]
|
18
|
+
no_accessible_names = []
|
19
|
+
protected_names = []
|
15
20
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
21
|
+
check_models do |name, model|
|
22
|
+
if model[:options][:attr_protected].nil?
|
23
|
+
no_accessible_names << name.to_s
|
24
|
+
elsif not tracker.options[:ignore_attr_protected]
|
25
|
+
protected_names << name.to_s
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
unless no_accessible_names.empty?
|
30
|
+
warn :model => no_accessible_names.sort.join(", "),
|
31
|
+
:warning_type => "Attribute Restriction",
|
32
|
+
:message => "Mass assignment is not restricted using attr_accessible",
|
33
|
+
:confidence => CONFIDENCE[:high]
|
34
|
+
end
|
35
|
+
|
36
|
+
unless protected_names.empty?
|
37
|
+
warn :model => protected_names.sort.join(", "),
|
38
|
+
:warning_type => "Attribute Restriction",
|
39
|
+
:message => "attr_accessible is recommended over attr_protected",
|
40
|
+
:confidence => CONFIDENCE[:low]
|
41
|
+
end
|
42
|
+
else #Output one warning per model
|
43
|
+
|
44
|
+
check_models do |name, model|
|
45
|
+
if model[:options][:attr_protected].nil?
|
46
|
+
warn :model => name,
|
47
|
+
:file => model[:file],
|
22
48
|
:warning_type => "Attribute Restriction",
|
23
|
-
:message => "Mass assignment is not restricted using attr_accessible",
|
49
|
+
:message => "Mass assignment is not restricted using attr_accessible",
|
24
50
|
:confidence => CONFIDENCE[:high]
|
51
|
+
elsif not tracker.options[:ignore_attr_protected]
|
52
|
+
warn :model => name,
|
53
|
+
:file => model[:file],
|
54
|
+
:line => model[:options][:attr_protected].first.line,
|
55
|
+
:warning_type => "Attribute Restriction",
|
56
|
+
:message => "attr_accessible is recommended over attr_protected",
|
57
|
+
:confidence => CONFIDENCE[:low]
|
25
58
|
end
|
26
59
|
end
|
27
60
|
end
|
61
|
+
end
|
28
62
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
63
|
+
def check_models
|
64
|
+
tracker.models.each do |name, model|
|
65
|
+
if model[:attr_accessible].nil? and parent? model, :"ActiveRecord::Base"
|
66
|
+
yield name, model
|
67
|
+
end
|
34
68
|
end
|
35
69
|
end
|
36
70
|
end
|
@@ -5,6 +5,8 @@ require 'brakeman/checks/base_check'
|
|
5
5
|
class Brakeman::CheckNestedAttributes < Brakeman::BaseCheck
|
6
6
|
Brakeman::Checks.add self
|
7
7
|
|
8
|
+
@description = "Checks for nested attributes vulnerability in Rails 2.3.9 and 3.0.0"
|
9
|
+
|
8
10
|
def run_check
|
9
11
|
version = tracker.config[:rails_version]
|
10
12
|
|
@@ -5,6 +5,8 @@ require 'brakeman/checks/base_check'
|
|
5
5
|
class Brakeman::CheckQuoteTableName < Brakeman::BaseCheck
|
6
6
|
Brakeman::Checks.add self
|
7
7
|
|
8
|
+
@description = "Checks for quote_table_name vulnerability in versions before 2.3.14 and 3.0.10"
|
9
|
+
|
8
10
|
def run_check
|
9
11
|
if (version_between?('2.0.0', '2.3.13') or
|
10
12
|
version_between?('3.0.0', '3.0.9'))
|
@@ -8,6 +8,8 @@ require 'brakeman/checks/base_check'
|
|
8
8
|
class Brakeman::CheckRedirect < Brakeman::BaseCheck
|
9
9
|
Brakeman::Checks.add self
|
10
10
|
|
11
|
+
@description = "Looks for calls to redirect_to with user input as arguments"
|
12
|
+
|
11
13
|
def run_check
|
12
14
|
Brakeman.debug "Finding calls to redirect_to()"
|
13
15
|
|
@@ -4,6 +4,8 @@ require 'brakeman/checks/base_check'
|
|
4
4
|
class Brakeman::CheckRender < Brakeman::BaseCheck
|
5
5
|
Brakeman::Checks.add self
|
6
6
|
|
7
|
+
@description = "Finds calls to render that might allow file access"
|
8
|
+
|
7
9
|
def run_check
|
8
10
|
tracker.find_call(:target => nil, :method => :render).each do |result|
|
9
11
|
process_render result
|
@@ -5,6 +5,8 @@ require 'brakeman/processors/lib/processor_helper'
|
|
5
5
|
class Brakeman::CheckSendFile < Brakeman::CheckFileAccess
|
6
6
|
Brakeman::Checks.add self
|
7
7
|
|
8
|
+
@description = "Check for user input in uses of send_file"
|
9
|
+
|
8
10
|
def run_check
|
9
11
|
Brakeman.debug "Finding all calls to send_file()"
|
10
12
|
|
@@ -11,6 +11,8 @@ require 'brakeman/checks/base_check'
|
|
11
11
|
class Brakeman::CheckSQL < Brakeman::BaseCheck
|
12
12
|
Brakeman::Checks.add self
|
13
13
|
|
14
|
+
@description = "Check for SQL injection"
|
15
|
+
|
14
16
|
def run_check
|
15
17
|
@rails_version = tracker.config[:rails_version]
|
16
18
|
|
@@ -49,7 +51,7 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
|
|
49
51
|
if model[:options][:named_scope]
|
50
52
|
model[:options][:named_scope].each do |args|
|
51
53
|
call = Sexp.new(:call, nil, :named_scope, args).line(args.line)
|
52
|
-
scope_calls << { :call => call, :location => [:class, name ] }
|
54
|
+
scope_calls << { :call => call, :location => [:class, name ], :method => :named_scope }
|
53
55
|
end
|
54
56
|
end
|
55
57
|
end
|
@@ -57,8 +59,18 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
|
|
57
59
|
tracker.models.each do |name, model|
|
58
60
|
if model[:options][:scope]
|
59
61
|
model[:options][:scope].each do |args|
|
60
|
-
|
61
|
-
|
62
|
+
second_arg = args[2]
|
63
|
+
|
64
|
+
if second_arg.node_type == :iter and
|
65
|
+
(second_arg[-1].node_type == :block or second_arg[-1].node_type == :call)
|
66
|
+
process_scope_with_block name, args
|
67
|
+
elsif second_arg.node_type == :call
|
68
|
+
call = second_arg
|
69
|
+
scope_calls << { :call => call, :location => [:class, name ], :method => call[2] }
|
70
|
+
else
|
71
|
+
call = Sexp.new(:call, nil, :scope, args).line(args.line)
|
72
|
+
scope_calls << { :call => call, :location => [:class, name ], :method => :scope }
|
73
|
+
end
|
62
74
|
end
|
63
75
|
end
|
64
76
|
end
|
@@ -67,8 +79,32 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
|
|
67
79
|
scope_calls
|
68
80
|
end
|
69
81
|
|
82
|
+
def process_scope_with_block model_name, args
|
83
|
+
scope_name = args[1][1]
|
84
|
+
block = args[-1][-1]
|
85
|
+
|
86
|
+
#Search lambda for calls to query methods
|
87
|
+
if block.node_type == :block
|
88
|
+
find_calls = Brakeman::FindAllCalls.new tracker
|
89
|
+
|
90
|
+
find_calls.process_source block, model_name, scope_name
|
91
|
+
|
92
|
+
find_calls.calls.each do |call|
|
93
|
+
if call[:method].to_s =~ /^(find.*|first|last|all|where|order|group|having)$/
|
94
|
+
puts "Looks like #{call.inspect}"
|
95
|
+
process_result call
|
96
|
+
end
|
97
|
+
end
|
98
|
+
elsif block.node_type == :call
|
99
|
+
process_result :target => block[1], :method => block[2], :call => block, :location => [:class, model_name, scope_name]
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
70
103
|
#Process result from Tracker#find_call.
|
71
104
|
def process_result result
|
105
|
+
#TODO: I don't like this method at all. It's a pain to figure out what
|
106
|
+
#it is actually doing...
|
107
|
+
|
72
108
|
call = result[:call]
|
73
109
|
|
74
110
|
args = call[3]
|
@@ -77,6 +113,9 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
|
|
77
113
|
failed = check_arguments args[1]
|
78
114
|
elsif call[2].to_s =~ /^find/
|
79
115
|
failed = (args.length > 2 and check_arguments args[-1])
|
116
|
+
elsif tracker.options[:rails3] and result[:method] != :scope
|
117
|
+
#This is for things like where("query = ?")
|
118
|
+
failed = check_arguments args[1]
|
80
119
|
else
|
81
120
|
failed = (args.length > 1 and check_arguments args[-1])
|
82
121
|
end
|
@@ -5,6 +5,8 @@ require 'brakeman/checks/base_check'
|
|
5
5
|
class Brakeman::CheckStripTags < Brakeman::BaseCheck
|
6
6
|
Brakeman::Checks.add self
|
7
7
|
|
8
|
+
@description = "Report strip_tags vulnerability in versions before 2.3.13 and 3.0.10"
|
9
|
+
|
8
10
|
def run_check
|
9
11
|
if (version_between?('2.0.0', '2.3.12') or
|
10
12
|
version_between?('3.0.0', '3.0.9')) and uses_strip_tags?
|
@@ -5,6 +5,8 @@ require 'brakeman/checks/base_check'
|
|
5
5
|
class Brakeman::CheckTranslateBug < Brakeman::BaseCheck
|
6
6
|
Brakeman::Checks.add self
|
7
7
|
|
8
|
+
@description = "Report XSS vulnerability in translate helper"
|
9
|
+
|
8
10
|
def run_check
|
9
11
|
if (version_between?('2.3.0', '2.3.99') and tracker.config[:escape_html]) or
|
10
12
|
version_between?('3.0.0', '3.0.10') or
|
@@ -10,6 +10,8 @@ require 'brakeman/checks/base_check'
|
|
10
10
|
class Brakeman::CheckValidationRegex < Brakeman::BaseCheck
|
11
11
|
Brakeman::Checks.add self
|
12
12
|
|
13
|
+
@description = "Report uses of validates_format_of with improper anchors"
|
14
|
+
|
13
15
|
WITH = Sexp.new(:lit, :with)
|
14
16
|
|
15
17
|
def run_check
|
@@ -7,6 +7,8 @@ require 'brakeman/checks/base_check'
|
|
7
7
|
class Brakeman::CheckWithoutProtection < Brakeman::BaseCheck
|
8
8
|
Brakeman::Checks.add self
|
9
9
|
|
10
|
+
@description = "Check for mass assignment using without_protection"
|
11
|
+
|
10
12
|
def run_check
|
11
13
|
if version_between? "0.0.0", "3.0.99"
|
12
14
|
return
|
@@ -14,7 +16,7 @@ class Brakeman::CheckWithoutProtection < Brakeman::BaseCheck
|
|
14
16
|
|
15
17
|
models = []
|
16
18
|
tracker.models.each do |name, m|
|
17
|
-
if parent?
|
19
|
+
if parent? m, :"ActiveRecord::Base"
|
18
20
|
models << name
|
19
21
|
end
|
20
22
|
end
|
data/lib/brakeman/options.rb
CHANGED
@@ -54,10 +54,6 @@ module Brakeman::Options
|
|
54
54
|
options[:assume_all_routes] = true
|
55
55
|
end
|
56
56
|
|
57
|
-
opts.on "--ignore-model-output", "Consider model attributes XSS-safe" do
|
58
|
-
options[:ignore_model_output] = true
|
59
|
-
end
|
60
|
-
|
61
57
|
opts.on "-e", "--escape-html", "Escape HTML by default" do
|
62
58
|
options[:escape_html] = true
|
63
59
|
end
|
@@ -67,6 +63,14 @@ module Brakeman::Options
|
|
67
63
|
options[:skip_libs] = true
|
68
64
|
end
|
69
65
|
|
66
|
+
opts.on "--ignore-model-output", "Consider model attributes XSS-safe" do
|
67
|
+
options[:ignore_model_output] = true
|
68
|
+
end
|
69
|
+
|
70
|
+
opts.on "--ignore-protected", "Consider models with attr_protected safe" do
|
71
|
+
options[:ignore_attr_protected] = true
|
72
|
+
end
|
73
|
+
|
70
74
|
opts.on "--no-branching", "Disable flow sensitivity on conditionals" do
|
71
75
|
options[:ignore_ifs] = true
|
72
76
|
end
|
@@ -80,6 +84,11 @@ module Brakeman::Options
|
|
80
84
|
options[:safe_methods].merge methods.map {|e| e.to_sym }
|
81
85
|
end
|
82
86
|
|
87
|
+
opts.on "--skip-files file1,file2,etc", Array, "Skip processing of these files" do |files|
|
88
|
+
options[:skip_files] ||= Set.new
|
89
|
+
options[:skip_files].merge files.map {|f| f.to_sym }
|
90
|
+
end
|
91
|
+
|
83
92
|
opts.on "--skip-libs", "Skip processing lib directory" do
|
84
93
|
options[:skip_libs] = true
|
85
94
|
end
|
data/lib/brakeman/processor.rb
CHANGED
@@ -47,7 +47,7 @@ module Brakeman
|
|
47
47
|
#Process a model source
|
48
48
|
def process_model src, file_name
|
49
49
|
result = ModelProcessor.new(@tracker).process_model src, file_name
|
50
|
-
AliasProcessor.new.process result
|
50
|
+
AliasProcessor.new(@tracker).process result
|
51
51
|
end
|
52
52
|
|
53
53
|
#Process either an ERB or HAML template
|
@@ -81,7 +81,7 @@ module Brakeman
|
|
81
81
|
#Process source for initializing files
|
82
82
|
def process_initializer name, src
|
83
83
|
res = BaseProcessor.new(@tracker).process src
|
84
|
-
res = AliasProcessor.new.process res
|
84
|
+
res = AliasProcessor.new(@tracker).process res
|
85
85
|
@tracker.initializers[Pathname.new(name).basename.to_s] = res
|
86
86
|
end
|
87
87
|
|
@@ -17,7 +17,7 @@ class Brakeman::AliasProcessor < SexpProcessor
|
|
17
17
|
#The recommended usage is:
|
18
18
|
#
|
19
19
|
# AliasProcessor.new.process_safely src
|
20
|
-
def initialize
|
20
|
+
def initialize tracker = nil
|
21
21
|
super()
|
22
22
|
self.strict = false
|
23
23
|
self.auto_shift_type = false
|
@@ -27,7 +27,8 @@ class Brakeman::AliasProcessor < SexpProcessor
|
|
27
27
|
@env = SexpProcessor::Environment.new
|
28
28
|
@inside_if = false
|
29
29
|
@ignore_ifs = false
|
30
|
-
@
|
30
|
+
@exp_context = []
|
31
|
+
@tracker = tracker #set in subclass as necessary
|
31
32
|
set_env_defaults
|
32
33
|
end
|
33
34
|
|
@@ -71,9 +72,12 @@ class Brakeman::AliasProcessor < SexpProcessor
|
|
71
72
|
#Process a Sexp. If the Sexp has a value associated with it in the
|
72
73
|
#environment, that value will be returned.
|
73
74
|
def process_default exp
|
75
|
+
@exp_context.push exp
|
76
|
+
|
74
77
|
begin
|
75
|
-
type = exp.shift
|
76
78
|
exp.each_with_index do |e, i|
|
79
|
+
next if i == 0
|
80
|
+
|
77
81
|
if sexp? e and not e.empty?
|
78
82
|
exp[i] = process e
|
79
83
|
else
|
@@ -82,18 +86,18 @@ class Brakeman::AliasProcessor < SexpProcessor
|
|
82
86
|
end
|
83
87
|
rescue Exception => err
|
84
88
|
@tracker.error err if @tracker
|
85
|
-
ensure
|
86
|
-
#The type must be put back on, or else later processing
|
87
|
-
#will trip up on it
|
88
|
-
exp.unshift type
|
89
89
|
end
|
90
90
|
|
91
91
|
#Generic replace
|
92
|
-
if replacement = env[exp]
|
93
|
-
set_line replacement.deep_clone, exp.line
|
92
|
+
if replacement = env[exp] and not duplicate? replacement
|
93
|
+
result = set_line replacement.deep_clone, exp.line
|
94
94
|
else
|
95
|
-
exp
|
95
|
+
result = exp
|
96
96
|
end
|
97
|
+
|
98
|
+
@exp_context.pop
|
99
|
+
|
100
|
+
result
|
97
101
|
end
|
98
102
|
|
99
103
|
#Process a method call.
|
@@ -102,7 +106,9 @@ class Brakeman::AliasProcessor < SexpProcessor
|
|
102
106
|
exp = process_default exp
|
103
107
|
|
104
108
|
#In case it is replaced with something else
|
105
|
-
|
109
|
+
unless call? exp
|
110
|
+
return exp
|
111
|
+
end
|
106
112
|
|
107
113
|
target = exp[1]
|
108
114
|
method = exp[2]
|
@@ -116,12 +122,24 @@ class Brakeman::AliasProcessor < SexpProcessor
|
|
116
122
|
joined = join_arrays target, args[1]
|
117
123
|
joined.line(exp.line)
|
118
124
|
exp = joined
|
119
|
-
elsif string?
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
+
elsif string? args[1]
|
126
|
+
if string? target # "blah" + "blah"
|
127
|
+
joined = join_strings target, args[1]
|
128
|
+
joined.line(exp.line)
|
129
|
+
exp = joined
|
130
|
+
elsif call? target and target[2] == :+ and string? target[3][1]
|
131
|
+
joined = join_strings target[3][1], args[1]
|
132
|
+
joined.line(exp.line)
|
133
|
+
target[3][1] = joined
|
134
|
+
exp = target
|
135
|
+
end
|
136
|
+
elsif number? args[1]
|
137
|
+
if number? target
|
138
|
+
exp = Sexp.new(:lit, target[1] + args[1][1])
|
139
|
+
elsif target[2] == :+ and number? target[3][1]
|
140
|
+
target[3][1] = Sexp.new(:lit, target[3][1][1] + args[1][1])
|
141
|
+
exp = target
|
142
|
+
end
|
125
143
|
end
|
126
144
|
when :-
|
127
145
|
if number? target and number? args[1]
|
@@ -211,10 +229,13 @@ class Brakeman::AliasProcessor < SexpProcessor
|
|
211
229
|
# x = 1
|
212
230
|
def process_lasgn exp
|
213
231
|
exp[2] = process exp[2] if sexp? exp[2]
|
232
|
+
return exp if exp[2].nil?
|
233
|
+
|
214
234
|
local = Sexp.new(:lvar, exp[1]).line(exp.line || -2)
|
215
235
|
|
216
236
|
if @inside_if and val = env[local]
|
217
|
-
|
237
|
+
#avoid setting to value it already is (e.g. "1 or 1")
|
238
|
+
if val != exp[2] and val[1] != exp[2] and val[2] != exp[2]
|
218
239
|
env[local] = Sexp.new(:or, val, exp[2]).line(exp.line || -2)
|
219
240
|
end
|
220
241
|
else
|
@@ -283,6 +304,7 @@ class Brakeman::AliasProcessor < SexpProcessor
|
|
283
304
|
tar_variable = exp[1]
|
284
305
|
target = exp[1] = process(exp[1])
|
285
306
|
method = exp[2]
|
307
|
+
|
286
308
|
if method == :[]=
|
287
309
|
index = exp[3][1] = process(exp[3][1])
|
288
310
|
value = exp[3][2] = process(exp[3][2])
|
@@ -369,6 +391,10 @@ class Brakeman::AliasProcessor < SexpProcessor
|
|
369
391
|
exp
|
370
392
|
end
|
371
393
|
|
394
|
+
def process_svalue exp
|
395
|
+
exp[1]
|
396
|
+
end
|
397
|
+
|
372
398
|
#Constant assignments like
|
373
399
|
# BIG_CONSTANT = 234810983
|
374
400
|
def process_cdecl exp
|
@@ -400,12 +426,18 @@ class Brakeman::AliasProcessor < SexpProcessor
|
|
400
426
|
else
|
401
427
|
exps = exp[2..-1]
|
402
428
|
end
|
403
|
-
|
429
|
+
|
404
430
|
was_inside = @inside_if
|
405
431
|
@inside_if = !@ignore_ifs
|
406
432
|
|
407
433
|
exps.each do |e|
|
408
|
-
|
434
|
+
if sexp? e
|
435
|
+
if e.node_type == :block
|
436
|
+
process_default e #avoid creating new scope
|
437
|
+
else
|
438
|
+
process e
|
439
|
+
end
|
440
|
+
end
|
409
441
|
end
|
410
442
|
|
411
443
|
@inside_if = was_inside
|
@@ -451,7 +483,11 @@ class Brakeman::AliasProcessor < SexpProcessor
|
|
451
483
|
def join_strings string1, string2
|
452
484
|
result = Sexp.new(:str)
|
453
485
|
result[1] = string1[1] + string2[1]
|
454
|
-
result
|
486
|
+
if result[1].length > 50
|
487
|
+
string1
|
488
|
+
else
|
489
|
+
result
|
490
|
+
end
|
455
491
|
end
|
456
492
|
|
457
493
|
#Returns a new SexpProcessor::Environment containing only instance variables.
|
@@ -487,4 +523,12 @@ class Brakeman::AliasProcessor < SexpProcessor
|
|
487
523
|
exp
|
488
524
|
end
|
489
525
|
end
|
526
|
+
|
527
|
+
def duplicate? exp
|
528
|
+
@exp_context[0..-2].reverse_each do |e|
|
529
|
+
return true if exp == e
|
530
|
+
end
|
531
|
+
|
532
|
+
false
|
533
|
+
end
|
490
534
|
end
|
@@ -84,18 +84,30 @@ class Brakeman::ControllerAliasProcessor < Brakeman::AliasProcessor
|
|
84
84
|
#Basically, adds any instance variable assignments to the environment.
|
85
85
|
#TODO: method arguments?
|
86
86
|
def process_before_filter name
|
87
|
-
|
87
|
+
filter = find_method name, @current_class
|
88
88
|
|
89
|
-
if
|
89
|
+
if filter.nil?
|
90
90
|
Brakeman.debug "[Notice] Could not find filter #{name}"
|
91
91
|
return
|
92
92
|
end
|
93
93
|
|
94
|
-
|
95
|
-
processor.process_safely(method[3])
|
94
|
+
method = filter[:method]
|
96
95
|
|
97
|
-
|
98
|
-
|
96
|
+
if ivars = @tracker.filter_cache[[filter[:controller], name]]
|
97
|
+
ivars.each do |variable, value|
|
98
|
+
env[variable] = value
|
99
|
+
end
|
100
|
+
else
|
101
|
+
processor = Brakeman::AliasProcessor.new @tracker
|
102
|
+
processor.process_safely(method[3])
|
103
|
+
|
104
|
+
ivars = processor.only_ivars.all
|
105
|
+
|
106
|
+
@tracker.filter_cache[[filter[:controller], name]] = ivars
|
107
|
+
|
108
|
+
ivars.each do |variable, value|
|
109
|
+
env[variable] = value
|
110
|
+
end
|
99
111
|
end
|
100
112
|
end
|
101
113
|
|
@@ -217,6 +229,10 @@ class Brakeman::ControllerAliasProcessor < Brakeman::AliasProcessor
|
|
217
229
|
end
|
218
230
|
|
219
231
|
#Finds a method in the given class or a parent class
|
232
|
+
#
|
233
|
+
#Returns nil if the method could not be found.
|
234
|
+
#
|
235
|
+
#If found, returns hash table with controller name and method sexp.
|
220
236
|
def find_method method_name, klass
|
221
237
|
return nil if sexp? method_name
|
222
238
|
method_name = method_name.to_sym
|
@@ -231,12 +247,14 @@ class Brakeman::ControllerAliasProcessor < Brakeman::AliasProcessor
|
|
231
247
|
if method.nil?
|
232
248
|
controller[:includes].each do |included|
|
233
249
|
method = find_method method_name, included
|
234
|
-
|
250
|
+
if method
|
251
|
+
return { :controller => controller[:name], :method => method }
|
252
|
+
end
|
235
253
|
end
|
236
254
|
|
237
255
|
find_method method_name, controller[:parent]
|
238
256
|
else
|
239
|
-
method
|
257
|
+
{ :controller => controller[:name], :method => method }
|
240
258
|
end
|
241
259
|
else
|
242
260
|
nil
|
@@ -120,7 +120,13 @@ class Brakeman::FindAllCalls < Brakeman::BaseProcessor
|
|
120
120
|
when :lit
|
121
121
|
exp[1]
|
122
122
|
when :colon2
|
123
|
-
|
123
|
+
begin
|
124
|
+
class_name exp
|
125
|
+
rescue StandardError
|
126
|
+
exp
|
127
|
+
end
|
128
|
+
when :self
|
129
|
+
@current_class || @current_module || nil
|
124
130
|
else
|
125
131
|
exp
|
126
132
|
end
|
@@ -23,7 +23,7 @@ class Brakeman::Rails3ConfigProcessor < Brakeman::BaseProcessor
|
|
23
23
|
|
24
24
|
#Use this method to process configuration file
|
25
25
|
def process_config src
|
26
|
-
res = Brakeman::AliasProcessor.new.process_safely(src)
|
26
|
+
res = Brakeman::AliasProcessor.new(@tracker).process_safely(src)
|
27
27
|
process res
|
28
28
|
end
|
29
29
|
|
@@ -7,7 +7,7 @@ class Brakeman::LibraryProcessor < Brakeman::BaseProcessor
|
|
7
7
|
def initialize tracker
|
8
8
|
super
|
9
9
|
@file_name = nil
|
10
|
-
@alias_processor = Brakeman::AliasProcessor.new
|
10
|
+
@alias_processor = Brakeman::AliasProcessor.new tracker
|
11
11
|
end
|
12
12
|
|
13
13
|
def process_library src, file_name = nil
|
data/lib/brakeman/report.rb
CHANGED
@@ -528,7 +528,8 @@ class Brakeman::Report
|
|
528
528
|
else
|
529
529
|
CGI.escapeHTML(message)
|
530
530
|
end <<
|
531
|
-
"<table id='#{code_id}' class='context' style='display:none'>"
|
531
|
+
"<table id='#{code_id}' class='context' style='display:none'>" <<
|
532
|
+
"<caption>#{(warning.file || '').gsub(tracker.options[:app_path], "")}</caption>"
|
532
533
|
|
533
534
|
unless context.empty?
|
534
535
|
if warning.line - 1 == 1 or warning.line + 1 == 1
|
data/lib/brakeman/rescanner.rb
CHANGED
@@ -23,7 +23,7 @@ class Brakeman::Rescanner < Brakeman::Scanner
|
|
23
23
|
|
24
24
|
tracker.run_checks if @changes
|
25
25
|
|
26
|
-
Brakeman::RescanReport.new @old_results, tracker
|
26
|
+
Brakeman::RescanReport.new @old_results, tracker
|
27
27
|
end
|
28
28
|
|
29
29
|
#Rescans changed files
|
@@ -206,9 +206,10 @@ end
|
|
206
206
|
class Brakeman::RescanReport
|
207
207
|
attr_reader :old_results, :new_results
|
208
208
|
|
209
|
-
def initialize old_results,
|
209
|
+
def initialize old_results, tracker
|
210
|
+
@tracker = tracker
|
210
211
|
@old_results = old_results
|
211
|
-
@new_results =
|
212
|
+
@new_results = tracker.checks
|
212
213
|
@all_warnings = nil
|
213
214
|
@diff = nil
|
214
215
|
end
|
@@ -253,11 +254,33 @@ class Brakeman::RescanReport
|
|
253
254
|
end
|
254
255
|
|
255
256
|
#Output total, fixed, and new warnings
|
256
|
-
def to_s
|
257
|
+
def to_s(verbose = false)
|
258
|
+
if !verbose
|
257
259
|
<<-OUTPUT
|
258
260
|
Total warnings: #{all_warnings.length}
|
259
261
|
Fixed warnings: #{fixed_warnings.length}
|
260
262
|
New warnings: #{new_warnings.length}
|
261
263
|
OUTPUT
|
264
|
+
else
|
265
|
+
existing_warnings = all_warnings - new_warnings
|
266
|
+
|
267
|
+
"".tap do |out|
|
268
|
+
{:fixed => fixed_warnings, :new => new_warnings, :existing => existing_warnings}.each do |warning_type, warnings|
|
269
|
+
if warnings.length > 0
|
270
|
+
out << "#{warning_type.to_s.titleize} warnings: #{warnings.length}\n"
|
271
|
+
table = Ruport::Data::Table(["Confidence", "Class", "Method", "Warning Type", "Message"])
|
272
|
+
warnings.sort_by{|w| w.confidence}.each do |warning|
|
273
|
+
next if warning.confidence > @tracker.options[:min_confidence]
|
274
|
+
w = warning.to_row
|
275
|
+
w["Confidence"] = Brakeman::Report::TEXT_CONFIDENCE[w["Confidence"]] if w["Confidence"].is_a?(Numeric)
|
276
|
+
table << warning.to_row
|
277
|
+
end
|
278
|
+
out << table.to_s
|
279
|
+
end
|
280
|
+
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
end
|
262
285
|
end
|
263
286
|
end
|
data/lib/brakeman/scanner.rb
CHANGED
@@ -36,6 +36,13 @@ class Brakeman::Scanner
|
|
36
36
|
@path = options[:app_path]
|
37
37
|
@app_path = File.join(@path, "app")
|
38
38
|
@processor = processor || Brakeman::Processor.new(options)
|
39
|
+
@skip_files = nil
|
40
|
+
|
41
|
+
#Convert files into Regexp for matching
|
42
|
+
if options[:skip_files]
|
43
|
+
list = "(?:" << options[:skip_files].map { |f| Regexp.escape f }.join("|") << ")$"
|
44
|
+
@skip_files = Regexp.new(list)
|
45
|
+
end
|
39
46
|
|
40
47
|
if RUBY_1_9
|
41
48
|
@ruby_parser = ::Ruby19Parser
|
@@ -123,7 +130,10 @@ class Brakeman::Scanner
|
|
123
130
|
#
|
124
131
|
#Adds parsed information to tracker.initializers
|
125
132
|
def process_initializers
|
126
|
-
Dir.glob(@path + "/config/initializers/**/*.rb").sort
|
133
|
+
initializer_files = Dir.glob(@path + "/config/initializers/**/*.rb").sort
|
134
|
+
initializer_files.reject! { |f| @skip_files.match f } if @skip_files
|
135
|
+
|
136
|
+
initializer_files.each do |f|
|
127
137
|
process_initializer f
|
128
138
|
end
|
129
139
|
end
|
@@ -149,6 +159,8 @@ class Brakeman::Scanner
|
|
149
159
|
end
|
150
160
|
|
151
161
|
lib_files = Dir.glob(@path + "/lib/**/*.rb").sort
|
162
|
+
lib_files.reject! { |f| @skip_files.match f } if @skip_files
|
163
|
+
|
152
164
|
total = lib_files.length
|
153
165
|
current = 0
|
154
166
|
|
@@ -196,6 +208,8 @@ class Brakeman::Scanner
|
|
196
208
|
#Adds processed controllers to tracker.controllers
|
197
209
|
def process_controllers
|
198
210
|
controller_files = Dir.glob(@app_path + "/controllers/**/*.rb").sort
|
211
|
+
controller_files.reject! { |f| @skip_files.match f } if @skip_files
|
212
|
+
|
199
213
|
total = controller_files.length * 2
|
200
214
|
current = 0
|
201
215
|
|
@@ -222,6 +236,9 @@ class Brakeman::Scanner
|
|
222
236
|
|
223
237
|
@processor.process_controller_alias controller[:src]
|
224
238
|
end
|
239
|
+
|
240
|
+
#No longer need these processed filter methods
|
241
|
+
tracker.filter_cache.clear
|
225
242
|
end
|
226
243
|
|
227
244
|
def process_controller path
|
@@ -244,6 +261,8 @@ class Brakeman::Scanner
|
|
244
261
|
count = 0
|
245
262
|
|
246
263
|
template_files = Dir.glob(views_path).sort
|
264
|
+
template_files.reject! { |f| @skip_files.match f } if @skip_files
|
265
|
+
|
247
266
|
total = template_files.length
|
248
267
|
|
249
268
|
template_files.each do |path|
|
@@ -327,6 +346,7 @@ class Brakeman::Scanner
|
|
327
346
|
#Adds the processed models to tracker.models
|
328
347
|
def process_models
|
329
348
|
model_files = Dir.glob(@app_path + "/models/*.rb").sort
|
349
|
+
model_files.reject! { |f| @skip_files.match f } if @skip_files
|
330
350
|
|
331
351
|
total = model_files.length
|
332
352
|
current = 0
|
data/lib/brakeman/tracker.rb
CHANGED
@@ -9,7 +9,7 @@ require 'brakeman/processors/lib/find_all_calls'
|
|
9
9
|
class Brakeman::Tracker
|
10
10
|
attr_accessor :controllers, :templates, :models, :errors,
|
11
11
|
:checks, :initializers, :config, :routes, :processor, :libs,
|
12
|
-
:template_cache, :options
|
12
|
+
:template_cache, :options, :filter_cache
|
13
13
|
|
14
14
|
#Place holder when there should be a model, but it is not
|
15
15
|
#clear what model it will be.
|
@@ -42,6 +42,7 @@ class Brakeman::Tracker
|
|
42
42
|
@checks = nil
|
43
43
|
@processed = nil
|
44
44
|
@template_cache = Set.new
|
45
|
+
@filter_cache = {}
|
45
46
|
@call_index = nil
|
46
47
|
end
|
47
48
|
|
data/lib/brakeman/util.rb
CHANGED
@@ -11,6 +11,8 @@ module Brakeman::Util
|
|
11
11
|
|
12
12
|
REQUEST_PARAMETERS = Sexp.new(:call, Sexp.new(:call, nil, :request, Sexp.new(:arglist)), :request_parameters, Sexp.new(:arglist))
|
13
13
|
|
14
|
+
REQUEST_ENV = Sexp.new(:call, Sexp.new(:call, nil, :request, Sexp.new(:arglist)), :env, Sexp.new(:arglist))
|
15
|
+
|
14
16
|
PARAMETERS = Sexp.new(:call, nil, :params, Sexp.new(:arglist))
|
15
17
|
|
16
18
|
COOKIES = Sexp.new(:call, nil, :cookies, Sexp.new(:arglist))
|
@@ -179,7 +181,10 @@ module Brakeman::Util
|
|
179
181
|
end
|
180
182
|
|
181
183
|
false
|
184
|
+
end
|
182
185
|
|
186
|
+
def request_env? exp
|
187
|
+
call? exp and (exp == REQUEST_ENV or exp[1] == REQUEST_ENV)
|
183
188
|
end
|
184
189
|
|
185
190
|
#Check if _exp_ is a Sexp.
|
data/lib/brakeman/version.rb
CHANGED
metadata
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: brakeman
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 27
|
5
|
+
prerelease:
|
5
6
|
segments:
|
6
7
|
- 1
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 1.
|
8
|
+
- 3
|
9
|
+
- 0
|
10
|
+
version: 1.3.0
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- Justin Collins
|
@@ -14,8 +15,7 @@ autorequire:
|
|
14
15
|
bindir: bin
|
15
16
|
cert_chain: []
|
16
17
|
|
17
|
-
date: 2012-
|
18
|
-
default_executable:
|
18
|
+
date: 2012-02-09 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: activesupport
|
@@ -25,6 +25,7 @@ dependencies:
|
|
25
25
|
requirements:
|
26
26
|
- - ">="
|
27
27
|
- !ruby/object:Gem::Version
|
28
|
+
hash: 3
|
28
29
|
segments:
|
29
30
|
- 0
|
30
31
|
version: "0"
|
@@ -38,6 +39,7 @@ dependencies:
|
|
38
39
|
requirements:
|
39
40
|
- - ">="
|
40
41
|
- !ruby/object:Gem::Version
|
42
|
+
hash: 3
|
41
43
|
segments:
|
42
44
|
- 0
|
43
45
|
version: "0"
|
@@ -51,6 +53,7 @@ dependencies:
|
|
51
53
|
requirements:
|
52
54
|
- - ~>
|
53
55
|
- !ruby/object:Gem::Version
|
56
|
+
hash: 11
|
54
57
|
segments:
|
55
58
|
- 1
|
56
59
|
- 2
|
@@ -65,6 +68,7 @@ dependencies:
|
|
65
68
|
requirements:
|
66
69
|
- - ~>
|
67
70
|
- !ruby/object:Gem::Version
|
71
|
+
hash: 3
|
68
72
|
segments:
|
69
73
|
- 1
|
70
74
|
- 6
|
@@ -79,6 +83,7 @@ dependencies:
|
|
79
83
|
requirements:
|
80
84
|
- - ~>
|
81
85
|
- !ruby/object:Gem::Version
|
86
|
+
hash: 15
|
82
87
|
segments:
|
83
88
|
- 2
|
84
89
|
- 6
|
@@ -93,6 +98,7 @@ dependencies:
|
|
93
98
|
requirements:
|
94
99
|
- - ~>
|
95
100
|
- !ruby/object:Gem::Version
|
101
|
+
hash: 7
|
96
102
|
segments:
|
97
103
|
- 3
|
98
104
|
- 0
|
@@ -107,6 +113,7 @@ dependencies:
|
|
107
113
|
requirements:
|
108
114
|
- - ~>
|
109
115
|
- !ruby/object:Gem::Version
|
116
|
+
hash: 7
|
110
117
|
segments:
|
111
118
|
- 3
|
112
119
|
- 0
|
@@ -195,7 +202,6 @@ files:
|
|
195
202
|
- lib/brakeman/processor.rb
|
196
203
|
- lib/brakeman.rb
|
197
204
|
- lib/brakeman/format/style.css
|
198
|
-
has_rdoc: true
|
199
205
|
homepage: http://brakemanscanner.org
|
200
206
|
licenses: []
|
201
207
|
|
@@ -209,6 +215,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
209
215
|
requirements:
|
210
216
|
- - ">="
|
211
217
|
- !ruby/object:Gem::Version
|
218
|
+
hash: 3
|
212
219
|
segments:
|
213
220
|
- 0
|
214
221
|
version: "0"
|
@@ -217,13 +224,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
217
224
|
requirements:
|
218
225
|
- - ">="
|
219
226
|
- !ruby/object:Gem::Version
|
227
|
+
hash: 3
|
220
228
|
segments:
|
221
229
|
- 0
|
222
230
|
version: "0"
|
223
231
|
requirements: []
|
224
232
|
|
225
233
|
rubyforge_project:
|
226
|
-
rubygems_version: 1.
|
234
|
+
rubygems_version: 1.8.15
|
227
235
|
signing_key:
|
228
236
|
specification_version: 3
|
229
237
|
summary: Security vulnerability scanner for Ruby on Rails.
|