brakeman 1.0.0 → 1.1.pre

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/bin/brakeman CHANGED
@@ -24,6 +24,10 @@ OptionParser.new do |opts|
24
24
  options[:parallel_checks] = false
25
25
  end
26
26
 
27
+ opts.on "--no-progress", "Do not show progress reports" do
28
+ options[:report_progress] = false
29
+ end
30
+
27
31
  opts.on "-p", "--path PATH", "Specify path to Rails application" do |path|
28
32
  options[:app_path] = File.expand_path path
29
33
  end
@@ -55,6 +59,15 @@ OptionParser.new do |opts|
55
59
  options[:escape_html] = true
56
60
  end
57
61
 
62
+ opts.on "--faster", "Faster, but less accurate scan" do
63
+ options[:ignore_ifs] = true
64
+ options[:skip_libs] = true
65
+ end
66
+
67
+ opts.on "--no-branching", "Disable flow sensitivity on conditionals" do
68
+ options[:ignore_ifs] = true
69
+ end
70
+
58
71
  opts.on "-r", "--report-direct", "Only report direct use of untrusted data" do |option|
59
72
  options[:check_arguments] = !option
60
73
  end
data/lib/brakeman.rb CHANGED
@@ -48,6 +48,7 @@ module Brakeman
48
48
  options = set_options options
49
49
 
50
50
  if options[:quiet]
51
+ options[:report_progress] = false
51
52
  $VERBOSE = nil
52
53
  end
53
54
 
@@ -120,6 +121,7 @@ module Brakeman
120
121
  :message_limit => 100,
121
122
  :parallel_checks => true,
122
123
  :quiet => true,
124
+ :report_progress => true,
123
125
  :html_style => "#{File.expand_path(File.dirname(__FILE__))}/brakeman/format/style.css"
124
126
  }
125
127
  end
@@ -206,7 +208,11 @@ module Brakeman
206
208
  warn "Processing application in #{options[:app_path]}"
207
209
  tracker = scanner.process
208
210
 
209
- warn "Running checks..."
211
+ if options[:parallel_checks]
212
+ warn "Running checks in parallel..."
213
+ else
214
+ warn "Runnning checks..."
215
+ end
210
216
  tracker.run_checks
211
217
 
212
218
  if options[:output_file]
@@ -25,6 +25,9 @@ class Brakeman::AliasProcessor < SexpProcessor
25
25
  self.default_method = :process_default
26
26
  self.warn_on_default = false
27
27
  @env = SexpProcessor::Environment.new
28
+ @inside_if = false
29
+ @ignore_ifs = false
30
+ @tracker = nil #set in subclass as necessary
28
31
  set_env_defaults
29
32
  end
30
33
 
@@ -117,6 +120,20 @@ class Brakeman::AliasProcessor < SexpProcessor
117
120
  joined = join_strings target, args[1]
118
121
  joined.line(exp.line)
119
122
  exp = joined
123
+ elsif number? target and number? args[1]
124
+ exp = Sexp.new(:lit, target[1] + args[1][1])
125
+ end
126
+ when :-
127
+ if number? target and number? args[1]
128
+ exp = Sexp.new(:lit, target[1] - args[1][1])
129
+ end
130
+ when :*
131
+ if number? target and number? args[1]
132
+ exp = Sexp.new(:lit, target[1] * args[1][1])
133
+ end
134
+ when :/
135
+ if number? target and number? args[1]
136
+ exp = Sexp.new(:lit, target[1] / args[1][1])
120
137
  end
121
138
  when :[]
122
139
  if array? target
@@ -136,6 +153,19 @@ class Brakeman::AliasProcessor < SexpProcessor
136
153
  if hash? target and hash? args[1]
137
154
  return process_hash_merge(target, args[1])
138
155
  end
156
+ when :<<
157
+ if string? target and string? args[1]
158
+ target[1] << args[1][1]
159
+ env[target_var] = target
160
+ return target
161
+ elsif array? target
162
+ target << args[1]
163
+ env[target_var] = target
164
+ return target
165
+ else
166
+ target = find_push_target exp
167
+ env[target] = exp unless target.nil? #Happens in TemplateAliasProcessor
168
+ end
139
169
  end
140
170
 
141
171
  exp
@@ -183,8 +213,10 @@ class Brakeman::AliasProcessor < SexpProcessor
183
213
  exp[2] = process exp[2] if sexp? exp[2]
184
214
  local = Sexp.new(:lvar, exp[1]).line(exp.line || -2)
185
215
 
186
- if @inside_if and env[local]
187
- env[local] = Sexp.new(:or, env[local], exp[2]).line(exp.line || -2)
216
+ if @inside_if and val = env[local]
217
+ if val != exp[2] #avoid setting to value it already is (e.g. "1 or 1")
218
+ env[local] = Sexp.new(:or, val, exp[2]).line(exp.line || -2)
219
+ end
188
220
  else
189
221
  env[local] = exp[2]
190
222
  end
@@ -198,8 +230,10 @@ class Brakeman::AliasProcessor < SexpProcessor
198
230
  exp[2] = process exp[2]
199
231
  ivar = Sexp.new(:ivar, exp[1]).line(exp.line)
200
232
 
201
- if @inside_if and env[ivar]
202
- env[ivar] = Sexp.new(:or, env[ivar], exp[2]).line(exp.line)
233
+ if @inside_if and val = env[ivar]
234
+ if val != exp[2]
235
+ env[ivar] = Sexp.new(:or, val, exp[2]).line(exp.line)
236
+ end
203
237
  else
204
238
  env[ivar] = exp[2]
205
239
  end
@@ -213,8 +247,10 @@ class Brakeman::AliasProcessor < SexpProcessor
213
247
  match = Sexp.new(:gvar, exp[1])
214
248
  value = exp[2] = process(exp[2])
215
249
 
216
- if @inside_if and env[match]
217
- env[match] = Sexp.new(:or, env[match], value)
250
+ if @inside_if and val = env[match]
251
+ if val != value
252
+ env[match] = Sexp.new(:or, env[match], value)
253
+ end
218
254
  else
219
255
  env[match] = value
220
256
  end
@@ -228,8 +264,10 @@ class Brakeman::AliasProcessor < SexpProcessor
228
264
  match = Sexp.new(:cvar, exp[1])
229
265
  value = exp[2] = process(exp[2])
230
266
 
231
- if @inside_if and env[match]
232
- env[match] = Sexp.new(:or, env[match], value)
267
+ if @inside_if and val = env[match]
268
+ if val != value
269
+ env[match] = Sexp.new(:or, env[match], value)
270
+ end
233
271
  else
234
272
  env[match] = value
235
273
  end
@@ -259,8 +297,10 @@ class Brakeman::AliasProcessor < SexpProcessor
259
297
  #This is what we'll replace with the value
260
298
  match = Sexp.new(:call, target, method.to_s[0..-2].to_sym, Sexp.new(:arglist))
261
299
 
262
- if @inside_if and env[match]
263
- env[match] = Sexp.new(:or, env[match], value)
300
+ if @inside_if and val = env[match]
301
+ if val != value
302
+ env[match] = Sexp.new(:or, env[match], value)
303
+ end
264
304
  else
265
305
  env[match] = value
266
306
  end
@@ -349,8 +389,7 @@ class Brakeman::AliasProcessor < SexpProcessor
349
389
 
350
390
  #Sets @inside_if = true
351
391
  def process_if exp
352
- was_inside = @inside_if
353
- @inside_if = true
392
+ @ignore_ifs ||= @tracker && @tracker.options[:ignore_ifs]
354
393
 
355
394
  condition = process exp[1]
356
395
 
@@ -362,6 +401,9 @@ class Brakeman::AliasProcessor < SexpProcessor
362
401
  exps = exp[2..-1]
363
402
  end
364
403
 
404
+ was_inside = @inside_if
405
+ @inside_if = !@ignore_ifs
406
+
365
407
  exps.each do |e|
366
408
  process e if sexp? e
367
409
  end
@@ -436,4 +478,13 @@ class Brakeman::AliasProcessor < SexpProcessor
436
478
 
437
479
  exp
438
480
  end
481
+
482
+ #Finds the inner most call target which is not the target of a call to <<
483
+ def find_push_target exp
484
+ if call? exp and exp[2] == :<<
485
+ find_push_target exp[1]
486
+ else
487
+ exp
488
+ end
489
+ end
439
490
  end
