brakeman 1.0.0 → 1.1.pre

Sign up to get free protection for your applications and to get access to all the features.
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: