brakeman 1.5.1 → 1.5.2

Sign up to get free protection for your applications and to get access to all the features.
data/bin/brakeman CHANGED
@@ -6,14 +6,6 @@ require 'brakeman'
6
6
  require 'brakeman/options'
7
7
  require 'brakeman/version'
8
8
 
9
- trap("INT") do
10
- $stderr.puts "\nInterrupted - exiting."
11
- if RUBY_VERSION.include? "1.9"
12
- $stderr.puts Thread.current.backtrace
13
- end
14
- exit!
15
- end
16
-
17
9
  #Parse options
18
10
  options, parser = Brakeman::Options.parse! ARGV
19
11
 
@@ -44,6 +36,16 @@ unless options[:app_path]
44
36
  end
45
37
  end
46
38
 
39
+ trap("INT") do
40
+ $stderr.puts "\nInterrupted - exiting."
41
+
42
+ if options[:debug]
43
+ $stderr.puts caller
44
+ end
45
+
46
+ exit!
47
+ end
48
+
47
49
  #Run scan and output a report
48
50
  tracker = Brakeman.run options.merge(:print_report => true, :quiet => options[:quiet])
49
51
 
@@ -78,6 +78,18 @@ class Brakeman::BaseCheck < SexpProcessor
78
78
  exp
79
79
  end
80
80
 
81
+ def process_if exp
82
+ #This is to ignore user input in condition
83
+ current_user_input = @has_user_input
84
+ process exp[1]
85
+ @has_user_input = current_user_input
86
+
87
+ process exp[2] if sexp? exp[2]
88
+ process exp[3] if sexp? exp[3]
89
+
90
+ exp
91
+ end
92
+
81
93
  #Note that params are included in current expression
82
94
  def process_params exp
83
95
  @has_user_input = :params
@@ -42,13 +42,25 @@ class Brakeman::CheckLinkTo < Brakeman::CheckCrossSiteScripting
42
42
 
43
43
  @matched = false
44
44
 
45
- return if call[3][1].nil?
45
+ #Skip if no arguments(?) or first argument is a hash
46
+ return if call[3][1].nil? or hash? call[3][1]
46
47
 
47
- #Only check first argument for +link_to+, as the second
48
- #will *usually* be a record or escaped.
49
- first_arg = process call[3][1]
48
+ if version_between? "2.0.0", "2.2.99"
49
+ check_argument result, call[3][1]
50
50
 
51
- type, match = has_immediate_user_input? first_arg
51
+ if call[3][2] and not hash? call[3][2]
52
+ check_argument result, call[3][2]
53
+ end
54
+ elsif call[3][2]
55
+ #Only check first argument if there is a second argument
56
+ #in Rails 2.3.x
57
+ check_argument result, call[3][1]
58
+ end
59
+ end
60
+
61
+ def check_argument result, exp
62
+ arg = process exp
63
+ type, match = has_immediate_user_input? arg
52
64
 
53
65
  if type
54
66
  case type
@@ -65,7 +77,7 @@ class Brakeman::CheckLinkTo < Brakeman::CheckCrossSiteScripting
65
77
  :warning_type => "Cross Site Scripting",
66
78
  :message => message,
67
79
  :confidence => CONFIDENCE[:high]
68
- elsif not tracker.options[:ignore_model_output] and match = has_immediate_model?(first_arg)
80
+ elsif not tracker.options[:ignore_model_output] and match = has_immediate_model?(arg)
69
81
  method = match[2]
70
82
 
71
83
  unless IGNORE_MODEL_METHODS.include? method
@@ -29,30 +29,44 @@ class Brakeman::CheckRender < Brakeman::BaseCheck
29
29
  def check_for_dynamic_path result
30
30
  view = result[:call][2]
31
31
 
32
- if sexp? view and view.node_type != :str and view.node_type != :lit and not duplicate? result
33
-
32
+ if sexp? view and not duplicate? result
34
33
  add_result result
35
34
 