@@ -31,7 +31,7 @@ class Brakeman::HamlTemplateProcessor < Brakeman::TemplateProcessor
31
31
 
32
32
  if (sexp? target and target[2] == :_hamlout) or target == :_hamlout
33
33
  res = case method
34
- when :adjust_tabs, :rstrip!
34
+ when :adjust_tabs, :rstrip!, :attributes #Check attributes, maybe?
35
35
  ignore
36
36
  when :options
37
37
  Sexp.new :call, :_hamlout, :options, exp[3]
@@ -59,7 +59,7 @@ module Brakeman::RenderHelper
59
59
  #Hash the environment and the source of the template to avoid
60
60
  #pointlessly processing templates, which can become prohibitively
61
61
  #expensive in terms of time and memory.
62
- digest = Digest::SHA1.new.update(template_env.instance_variable_get(:@env).to_a.sort.to_s << template[:src].to_s).to_s.to_sym
62
+ digest = Digest::SHA1.new.update(template_env.instance_variable_get(:@env).to_a.sort.to_s << name).to_s.to_sym
63
63
 
64
64
  if @tracker.template_cache.include? digest
65
65
  #Already processed this template with identical environment
@@ -92,7 +92,7 @@ class Brakeman::LibraryProcessor < Brakeman::BaseProcessor
92
92
 
93
93
  def process_defn exp
94
94
  exp[0] = :methdef
95
- exp[3] = @alias_processor.process_safely process(exp[3]), SexpProcessor::Environment.new
95
+ exp[3] = @alias_processor.process exp[3]
96
96
 
97
97
  if @current_class
98
98
  @current_class[:public][exp[1]] = exp[3]
@@ -105,7 +105,7 @@ class Brakeman::LibraryProcessor < Brakeman::BaseProcessor
105
105
 
106
106
  def process_defs exp
107
107
  exp[0] = :selfdef
108
- exp[4] = @alias_processor.process_safely process(exp[4]), SexpProcessor::Environment.new
108
+ exp[4] = @alias_processor.process exp[4]
109
109
 
110
110
  if @current_class
111
111
  @current_class[:public][exp[2]] = exp[4]
@@ -83,4 +83,16 @@ class Brakeman::TemplateAliasProcessor < Brakeman::AliasProcessor
83
83
 
84
84
  false
85
85
  end
86
+
87
+ def find_push_target exp
88
+ if sexp? exp
89
+ if exp.node_type == :lvar and (exp[1] == :_buf or exp[1] == :_erbout)
90
+ return nil
91
+ elsif exp.node_type == :ivar and exp[1] == :@output_buffer
92
+ return nil
93
+ end
94
+ end
95
+
96
+ super
97
+ end
86
98
  end
@@ -32,6 +32,7 @@ class Brakeman::Scanner
32
32
  #Pass in path to the root of the Rails application
33
33
  def initialize options
34
34
  @options = options
35
+ @report_progress = options[:report_progress]
35
36
  @path = options[:app_path]
36
37
  @app_path = File.join(@path, "app")
37
38
  @processor = Brakeman::Processor.new options
@@ -58,15 +59,15 @@ class Brakeman::Scanner
58
59
  process_initializers
59
60
  warn "Processing libs..."
60
61
  process_libs
61
- warn "Processing routes..."
62
+ warn "Processing routes... "
62
63
  process_routes
63
- warn "Processing templates..."
64
+ warn "Processing templates... "
64
65
  process_templates
65
- warn "Processing models..."
66
+ warn "Processing models... "
66
67
  process_models
67
- warn "Processing controllers..."
68
+ warn "Processing controllers... "
68
69
  process_controllers
69
- warn "Indexing call sites..."
70
+ warn "Indexing call sites... "
70
71
  index_call_sites
71
72
  tracker
72
73
  end
@@ -76,18 +77,14 @@ class Brakeman::Scanner
76
77
  #Stores parsed information in tracker.config
77
78
  def process_config
78
79
  if options[:rails3]
79
- @processor.process_config(parse_ruby(File.read("#@path/config/application.rb")))
80
- @processor.process_config(parse_ruby(File.read("#@path/config/environments/production.rb")))
80
+ process_config_file "application.rb"
81
+ process_config_file "environments/production.rb"
81
82
  else
