brakeman 1.2.2 → 1.3.0
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.
- 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.
|