36
- if include_user_input? view
35
+ type, match = has_immediate_user_input? view
36
+
37
+ if type
37
38
  confidence = CONFIDENCE[:high]
39
+ elsif type = include_user_input?(view)
40
+ if node_type? view, :string_interp, :dstr
41
+ confidence = CONFIDENCE[:med]
42
+ else
43
+ confidence = CONFIDENCE[:low]
44
+ end
38
45
  else
39
- confidence = CONFIDENCE[:low]
46
+ return
40
47
  end
41
48
 
42
- warning = { :warning_type => "Dynamic Render Path",
43
- :message => "Render path is dynamic",
44
- :line => result[:call].line,
45
- :code => result[:call],
46
- :confidence => confidence }
49
+ message = "Render path contains "
47
50
 
48
- if result[:location][0] == :template
49
- warning[:template] = result[:location][1]
51
+ case type
52
+ when :params
53
+ message << "parameter value"
54
+ when :cookies
55
+ message << "cookie value"
56
+ when :request
57
+ message << "request value"
58
+ when :model
59
+ #Skip models
60
+ return
50
61
  else
51
- warning[:class] = result[:location][1]
52
- warning[:method] = result[:location][2]
62
+ message << "user input value"
53
63
  end
54
64
 
55
- warn warning
65
+
66
+ warn :result => result,
67
+ :warning_type => "Dynamic Render Path",
68
+ :message => message,
69
+ :confidence => confidence
56
70
  end
57
71
  end
58
72
  end
@@ -201,7 +201,7 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
201
201
  true
202
202
  elsif call? target
203
203
  check_call target
204
- elsif target == nil and tracker.options[:rails3] and method.to_s.match /^first|last|all|where|order|group|having$/
204
+ elsif target == nil and tracker.options[:rails3] and method.to_s.match(/^first|last|all|where|order|group|having$/)
205
205
  check_arguments args
206
206
  else
207
207
  false
@@ -91,7 +91,7 @@ module Brakeman::Options
91
91
 
92
92
  opts.on "--skip-files file1,file2,etc", Array, "Skip processing of these files" do |files|
93
93
  options[:skip_files] ||= Set.new
94
- options[:skip_files].merge files.map {|f| f.to_sym }
94
+ options[:skip_files].merge files
95
95
  end
96
96
 
97
97
  opts.on "--skip-libs", "Skip processing lib directory" do
@@ -12,16 +12,22 @@ class Brakeman::ErubisTemplateProcessor < Brakeman::TemplateProcessor
12
12
  method = exp[2]
13
13
 
14
14
  #_buf is the default output variable for Erubis
15
- if target and (target[1] == :_buf or target[1] == :output_buffer)
15
+ if target and (target[1] == :_buf or target[1] == :@output_buffer)
16
16
  if method == :<< or method == :safe_concat
17
17
  args = exp[3][1] = process(exp[3][1])
18
18
 
19
- if args.node_type == :call and args[2] == :to_s #just calling to_s on inner code
19
+ #We want the actual content
20
+ if args.node_type == :call and (args[2] == :to_s or args[2] == :html_safe!)
20
21
  args = args[1]
21
22
  end
22
23
 
23
24
  if args.node_type == :str #ignore plain strings
24
25
  ignore
26
+ elsif target[1] == :@output_buffer
27
+ s = Sexp.new :escaped_output, args
28
+ s.line(exp.line)
29
+ @current_template[:outputs] << s
30
+ s
25
31
  else
26
32
  s = Sexp.new :output, args
27
33
  s.line(exp.line)
@@ -31,7 +37,7 @@ class Brakeman::ErubisTemplateProcessor < Brakeman::TemplateProcessor
31
37
  elsif method == :to_s
32
38
  ignore
33
39
  else
34
- abort "Unrecognized action on _buf: #{method}"
40
+ abort "Unrecognized action on buffer: #{method}"
35
41
  end
36
42
  elsif target == nil and method == :render