82
- @processor.process_config(parse_ruby(File.read("#@path/config/environment.rb")))
83
-
84
- if File.exists? "#@path/config/gems.rb"
85
- @processor.process_config(parse_ruby(File.read("#@path/config/gems.rb")))
86
- end
87
-
83
+ process_config_file "environment.rb"
84
+ process_config_file "gems.rb"
88
85
  end
89
86
 
90
- if File.exists? "#@path/vendor/plugins/rails_xss" or
87
+ if File.exists? "#@path/vendor/plugins/rails_xss" or
91
88
  options[:rails3] or options[:escape_html] or
92
89
  (File.exists? "#@path/Gemfile" and File.read("#@path/Gemfile").include? "rails_xss")
93
90
 
@@ -96,6 +93,18 @@ class Brakeman::Scanner
96
93
  end
97
94
  end
98
95
 
96
+ def process_config_file file
97
+ if File.exists? "#@path/config/#{file}"
98
+ @processor.process_config(parse_ruby(File.read("#@path/config/#{file}")))
99
+ end
100
+
101
+ rescue Exception => e
102
+ warn "[Notice] Error while processing config/#{file}"
103
+ tracker.error e.exception(e.message + "\nwhile processing Gemfile"), e.backtrace
104
+ end
105
+
106
+ private :process_config_file
107
+
99
108
  #Process Gemfile
100
109
  def process_gems
101
110
  if File.exists? "#@path/Gemfile"
@@ -105,6 +114,9 @@ class Brakeman::Scanner
105
114
  @processor.process_gems(parse_ruby(File.read("#@path/Gemfile")))
106
115
  end
107
116
  end
117
+ rescue Exception => e
118
+ warn "[Notice] Error while processing Gemfile."
119
+ tracker.error e.exception(e.message + "\nWhile processing Gemfile"), e.backtrace
108
120
  end
109
121
 
110
122
  #Process all the .rb files in config/initializers/
@@ -131,7 +143,17 @@ class Brakeman::Scanner
131
143
  return
132
144
  end
133
145
 
134
- Dir.glob(@path + "/lib/**/*.rb").sort.each do |f|
146
+ lib_files = Dir.glob(@path + "/lib/**/*.rb").sort
147
+ total = lib_files.length
148
+ current = 0
149
+
150
+ lib_files.each do |f|
151
+ warn "Processing #{f}" if options[:debug]
152
+ if @report_progress
153
+ $stderr.print " #{current}/#{total} files processed\r"
154
+ current += 1
155
+ end
156
+
135
157
  begin
136
158
  @processor.process_lib parse_ruby(File.read(f)), f
137
159
  rescue Racc::ParseError => e
@@ -163,7 +185,17 @@ class Brakeman::Scanner
163
185
  #
164
186
  #Adds processed controllers to tracker.controllers
165
187
  def process_controllers
166
- Dir.glob(@app_path + "/controllers/**/*.rb").sort.each do |f|
188
+ controller_files = Dir.glob(@app_path + "/controllers/**/*.rb").sort
189
+ total = controller_files.length * 2
190
+ current = 0
191
+
192
+ controller_files.each do |f|
193
+ warn "Processing #{f}" if options[:debug]
194
+ if @report_progress
195
+ $stderr.print " #{current}/#{total} files processed\r"
196
+ current += 1
197
+ end
198
+
167
199
  begin
168
200
  @processor.process_controller(parse_ruby(File.read(f)), f)
169
201
  rescue Racc::ParseError => e
@@ -173,7 +205,17 @@ class Brakeman::Scanner
173
205
  end
174
206
  end
175
207
 
208
+ current = 0
209
+ total = tracker.controllers.length
210
+
211
+ warn "Processing data flow in controllers..."
212
+
176
213
  tracker.controllers.each do |name, controller|
214
+ if @report_progress
215
+ $stderr.print " #{current}/#{total} controllers processed\r"
216
+ current += 1
217
+ end
218
+
177
219
  @processor.process_controller_alias controller[:src]
178
220
  end
179
221
  end
@@ -187,8 +229,15 @@ class Brakeman::Scanner
187
229
  $stdout.sync = true
188
230
  count = 0
