brakeman-min 2.4.3 → 2.5.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.
- checksums.yaml +15 -0
- checksums.yaml.gz.sig +3 -0
- data.tar.gz.sig +0 -0
- data/CHANGES +15 -0
- data/lib/brakeman.rb +22 -0
- data/lib/brakeman/checks/base_check.rb +1 -1
- data/lib/brakeman/checks/check_number_to_currency.rb +2 -0
- data/lib/brakeman/checks/check_redirect.rb +15 -1
- data/lib/brakeman/checks/check_regex_dos.rb +69 -0
- data/lib/brakeman/checks/check_select_vulnerability.rb +3 -1
- data/lib/brakeman/checks/check_skip_before_filter.rb +1 -1
- data/lib/brakeman/checks/check_sql.rb +10 -89
- data/lib/brakeman/checks/check_sql_cves.rb +89 -0
- data/lib/brakeman/checks/check_symbol_dos.rb +6 -4
- data/lib/brakeman/options.rb +6 -2
- data/lib/brakeman/processors/controller_processor.rb +4 -3
- data/lib/brakeman/processors/lib/find_all_calls.rb +13 -0
- data/lib/brakeman/processors/lib/rails3_route_processor.rb +6 -1
- data/lib/brakeman/processors/output_processor.rb +7 -0
- data/lib/brakeman/report.rb +8 -1
- data/lib/brakeman/report/report_html.rb +6 -1
- data/lib/brakeman/report/report_markdown.rb +158 -0
- data/lib/brakeman/util.rb +9 -0
- data/lib/brakeman/version.rb +1 -1
- data/lib/brakeman/warning_codes.rb +1 -0
- metadata +93 -106
- metadata.gz.sig +0 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
!binary "U0hBMQ==":
|
|
3
|
+
metadata.gz: !binary |-
|
|
4
|
+
OTcwMjUwMDYwZjJjMmZhZTY4YjBmM2ZjZjBkMmYyZWVmZmFmYTlmZQ==
|
|
5
|
+
data.tar.gz: !binary |-
|
|
6
|
+
N2M5MTJlYmMwMjViN2RlMWUxODYwODZlNDBmY2NmMzFhYjNhZTkxOA==
|
|
7
|
+
SHA512:
|
|
8
|
+
metadata.gz: !binary |-
|
|
9
|
+
OWRiNDM3ZmYzNWExNGJmZWUyNmE0MDRiODA5YzkxMjgzNWRlMDBlNjBiZTky
|
|
10
|
+
OTQ1MTZhNmU0YjQ0MjcyZDRkNzY1NzJjNDZkYmM3NjE1NzY2YTZlY2NkZjQx
|
|
11
|
+
NDFmOTAxYjJhYjI1NDBlMmE3NjkzNTIwZDYwNWEzYzRkNjQ5YjA=
|
|
12
|
+
data.tar.gz: !binary |-
|
|
13
|
+
YzU0ZDU0YmZkNDM4MjhiYzZkMTMzNmNjNzVkY2U1NTg4MTJiODY1ODZiMTc1
|
|
14
|
+
YmJjYjY0OTVkZTVmZDhlYmI1YWE4ZDYyZTViMTgxYTEzMjZmNTQzZjFlZGFm
|
|
15
|
+
ZmFhOTc5NGQzZWQ4M2QxYzc5ZTA1YjAxMDQwNjg0MjA4Mjk1OTQ=
|
checksums.yaml.gz.sig
ADDED
data.tar.gz.sig
CHANGED
|
Binary file
|
data/CHANGES
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
# 2.5.0
|
|
2
|
+
|
|
3
|
+
* Add support for RailsLTS 2.3.18.7 and 2.3.18.8
|
|
4
|
+
* Add support for Rails 4 `before_actions` and friends
|
|
5
|
+
* Move SQLi CVE checks to `CheckSQLCVEs`
|
|
6
|
+
* Check for protected_attributes gem
|
|
7
|
+
* Fix SQLi detection in chain calls in scopes
|
|
8
|
+
* Add GitHub-flavored Markdown output format (Greg Ose)
|
|
9
|
+
* Fix false positives when sanitize() is used in SQL (Jeff Yip)
|
|
10
|
+
* Add String#intern and Hash#symbolize_keys DoS check (Jan Rusnacko)
|
|
11
|
+
* Check all arguments in Model.select for SQLi
|
|
12
|
+
* Fix false positive when :host is specified in redirect
|
|
13
|
+
* Handle more non-literals in routes
|
|
14
|
+
* Add check for regex denial of service (Ben Toews)
|
|
15
|
+
|
|
1
16
|
# 2.4.3
|
|
2
17
|
|
|
3
18
|
No changes. 2.4.2 gem release was unsigned, 2.4.3 is signed.
|
data/lib/brakeman.rb
CHANGED
|
@@ -24,6 +24,7 @@ module Brakeman
|
|
|
24
24
|
# * :config_file - configuration file
|
|
25
25
|
# * :escape_html - escape HTML by default (automatic)
|
|
26
26
|
# * :exit_on_warn - return false if warnings found, true otherwise. Not recommended for library use (default: false)
|
|
27
|
+
# * :github_repo - github repo to use for file links (user/repo[/path][@ref])
|
|
27
28
|
# * :highlight_user_input - highlight user input in reported warnings (default: true)
|
|
28
29
|
# * :html_style - path to CSS file
|
|
29
30
|
# * :ignore_model_output - consider models safe (default: false)
|
|
@@ -77,6 +78,7 @@ module Brakeman
|
|
|
77
78
|
|
|
78
79
|
options[:app_path] = File.expand_path(options[:app_path])
|
|
79
80
|
options[:output_formats] = get_output_formats options
|
|
81
|
+
options[:github_url] = get_github_url options
|
|
80
82
|
|
|
81
83
|
options
|
|
82
84
|
end
|
|
@@ -166,6 +168,8 @@ module Brakeman
|
|
|
166
168
|
[:to_tabs]
|
|
167
169
|
when :json, :to_json
|
|
168
170
|
[:to_json]
|
|
171
|
+
when :markdown, :to_markdown
|
|
172
|
+
[:to_markdown]
|
|
169
173
|
else
|
|
170
174
|
[:to_s]
|
|
171
175
|
end
|
|
@@ -185,6 +189,8 @@ module Brakeman
|
|
|
185
189
|
:to_tabs
|
|
186
190
|
when /\.json$/i
|
|
187
191
|
:to_json
|
|
192
|
+
when /\.md$/i
|
|
193
|
+
:to_markdown
|
|
188
194
|
else
|
|
189
195
|
:to_s
|
|
190
196
|
end
|
|
@@ -192,6 +198,22 @@ module Brakeman
|
|
|
192
198
|
end
|
|
193
199
|
private_class_method :get_formats_from_output_files
|
|
194
200
|
|
|
201
|
+
def self.get_github_url options
|
|
202
|
+
if github_repo = options[:github_repo]
|
|
203
|
+
full_repo, ref = github_repo.split '@', 2
|
|
204
|
+
name, repo, path = full_repo.split '/', 3
|
|
205
|
+
unless name && repo && !(name.empty? || repo.empty?)
|
|
206
|
+
raise ArgumentError, "Invalid GitHub repository format"
|
|
207
|
+
end
|
|
208
|
+
path.chomp '/' if path
|
|
209
|
+
ref ||= 'master'
|
|
210
|
+
['https://github.com', name, repo, 'blob', ref, path].compact.join '/'
|
|
211
|
+
else
|
|
212
|
+
nil
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
private_class_method :get_github_url
|
|
216
|
+
|
|
195
217
|
#Output list of checks (for `-k` option)
|
|
196
218
|
def self.list_checks
|
|
197
219
|
require 'brakeman/scanner'
|
|
@@ -177,7 +177,7 @@ class Brakeman::BaseCheck < Brakeman::SexpProcessor
|
|
|
177
177
|
tracker.config[:rails][:active_record][:whitelist_attributes] == Sexp.new(:true)
|
|
178
178
|
|
|
179
179
|
@mass_assign_disabled = true
|
|
180
|
-
elsif version_between?("4.0.0", "4.9.9")
|
|
180
|
+
elsif version_between?("4.0.0", "4.9.9") and not tracker.config[:gems][:protected_attributes]
|
|
181
181
|
#May need to revisit dependng on what Rails 4 actually does/has
|
|
182
182
|
@mass_assign_disabled = true
|
|
183
183
|
else
|
|
@@ -31,7 +31,11 @@ class Brakeman::CheckRedirect < Brakeman::BaseCheck
|
|
|
31
31
|
|
|
32
32
|
method = call.method
|
|
33
33
|
|
|
34
|
-
if method == :redirect_to and
|
|
34
|
+
if method == :redirect_to and
|
|
35
|
+
not only_path?(call) and
|
|
36
|
+
not explicit_host?(call) and
|
|
37
|
+
res = include_user_input?(call)
|
|
38
|
+
|
|
35
39
|
add_result result
|
|
36
40
|
|
|
37
41
|
if res.type == :immediate
|
|
@@ -109,6 +113,16 @@ class Brakeman::CheckRedirect < Brakeman::BaseCheck
|
|
|
109
113
|
false
|
|
110
114
|
end
|
|
111
115
|
|
|
116
|
+
def explicit_host? call
|
|
117
|
+
arg = call.first_arg
|
|
118
|
+
|
|
119
|
+
if hash? arg and value = hash_access(arg, :host)
|
|
120
|
+
return !has_immediate_user_input?(value)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
false
|
|
124
|
+
end
|
|
125
|
+
|
|
112
126
|
#+url_for+ is only_path => true by default. This checks to see if it is
|
|
113
127
|
#set to false for some reason.
|
|
114
128
|
def check_url_for call
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
require 'brakeman/checks/base_check'
|
|
2
|
+
|
|
3
|
+
#This check looks for regexes that include user input.
|
|
4
|
+
class Brakeman::CheckRegexDoS < Brakeman::BaseCheck
|
|
5
|
+
Brakeman::Checks.add self
|
|
6
|
+
|
|
7
|
+
ESCAPES = {
|
|
8
|
+
s(:const, :Regexp) => [
|
|
9
|
+
:escape,
|
|
10
|
+
:quote
|
|
11
|
+
]
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
@description = "Searches regexes including user input"
|
|
15
|
+
|
|
16
|
+
#Process calls
|
|
17
|
+
def run_check
|
|
18
|
+
Brakeman.debug "Finding dynamic regexes"
|
|
19
|
+
calls = tracker.find_call :method => [:brakeman_regex_interp]
|
|
20
|
+
|
|
21
|
+
Brakeman.debug "Processing dynamic regexes"
|
|
22
|
+
calls.each do |call|
|
|
23
|
+
process_result call
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
#Warns if regex includes user input
|
|
28
|
+
def process_result result
|
|
29
|
+
return if duplicate? result
|
|
30
|
+
add_result result
|
|
31
|
+
|
|
32
|
+
call = result[:call]
|
|
33
|
+
components = call[1..-1]
|
|
34
|
+
|
|
35
|
+
components.any? do |component|
|
|
36
|
+
next unless sexp? component
|
|
37
|
+
|
|
38
|
+
if match = has_immediate_user_input?(component)
|
|
39
|
+
confidence = CONFIDENCE[:high]
|
|
40
|
+
elsif match = has_immediate_model?(component)
|
|
41
|
+
match = Match.new(:model, match)
|
|
42
|
+
confidence = CONFIDENCE[:med]
|
|
43
|
+
elsif match = include_user_input?(component)
|
|
44
|
+
confidence = CONFIDENCE[:low]
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
if match
|
|
48
|
+
message = "#{friendly_type_of(match).capitalize} used in regex"
|
|
49
|
+
|
|
50
|
+
warn :result => result,
|
|
51
|
+
:warning_type => "Denial of Service",
|
|
52
|
+
:warning_code => :regex_dos,
|
|
53
|
+
:message => message,
|
|
54
|
+
:confidence => confidence,
|
|
55
|
+
:user_input => match.match
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def process_call(exp)
|
|
61
|
+
if escape_methods = ESCAPES[exp.target]
|
|
62
|
+
if escape_methods.include? exp.method
|
|
63
|
+
return exp
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
super
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -9,7 +9,9 @@ class Brakeman::CheckSelectVulnerability < Brakeman::BaseCheck
|
|
|
9
9
|
|
|
10
10
|
def run_check
|
|
11
11
|
|
|
12
|
-
if
|
|
12
|
+
if lts_version? "2.3.18.7"
|
|
13
|
+
return
|
|
14
|
+
elsif version_between? "3.0.0", "3.0.11"
|
|
13
15
|
suggested_version = "3.0.12"
|
|
14
16
|
elsif version_between? "3.1.0", "3.1.3"
|
|
15
17
|
suggested_version = "3.1.4"
|
|
@@ -14,7 +14,7 @@ class Brakeman::CheckSkipBeforeFilter < Brakeman::BaseCheck
|
|
|
14
14
|
|
|
15
15
|
def run_check
|
|
16
16
|
tracker.controllers.each do |name, controller|
|
|
17
|
-
filter_skips =
|
|
17
|
+
filter_skips = controller[:options].values_at(:skip_before_filter, :skip_filter, :skip_before_action, :skip_action_callback).compact.flatten(1)
|
|
18
18
|
|
|
19
19
|
filter_skips.each do |filter|
|
|
20
20
|
process_skip_filter filter, controller
|
|
@@ -46,13 +46,8 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
|
|
|
46
46
|
Brakeman.debug "Finding calls to named_scope or scope"
|
|
47
47
|
calls.concat find_scope_calls
|
|
48
48
|
|
|
49
|
-
Brakeman.debug "Checking version of Rails for CVE issues"
|
|
50
|
-
check_rails_versions_against_cve_issues
|
|
51
|
-
|
|
52
49
|
Brakeman.debug "Processing possible SQL calls"
|
|
53
50
|
calls.each { |call| process_result call }
|
|
54
|
-
|
|
55
|
-
check_CVE_2014_0080
|
|
56
51
|
end
|
|
57
52
|
|
|
58
53
|
#Find calls to named_scope() or scope() in models
|
|
@@ -65,7 +60,7 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
|
|
|
65
60
|
call = make_call(nil, :named_scope, args).line(args.line)
|
|
66
61
|
scope_calls << scope_call_hash(call, name, :named_scope)
|
|
67
62
|
end
|
|
68
|
-
elsif version_between?("3.1.0", "
|
|
63
|
+
elsif version_between?("3.1.0", "4.9.9")
|
|
69
64
|
ar_scope_calls(:scope) do |name, args|
|
|
70
65
|
second_arg = args[2]
|
|
71
66
|
next unless sexp? second_arg
|
|
@@ -114,8 +109,12 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
|
|
|
114
109
|
find_calls.process_source(block, :class => model_name, :method => scope_name)
|
|
115
110
|
find_calls.calls.each { |call| process_result(call) if @sql_targets.include?(call[:method]) }
|
|
116
111
|
elsif block.node_type == :call
|
|
117
|
-
|
|
118
|
-
|
|
112
|
+
while call? block
|
|
113
|
+
process_result :target => block.target, :method => block.method, :call => block,
|
|
114
|
+
:location => { :type => :class, :class => model_name, :method => scope_name }
|
|
115
|
+
|
|
116
|
+
block = block.target
|
|
117
|
+
end
|
|
119
118
|
end
|
|
120
119
|
end
|
|
121
120
|
|
|
@@ -179,13 +178,13 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
|
|
|
179
178
|
check_order_arguments call.arglist
|
|
180
179
|
when :joins
|
|
181
180
|
check_joins_arguments call.first_arg
|
|
182
|
-
when :from
|
|
181
|
+
when :from
|
|
183
182
|
unsafe_sql? call.first_arg
|
|
184
183
|
when :lock
|
|
185
184
|
check_lock_arguments call.first_arg
|
|
186
185
|
when :pluck
|
|
187
186
|
unsafe_sql? call.first_arg
|
|
188
|
-
when :update_all
|
|
187
|
+
when :update_all, :select
|
|
189
188
|
check_update_all_arguments call.args
|
|
190
189
|
when *@connection_calls
|
|
191
190
|
check_by_sql_arguments call.first_arg
|
|
@@ -540,7 +539,7 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
|
|
|
540
539
|
:sanitize_sql, :sanitize_sql_array, :sanitize_sql_for_assignment,
|
|
541
540
|
:sanitize_sql_for_conditions, :sanitize_sql_hash,
|
|
542
541
|
:sanitize_sql_hash_for_assignment, :sanitize_sql_hash_for_conditions,
|
|
543
|
-
:to_sql]
|
|
542
|
+
:to_sql, :sanitize]
|
|
544
543
|
|
|
545
544
|
def safe_value? exp
|
|
546
545
|
return true unless sexp? exp
|
|
@@ -639,82 +638,4 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
|
|
|
639
638
|
active_record_models.include? klass
|
|
640
639
|
end
|
|
641
640
|
end
|
|
642
|
-
|
|
643
|
-
# TODO: Move all SQL CVE checks to separate class
|
|
644
|
-
def check_CVE_2014_0080
|
|
645
|
-
return unless version_between? "4.0.0", "4.0.2" and
|
|
646
|
-
@tracker.config[:gems].include? :pg
|
|
647
|
-
|
|
648
|
-
warn :warning_type => 'SQL Injection',
|
|
649
|
-
:warning_code => :CVE_2014_0080,
|
|
650
|
-
:message => "Rails #{tracker.config[:rails_version]} contains a SQL injection vulnerability (CVE-2014-0080) with PostgreSQL. Upgrade to 4.0.3",
|
|
651
|
-
:confidence => CONFIDENCE[:high],
|
|
652
|
-
:file => gemfile_or_environment,
|
|
653
|
-
:link_path => "https://groups.google.com/d/msg/rubyonrails-security/Wu96YkTUR6s/pPLBMZrlwvYJ"
|
|
654
|
-
end
|
|
655
|
-
|
|
656
|
-
def upgrade_version? versions
|
|
657
|
-
versions.each do |low, high, upgrade|
|
|
658
|
-
return upgrade if version_between? low, high
|
|
659
|
-
end
|
|
660
|
-
|
|
661
|
-
false
|
|
662
|
-
end
|
|
663
|
-
|
|
664
|
-
def check_rails_versions_against_cve_issues
|
|
665
|
-
issues = [
|
|
666
|
-
{
|
|
667
|
-
:cve => "CVE-2012-2660",
|
|
668
|
-
:versions => [%w[2.0.0 2.3.14 2.3.17], %w[3.0.0 3.0.12 3.0.13], %w[3.1.0 3.1.4 3.1.5], %w[3.2.0 3.2.3 3.2.4]],
|
|
669
|
-
:url => "https://groups.google.com/d/topic/rubyonrails-security/8SA-M3as7A8/discussion"
|
|
670
|
-
},
|
|
671
|
-
{
|
|
672
|
-
:cve => "CVE-2012-2661",
|
|
673
|
-
:versions => [%w[3.0.0 3.0.12 3.0.13], %w[3.1.0 3.1.4 3.1.5], %w[3.2.0 3.2.3 3.2.5]],
|
|
674
|
-
:url => "https://groups.google.com/d/topic/rubyonrails-security/dUaiOOGWL1k/discussion"
|
|
675
|
-
},
|
|
676
|
-
{
|
|
677
|
-
:cve => "CVE-2012-2695",
|
|
678
|
-
:versions => [%w[2.0.0 2.3.14 2.3.15], %w[3.0.0 3.0.13 3.0.14], %w[3.1.0 3.1.5 3.1.6], %w[3.2.0 3.2.5 3.2.6]],
|
|
679
|
-
:url => "https://groups.google.com/d/topic/rubyonrails-security/l4L0TEVAz1k/discussion"
|
|
680
|
-
},
|
|
681
|
-
{
|
|
682
|
-
:cve => "CVE-2012-5664",
|
|
683
|
-
:versions => [%w[2.0.0 2.3.14 2.3.15], %w[3.0.0 3.0.17 3.0.18], %w[3.1.0 3.1.8 3.1.9], %w[3.2.0 3.2.9 3.2.18]],
|
|
684
|
-
:url => "https://groups.google.com/d/topic/rubyonrails-security/DCNTNp_qjFM/discussion"
|
|
685
|
-
},
|
|
686
|
-
{
|
|
687
|
-
:cve => "CVE-2013-0155",
|
|
688
|
-
:versions => [%w[2.0.0 2.3.15 2.3.16], %w[3.0.0 3.0.18 3.0.19], %w[3.1.0 3.1.9 3.1.10], %w[3.2.0 3.2.10 3.2.11]],
|
|
689
|
-
:url => "https://groups.google.com/d/topic/rubyonrails-security/c7jT-EeN9eI/discussion"
|
|
690
|
-
},
|
|
691
|
-
|
|
692
|
-
]
|
|
693
|
-
|
|
694
|
-
unless lts_version? '2.3.18.6'
|
|
695
|
-
issues << {
|
|
696
|
-
:cve => "CVE-2013-6417",
|
|
697
|
-
:versions => [%w[2.0.0 3.2.15 3.2.16], %w[4.0.0 4.0.1 4.0.2]],
|
|
698
|
-
:url => "https://groups.google.com/d/msg/ruby-security-ann/niK4drpSHT4/g8JW8ZsayRkJ"
|
|
699
|
-
}
|
|
700
|
-
end
|
|
701
|
-
|
|
702
|
-
issues.each do |cve_issue|
|
|
703
|
-
cve_warning_for cve_issue[:versions], cve_issue[:cve], cve_issue[:url]
|
|
704
|
-
end
|
|
705
|
-
end
|
|
706
|
-
|
|
707
|
-
def cve_warning_for versions, cve, link
|
|
708
|
-
upgrade_version = upgrade_version? versions
|
|
709
|
-
return unless upgrade_version
|
|
710
|
-
|
|
711
|
-
code = cve.tr('-', '_').to_sym
|
|
712
|
-
|
|
713
|
-
warn :warning_type => 'SQL Injection',
|
|
714
|
-
:warning_code => code,
|
|
715
|
-
:message => "Rails #{tracker.config[:rails_version]} contains a SQL injection vulnerability (#{cve}). Upgrade to #{upgrade_version}",
|
|
716
|
-
:confidence => CONFIDENCE[:high],
|
|
717
|
-
:file => gemfile_or_environment,
|
|
718
|
-
:link_path => link
|
|
719
|
-
end
|
|
720
641
|
end
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
require 'brakeman/checks/base_check'
|
|
2
|
+
|
|
3
|
+
class Brakeman::CheckSQLCVEs < Brakeman::BaseCheck
|
|
4
|
+
Brakeman::Checks.add self
|
|
5
|
+
|
|
6
|
+
@description = "Checks for several SQL CVEs"
|
|
7
|
+
|
|
8
|
+
def run_check
|
|
9
|
+
check_rails_versions_against_cve_issues
|
|
10
|
+
check_cve_2014_0080
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def check_rails_versions_against_cve_issues
|
|
14
|
+
issues = [
|
|
15
|
+
{
|
|
16
|
+
:cve => "CVE-2012-2660",
|
|
17
|
+
:versions => [%w[2.0.0 2.3.14 2.3.17], %w[3.0.0 3.0.12 3.0.13], %w[3.1.0 3.1.4 3.1.5], %w[3.2.0 3.2.3 3.2.4]],
|
|
18
|
+
:url => "https://groups.google.com/d/topic/rubyonrails-security/8SA-M3as7A8/discussion"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
:cve => "CVE-2012-2661",
|
|
22
|
+
:versions => [%w[3.0.0 3.0.12 3.0.13], %w[3.1.0 3.1.4 3.1.5], %w[3.2.0 3.2.3 3.2.5]],
|
|
23
|
+
:url => "https://groups.google.com/d/topic/rubyonrails-security/dUaiOOGWL1k/discussion"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
:cve => "CVE-2012-2695",
|
|
27
|
+
:versions => [%w[2.0.0 2.3.14 2.3.15], %w[3.0.0 3.0.13 3.0.14], %w[3.1.0 3.1.5 3.1.6], %w[3.2.0 3.2.5 3.2.6]],
|
|
28
|
+
:url => "https://groups.google.com/d/topic/rubyonrails-security/l4L0TEVAz1k/discussion"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
:cve => "CVE-2012-5664",
|
|
32
|
+
:versions => [%w[2.0.0 2.3.14 2.3.15], %w[3.0.0 3.0.17 3.0.18], %w[3.1.0 3.1.8 3.1.9], %w[3.2.0 3.2.9 3.2.18]],
|
|
33
|
+
:url => "https://groups.google.com/d/topic/rubyonrails-security/DCNTNp_qjFM/discussion"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
:cve => "CVE-2013-0155",
|
|
37
|
+
:versions => [%w[2.0.0 2.3.15 2.3.16], %w[3.0.0 3.0.18 3.0.19], %w[3.1.0 3.1.9 3.1.10], %w[3.2.0 3.2.10 3.2.11]],
|
|
38
|
+
:url => "https://groups.google.com/d/topic/rubyonrails-security/c7jT-EeN9eI/discussion"
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
unless lts_version? '2.3.18.6'
|
|
44
|
+
issues << {
|
|
45
|
+
:cve => "CVE-2013-6417",
|
|
46
|
+
:versions => [%w[2.0.0 3.2.15 3.2.16], %w[4.0.0 4.0.1 4.0.2]],
|
|
47
|
+
:url => "https://groups.google.com/d/msg/ruby-security-ann/niK4drpSHT4/g8JW8ZsayRkJ"
|
|
48
|
+
}
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
issues.each do |cve_issue|
|
|
52
|
+
cve_warning_for cve_issue[:versions], cve_issue[:cve], cve_issue[:url]
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def cve_warning_for versions, cve, link
|
|
57
|
+
upgrade_version = upgrade_version? versions
|
|
58
|
+
return unless upgrade_version
|
|
59
|
+
|
|
60
|
+
code = cve.tr('-', '_').to_sym
|
|
61
|
+
|
|
62
|
+
warn :warning_type => 'SQL Injection',
|
|
63
|
+
:warning_code => code,
|
|
64
|
+
:message => "Rails #{tracker.config[:rails_version]} contains a SQL injection vulnerability (#{cve}). Upgrade to #{upgrade_version}",
|
|
65
|
+
:confidence => CONFIDENCE[:high],
|
|
66
|
+
:file => gemfile_or_environment,
|
|
67
|
+
:link_path => link
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def upgrade_version? versions
|
|
71
|
+
versions.each do |low, high, upgrade|
|
|
72
|
+
return upgrade if version_between? low, high
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
false
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def check_cve_2014_0080
|
|
79
|
+
return unless version_between? "4.0.0", "4.0.2" and
|
|
80
|
+
@tracker.config[:gems].include? :pg
|
|
81
|
+
|
|
82
|
+
warn :warning_type => 'SQL Injection',
|
|
83
|
+
:warning_code => :CVE_2014_0080,
|
|
84
|
+
:message => "Rails #{tracker.config[:rails_version]} contains a SQL injection vulnerability (CVE-2014-0080) with PostgreSQL. Upgrade to 4.0.3",
|
|
85
|
+
:confidence => CONFIDENCE[:high],
|
|
86
|
+
:file => gemfile_or_environment,
|
|
87
|
+
:link_path => "https://groups.google.com/d/msg/rubyonrails-security/Wu96YkTUR6s/pPLBMZrlwvYJ"
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -3,6 +3,8 @@ require 'brakeman/checks/base_check'
|
|
|
3
3
|
class Brakeman::CheckSymbolDoS < Brakeman::BaseCheck
|
|
4
4
|
Brakeman::Checks.add self
|
|
5
5
|
|
|
6
|
+
UNSAFE_METHODS = [:to_sym, :literal_to_sym, :intern, :symbolize_keys, :symbolize_keys!]
|
|
7
|
+
|
|
6
8
|
@description = "Checks for versions with ActiveRecord symbol denial of service, or code with a similar vulnerability"
|
|
7
9
|
|
|
8
10
|
def run_check
|
|
@@ -26,7 +28,7 @@ class Brakeman::CheckSymbolDoS < Brakeman::BaseCheck
|
|
|
26
28
|
:link => "https://groups.google.com/d/msg/rubyonrails-security/jgJ4cjjS8FE/BGbHRxnDRTIJ"
|
|
27
29
|
end
|
|
28
30
|
|
|
29
|
-
tracker.find_call(:methods =>
|
|
31
|
+
tracker.find_call(:methods => UNSAFE_METHODS, :nested => true).each do |result|
|
|
30
32
|
check_unsafe_symbol_creation(result)
|
|
31
33
|
end
|
|
32
34
|
|
|
@@ -39,10 +41,10 @@ class Brakeman::CheckSymbolDoS < Brakeman::BaseCheck
|
|
|
39
41
|
|
|
40
42
|
call = result[:call]
|
|
41
43
|
|
|
42
|
-
if result[:method] == :
|
|
43
|
-
args = [call.target]
|
|
44
|
-
else
|
|
44
|
+
if result[:method] == :literal_to_sym
|
|
45
45
|
args = call.select { |e| sexp? e }
|
|
46
|
+
else
|
|
47
|
+
args = [call.target]
|
|
46
48
|
end
|
|
47
49
|
|
|
48
50
|
if input = args.map{ |arg| has_immediate_user_input?(arg) }.compact.first
|
data/lib/brakeman/options.rb
CHANGED
|
@@ -142,7 +142,7 @@ module Brakeman::Options
|
|
|
142
142
|
|
|
143
143
|
opts.on "-f",
|
|
144
144
|
"--format TYPE",
|
|
145
|
-
[:pdf, :text, :html, :csv, :tabs, :json],
|
|
145
|
+
[:pdf, :text, :html, :csv, :tabs, :json, :markdown],
|
|
146
146
|
"Specify output formats. Default is text" do |type|
|
|
147
147
|
|
|
148
148
|
type = "s" if type == :text
|
|
@@ -158,7 +158,7 @@ module Brakeman::Options
|
|
|
158
158
|
end
|
|
159
159
|
|
|
160
160
|
opts.on "-I", "--interactive-ignore", "Interactively ignore warnings" do
|
|
161
|
-
options[:interactive_ignore] = true
|
|
161
|
+
options[:interactive_ignore] = true
|
|
162
162
|
end
|
|
163
163
|
|
|
164
164
|
opts.on "-l", "--[no-]combine-locations", "Combine warning locations (Default)" do |combine|
|
|
@@ -198,6 +198,10 @@ module Brakeman::Options
|
|
|
198
198
|
options[:absolute_paths] = true
|
|
199
199
|
end
|
|
200
200
|
|
|
201
|
+
opts.on "--github-repo USER/REPO[/PATH][@REF]", "Output links to GitHub in markdown and HTML reports using specified repo" do |repo|
|
|
202
|
+
options[:github_repo] = repo
|
|
203
|
+
end
|
|
204
|
+
|
|
201
205
|
opts.on "-w",
|
|
202
206
|
"--confidence-level LEVEL",
|
|
203
207
|
["1", "2", "3"],
|
|
@@ -116,9 +116,9 @@ class Brakeman::ControllerProcessor < Brakeman::BaseProcessor
|
|
|
116
116
|
case method
|
|
117
117
|
when :include
|
|
118
118
|
@controller[:includes] << class_name(first_arg) if @controller
|
|
119
|
-
when :before_filter, :append_before_filter
|
|
119
|
+
when :before_filter, :append_before_filter, :before_action, :append_before_action
|
|
120
120
|
@controller[:options][:before_filters] << exp.args
|
|
121
|
-
when :prepend_before_filter
|
|
121
|
+
when :prepend_before_filter, :prepend_before_action
|
|
122
122
|
@controller[:options][:before_filters].unshift exp.args
|
|
123
123
|
when :layout
|
|
124
124
|
if string? last_arg
|
|
@@ -196,7 +196,8 @@ class Brakeman::ControllerProcessor < Brakeman::BaseProcessor
|
|
|
196
196
|
|
|
197
197
|
#Look for before_filters and add fake ones if necessary
|
|
198
198
|
def process_iter exp
|
|
199
|
-
|
|
199
|
+
block_call_name = exp.block_call.method
|
|
200
|
+
if block_call_name == :before_filter or block_call_name == :before_action
|
|
200
201
|
add_fake_filter exp
|
|
201
202
|
else
|
|
202
203
|
super
|
|
@@ -106,6 +106,19 @@ class Brakeman::FindAllCalls < Brakeman::BaseProcessor
|
|
|
106
106
|
exp
|
|
107
107
|
end
|
|
108
108
|
|
|
109
|
+
# Process a dynamic regex like a call
|
|
110
|
+
def process_dregx exp
|
|
111
|
+
exp.each { |arg| process arg if sexp? arg }
|
|
112
|
+
|
|
113
|
+
@calls << { :target => nil,
|
|
114
|
+
:method => :brakeman_regex_interp,
|
|
115
|
+
:call => exp,
|
|
116
|
+
:nested => false,
|
|
117
|
+
:location => make_location }
|
|
118
|
+
|
|
119
|
+
exp
|
|
120
|
+
end
|
|
121
|
+
|
|
109
122
|
#Process an assignment like a call
|
|
110
123
|
def process_attrasgn exp
|
|
111
124
|
process_call exp
|
|
@@ -58,7 +58,10 @@ class Brakeman::Rails3RoutesProcessor < Brakeman::BaseProcessor
|
|
|
58
58
|
end
|
|
59
59
|
|
|
60
60
|
def process_namespace exp
|
|
61
|
-
|
|
61
|
+
arg = exp.block_call.first_arg
|
|
62
|
+
return exp unless symbol? arg or string? arg
|
|
63
|
+
|
|
64
|
+
name = arg.value
|
|
62
65
|
block = exp.block
|
|
63
66
|
|
|
64
67
|
@prefix << camelize(name)
|
|
@@ -197,6 +200,8 @@ class Brakeman::Rails3RoutesProcessor < Brakeman::BaseProcessor
|
|
|
197
200
|
first_arg = exp.first_arg
|
|
198
201
|
second_arg = exp.second_arg
|
|
199
202
|
|
|
203
|
+
return exp unless symbol? first_arg or string? first_arg
|
|
204
|
+
|
|
200
205
|
if second_arg and second_arg.node_type == :hash
|
|
201
206
|
self.current_controller = first_arg.value
|
|
202
207
|
#handle hash
|
data/lib/brakeman/report.rb
CHANGED
|
@@ -6,7 +6,7 @@ require 'brakeman/report/report_base'
|
|
|
6
6
|
class Brakeman::Report
|
|
7
7
|
attr_reader :tracker
|
|
8
8
|
|
|
9
|
-
VALID_FORMATS = [:to_html, :to_pdf, :to_csv, :to_json, :to_tabs, :to_hash, :to_s]
|
|
9
|
+
VALID_FORMATS = [:to_html, :to_pdf, :to_csv, :to_json, :to_tabs, :to_hash, :to_s, :to_markdown]
|
|
10
10
|
|
|
11
11
|
def initialize app_tree, tracker
|
|
12
12
|
@app_tree = app_tree
|
|
@@ -29,6 +29,8 @@ class Brakeman::Report
|
|
|
29
29
|
when :to_hash
|
|
30
30
|
require_report 'hash'
|
|
31
31
|
Brakeman::Report::Hash
|
|
32
|
+
when :to_markdown
|
|
33
|
+
return self.to_markdown
|
|
32
34
|
when :to_s
|
|
33
35
|
return self.to_s
|
|
34
36
|
when :to_pdf
|
|
@@ -62,6 +64,11 @@ class Brakeman::Report
|
|
|
62
64
|
generate Brakeman::Report::Table
|
|
63
65
|
end
|
|
64
66
|
|
|
67
|
+
def to_markdown
|
|
68
|
+
require_report 'markdown'
|
|
69
|
+
generate Brakeman::Report::Markdown
|
|
70
|
+
end
|
|
71
|
+
|
|
65
72
|
def generate reporter
|
|
66
73
|
reporter.new(@app_tree, @tracker).generate_report
|
|
67
74
|
end
|
|
@@ -139,7 +139,7 @@ class Brakeman::Report::HTML < Brakeman::Report::Base
|
|
|
139
139
|
message
|
|
140
140
|
end <<
|
|
141
141
|
"<table id='#{code_id}' class='context' style='display:none'>" <<
|
|
142
|
-
"<caption>#{warning_file(warning) || ''}</caption>"
|
|
142
|
+
"<caption>#{CGI.escapeHTML warning_file(warning) || ''}</caption>"
|
|
143
143
|
|
|
144
144
|
unless context.empty?
|
|
145
145
|
if warning.line - 1 == 1 or warning.line + 1 == 1
|
|
@@ -193,6 +193,11 @@ class Brakeman::Report::HTML < Brakeman::Report::Base
|
|
|
193
193
|
def html_message warning, message
|
|
194
194
|
message = CGI.escapeHTML(message)
|
|
195
195
|
|
|
196
|
+
if warning.file
|
|
197
|
+
github_url = github_url warning.file, warning.line
|
|
198
|
+
message.gsub!(/(near line \d+)/, "<a href='#{URI.escape github_url, /'/}' target='_blank'>\\1</a>") if github_url
|
|
199
|
+
end
|
|
200
|
+
|
|
196
201
|
if @highlight_user_input and warning.user_input
|
|
197
202
|
user_input = CGI.escapeHTML(warning.format_user_input)
|
|
198
203
|
message.gsub!(user_input, "<span class=\"user_input\">#{user_input}</span>")
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
Brakeman.load_brakeman_dependency 'terminal-table'
|
|
2
|
+
|
|
3
|
+
class Brakeman::Report::Markdown < Brakeman::Report::Base
|
|
4
|
+
|
|
5
|
+
class MarkdownTable < Terminal::Table
|
|
6
|
+
|
|
7
|
+
def initialize options = {}, &block
|
|
8
|
+
options[:style] ||= {}
|
|
9
|
+
options[:style].merge!({
|
|
10
|
+
:border_x => '-',
|
|
11
|
+
:border_y => '|',
|
|
12
|
+
:border_i => '|'
|
|
13
|
+
})
|
|
14
|
+
super options, &block
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def render
|
|
18
|
+
super.split("\n")[1...-1].join("\n")
|
|
19
|
+
end
|
|
20
|
+
alias :to_s :render
|
|
21
|
+
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def generate_report
|
|
25
|
+
out = "# BRAKEMAN REPORT\n\n" <<
|
|
26
|
+
generate_metadata.to_s << "\n\n" <<
|
|
27
|
+
generate_checks.to_s << "\n\n" <<
|
|
28
|
+
"### SUMMARY\n\n" <<
|
|
29
|
+
generate_overview.to_s << "\n\n" <<
|
|
30
|
+
generate_warning_overview.to_s << "\n\n"
|
|
31
|
+
|
|
32
|
+
#Return output early if only summarizing
|
|
33
|
+
return out if tracker.options[:summary_only]
|
|
34
|
+
|
|
35
|
+
if tracker.options[:report_routes] or tracker.options[:debug]
|
|
36
|
+
out << "### CONTROLLERS" << "\n\n" <<
|
|
37
|
+
generate_controllers.to_s << "\n\n"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
if tracker.options[:debug]
|
|
41
|
+
out << "### TEMPLATES\n\n" <<
|
|
42
|
+
generate_templates.to_s << "\n\n"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
res = generate_errors
|
|
46
|
+
out << "### Errors\n\n" << res.to_s << "\n\n" if res
|
|
47
|
+
|
|
48
|
+
res = generate_warnings
|
|
49
|
+
out << "### SECURITY WARNINGS\n\n" << res.to_s << "\n\n" if res
|
|
50
|
+
|
|
51
|
+
res = generate_controller_warnings
|
|
52
|
+
out << "### Controller Warnings:\n\n" << res.to_s << "\n\n" if res
|
|
53
|
+
|
|
54
|
+
res = generate_model_warnings
|
|
55
|
+
out << "### Model Warnings:\n\n" << res.to_s << "\n\n" if res
|
|
56
|
+
|
|
57
|
+
res = generate_template_warnings
|
|
58
|
+
out << "### View Warnings:\n\n" << res.to_s << "\n\n" if res
|
|
59
|
+
|
|
60
|
+
out
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def generate_metadata
|
|
64
|
+
MarkdownTable.new(
|
|
65
|
+
:headings =>
|
|
66
|
+
['Application path', 'Rails version', 'Brakeman version', 'Started at', 'Duration']
|
|
67
|
+
) do |t|
|
|
68
|
+
t.add_row([
|
|
69
|
+
File.expand_path(tracker.options[:app_path]),
|
|
70
|
+
rails_version,
|
|
71
|
+
Brakeman::Version,
|
|
72
|
+
tracker.start_time,
|
|
73
|
+
"#{tracker.duration} seconds",
|
|
74
|
+
])
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def generate_checks
|
|
79
|
+
MarkdownTable.new(:headings => ['Checks performed']) do |t|
|
|
80
|
+
t.add_row([checks.checks_run.sort.join(", ")])
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def generate_overview
|
|
85
|
+
num_warnings = all_warnings.length
|
|
86
|
+
|
|
87
|
+
MarkdownTable.new(:headings => ['Scanned/Reported', 'Total']) do |t|
|
|
88
|
+
t.add_row ['Controllers', tracker.controllers.length]
|
|
89
|
+
t.add_row ['Models', tracker.models.length - 1]
|
|
90
|
+
t.add_row ['Templates', number_of_templates(@tracker)]
|
|
91
|
+
t.add_row ['Errors', tracker.errors.length]
|
|
92
|
+
t.add_row ['Security Warnings', "#{num_warnings} (#{warnings_summary[:high_confidence]})"]
|
|
93
|
+
t.add_row ['Ignored Warnings', ignored_warnings.length] unless ignored_warnings.empty?
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
#Generate listings of templates and their output
|
|
98
|
+
def generate_templates
|
|
99
|
+
out_processor = Brakeman::OutputProcessor.new
|
|
100
|
+
template_rows = {}
|
|
101
|
+
tracker.templates.each do |name, template|
|
|
102
|
+
unless template[:outputs].empty?
|
|
103
|
+
template[:outputs].each do |out|
|
|
104
|
+
out = out_processor.format out
|
|
105
|
+
template_rows[name] ||= []
|
|
106
|
+
template_rows[name] << out.gsub("\n", ";").gsub(/\s+/, " ")
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
template_rows = template_rows.sort_by{|name, value| name.to_s}
|
|
112
|
+
|
|
113
|
+
output = ''
|
|
114
|
+
template_rows.each do |template|
|
|
115
|
+
output << template.first.to_s << "\n\n"
|
|
116
|
+
table = MarkdownTable.new(:headings => ['Output']) do |t|
|
|
117
|
+
# template[1] is an array of calls
|
|
118
|
+
template[1].each do |v|
|
|
119
|
+
t.add_row [v]
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
output << table.to_s << "\n\n"
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
output
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def render_array template, headings, value_array, locals
|
|
130
|
+
return if value_array.empty?
|
|
131
|
+
|
|
132
|
+
MarkdownTable.new(:headings => headings) do |t|
|
|
133
|
+
value_array.each { |value_row| t.add_row value_row }
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def convert_warning warning, original
|
|
138
|
+
warning["Confidence"] = TEXT_CONFIDENCE[warning["Confidence"]]
|
|
139
|
+
warning["Message"] = markdown_message original, warning["Message"]
|
|
140
|
+
warning["Warning Type"] = "[#{warning['Warning Type']}](#{original.link})" if original.link
|
|
141
|
+
warning
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Escape and code format warning message
|
|
145
|
+
def markdown_message warning, message
|
|
146
|
+
if warning.file
|
|
147
|
+
github_url = github_url warning.file, warning.line
|
|
148
|
+
message.gsub!(/(near line \d+)/, "[\\1](#{github_url})") if github_url
|
|
149
|
+
end
|
|
150
|
+
if warning.code
|
|
151
|
+
code = warning.format_code
|
|
152
|
+
message.gsub(code, "`#{code.gsub('`','``').gsub(/\A``|``\z/, '` `')}`")
|
|
153
|
+
else
|
|
154
|
+
message
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
end
|
data/lib/brakeman/util.rb
CHANGED
|
@@ -383,6 +383,15 @@ module Brakeman::Util
|
|
|
383
383
|
end
|
|
384
384
|
end
|
|
385
385
|
|
|
386
|
+
def github_url file, line=nil
|
|
387
|
+
if repo_url = @tracker.options[:github_url] and file and not file.empty? and file.start_with? '/'
|
|
388
|
+
url = "#{repo_url}/#{relative_path(file)}"
|
|
389
|
+
url << "#L#{line}" if line
|
|
390
|
+
else
|
|
391
|
+
nil
|
|
392
|
+
end
|
|
393
|
+
end
|
|
394
|
+
|
|
386
395
|
def truncate_table str
|
|
387
396
|
@terminal_width ||= if @tracker.options[:table_width]
|
|
388
397
|
@tracker.options[:table_width]
|
data/lib/brakeman/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,107 +1,103 @@
|
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: brakeman-min
|
|
3
|
-
version: !ruby/object:Gem::Version
|
|
4
|
-
|
|
5
|
-
prerelease:
|
|
6
|
-
segments:
|
|
7
|
-
- 2
|
|
8
|
-
- 4
|
|
9
|
-
- 3
|
|
10
|
-
version: 2.4.3
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 2.5.0
|
|
11
5
|
platform: ruby
|
|
12
|
-
authors:
|
|
6
|
+
authors:
|
|
13
7
|
- Justin Collins
|
|
14
8
|
autorequire:
|
|
15
9
|
bindir: bin
|
|
16
|
-
cert_chain:
|
|
17
|
-
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
10
|
+
cert_chain:
|
|
11
|
+
- !binary |-
|
|
12
|
+
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURMakNDQWhhZ0F3SUJB
|
|
13
|
+
Z0lCQURBTkJna3Foa2lHOXcwQkFRVUZBREE5TVF3d0NnWURWUVFEREFOblpX
|
|
14
|
+
MHgKR0RBV0Jnb0praWFKay9Jc1pBRVpGZ2hpY21GclpXMWhiakVUTUJFR0Nn
|
|
15
|
+
bVNKb21UOGl4a0FSa1dBMjl5WnpBZQpGdzB4TXpFeU1USXdNRE14TlRkYUZ3
|
|
16
|
+
MHhOREV5TVRJd01ETXhOVGRhTUQweEREQUtCZ05WQkFNTUEyZGxiVEVZCk1C
|
|
17
|
+
WUdDZ21TSm9tVDhpeGtBUmtXQ0dKeVlXdGxiV0Z1TVJNd0VRWUtDWkltaVpQ
|
|
18
|
+
eUxHUUJHUllEYjNKbk1JSUIKSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4
|
|
19
|
+
QU1JSUJDZ0tDQVFFQXhDSG1YQ2FBY1o0YlZqaWpLb3lRRng0TgpkeU43Qjdi
|
|
20
|
+
cVk4d09YeTZmL1VaNm1kQzhJUkFqODJLYVdRak5FMkxUL09iRlVXcENSeUxk
|
|
21
|
+
cndqa0RqZEZEeU9UCm1aQ1praU9lRXkyWnhZR2Z4WE1JL3hnMjRjOHI1WG1o
|
|
22
|
+
MTZFcnNZdXByUmNnKy9LWjZzNFVqc2VCTlRBUm1CSzQKSUhjcUlkbm9XYllh
|
|
23
|
+
M0JXSG9mbEpQYUpVSWFVKy95VGNsekZRSHBzd1U3a2E4ZnRJQVdlb0RRbzIy
|
|
24
|
+
Z2FzUC80TgpIdEp2QUl5ZzFEY1dQTGNuMHFiWm1kZWhnOEhadjhDKzJNdUxL
|
|
25
|
+
WC8ycVpHOWVzZWVnTXFNbEhIYWJ3d0V5OVZ2CmYvdC8rbHRMakMwQ1JhMlRx
|
|
26
|
+
WjJFdVE1RUV6Yk9zcUFmdGFaSkZtd3Y5VXQxVWhqbWR2UjVSZk42ZFdNUTVR
|
|
27
|
+
SUQKQVFBQm96a3dOekFMQmdOVkhROEVCQU1DQkxBd0hRWURWUjBPQkJZRUZQ
|
|
28
|
+
eUVLZVJ5MDlpOHFTcis5S0ZiZVRxdwprTUNTTUFrR0ExVWRFd1FDTUFBd0RR
|
|
29
|
+
WUpLb1pJaHZjTkFRRUZCUUFEZ2dFQkFMRWs4L1dubDJWQXFjaHhXbGJnClJO
|
|
30
|
+
ME1rVlVXTWY4TDB4eFVpVktvNVFlTDROQlZpQUxNQnJVNklTNHk2enluK0Zv
|
|
31
|
+
VUxBTUVhd1VqWmxaZjRIY2cKUzl1bmV2M3ArUlRXVXlrc0FuQTI3d0hacy9O
|
|
32
|
+
UklrVzM0czFaSTVOTkUveHl1NFVMT1FqZmgxd09qbFd6eUh1OQowdDQxL0N0
|
|
33
|
+
cGdOUE0ydUFqRzNSSXFscDdRS1hsYnk1MGNRcVdKUUNnVEgzSk5qTWhtUk9F
|
|
34
|
+
aFRzSTZDT29BcHZkCkNlN0JyMzl5amVvYXJ2ZWtxMHdDWEJZYWtVQncvRGRa
|
|
35
|
+
Q0c3bUZaNnhnaDAxZXFuWlVzTmQ4dk0rNlY2djIzVnUKamsydE1qRlQ0TDFk
|
|
36
|
+
QTNNRXN6MytNUDE0NFBEaFBDaDd0UGU2eXk4MUJPdnlZVFZrS3pyQWtnS3dI
|
|
37
|
+
RDFDdXZzSApiZHc9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
|
|
38
|
+
date: 2014-04-30 00:00:00.000000000 Z
|
|
39
|
+
dependencies:
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
42
41
|
name: ruby_parser
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
none: false
|
|
46
|
-
requirements:
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
47
44
|
- - ~>
|
|
48
|
-
- !ruby/object:Gem::Version
|
|
49
|
-
hash: 23
|
|
50
|
-
segments:
|
|
51
|
-
- 3
|
|
52
|
-
- 4
|
|
53
|
-
- 0
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
54
46
|
version: 3.4.0
|
|
55
47
|
type: :runtime
|
|
56
|
-
version_requirements: *id001
|
|
57
|
-
- !ruby/object:Gem::Dependency
|
|
58
|
-
name: ruby2ruby
|
|
59
48
|
prerelease: false
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ~>
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: 3.4.0
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: ruby2ruby
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
63
58
|
- - ~>
|
|
64
|
-
- !ruby/object:Gem::Version
|
|
65
|
-
hash: 5
|
|
66
|
-
segments:
|
|
67
|
-
- 2
|
|
68
|
-
- 0
|
|
69
|
-
- 5
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
70
60
|
version: 2.0.5
|
|
71
61
|
type: :runtime
|
|
72
|
-
version_requirements: *id002
|
|
73
|
-
- !ruby/object:Gem::Dependency
|
|
74
|
-
name: multi_json
|
|
75
62
|
prerelease: false
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
requirements:
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
79
65
|
- - ~>
|
|
80
|
-
- !ruby/object:Gem::Version
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: 2.0.5
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: multi_json
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - ~>
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '1.2'
|
|
86
75
|
type: :runtime
|
|
87
|
-
|
|
88
|
-
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - ~>
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '1.2'
|
|
82
|
+
description: Brakeman detects security vulnerabilities in Ruby on Rails applications
|
|
83
|
+
via static analysis. This version of the gem only requires the minimum number of
|
|
84
|
+
dependencies. Use the 'brakeman' gem for a full install.
|
|
89
85
|
email: gem@brakeman.org
|
|
90
|
-
executables:
|
|
86
|
+
executables:
|
|
91
87
|
- brakeman
|
|
92
88
|
extensions: []
|
|
93
|
-
|
|
94
89
|
extra_rdoc_files: []
|
|
95
|
-
|
|
96
|
-
files:
|
|
97
|
-
- bin/brakeman
|
|
90
|
+
files:
|
|
98
91
|
- CHANGES
|
|
99
|
-
- WARNING_TYPES
|
|
100
92
|
- FEATURES
|
|
101
93
|
- README.md
|
|
94
|
+
- WARNING_TYPES
|
|
95
|
+
- bin/brakeman
|
|
96
|
+
- lib/brakeman.rb
|
|
102
97
|
- lib/brakeman/app_tree.rb
|
|
103
98
|
- lib/brakeman/brakeman.rake
|
|
104
99
|
- lib/brakeman/call_index.rb
|
|
100
|
+
- lib/brakeman/checks.rb
|
|
105
101
|
- lib/brakeman/checks/base_check.rb
|
|
106
102
|
- lib/brakeman/checks/check_basic_auth.rb
|
|
107
103
|
- lib/brakeman/checks/check_content_tag.rb
|
|
@@ -131,6 +127,7 @@ files:
|
|
|
131
127
|
- lib/brakeman/checks/check_number_to_currency.rb
|
|
132
128
|
- lib/brakeman/checks/check_quote_table_name.rb
|
|
133
129
|
- lib/brakeman/checks/check_redirect.rb
|
|
130
|
+
- lib/brakeman/checks/check_regex_dos.rb
|
|
134
131
|
- lib/brakeman/checks/check_render.rb
|
|
135
132
|
- lib/brakeman/checks/check_render_dos.rb
|
|
136
133
|
- lib/brakeman/checks/check_response_splitting.rb
|
|
@@ -145,6 +142,7 @@ files:
|
|
|
145
142
|
- lib/brakeman/checks/check_single_quotes.rb
|
|
146
143
|
- lib/brakeman/checks/check_skip_before_filter.rb
|
|
147
144
|
- lib/brakeman/checks/check_sql.rb
|
|
145
|
+
- lib/brakeman/checks/check_sql_cves.rb
|
|
148
146
|
- lib/brakeman/checks/check_ssl_verify.rb
|
|
149
147
|
- lib/brakeman/checks/check_strip_tags.rb
|
|
150
148
|
- lib/brakeman/checks/check_symbol_dos.rb
|
|
@@ -153,7 +151,6 @@ files:
|
|
|
153
151
|
- lib/brakeman/checks/check_validation_regex.rb
|
|
154
152
|
- lib/brakeman/checks/check_without_protection.rb
|
|
155
153
|
- lib/brakeman/checks/check_yaml_parsing.rb
|
|
156
|
-
- lib/brakeman/checks.rb
|
|
157
154
|
- lib/brakeman/differ.rb
|
|
158
155
|
- lib/brakeman/format/style.css
|
|
159
156
|
- lib/brakeman/options.rb
|
|
@@ -187,6 +184,7 @@ files:
|
|
|
187
184
|
- lib/brakeman/processors/slim_template_processor.rb
|
|
188
185
|
- lib/brakeman/processors/template_alias_processor.rb
|
|
189
186
|
- lib/brakeman/processors/template_processor.rb
|
|
187
|
+
- lib/brakeman/report.rb
|
|
190
188
|
- lib/brakeman/report/ignore/config.rb
|
|
191
189
|
- lib/brakeman/report/ignore/interactive.rb
|
|
192
190
|
- lib/brakeman/report/initializers/faster_csv.rb
|
|
@@ -197,6 +195,7 @@ files:
|
|
|
197
195
|
- lib/brakeman/report/report_hash.rb
|
|
198
196
|
- lib/brakeman/report/report_html.rb
|
|
199
197
|
- lib/brakeman/report/report_json.rb
|
|
198
|
+
- lib/brakeman/report/report_markdown.rb
|
|
200
199
|
- lib/brakeman/report/report_table.rb
|
|
201
200
|
- lib/brakeman/report/report_tabs.rb
|
|
202
201
|
- lib/brakeman/report/templates/controller_overview.html.erb
|
|
@@ -210,7 +209,6 @@ files:
|
|
|
210
209
|
- lib/brakeman/report/templates/template_overview.html.erb
|
|
211
210
|
- lib/brakeman/report/templates/view_warnings.html.erb
|
|
212
211
|
- lib/brakeman/report/templates/warning_overview.html.erb
|
|
213
|
-
- lib/brakeman/report.rb
|
|
214
212
|
- lib/brakeman/rescanner.rb
|
|
215
213
|
- lib/brakeman/scanner.rb
|
|
216
214
|
- lib/brakeman/tracker.rb
|
|
@@ -218,41 +216,30 @@ files:
|
|
|
218
216
|
- lib/brakeman/version.rb
|
|
219
217
|
- lib/brakeman/warning.rb
|
|
220
218
|
- lib/brakeman/warning_codes.rb
|
|
221
|
-
- lib/brakeman.rb
|
|
222
219
|
- lib/ruby_parser/bm_sexp.rb
|
|
223
220
|
- lib/ruby_parser/bm_sexp_processor.rb
|
|
224
221
|
homepage: http://brakemanscanner.org
|
|
225
|
-
licenses:
|
|
222
|
+
licenses:
|
|
226
223
|
- MIT
|
|
224
|
+
metadata: {}
|
|
227
225
|
post_install_message:
|
|
228
226
|
rdoc_options: []
|
|
229
|
-
|
|
230
|
-
require_paths:
|
|
227
|
+
require_paths:
|
|
231
228
|
- lib
|
|
232
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
none: false
|
|
243
|
-
requirements:
|
|
244
|
-
- - ">="
|
|
245
|
-
- !ruby/object:Gem::Version
|
|
246
|
-
hash: 3
|
|
247
|
-
segments:
|
|
248
|
-
- 0
|
|
249
|
-
version: "0"
|
|
229
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
230
|
+
requirements:
|
|
231
|
+
- - ! '>='
|
|
232
|
+
- !ruby/object:Gem::Version
|
|
233
|
+
version: '0'
|
|
234
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
235
|
+
requirements:
|
|
236
|
+
- - ! '>='
|
|
237
|
+
- !ruby/object:Gem::Version
|
|
238
|
+
version: '0'
|
|
250
239
|
requirements: []
|
|
251
|
-
|
|
252
240
|
rubyforge_project:
|
|
253
|
-
rubygems_version:
|
|
241
|
+
rubygems_version: 2.2.2
|
|
254
242
|
signing_key:
|
|
255
|
-
specification_version:
|
|
243
|
+
specification_version: 4
|
|
256
244
|
summary: Security vulnerability scanner for Ruby on Rails.
|
|
257
245
|
test_files: []
|
|
258
|
-
|
metadata.gz.sig
CHANGED
|
Binary file
|