37
43
  exp[3] = process exp[3]
@@ -74,7 +74,7 @@ class Brakeman::Rescanner < Brakeman::Scanner
74
74
  when :model
75
75
  rescan_model path
76
76
  when :lib
77
- process_library path
77
+ process_lib path
78
78
  when :config
79
79
  process_config
80
80
  when :initializer
@@ -1,7 +1,12 @@
1
1
  require 'rubygems'
2
2
  begin
3
- #Load our own version of ruby_parser :'(
4
- require 'ruby_parser/ruby_parser.rb'
3
+ if RUBY_VERSION =~ /^1\.9/
4
+ #Load our own version of ruby_parser :'(
5
+ require 'ruby_parser/ruby_parser.rb'
6
+ else
7
+ require 'ruby_parser'
8
+ require 'ruby_parser/bm_sexp.rb'
9
+ end
5
10
 
6
11
  require 'haml'
7
12
  require 'sass'
@@ -47,7 +52,7 @@ class Brakeman::Scanner
47
52
  if RUBY_1_9
48
53
  @ruby_parser = ::Ruby19Parser
49
54
  else
50
- @ruby_parser = ::Ruby18Parser
55
+ @ruby_parser = ::RubyParser
51
56
  end
52
57
  end
53
58
 
@@ -1,3 +1,3 @@
1
1
  module Brakeman
2
- Version = "1.5.1"
2
+ Version = "1.5.2"
3
3
  end
@@ -0,0 +1,112 @@
1
+ #Sexp changes from ruby_parser
2
+ #and some changes for caching hash value and tracking 'original' line number
3
+ #of a Sexp.
4
+ class Sexp
5
+ attr_reader :paren
6
+
7
+ def paren
8
+ @paren ||= false
9
+ end
10
+
11
+ def value
12
+ raise "multi item sexp" if size > 2
13
+ last
14
+ end
15
+
16
+ def to_sym
17
+ self.value.to_sym
18
+ end
19
+
20
+ alias :node_type :sexp_type
21
+ alias :values :sexp_body # TODO: retire
22
+
23
+ alias :old_init :initialize
24
+ alias :old_push :<<
25
+ alias :old_line :line
26
+ alias :old_line_set :line=
27
+ alias :old_file_set :file=
28
+ alias :old_comments_set :comments=
29
+ alias :old_compact :compact
30
+ alias :old_fara :find_and_replace_all
31
+ alias :old_find_node :find_node
32
+
33
+ def initialize *args
34
+ old_init(*args)
35
+ @original_line = nil
36
+ @my_hash_value = nil
37
+ end
38
+
39
+ def original_line line = nil
40
+ if line
41
+ @my_hash_value = nil
42
+ @original_line = line
43
+ else
44
+ @original_line
45
+ end
46
+ end
47
+
48
+ def hash
49
+ #There still seems to be some instances in which the hash of the
50
+ #Sexp changes, but I have not found what method call is doing it.
51
+ #Of course, Sexp is subclasses from Array, so who knows what might
52
+ #be going on.
53
+ @my_hash_value ||= super
54
+ end
55
+
56
+ def line *args
57
+ @my_hash_value = nil
58
+ old_line(*args)
59
+ end
60
+
61
+ def line= *args
62
+ @my_hash_value = nil
63
+ old_line_set(*args)
64
+ end
65
+
66
+ def file= *args
67
+ @my_hash_value = nil
68
+ old_file_set(*args)
69
+ end
70
+
71
+ def compact
72
+ @my_hash_value = nil
73
+ old_compact
74
+ end
75
+
76
+ def find_and_replace_all *args
77
+ @my_hash_value = nil
78
+ old_fara(*args)
79
+ end
80
+
81
+ def find_node *args
82
+ @my_hash_value = nil
83
+ old_find_node(*args)
84
+ end
85
+
86
+ def paren= arg
87
+ @my_hash_value = nil
88
+ @paren = arg
89
+ end
90
+
91
+ def comments= *args
92
+ @my_hash_value = nil
93
+ old_comments_set(*args)
94
+ end
95
+ end
96
+
97
+ #Invalidate hash cache if the Sexp changes
98
+ [:[]=, :clear, :collect!, :compact!, :concat, :delete, :delete_at,
99
+ :delete_if, :drop, :drop_while, :fill, :flatten!, :replace, :insert,
100
+ :keep_if, :map!, :pop, :push, :reject!, :replace, :reverse!, :rotate!,
101
+ :select!, :shift, :shuffle!, :slice!, :sort!, :sort_by!, :transpose,
102
+ :uniq!, :unshift].each do |method|
103
+
104
+ Sexp.class_eval <<-RUBY
105
+ def #{method} *args
106
+ @my_hash_value = nil
107
+ super
108
+ end
109
+ RUBY
110
+ end
111
+
112
+
@@ -1051,113 +1051,7 @@ class Symbol
1051
1051
  end