189
231
 
190
- Dir.glob(views_path).sort.each do |f|
191
- count += 1
232
+ template_files = Dir.glob(views_path).sort
233
+ total = template_files.length
234
+
235
+ template_files.each do |f|
236
+ if @report_progress
237
+ $stderr.print " #{count}/#{total} files processed\r"
238
+ count += 1
239
+ end
240
+
192
241
  type = f.match(/.*\.(erb|haml|rhtml)$/)[1].to_sym
193
242
  type = :erb if type == :rhtml
194
243
  name = template_path_to_name f
@@ -231,7 +280,17 @@ class Brakeman::Scanner
231
280
  end
232
281
  end
233
282
 
283
+ total = tracker.templates.length
284
+ count = 0
285
+
286
+ warn "Processing data flow in templates..."
287
+
234
288
  tracker.templates.keys.dup.each do |name|
289
+ if @report_progress
290
+ count += 1
291
+ $stderr.print " #{count}/#{total} templates processed\r"
292
+ end
293
+
235
294
  @processor.process_template_alias tracker.templates[name]
236
295
  end
237
296
 
@@ -250,7 +309,17 @@ class Brakeman::Scanner
250
309
  #
251
310
  #Adds the processed models to tracker.models
252
311
  def process_models
253
- Dir.glob(@app_path + "/models/*.rb").sort.each do |f|
312
+ model_files = Dir.glob(@app_path + "/models/*.rb").sort
313
+
314
+ total = model_files.length
315
+ current = 0
316
+
317
+ model_files.each do |f|
318
+ if @report_progress
319
+ $stderr.print " #{current}/#{total} files processed\r"
320
+ current += 1
321
+ end
322
+
254
323
  begin
255
324
  @processor.process_model(parse_ruby(File.read(f)), f)
256
325
  rescue Racc::ParseError => e
@@ -294,7 +363,7 @@ class Brakeman::RailsXSSErubis < ::Erubis::Eruby
294
363
  lines[0..-2].each do |line|
295
364
  src << "@output_buffer << ('" << escape_text(line) << "'.html_safe!);\n"
296
365
  end
297
-
366
+
298
367
  src << "@output_buffer << ('" << escape_text(lines.last) << "'.html_safe!);"
299
368
  end
300
369
  else
data/lib/brakeman/util.rb CHANGED
@@ -125,6 +125,11 @@ module Brakeman::Util
125
125
  exp.is_a? Sexp and exp.node_type == :lit and exp[1].is_a? Integer
126
126
  end
127
127
 
128
+ #Check if _exp_ represents a number: s(:lit, ...)
129
+ def number? exp
130
+ exp.is_a? Sexp and exp.node_type == :lit and exp[1].is_a? Numeric
131
+ end
132
+
128
133
  #Check if _exp_ represents a result: s(:result, ...)
129
134
  def result? exp
130
135
  exp.is_a? Sexp and exp.node_type == :result
@@ -182,13 +187,3 @@ module Brakeman::Util
182
187
  exp.is_a? Sexp
183
188
  end
184
189
  end
185
-
186
- class Sexp
187
- def original_line line = nil
188
- if line
189
- @original_line = line
190
- else
191
- @original_line
192
- end
193
- end
194
- end
@@ -1,3 +1,3 @@
1
1
  module Brakeman
2
- Version = "1.0.0"
2
+ Version = "1.1.pre"
3
3
  end
@@ -1052,7 +1052,7 @@ class Symbol
1052
1052
  end
1053
1053
 
1054
1054
  class Sexp
1055
- attr_writer :paren
1055
+ attr_reader :paren
1056
1056
 
1057
1057
  def paren
1058
1058
  @paren ||= false
@@ -1069,6 +1069,94 @@ class Sexp
1069
1069
 
1070
1070
  alias :node_type :sexp_type
1071
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
1072
1160
  end
1073
1161
 
1074
1162
  # END HACK
metadata CHANGED
@@ -1,12 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brakeman
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: false
4
+ prerelease: true
5
5
  segments:
6
6
  - 1
7
- - 0
8
- - 0
9
- version: 1.0.0
7
+ - 1
8
+ - pre
9
+ version: 1.1.pre
10
10
  platform: ruby
11
11
  authors:
