brakeman-min 4.4.0 → 4.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES.md +17 -0
- data/lib/brakeman/checks/base_check.rb +16 -0
- data/lib/brakeman/checks/check_content_tag.rb +12 -0
- data/lib/brakeman/checks/check_cross_site_scripting.rb +6 -6
- data/lib/brakeman/checks/check_evaluation.rb +0 -1
- data/lib/brakeman/checks/check_execute.rb +18 -0
- data/lib/brakeman/checks/check_send.rb +0 -1
- data/lib/brakeman/checks/check_session_manipulation.rb +0 -1
- data/lib/brakeman/checks/check_sql.rb +12 -3
- data/lib/brakeman/file_parser.rb +8 -4
- data/lib/brakeman/parsers/haml_embedded.rb +44 -0
- data/lib/brakeman/parsers/slim_embedded.rb +44 -0
- data/lib/brakeman/parsers/template_parser.rb +2 -4
- data/lib/brakeman/processors/alias_processor.rb +23 -1
- data/lib/brakeman/processors/lib/call_conversion_helper.rb +4 -0
- data/lib/brakeman/processors/slim_template_processor.rb +16 -0
- data/lib/brakeman/processors/template_alias_processor.rb +2 -2
- data/lib/brakeman/scanner.rb +11 -10
- data/lib/brakeman/tracker.rb +5 -1
- data/lib/brakeman/tracker/config.rb +32 -7
- data/lib/brakeman/util.rb +17 -0
- data/lib/brakeman/version.rb +1 -1
- metadata +35 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 40fc5a73b9d4b7911a901dfd0c7d537bb83c7fc9dcd9d4b67b63236d8d5e46d3
|
4
|
+
data.tar.gz: 3999b64908f9a50b111e17cdd7e899d897bbdd900a44016e9a24afc5b810a6c9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 32246f144782227e0f3a024a4035862e46a93bbe83113a017d0f3c1fba4b1eb21f9f196b4a2d5a758b64cbdafc964533423e5c615e6124840d1f5b8e1ca89d4b
|
7
|
+
data.tar.gz: 42d84682807291640dc249fe12c9a0986d869d5ff51464af7ad4cfdeb9ad6a2d9e5e9a2c13adbdec7e7ed0c1471792f74bd371d7f04c577ca40178617f224831
|
data/CHANGES.md
CHANGED
@@ -1,3 +1,20 @@
|
|
1
|
+
# 4.5.0
|
2
|
+
|
3
|
+
* Update `ruby_parser`, use `ruby_parser-legacy`
|
4
|
+
* More thoroughly handle `Shellwords` escaping
|
5
|
+
* Handle non-integer version number comparisons
|
6
|
+
* Use `FileParser` in `Scanner` to parse files
|
7
|
+
* Add original exception to `Tracker#errors` list
|
8
|
+
* Add support for CoffeeScript in Slim templates
|
9
|
+
* Improve support for embedded template "filters"
|
10
|
+
* Remove Sass dependency
|
11
|
+
* Set location information in `CheckContentTag`
|
12
|
+
* Stop swallowing exceptions in `AliasProcessor`
|
13
|
+
* Avoid joining strings with different encodings
|
14
|
+
* Handle `**` inside Hash literals
|
15
|
+
* Better handling of splat/kwsplat arguments
|
16
|
+
* Improve "user input" reported for SQL injection
|
17
|
+
|
1
18
|
# 4.4.0
|
2
19
|
|
3
20
|
* Set default encoding to UTF-8
|
@@ -348,6 +348,22 @@ class Brakeman::BaseCheck < Brakeman::SexpProcessor
|
|
348
348
|
when :or
|
349
349
|
has_immediate_user_input? exp.lhs or
|
350
350
|
has_immediate_user_input? exp.rhs
|
351
|
+
when :splat, :kwsplat
|
352
|
+
exp.each_sexp do |e|
|
353
|
+
match = has_immediate_user_input?(e)
|
354
|
+
return match if match
|
355
|
+
end
|
356
|
+
|
357
|
+
false
|
358
|
+
when :hash
|
359
|
+
if kwsplat? exp
|
360
|
+
exp[1].each_sexp do |e|
|
361
|
+
match = has_immediate_user_input?(e)
|
362
|
+
return match if match
|
363
|
+
end
|
364
|
+
|
365
|
+
false
|
366
|
+
end
|
351
367
|
else
|
352
368
|
false
|
353
369
|
end
|
@@ -45,6 +45,16 @@ class Brakeman::CheckContentTag < Brakeman::CheckCrossSiteScripting
|
|
45
45
|
def process_result result
|
46
46
|
return if duplicate? result
|
47
47
|
|
48
|
+
case result[:location][:type]
|
49
|
+
when :template
|
50
|
+
@current_template = result[:location][:template]
|
51
|
+
when :class
|
52
|
+
@current_class = result[:location][:class]
|
53
|
+
@current_method = result[:location][:method]
|
54
|
+
end
|
55
|
+
|
56
|
+
@current_file = result[:location][:file]
|
57
|
+
|
48
58
|
call = result[:call] = result[:call].dup
|
49
59
|
|
50
60
|
args = call.arglist
|
@@ -85,6 +95,8 @@ class Brakeman::CheckContentTag < Brakeman::CheckCrossSiteScripting
|
|
85
95
|
end
|
86
96
|
end
|
87
97
|
end
|
98
|
+
ensure
|
99
|
+
@current_template = @current_class = @current_method = @current_file = nil
|
88
100
|
end
|
89
101
|
|
90
102
|
def check_argument result, exp
|
@@ -57,12 +57,12 @@ class Brakeman::CheckCrossSiteScripting < Brakeman::BaseCheck
|
|
57
57
|
|
58
58
|
if exp.node_type == :output
|
59
59
|
out = exp.value
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
60
|
+
end
|
61
|
+
|
62
|
+
if raw_call? exp
|
63
|
+
out = exp.value.first_arg
|
64
|
+
elsif html_safe_call? exp
|
65
|
+
out = exp.value.target
|
66
66
|
end
|
67
67
|
|
68
68
|
return if call? out and ignore_call? out.target, out.method
|
@@ -90,6 +90,24 @@ class Brakeman::CheckExecute < Brakeman::BaseCheck
|
|
90
90
|
end
|
91
91
|
end
|
92
92
|
|
93
|
+
def include_user_input? exp
|
94
|
+
if node_type? exp, :arglist, :dstr, :evstr, :dxstr
|
95
|
+
exp.each_sexp do |e|
|
96
|
+
if res = include_user_input?(e)
|
97
|
+
return res
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
false
|
102
|
+
else
|
103
|
+
if shell_escape? exp
|
104
|
+
false
|
105
|
+
else
|
106
|
+
super exp
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
93
111
|
def dangerous_open_arg? exp
|
94
112
|
if string_interp? exp
|
95
113
|
# Check for input at start of string
|
@@ -27,7 +27,6 @@ class Brakeman::CheckSessionManipulation < Brakeman::BaseCheck
|
|
27
27
|
:warning_type => "Session Manipulation",
|
28
28
|
:warning_code => :session_key_manipulation,
|
29
29
|
:message => msg(msg_input(input), " used as key in session hash"),
|
30
|
-
:code => result[:call],
|
31
30
|
:user_input => input,
|
32
31
|
:confidence => confidence
|
33
32
|
end
|
@@ -14,7 +14,9 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
|
|
14
14
|
@description = "Check for SQL injection"
|
15
15
|
|
16
16
|
def run_check
|
17
|
-
|
17
|
+
# Avoid reporting `user_input` on silly values when generating warning.
|
18
|
+
# Note that we retroactively find `user_input` inside the "dangerous" value.
|
19
|
+
@safe_input_attributes.merge IGNORE_METHODS_IN_SQL
|
18
20
|
|
19
21
|
@sql_targets = [:average, :calculate, :count, :count_by_sql, :delete_all, :destroy_all,
|
20
22
|
:find_by_sql, :maximum, :minimum, :pluck, :sum, :update_all]
|
@@ -43,6 +45,7 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
|
|
43
45
|
Brakeman.debug "Finding possible SQL calls on models"
|
44
46
|
calls = tracker.find_call(:methods => @sql_targets, :nested => true)
|
45
47
|
|
48
|
+
narrow_targets = [:exists?, :select]
|
46
49
|
calls.concat tracker.find_call(:targets => active_record_models.keys, :methods => narrow_targets, :chained => true)
|
47
50
|
|
48
51
|
Brakeman.debug "Finding possible SQL calls with no target"
|
@@ -294,7 +297,7 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
|
|
294
297
|
# Model.where(params[:where])
|
295
298
|
arg
|
296
299
|
end
|
297
|
-
elsif hash? arg
|
300
|
+
elsif hash? arg and not kwsplat? arg
|
298
301
|
#This is generally going to be a hash of column names and values, which
|
299
302
|
#would escape the values. But the keys _could_ be user input.
|
300
303
|
check_hash_keys arg
|
@@ -452,7 +455,13 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
|
|
452
455
|
when :dstr
|
453
456
|
check_string_interp exp
|
454
457
|
when :hash
|
455
|
-
|
458
|
+
if kwsplat? exp and has_immediate_user_input? exp
|
459
|
+
exp
|
460
|
+
elsif not ignore_hash
|
461
|
+
check_hash_values exp
|
462
|
+
else
|
463
|
+
nil
|
464
|
+
end
|
456
465
|
when :if
|
457
466
|
unsafe_sql? exp.then_clause or unsafe_sql? exp.else_clause
|
458
467
|
when :call
|
data/lib/brakeman/file_parser.rb
CHANGED
@@ -31,13 +31,17 @@ module Brakeman
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
-
def parse_ruby input, path
|
34
|
+
def parse_ruby input, path, parser = RubyParser.new
|
35
35
|
begin
|
36
36
|
Brakeman.debug "Parsing #{path}"
|
37
|
-
|
37
|
+
parser.parse input, path, @timeout
|
38
38
|
rescue Racc::ParseError => e
|
39
|
-
|
40
|
-
|
39
|
+
if parser.class == RubyParser
|
40
|
+
return parse_ruby(input, path, RubyParser.latest)
|
41
|
+
else
|
42
|
+
@tracker.error e, "Could not parse #{path}"
|
43
|
+
nil
|
44
|
+
end
|
41
45
|
rescue Timeout::Error => e
|
42
46
|
@tracker.error Exception.new("Parsing #{path} took too long (> #{@timeout} seconds). Try increasing the limit with --parser-timeout"), caller
|
43
47
|
nil
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Brakeman
|
2
|
+
module FakeHamlFilter
|
3
|
+
# Copied from Haml - force delayed compilation
|
4
|
+
def compile(compiler, text)
|
5
|
+
filter = self
|
6
|
+
compiler.instance_eval do
|
7
|
+
text = unescape_interpolation(text).gsub(/(\\+)n/) do |s|
|
8
|
+
escapes = $1.size
|
9
|
+
next s if escapes % 2 == 0
|
10
|
+
("\\" * (escapes - 1)) + "\n"
|
11
|
+
end
|
12
|
+
# We need to add a newline at the beginning to get the
|
13
|
+
# filter lines to line up (since the Haml filter contains
|
14
|
+
# a line that doesn't show up in the source, namely the
|
15
|
+
# filter name). Then we need to escape the trailing
|
16
|
+
# newline so that the whole filter block doesn't take up
|
17
|
+
# too many.
|
18
|
+
text = "\n" + text.sub(/\n"\Z/, "\\n\"")
|
19
|
+
push_script <<RUBY.rstrip, :escape_html => false
|
20
|
+
find_and_preserve(#{filter.inspect}.render_with_options(#{text}, _hamlout.options))
|
21
|
+
RUBY
|
22
|
+
return
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Fake CoffeeScript filter for Haml
|
29
|
+
module Haml::Filters::Coffee
|
30
|
+
include Haml::Filters::Base
|
31
|
+
extend Brakeman::FakeHamlFilter
|
32
|
+
end
|
33
|
+
|
34
|
+
# Fake Markdown filter for Haml
|
35
|
+
module Haml::Filters::Markdown
|
36
|
+
include Haml::Filters::Base
|
37
|
+
extend Brakeman::FakeHamlFilter
|
38
|
+
end
|
39
|
+
|
40
|
+
# Fake Sass filter for Haml
|
41
|
+
module Haml::Filters::Sass
|
42
|
+
include Haml::Filters::Base
|
43
|
+
extend Brakeman::FakeHamlFilter
|
44
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# Fake filters for Slim
|
2
|
+
module Slim
|
3
|
+
class Embedded
|
4
|
+
class TiltEngine
|
5
|
+
def on_slim_embedded(engine, body, attrs)
|
6
|
+
# Override this method to avoid Slim trying to load sass/scss and failing
|
7
|
+
case engine
|
8
|
+
when :sass, :scss, :coffee
|
9
|
+
tilt_engine = nil # Doesn't really matter, ignored below
|
10
|
+
else
|
11
|
+
# Original Slim code
|
12
|
+
tilt_engine = Tilt[engine] || raise(Temple::FilterError, "Tilt engine #{engine} is not available.")
|
13
|
+
end
|
14
|
+
|
15
|
+
tilt_options = options[engine.to_sym] || {}
|
16
|
+
tilt_options[:default_encoding] ||= 'utf-8'
|
17
|
+
|
18
|
+
[:multi, tilt_render(tilt_engine, tilt_options, collect_text(body)), collect_newlines(body)]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class SassEngine
|
23
|
+
protected
|
24
|
+
|
25
|
+
def tilt_render(tilt_engine, tilt_options, text)
|
26
|
+
[:dynamic,
|
27
|
+
"BrakemanFilter.render(#{text.inspect}, #{self.class})"]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class CoffeeEngine < TiltEngine
|
32
|
+
protected
|
33
|
+
|
34
|
+
def tilt_render(tilt_engine, tilt_options, text)
|
35
|
+
[:dynamic,
|
36
|
+
"BrakemanFilter.render(#{text.inspect}, #{self.class})"]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Override the engine for CoffeeScript, because Slim doesn't have
|
41
|
+
# one, it just uses Tilt's
|
42
|
+
register :coffee, JavaScriptEngine, engine: CoffeeEngine
|
43
|
+
end
|
44
|
+
end
|
@@ -75,7 +75,7 @@ module Brakeman
|
|
75
75
|
|
76
76
|
def parse_haml path, text
|
77
77
|
Brakeman.load_brakeman_dependency 'haml'
|
78
|
-
|
78
|
+
require_relative 'haml_embedded'
|
79
79
|
|
80
80
|
Haml::Engine.new(text,
|
81
81
|
:filename => path,
|
@@ -83,13 +83,11 @@ module Brakeman
|
|
83
83
|
rescue Haml::Error => e
|
84
84
|
tracker.error e, ["While compiling HAML in #{path}"] << e.backtrace
|
85
85
|
nil
|
86
|
-
rescue Sass::SyntaxError => e
|
87
|
-
tracker.error e, "While processing #{path}"
|
88
|
-
nil
|
89
86
|
end
|
90
87
|
|
91
88
|
def parse_slim path, text
|
92
89
|
Brakeman.load_brakeman_dependency 'slim'
|
90
|
+
require_relative 'slim_embedded'
|
93
91
|
|
94
92
|
Slim::Template.new(path,
|
95
93
|
:disable_capture => true,
|
@@ -66,7 +66,11 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
|
|
66
66
|
end
|
67
67
|
end
|
68
68
|
rescue => err
|
69
|
-
|
69
|
+
if @tracker
|
70
|
+
@tracker.error err
|
71
|
+
else
|
72
|
+
raise err
|
73
|
+
end
|
70
74
|
end
|
71
75
|
|
72
76
|
result = replace(exp)
|
@@ -585,6 +589,24 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
|
|
585
589
|
exp
|
586
590
|
end
|
587
591
|
|
592
|
+
def process_hash exp
|
593
|
+
exp = process_default(exp)
|
594
|
+
|
595
|
+
# Handle { **kw }
|
596
|
+
if node_type? exp, :hash
|
597
|
+
if exp.any? { |e| node_type? e, :kwsplat and node_type? e.value, :hash }
|
598
|
+
kwsplats, rest = exp.partition { |e| node_type? e, :kwsplat and node_type? e.value, :hash }
|
599
|
+
exp = Sexp.new.concat(rest).line(exp)
|
600
|
+
|
601
|
+
kwsplats.each do |e|
|
602
|
+
exp = process_hash_merge! exp, e.value
|
603
|
+
end
|
604
|
+
end
|
605
|
+
end
|
606
|
+
|
607
|
+
exp
|
608
|
+
end
|
609
|
+
|
588
610
|
#Merge values into hash when processing
|
589
611
|
#
|
590
612
|
# h.merge! :something => "value"
|
@@ -40,6 +40,10 @@ module Brakeman
|
|
40
40
|
else
|
41
41
|
original_exp
|
42
42
|
end
|
43
|
+
rescue Encoding::CompatibilityError => e
|
44
|
+
# If the two strings are different encodings, we can't join them.
|
45
|
+
Brakeman.debug e.inspect
|
46
|
+
original_exp
|
43
47
|
end
|
44
48
|
|
45
49
|
def math_op op, lhs, rhs, original_exp = nil
|
@@ -8,6 +8,7 @@ class Brakeman::SlimTemplateProcessor < Brakeman::TemplateProcessor
|
|
8
8
|
OUTPUT_BUFFER = s(:ivar, :@output_buffer)
|
9
9
|
TEMPLE_UTILS = s(:colon2, s(:colon3, :Temple), :Utils)
|
10
10
|
ATTR_MERGE = s(:call, s(:call, s(:array), :reject, s(:block_pass, s(:lit, :empty?))), :join, s(:str, " "))
|
11
|
+
EMBEDDED_FILTER = s(:const, :BrakemanFilter)
|
11
12
|
|
12
13
|
def process_call exp
|
13
14
|
target = exp.target
|
@@ -44,6 +45,21 @@ class Brakeman::SlimTemplateProcessor < Brakeman::TemplateProcessor
|
|
44
45
|
end
|
45
46
|
end
|
46
47
|
|
48
|
+
def normalize_output arg
|
49
|
+
arg = super(arg)
|
50
|
+
|
51
|
+
if embedded_filter? arg
|
52
|
+
super(arg.first_arg)
|
53
|
+
else
|
54
|
+
arg
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Handle our "fake" embedded filters
|
59
|
+
def embedded_filter? arg
|
60
|
+
call? arg and arg.method == :render and arg.target == EMBEDDED_FILTER
|
61
|
+
end
|
62
|
+
|
47
63
|
#Slim likes to interpolate output into strings then pass them to safe_concat.
|
48
64
|
#Better to pull those values out directly.
|
49
65
|
def process_inside_interp exp
|
@@ -27,9 +27,9 @@ class Brakeman::TemplateAliasProcessor < Brakeman::AliasProcessor
|
|
27
27
|
return
|
28
28
|
end
|
29
29
|
|
30
|
-
super name, args, @called_from.dup.add_template_render(@template.name, line, @file_name)
|
30
|
+
super name, args, @called_from.dup.add_template_render(@template.name, line, @file_name), line
|
31
31
|
else
|
32
|
-
super name, args, Brakeman::RenderPath.new.add_template_render(@template.name, line, @file_name)
|
32
|
+
super name, args, Brakeman::RenderPath.new.add_template_render(@template.name, line, @file_name), line
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
data/lib/brakeman/scanner.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
begin
|
2
2
|
Brakeman.load_brakeman_dependency 'ruby_parser'
|
3
|
+
Brakeman.load_brakeman_dependency 'ruby_parser/legacy'
|
3
4
|
require 'ruby_parser/bm_sexp.rb'
|
4
5
|
require 'ruby_parser/bm_sexp_processor.rb'
|
5
6
|
require 'brakeman/processor'
|
@@ -118,7 +119,7 @@ class Brakeman::Scanner
|
|
118
119
|
path = "config/#{file}"
|
119
120
|
|
120
121
|
if @app_tree.exists?(path)
|
121
|
-
@processor.process_config(
|
122
|
+
@processor.process_config(parse_ruby_file(path), path)
|
122
123
|
end
|
123
124
|
|
124
125
|
rescue => e
|
@@ -132,9 +133,9 @@ class Brakeman::Scanner
|
|
132
133
|
def process_gems
|
133
134
|
gem_files = {}
|
134
135
|
if @app_tree.exists? "Gemfile"
|
135
|
-
gem_files[:gemfile] = { :src =>
|
136
|
+
gem_files[:gemfile] = { :src => parse_ruby_file("Gemfile"), :file => "Gemfile" }
|
136
137
|
elsif @app_tree.exists? "gems.rb"
|
137
|
-
gem_files[:gemfile] = { :src =>
|
138
|
+
gem_files[:gemfile] = { :src => parse_ruby_file("gems.rb"), :file => "gems.rb" }
|
138
139
|
end
|
139
140
|
|
140
141
|
if @app_tree.exists? "Gemfile.lock"
|
@@ -144,7 +145,7 @@ class Brakeman::Scanner
|
|
144
145
|
end
|
145
146
|
|
146
147
|
if @app_tree.gemspec
|
147
|
-
gem_files[:gemspec] = { :src =>
|
148
|
+
gem_files[:gemspec] = { :src => parse_ruby_file(@app_tree.gemspec), :file => @app_tree.gemspec }
|
148
149
|
end
|
149
150
|
|
150
151
|
if not gem_files.empty?
|
@@ -214,10 +215,9 @@ class Brakeman::Scanner
|
|
214
215
|
#Adds parsed information to tracker.routes
|
215
216
|
def process_routes
|
216
217
|
if @app_tree.exists?("config/routes.rb")
|
217
|
-
|
218
|
-
@processor.process_routes
|
219
|
-
|
220
|
-
tracker.error e.exception(e.message + "\nWhile processing routes.rb"), e.backtrace
|
218
|
+
if routes_sexp = parse_ruby_file("config/routes.rb")
|
219
|
+
@processor.process_routes routes_sexp
|
220
|
+
else
|
221
221
|
Brakeman.notify "[Notice] Error while processing routes - assuming all public controller methods are actions."
|
222
222
|
options[:assume_all_routes] = true
|
223
223
|
end
|
@@ -316,8 +316,9 @@ class Brakeman::Scanner
|
|
316
316
|
tracker.index_call_sites
|
317
317
|
end
|
318
318
|
|
319
|
-
def
|
320
|
-
|
319
|
+
def parse_ruby_file path
|
320
|
+
fp = Brakeman::FileParser.new(self.tracker, @app_tree)
|
321
|
+
fp.parse_ruby(@app_tree.read(path), path)
|
321
322
|
end
|
322
323
|
end
|
323
324
|
|
data/lib/brakeman/tracker.rb
CHANGED
@@ -61,7 +61,11 @@ class Brakeman::Tracker
|
|
61
61
|
Brakeman.debug exception
|
62
62
|
Brakeman.debug backtrace
|
63
63
|
|
64
|
-
@errors << {
|
64
|
+
@errors << {
|
65
|
+
:exception => exception,
|
66
|
+
:error => exception.to_s.gsub("\n", " "),
|
67
|
+
:backtrace => backtrace
|
68
|
+
}
|
65
69
|
end
|
66
70
|
|
67
71
|
#Run a set of checks on the current information. Results will be stored
|
@@ -122,22 +122,22 @@ module Brakeman
|
|
122
122
|
current_version ||= rails_version
|
123
123
|
return false unless current_version
|
124
124
|
|
125
|
-
version = current_version.split(".").map!
|
126
|
-
low_version = low_version.split(".").map!
|
127
|
-
high_version = high_version.split(".").map!
|
125
|
+
version = current_version.split(".").map! { |v| convert_version_number v }
|
126
|
+
low_version = low_version.split(".").map! { |v| convert_version_number v }
|
127
|
+
high_version = high_version.split(".").map! { |v| convert_version_number v }
|
128
128
|
|
129
129
|
version.each_with_index do |v, i|
|
130
|
-
if v
|
130
|
+
if lower? v, low_version.fetch(i, 0)
|
131
131
|
return false
|
132
|
-
elsif v
|
132
|
+
elsif higher? v, low_version.fetch(i, 0)
|
133
133
|
break
|
134
134
|
end
|
135
135
|
end
|
136
136
|
|
137
137
|
version.each_with_index do |v, i|
|
138
|
-
if v
|
138
|
+
if higher? v, high_version.fetch(i, 0)
|
139
139
|
return false
|
140
|
-
elsif v
|
140
|
+
elsif lower? v, high_version.fetch(i, 0)
|
141
141
|
break
|
142
142
|
end
|
143
143
|
end
|
@@ -150,5 +150,30 @@ module Brakeman
|
|
150
150
|
@rails[:action_controller][:session]
|
151
151
|
end
|
152
152
|
|
153
|
+
private
|
154
|
+
|
155
|
+
def convert_version_number value
|
156
|
+
if value.match(/\A\d+\z/)
|
157
|
+
value.to_i
|
158
|
+
else
|
159
|
+
value
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def lower? lhs, rhs
|
164
|
+
if lhs.class == rhs.class
|
165
|
+
lhs < rhs
|
166
|
+
else
|
167
|
+
false
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def higher? lhs, rhs
|
172
|
+
if lhs.class == rhs.class
|
173
|
+
lhs > rhs
|
174
|
+
else
|
175
|
+
false
|
176
|
+
end
|
177
|
+
end
|
153
178
|
end
|
154
179
|
end
|
data/lib/brakeman/util.rb
CHANGED
@@ -94,11 +94,21 @@ module Brakeman::Util
|
|
94
94
|
# end
|
95
95
|
# names #["bob"]
|
96
96
|
def hash_iterate hash
|
97
|
+
hash = remove_kwsplat(hash)
|
98
|
+
|
97
99
|
1.step(hash.length - 1, 2) do |i|
|
98
100
|
yield hash[i], hash[i + 1]
|
99
101
|
end
|
100
102
|
end
|
101
103
|
|
104
|
+
def remove_kwsplat exp
|
105
|
+
if exp.any? { |e| node_type? e, :kwsplat }
|
106
|
+
exp.reject { |e| node_type? e, :kwsplat }
|
107
|
+
else
|
108
|
+
exp
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
102
112
|
#Insert value into Hash Sexp
|
103
113
|
def hash_insert hash, key, value
|
104
114
|
index = 1
|
@@ -264,6 +274,13 @@ module Brakeman::Util
|
|
264
274
|
node_type? exp, :const, :colon2, :colon3
|
265
275
|
end
|
266
276
|
|
277
|
+
def kwsplat? exp
|
278
|
+
exp.is_a? Sexp and
|
279
|
+
exp.node_type == :hash and
|
280
|
+
exp[1].is_a? Sexp and
|
281
|
+
exp[1].node_type == :kwsplat
|
282
|
+
end
|
283
|
+
|
267
284
|
#Check if _exp_ is a Sexp.
|
268
285
|
def sexp? exp
|
269
286
|
exp.is_a? Sexp
|
data/lib/brakeman/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: brakeman-min
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin Collins
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain:
|
11
11
|
- brakeman-public_cert.pem
|
12
|
-
date: 2019-
|
12
|
+
date: 2019-03-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: minitest
|
@@ -25,20 +25,48 @@ dependencies:
|
|
25
25
|
- - ">="
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
version: '0'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: minitest-ci
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
28
42
|
- !ruby/object:Gem::Dependency
|
29
43
|
name: ruby_parser
|
30
44
|
requirement: !ruby/object:Gem::Requirement
|
31
45
|
requirements:
|
32
46
|
- - "~>"
|
33
47
|
- !ruby/object:Gem::Version
|
34
|
-
version: '3.
|
48
|
+
version: '3.13'
|
35
49
|
type: :runtime
|
36
50
|
prerelease: false
|
37
51
|
version_requirements: !ruby/object:Gem::Requirement
|
38
52
|
requirements:
|
39
53
|
- - "~>"
|
40
54
|
- !ruby/object:Gem::Version
|
41
|
-
version: '3.
|
55
|
+
version: '3.13'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: ruby_parser-legacy
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - "~>"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '1.0'
|
63
|
+
type: :runtime
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '1.0'
|
42
70
|
- !ruby/object:Gem::Dependency
|
43
71
|
name: sexp_processor
|
44
72
|
requirement: !ruby/object:Gem::Requirement
|
@@ -176,9 +204,11 @@ files:
|
|
176
204
|
- lib/brakeman/format/style.css
|
177
205
|
- lib/brakeman/messages.rb
|
178
206
|
- lib/brakeman/options.rb
|
207
|
+
- lib/brakeman/parsers/haml_embedded.rb
|
179
208
|
- lib/brakeman/parsers/rails2_erubis.rb
|
180
209
|
- lib/brakeman/parsers/rails2_xss_plugin_erubis.rb
|
181
210
|
- lib/brakeman/parsers/rails3_erubis.rb
|
211
|
+
- lib/brakeman/parsers/slim_embedded.rb
|
182
212
|
- lib/brakeman/parsers/template_parser.rb
|
183
213
|
- lib/brakeman/processor.rb
|
184
214
|
- lib/brakeman/processors/alias_processor.rb
|
@@ -258,7 +288,7 @@ files:
|
|
258
288
|
- lib/ruby_parser/bm_sexp_processor.rb
|
259
289
|
homepage: http://brakemanscanner.org
|
260
290
|
licenses:
|
261
|
-
-
|
291
|
+
- Brakeman Public Use License
|
262
292
|
metadata: {}
|
263
293
|
post_install_message:
|
264
294
|
rdoc_options: []
|