1052
1052
  end
1053
1053
 
1054
- class Sexp
1055
- attr_reader :paren
1056
-
1057
- def paren
1058
- @paren ||= false
1059
- end
1060
-
1061
- def value
1062
- raise "multi item sexp" if size > 2
1063
- last
1064
- end
1065
-
1066
- def to_sym
1067
- self.value.to_sym
1068
- end
1069
-
1070
- alias :node_type :sexp_type
1071
- alias :values :sexp_body # TODO: retire
1072
-
1073
- alias :old_init :initialize
1074
- alias :old_push :<<
1075
- alias :old_line :line
1076
- alias :old_line_set :line=
1077
- alias :old_file_set :file=
1078
- alias :old_comments_set :comments=
1079
- alias :old_compact :compact
1080
- alias :old_fara :find_and_replace_all
1081
- alias :old_find_node :find_node
1082
-
1083
- def initialize *args
1084
- old_init *args
1085
- @original_line = nil
1086
- @my_hash_value = nil
1087
- end
1088
-
1089
- def original_line line = nil
1090
- if line
1091
- @my_hash_value = nil
1092
- @original_line = line
1093
- else
1094
- @original_line
1095
- end
1096
- end
1097
-
1098
- def hash
1099
- #There still seems to be some instances in which the hash of the
1100
- #Sexp changes, but I have not found what method call is doing it.
1101
- #Of course, Sexp is subclasses from Array, so who knows what might
1102
- #be going on.
1103
- @my_hash_value ||= super
1104
- end
1105
-
1106
- def line *args
1107
- @my_hash_value = nil
1108
- old_line *args
1109
- end
1110
-
1111
- def line= *args
1112
- @my_hash_value = nil
1113
- old_line_set *args
1114
- end
1115
-
1116
- def file= *args
1117
- @my_hash_value = nil
1118
- old_file_set *args
1119
- end
1120
-
1121
- def compact
1122
- @my_hash_value = nil
1123
- old_compact
1124
- end
1125
-
1126
- def find_and_replace_all *args
1127
- @my_hash_value = nil
1128
- old_fara *args
1129
- end
1130
-
1131
- def find_node *args
1132
- @my_hash_value = nil
1133
- old_find_node *args
1134
- end
1135
-
1136
- def paren= arg
1137
- @my_hash_value = nil
1138
- @paren = arg
1139
- end
1140
-
1141
- def comments= *args
1142
- @my_hash_value = nil
1143
- old_comments_set *args
1144
- end
1145
- end
1146
-
1147
- #Invalidate hash cache if the Sexp changes
1148
- [:[]=, :clear, :collect!, :compact!, :concat, :delete, :delete_at,
1149
- :delete_if, :drop, :drop_while, :fill, :flatten!, :replace, :insert,
1150
- :keep_if, :map!, :pop, :push, :reject!, :replace, :reverse!, :rotate!,
1151
- :select!, :shift, :shuffle!, :slice!, :sort!, :sort_by!, :transpose,
1152
- :uniq!, :unshift].each do |method|
1153
-
1154
- Sexp.class_eval <<-RUBY
1155
- def #{method} *args
1156
- @my_hash_value = nil
1157
- super
1158
- end
1159
- RUBY
1160
- end
1054
+ require 'bm_sexp'
1161
1055
 
1162
1056
  # END HACK
1163
1057
  ############################################################
metadata CHANGED
@@ -1,107 +1,141 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: brakeman
3
- version: !ruby/object:Gem::Version
4
- version: 1.5.1
3
+ version: !ruby/object:Gem::Version
4
+ hash: 7
5
5
  prerelease:
6
+ segments:
7
+ - 1
8
+ - 5
9
+ - 2
10
+ version: 1.5.2
6
11
  platform: ruby
7
- authors:
12
+ authors:
8
13
  - Justin Collins
9
14
  autorequire:
10
15
  bindir: bin
11
16
  cert_chain: []
12
- date: 2012-03-06 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
17
+
18
+ date: 2012-03-22 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
15
21
  name: activesupport
16
- requirement: &72282300 !ruby/object:Gem::Requirement
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
17
24
  none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
21
- version: '0'
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 0
31
+ version: "0"
22
32
  type: :runtime
23
- prerelease: false
24
- version_requirements: *72282300
25
- - !ruby/object:Gem::Dependency
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
26
35
  name: i18n
27
- requirement: &72282080 !ruby/object:Gem::Requirement
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
28
38
  none: false
29
- requirements:
30
- - - ! '>='
31
- - !ruby/object:Gem::Version
32
- version: '0'
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ hash: 3
43
+ segments:
44
+ - 0
45
+ version: "0"
33
46
  type: :runtime
34
- prerelease: false
35
- version_requirements: *72282080
36
- - !ruby/object:Gem::Dependency
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
37
49
  name: ruby2ruby
38
- requirement: &72281550 !ruby/object:Gem::Requirement
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
39
52
  none: false
40
- requirements:
53
+ requirements:
41
54
  - - ~>
42
- - !ruby/object:Gem::Version
43
- version: '1.2'
55
+ - !ruby/object:Gem::Version
56
+ hash: 11
57
+ segments:
58
+ - 1
59
+ - 2
60
+ version: "1.2"
44
61
  type: :runtime
45
- prerelease: false
46
- version_requirements: *72281550
47
- - !ruby/object:Gem::Dependency
62
+ version_requirements: *id003
63
+ - !ruby/object:Gem::Dependency
48
64
  name: ruport
49
- requirement: &72280450 !ruby/object:Gem::Requirement
65
+ prerelease: false
66
+ requirement: &id004 !ruby/object:Gem::Requirement
50
67
  none: false
51
- requirements:
68
+ requirements:
52
69
  - - ~>
53
- - !ruby/object:Gem::Version
54
- version: '1.6'
70
+ - !ruby/object:Gem::Version
71
+ hash: 3
72
+ segments:
73
+ - 1
74
+ - 6
75
+ version: "1.6"
55
76
  type: :runtime
56
- prerelease: false
57
- version_requirements: *72280450
58
- - !ruby/object:Gem::Dependency
77
+ version_requirements: *id004
78
+ - !ruby/object:Gem::Dependency
59
79
  name: erubis
60
- requirement: &72280190 !ruby/object:Gem::Requirement
80
+ prerelease: false
81
+ requirement: &id005 !ruby/object:Gem::Requirement
61
82
  none: false
62
- requirements:
83
+ requirements:
63
84
  - - ~>
64
- - !ruby/object:Gem::Version
65
- version: '2.6'
85
+ - !ruby/object:Gem::Version
86
+ hash: 15
87
+ segments:
88
+ - 2
89
+ - 6
90
+ version: "2.6"
66
91
  type: :runtime
67
- prerelease: false
68
- version_requirements: *72280190
69
- - !ruby/object:Gem::Dependency
92
+ version_requirements: *id005
93
+ - !ruby/object:Gem::Dependency
70
94
  name: haml
71
- requirement: &72279750 !ruby/object:Gem::Requirement
95
+ prerelease: false
96
+ requirement: &id006 !ruby/object:Gem::Requirement
72
97
  none: false
73
- requirements:
98
+ requirements:
74
99
  - - ~>
75
- - !ruby/object:Gem::Version
76
- version: '3.0'
100
+ - !ruby/object:Gem::Version
101
+ hash: 7
102
+ segments:
103
+ - 3
104
+ - 0
105
+ version: "3.0"
77
106
  type: :runtime
78
- prerelease: false
79
- version_requirements: *72279750
80
- - !ruby/object:Gem::Dependency
107
+ version_requirements: *id006
108
+ - !ruby/object:Gem::Dependency
81
109
  name: sass
82
- requirement: &72279400 !ruby/object:Gem::Requirement
110
+ prerelease: false
111
+ requirement: &id007 !ruby/object:Gem::Requirement
83
112
  none: false
84
- requirements:
113
+ requirements:
85
114
  - - ~>
86
- - !ruby/object:Gem::Version
87
- version: '3.0'
115
+ - !ruby/object:Gem::Version
116
+ hash: 7
117
+ segments:
118
+ - 3
119
+ - 0
120
+ version: "3.0"
88
121
  type: :runtime
89
- prerelease: false
90
- version_requirements: *72279400
91
- description: Brakeman detects security vulnerabilities in Ruby on Rails applications
92
- via static analysis.
122
+ version_requirements: *id007
123
+ description: Brakeman detects security vulnerabilities in Ruby on Rails applications via static analysis.
93
124
  email:
94
- executables:
125
+ executables:
95
126
  - brakeman
96
127
  extensions: []
128
+
97
129
  extra_rdoc_files: []
98
- files:
130
+
131
+ files:
99
132
  - bin/brakeman
100
133
  - WARNING_TYPES
101
134
  - FEATURES
102
135
  - README.md
103
136
  - lib/ruby_parser/ruby18_parser.rb
104
137
  - lib/ruby_parser/ruby_parser_extras.rb
138
+ - lib/ruby_parser/bm_sexp.rb
105
139
  - lib/ruby_parser/ruby_lexer.rb
106
140
  - lib/ruby_parser/ruby_parser.rb
107
141
  - lib/ruby_parser/ruby19_parser.rb
@@ -175,26 +209,36 @@ files:
175
209
  - lib/brakeman/format/style.css
176
210
  homepage: http://brakemanscanner.org
177
211
  licenses: []
212
+
178
213
  post_install_message:
179
214
  rdoc_options: []
180
- require_paths:
215
+
216
+ require_paths:
181
217
  - lib
182
- required_ruby_version: !ruby/object:Gem::Requirement
218
+ required_ruby_version: !ruby/object:Gem::Requirement
183
219
  none: false
184
- requirements:
185
- - - ! '>='
186
- - !ruby/object:Gem::Version
187
- version: '0'
188
- required_rubygems_version: !ruby/object:Gem::Requirement
220
+ requirements:
221
+ - - ">="
222
+ - !ruby/object:Gem::Version
223
+ hash: 3
224
+ segments:
225
+ - 0
226
+ version: "0"
227
+ required_rubygems_version: !ruby/object:Gem::Requirement
189
228
  none: false
190
- requirements:
191
- - - ! '>='
192
- - !ruby/object:Gem::Version
193
- version: '0'
229
+ requirements:
230
+ - - ">="
231
+ - !ruby/object:Gem::Version
232
+ hash: 3
233
+ segments:
234
+ - 0
235
+ version: "0"
194
236
  requirements: []
237
+
195
238
  rubyforge_project:
196
239
  rubygems_version: 1.8.15
197
240
  signing_key:
198
241
  specification_version: 3
199
242
  summary: Security vulnerability scanner for Ruby on Rails.
200
243
  test_files: []
244
+