12
12
  - Justin Collins
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-12-08 00:00:00 -08:00
17
+ date: 2011-12-21 00:00:00 -08:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -23,18 +23,30 @@ dependencies:
23
23
  requirement: &id001 !ruby/object:Gem::Requirement
24
24
  none: false
25
25
  requirements:
26
- - - ~>
26
+ - - ">="
27
27
  - !ruby/object:Gem::Version
28
28
  segments:
29
- - 2
30
- - 2
31
- version: "2.2"
29
+ - 0
30
+ version: "0"
32
31
  type: :runtime
33
32
  version_requirements: *id001
34
33
  - !ruby/object:Gem::Dependency
35
- name: ruby2ruby
34
+ name: i18n
36
35
  prerelease: false
37
36
  requirement: &id002 !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 0
43
+ version: "0"
44
+ type: :runtime
45
+ version_requirements: *id002
46
+ - !ruby/object:Gem::Dependency
47
+ name: ruby2ruby
48
+ prerelease: false
49
+ requirement: &id003 !ruby/object:Gem::Requirement
38
50
  none: false
39
51
  requirements:
40
52
  - - ~>
@@ -42,14 +54,13 @@ dependencies:
42
54
  segments:
43
55
  - 1
44
56
  - 2
45
- - 4
46
- version: 1.2.4
57
+ version: "1.2"
47
58
  type: :runtime
48
- version_requirements: *id002
59
+ version_requirements: *id003
49
60
  - !ruby/object:Gem::Dependency
50
61
  name: ruport
51
62
  prerelease: false
52
- requirement: &id003 !ruby/object:Gem::Requirement
63
+ requirement: &id004 !ruby/object:Gem::Requirement
53
64
  none: false
54
65
  requirements:
55
66
  - - ~>
@@ -57,14 +68,13 @@ dependencies:
57
68
  segments:
58
69
  - 1
59
70
  - 6
60
- - 3
61
- version: 1.6.3
71
+ version: "1.6"
62
72
  type: :runtime
63
- version_requirements: *id003
73
+ version_requirements: *id004
64
74
  - !ruby/object:Gem::Dependency
65
75
  name: erubis
66
76
  prerelease: false
67
- requirement: &id004 !ruby/object:Gem::Requirement
77
+ requirement: &id005 !ruby/object:Gem::Requirement
68
78
  none: false
69
79
  requirements:
70
80
  - - ~>
@@ -72,14 +82,13 @@ dependencies:
72
82
  segments:
73
83
  - 2
74
84
  - 6
75
- - 5
76
- version: 2.6.5
85
+ version: "2.6"
77
86
  type: :runtime
78
- version_requirements: *id004
87
+ version_requirements: *id005
79
88
  - !ruby/object:Gem::Dependency
80
89
  name: haml
81
90
  prerelease: false
82
- requirement: &id005 !ruby/object:Gem::Requirement
91
+ requirement: &id006 !ruby/object:Gem::Requirement
83
92
  none: false
84
93
  requirements:
85
94
  - - ~>
@@ -87,10 +96,23 @@ dependencies:
87
96
  segments:
88
97
  - 3
89
98
  - 0
90
- - 12
91
- version: 3.0.12
99
+ version: "3.0"
92
100
  type: :runtime
93
- version_requirements: *id005
101
+ version_requirements: *id006
102
+ - !ruby/object:Gem::Dependency
103
+ name: sass
104
+ prerelease: false
105
+ requirement: &id007 !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ segments:
111
+ - 3
112
+ - 0
113
+ version: "3.0"
114
+ type: :runtime
115
+ version_requirements: *id007
94
116
  description: Brakeman detects security vulnerabilities in Ruby on Rails applications via static analysis.
95
117
  email:
96
118
  executables:
@@ -190,11 +212,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
190
212
  required_rubygems_version: !ruby/object:Gem::Requirement
191
213
  none: false
192
214
  requirements:
193
- - - ">="
215
+ - - ">"
194
216
  - !ruby/object:Gem::Version
195
217
  segments:
196
- - 0
197
- version: "0"
218
+ - 1
219
+ - 3
220
+ - 1
221
+ version: 1.3.1
198
222
  requirements: []
199
223
 
200
224
  rubyforge_project: