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 +13 -0
- data/lib/brakeman.rb +7 -1
- data/lib/brakeman/processors/alias_processor.rb +63 -12
- data/lib/brakeman/processors/haml_template_processor.rb +1 -1
- data/lib/brakeman/processors/lib/render_helper.rb +1 -1
- data/lib/brakeman/processors/library_processor.rb +2 -2
- data/lib/brakeman/processors/template_alias_processor.rb +12 -0
- data/lib/brakeman/scanner.rb +89 -20
- data/lib/brakeman/util.rb +5 -10
- data/lib/brakeman/version.rb +1 -1
- data/lib/ruby_parser/ruby_parser_extras.rb +89 -1
- metadata +52 -28
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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 <<
|
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.
|
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.
|
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
|
data/lib/brakeman/scanner.rb
CHANGED
@@ -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
|
-
|
80
|
-
|
80
|
+
process_config_file "application.rb"
|
81
|
+
process_config_file "environments/production.rb"
|
81
82
|
else
|
82
|
-
|
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
|
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
|
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
|
191
|
-
|
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
|
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
|
data/lib/brakeman/version.rb
CHANGED
@@ -1052,7 +1052,7 @@ class Symbol
|
|
1052
1052
|
end
|
1053
1053
|
|
1054
1054
|
class Sexp
|
1055
|
-
|
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:
|
4
|
+
prerelease: true
|
5
5
|
segments:
|
6
6
|
- 1
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 1.
|
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-
|
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
|
-
-
|
30
|
-
|
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:
|
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
|
-
|
46
|
-
version: 1.2.4
|
57
|
+
version: "1.2"
|
47
58
|
type: :runtime
|
48
|
-
version_requirements: *
|
59
|
+
version_requirements: *id003
|
49
60
|
- !ruby/object:Gem::Dependency
|
50
61
|
name: ruport
|
51
62
|
prerelease: false
|
52
|
-
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
|
-
|
61
|
-
version: 1.6.3
|
71
|
+
version: "1.6"
|
62
72
|
type: :runtime
|
63
|
-
version_requirements: *
|
73
|
+
version_requirements: *id004
|
64
74
|
- !ruby/object:Gem::Dependency
|
65
75
|
name: erubis
|
66
76
|
prerelease: false
|
67
|
-
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
|
-
|
76
|
-
version: 2.6.5
|
85
|
+
version: "2.6"
|
77
86
|
type: :runtime
|
78
|
-
version_requirements: *
|
87
|
+
version_requirements: *id005
|
79
88
|
- !ruby/object:Gem::Dependency
|
80
89
|
name: haml
|
81
90
|
prerelease: false
|
82
|
-
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
|
-
|
91
|
-
version: 3.0.12
|
99
|
+
version: "3.0"
|
92
100
|
type: :runtime
|
93
|
-
version_requirements: *
|
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
|
-
-
|
197
|
-
|
218
|
+
- 1
|
219
|
+
- 3
|
220
|
+
- 1
|
221
|
+
version: 1.3.1
|
198
222
|
requirements: []
|
199
223
|
|
200
224
|
rubyforge_project:
|