brakeman-lib 3.3.1
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.
- checksums.yaml +7 -0
- data/CHANGES +872 -0
- data/FEATURES +16 -0
- data/README.md +169 -0
- data/WARNING_TYPES +95 -0
- data/bin/brakeman +89 -0
- data/lib/brakeman.rb +495 -0
- data/lib/brakeman/app_tree.rb +161 -0
- data/lib/brakeman/brakeman.rake +17 -0
- data/lib/brakeman/call_index.rb +219 -0
- data/lib/brakeman/checks.rb +191 -0
- data/lib/brakeman/checks/base_check.rb +518 -0
- data/lib/brakeman/checks/check_basic_auth.rb +88 -0
- data/lib/brakeman/checks/check_basic_auth_timing_attack.rb +33 -0
- data/lib/brakeman/checks/check_content_tag.rb +160 -0
- data/lib/brakeman/checks/check_create_with.rb +75 -0
- data/lib/brakeman/checks/check_cross_site_scripting.rb +385 -0
- data/lib/brakeman/checks/check_default_routes.rb +86 -0
- data/lib/brakeman/checks/check_deserialize.rb +57 -0
- data/lib/brakeman/checks/check_detailed_exceptions.rb +55 -0
- data/lib/brakeman/checks/check_digest_dos.rb +38 -0
- data/lib/brakeman/checks/check_dynamic_finders.rb +49 -0
- data/lib/brakeman/checks/check_escape_function.rb +21 -0
- data/lib/brakeman/checks/check_evaluation.rb +36 -0
- data/lib/brakeman/checks/check_execute.rb +167 -0
- data/lib/brakeman/checks/check_file_access.rb +63 -0
- data/lib/brakeman/checks/check_file_disclosure.rb +35 -0
- data/lib/brakeman/checks/check_filter_skipping.rb +31 -0
- data/lib/brakeman/checks/check_forgery_setting.rb +74 -0
- data/lib/brakeman/checks/check_header_dos.rb +31 -0
- data/lib/brakeman/checks/check_i18n_xss.rb +48 -0
- data/lib/brakeman/checks/check_jruby_xml.rb +38 -0
- data/lib/brakeman/checks/check_json_encoding.rb +47 -0
- data/lib/brakeman/checks/check_json_parsing.rb +107 -0
- data/lib/brakeman/checks/check_link_to.rb +132 -0
- data/lib/brakeman/checks/check_link_to_href.rb +115 -0
- data/lib/brakeman/checks/check_mail_to.rb +49 -0
- data/lib/brakeman/checks/check_mass_assignment.rb +198 -0
- data/lib/brakeman/checks/check_mime_type_dos.rb +39 -0
- data/lib/brakeman/checks/check_model_attr_accessible.rb +55 -0
- data/lib/brakeman/checks/check_model_attributes.rb +119 -0
- data/lib/brakeman/checks/check_model_serialize.rb +67 -0
- data/lib/brakeman/checks/check_nested_attributes.rb +38 -0
- data/lib/brakeman/checks/check_nested_attributes_bypass.rb +58 -0
- data/lib/brakeman/checks/check_number_to_currency.rb +74 -0
- data/lib/brakeman/checks/check_quote_table_name.rb +40 -0
- data/lib/brakeman/checks/check_redirect.rb +215 -0
- data/lib/brakeman/checks/check_regex_dos.rb +69 -0
- data/lib/brakeman/checks/check_render.rb +92 -0
- data/lib/brakeman/checks/check_render_dos.rb +37 -0
- data/lib/brakeman/checks/check_render_inline.rb +54 -0
- data/lib/brakeman/checks/check_response_splitting.rb +21 -0
- data/lib/brakeman/checks/check_route_dos.rb +42 -0
- data/lib/brakeman/checks/check_safe_buffer_manipulation.rb +31 -0
- data/lib/brakeman/checks/check_sanitize_methods.rb +79 -0
- data/lib/brakeman/checks/check_secrets.rb +40 -0
- data/lib/brakeman/checks/check_select_tag.rb +60 -0
- data/lib/brakeman/checks/check_select_vulnerability.rb +60 -0
- data/lib/brakeman/checks/check_send.rb +48 -0
- data/lib/brakeman/checks/check_send_file.rb +19 -0
- data/lib/brakeman/checks/check_session_manipulation.rb +36 -0
- data/lib/brakeman/checks/check_session_settings.rb +170 -0
- data/lib/brakeman/checks/check_simple_format.rb +59 -0
- data/lib/brakeman/checks/check_single_quotes.rb +101 -0
- data/lib/brakeman/checks/check_skip_before_filter.rb +60 -0
- data/lib/brakeman/checks/check_sql.rb +660 -0
- data/lib/brakeman/checks/check_sql_cves.rb +101 -0
- data/lib/brakeman/checks/check_ssl_verify.rb +49 -0
- data/lib/brakeman/checks/check_strip_tags.rb +89 -0
- data/lib/brakeman/checks/check_symbol_dos.rb +64 -0
- data/lib/brakeman/checks/check_symbol_dos_cve.rb +30 -0
- data/lib/brakeman/checks/check_translate_bug.rb +45 -0
- data/lib/brakeman/checks/check_unsafe_reflection.rb +51 -0
- data/lib/brakeman/checks/check_unscoped_find.rb +41 -0
- data/lib/brakeman/checks/check_validation_regex.rb +116 -0
- data/lib/brakeman/checks/check_weak_hash.rb +151 -0
- data/lib/brakeman/checks/check_without_protection.rb +80 -0
- data/lib/brakeman/checks/check_xml_dos.rb +51 -0
- data/lib/brakeman/checks/check_yaml_parsing.rb +121 -0
- data/lib/brakeman/differ.rb +66 -0
- data/lib/brakeman/file_parser.rb +50 -0
- data/lib/brakeman/format/style.css +133 -0
- data/lib/brakeman/options.rb +301 -0
- data/lib/brakeman/parsers/rails2_erubis.rb +6 -0
- data/lib/brakeman/parsers/rails2_xss_plugin_erubis.rb +48 -0
- data/lib/brakeman/parsers/rails3_erubis.rb +74 -0
- data/lib/brakeman/parsers/template_parser.rb +89 -0
- data/lib/brakeman/processor.rb +102 -0
- data/lib/brakeman/processors/alias_processor.rb +1013 -0
- data/lib/brakeman/processors/base_processor.rb +277 -0
- data/lib/brakeman/processors/config_processor.rb +14 -0
- data/lib/brakeman/processors/controller_alias_processor.rb +273 -0
- data/lib/brakeman/processors/controller_processor.rb +326 -0
- data/lib/brakeman/processors/erb_template_processor.rb +80 -0
- data/lib/brakeman/processors/erubis_template_processor.rb +104 -0
- data/lib/brakeman/processors/gem_processor.rb +57 -0
- data/lib/brakeman/processors/haml_template_processor.rb +190 -0
- data/lib/brakeman/processors/lib/basic_processor.rb +37 -0
- data/lib/brakeman/processors/lib/find_all_calls.rb +223 -0
- data/lib/brakeman/processors/lib/find_call.rb +183 -0
- data/lib/brakeman/processors/lib/find_return_value.rb +134 -0
- data/lib/brakeman/processors/lib/processor_helper.rb +75 -0
- data/lib/brakeman/processors/lib/rails2_config_processor.rb +145 -0
- data/lib/brakeman/processors/lib/rails2_route_processor.rb +313 -0
- data/lib/brakeman/processors/lib/rails3_config_processor.rb +132 -0
- data/lib/brakeman/processors/lib/rails3_route_processor.rb +308 -0
- data/lib/brakeman/processors/lib/render_helper.rb +181 -0
- data/lib/brakeman/processors/lib/render_path.rb +107 -0
- data/lib/brakeman/processors/lib/route_helper.rb +68 -0
- data/lib/brakeman/processors/lib/safe_call_helper.rb +16 -0
- data/lib/brakeman/processors/library_processor.rb +119 -0
- data/lib/brakeman/processors/model_processor.rb +191 -0
- data/lib/brakeman/processors/output_processor.rb +171 -0
- data/lib/brakeman/processors/route_processor.rb +17 -0
- data/lib/brakeman/processors/slim_template_processor.rb +107 -0
- data/lib/brakeman/processors/template_alias_processor.rb +116 -0
- data/lib/brakeman/processors/template_processor.rb +74 -0
- data/lib/brakeman/report.rb +78 -0
- data/lib/brakeman/report/config/remediation.yml +71 -0
- data/lib/brakeman/report/ignore/config.rb +135 -0
- data/lib/brakeman/report/ignore/interactive.rb +311 -0
- data/lib/brakeman/report/renderer.rb +24 -0
- data/lib/brakeman/report/report_base.rb +286 -0
- data/lib/brakeman/report/report_codeclimate.rb +70 -0
- data/lib/brakeman/report/report_csv.rb +55 -0
- data/lib/brakeman/report/report_hash.rb +23 -0
- data/lib/brakeman/report/report_html.rb +216 -0
- data/lib/brakeman/report/report_json.rb +42 -0
- data/lib/brakeman/report/report_markdown.rb +156 -0
- data/lib/brakeman/report/report_table.rb +107 -0
- data/lib/brakeman/report/report_tabs.rb +17 -0
- data/lib/brakeman/report/templates/controller_overview.html.erb +22 -0
- data/lib/brakeman/report/templates/controller_warnings.html.erb +21 -0
- data/lib/brakeman/report/templates/error_overview.html.erb +29 -0
- data/lib/brakeman/report/templates/header.html.erb +58 -0
- data/lib/brakeman/report/templates/ignored_warnings.html.erb +25 -0
- data/lib/brakeman/report/templates/model_warnings.html.erb +21 -0
- data/lib/brakeman/report/templates/overview.html.erb +38 -0
- data/lib/brakeman/report/templates/security_warnings.html.erb +23 -0
- data/lib/brakeman/report/templates/template_overview.html.erb +21 -0
- data/lib/brakeman/report/templates/view_warnings.html.erb +34 -0
- data/lib/brakeman/report/templates/warning_overview.html.erb +17 -0
- data/lib/brakeman/rescanner.rb +483 -0
- data/lib/brakeman/scanner.rb +317 -0
- data/lib/brakeman/tracker.rb +347 -0
- data/lib/brakeman/tracker/collection.rb +93 -0
- data/lib/brakeman/tracker/config.rb +101 -0
- data/lib/brakeman/tracker/constants.rb +101 -0
- data/lib/brakeman/tracker/controller.rb +161 -0
- data/lib/brakeman/tracker/library.rb +17 -0
- data/lib/brakeman/tracker/model.rb +90 -0
- data/lib/brakeman/tracker/template.rb +33 -0
- data/lib/brakeman/util.rb +481 -0
- data/lib/brakeman/version.rb +3 -0
- data/lib/brakeman/warning.rb +255 -0
- data/lib/brakeman/warning_codes.rb +111 -0
- data/lib/ruby_parser/bm_sexp.rb +610 -0
- data/lib/ruby_parser/bm_sexp_processor.rb +116 -0
- metadata +362 -0
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
require 'brakeman/processors/base_processor'
|
|
2
|
+
require 'brakeman/tracker/model'
|
|
3
|
+
|
|
4
|
+
#Processes models. Puts results in tracker.models
|
|
5
|
+
class Brakeman::ModelProcessor < Brakeman::BaseProcessor
|
|
6
|
+
|
|
7
|
+
def initialize tracker
|
|
8
|
+
super
|
|
9
|
+
@current_class = nil
|
|
10
|
+
@current_method = nil
|
|
11
|
+
@current_module = nil
|
|
12
|
+
@visibility = :public
|
|
13
|
+
@file_name = nil
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
#Process model source
|
|
17
|
+
def process_model src, file_name = nil
|
|
18
|
+
@file_name = file_name
|
|
19
|
+
process src
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
#s(:class, NAME, PARENT, BODY)
|
|
23
|
+
def process_class exp
|
|
24
|
+
name = class_name(exp.class_name)
|
|
25
|
+
parent = class_name(exp.parent_name)
|
|
26
|
+
|
|
27
|
+
#If inside an inner class we treat it as a library.
|
|
28
|
+
if @current_class
|
|
29
|
+
Brakeman.debug "[Notice] Treating inner class as library: #{name}"
|
|
30
|
+
Brakeman::LibraryProcessor.new(@tracker).process_library exp, @file_name
|
|
31
|
+
return exp
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
if @current_class
|
|
35
|
+
outer_class = @current_class
|
|
36
|
+
name = (outer_class.name.to_s + "::" + name.to_s).to_sym
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
if @current_module
|
|
40
|
+
name = (@current_module.name.to_s + "::" + name.to_s).to_sym
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
if @tracker.models[name]
|
|
44
|
+
@current_class = @tracker.models[name]
|
|
45
|
+
@current_class.add_file @file_name, exp
|
|
46
|
+
else
|
|
47
|
+
@current_class = Brakeman::Model.new name, parent, @file_name, exp, @tracker
|
|
48
|
+
@tracker.models[name] = @current_class
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
exp.body = process_all! exp.body
|
|
52
|
+
|
|
53
|
+
if outer_class
|
|
54
|
+
@current_class = outer_class
|
|
55
|
+
else
|
|
56
|
+
@current_class = nil
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
exp
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def process_module exp
|
|
63
|
+
name = class_name(exp.class_name)
|
|
64
|
+
|
|
65
|
+
if @current_module
|
|
66
|
+
outer_module = @current_module
|
|
67
|
+
name = (outer_module.name.to_s + "::" + name.to_s).to_sym
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
if @current_class
|
|
71
|
+
name = (@current_class.name.to_s + "::" + name.to_s).to_sym
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
if @tracker.libs[name]
|
|
75
|
+
@current_module = @tracker.libs[name]
|
|
76
|
+
@current_module.add_file @file_name, exp
|
|
77
|
+
else
|
|
78
|
+
@current_module = Brakeman::Model.new name, nil, @file_name, exp, @tracker
|
|
79
|
+
@tracker.libs[name] = @current_module
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
exp.body = process_all! exp.body
|
|
83
|
+
|
|
84
|
+
if outer_module
|
|
85
|
+
@current_module = outer_module
|
|
86
|
+
else
|
|
87
|
+
@current_module = nil
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
exp
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
#Handle calls outside of methods,
|
|
94
|
+
#such as include, attr_accessible, private, etc.
|
|
95
|
+
def process_call exp
|
|
96
|
+
return exp unless @current_class
|
|
97
|
+
return exp if process_call_defn? exp
|
|
98
|
+
|
|
99
|
+
target = exp.target
|
|
100
|
+
if sexp? target
|
|
101
|
+
target = process target
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
method = exp.method
|
|
105
|
+
first_arg = exp.first_arg
|
|
106
|
+
|
|
107
|
+
#Methods called inside class definition
|
|
108
|
+
#like attr_* and other settings
|
|
109
|
+
if @current_method.nil? and target.nil?
|
|
110
|
+
if first_arg.nil?
|
|
111
|
+
case method
|
|
112
|
+
when :private, :protected, :public
|
|
113
|
+
@visibility = method
|
|
114
|
+
when :attr_accessible
|
|
115
|
+
@current_class.set_attr_accessible
|
|
116
|
+
else
|
|
117
|
+
#??
|
|
118
|
+
end
|
|
119
|
+
else
|
|
120
|
+
case method
|
|
121
|
+
when :include
|
|
122
|
+
@current_class.add_include class_name(first_arg) if @current_class
|
|
123
|
+
when :attr_accessible
|
|
124
|
+
@current_class.set_attr_accessible exp
|
|
125
|
+
when :attr_protected
|
|
126
|
+
@current_class.set_attr_protected exp
|
|
127
|
+
else
|
|
128
|
+
if @current_class
|
|
129
|
+
@current_class.add_option method, exp
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
exp
|
|
135
|
+
else
|
|
136
|
+
call = make_call target, method, process_all!(exp.args)
|
|
137
|
+
call.line(exp.line)
|
|
138
|
+
call
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
#Add method definition to tracker
|
|
143
|
+
def process_defn exp
|
|
144
|
+
return exp unless @current_class
|
|
145
|
+
name = exp.method_name
|
|
146
|
+
|
|
147
|
+
@current_method = name
|
|
148
|
+
res = Sexp.new :defn, name, exp.formal_args, *process_all!(exp.body)
|
|
149
|
+
res.line(exp.line)
|
|
150
|
+
@current_method = nil
|
|
151
|
+
|
|
152
|
+
if @current_class
|
|
153
|
+
@current_class.add_method @visibility, name, res, @file_name
|
|
154
|
+
elsif @current_module
|
|
155
|
+
@current_module.add_method @visibility, name, res, @file_name
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
res
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
#Add method definition to tracker
|
|
162
|
+
def process_defs exp
|
|
163
|
+
return exp unless @current_class
|
|
164
|
+
name = exp.method_name
|
|
165
|
+
|
|
166
|
+
if node_type? exp[1], :self
|
|
167
|
+
if @current_class
|
|
168
|
+
target = @current_class.name
|
|
169
|
+
elsif @current_module
|
|
170
|
+
target = @current_module.name
|
|
171
|
+
else
|
|
172
|
+
target = nil
|
|
173
|
+
end
|
|
174
|
+
else
|
|
175
|
+
target = class_name exp[1]
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
@current_method = name
|
|
179
|
+
res = Sexp.new :defs, target, name, exp.formal_args, *process_all!(exp.body)
|
|
180
|
+
res.line(exp.line)
|
|
181
|
+
@current_method = nil
|
|
182
|
+
|
|
183
|
+
if @current_class
|
|
184
|
+
@current_class.add_method @visibility, name, res, @file_name
|
|
185
|
+
elsif @current_module
|
|
186
|
+
@current_module.add_method @visibility, name, res, @file_name
|
|
187
|
+
end
|
|
188
|
+
res
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
end
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
Brakeman.load_brakeman_dependency 'ruby2ruby'
|
|
2
|
+
require 'brakeman/util'
|
|
3
|
+
|
|
4
|
+
#Produces formatted output strings from Sexps.
|
|
5
|
+
#Recommended usage is
|
|
6
|
+
#
|
|
7
|
+
# OutputProcessor.new.format(Sexp.new(:str, "hello"))
|
|
8
|
+
class Brakeman::OutputProcessor < Ruby2Ruby
|
|
9
|
+
include Brakeman::Util
|
|
10
|
+
|
|
11
|
+
#Copies +exp+ and then formats it.
|
|
12
|
+
def format exp
|
|
13
|
+
process(exp.deep_clone) || "[Format Error]"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
alias process_safely format
|
|
17
|
+
|
|
18
|
+
def process exp
|
|
19
|
+
begin
|
|
20
|
+
super exp if sexp? exp and not exp.empty?
|
|
21
|
+
rescue => e
|
|
22
|
+
Brakeman.debug "While formatting #{exp}: #{e}\n#{e.backtrace.join("\n")}"
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def process_ignore exp
|
|
27
|
+
exp.clear
|
|
28
|
+
"[ignored]"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def process_params exp
|
|
32
|
+
exp.clear
|
|
33
|
+
"params"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def process_session exp
|
|
37
|
+
exp.clear
|
|
38
|
+
"session"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def process_cookies exp
|
|
42
|
+
exp.clear
|
|
43
|
+
"cookies"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def process_rlist exp
|
|
47
|
+
out = exp.map do |e|
|
|
48
|
+
res = process e
|
|
49
|
+
if res == ""
|
|
50
|
+
nil
|
|
51
|
+
else
|
|
52
|
+
res
|
|
53
|
+
end
|
|
54
|
+
end.compact.join("\n")
|
|
55
|
+
exp.clear
|
|
56
|
+
out
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def process_defn exp
|
|
60
|
+
# Copied from Ruby2Ruby except without the whole
|
|
61
|
+
# "convert methods to attr_*" stuff
|
|
62
|
+
name = exp.shift
|
|
63
|
+
args = process exp.shift
|
|
64
|
+
args = "" if args == "()"
|
|
65
|
+
|
|
66
|
+
exp.shift if exp == s(s(:nil)) # empty it out of a default nil expression
|
|
67
|
+
|
|
68
|
+
body = []
|
|
69
|
+
until exp.empty? do
|
|
70
|
+
body << indent(process(exp.shift))
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
body << indent("# do nothing") if body.empty?
|
|
74
|
+
|
|
75
|
+
body = body.join("\n")
|
|
76
|
+
|
|
77
|
+
return "def #{name}#{args}\n#{body}\nend".gsub(/\n\s*\n+/, "\n")
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def process_iter exp
|
|
81
|
+
call = process exp[0]
|
|
82
|
+
block = process_rlist exp[2..-1]
|
|
83
|
+
out = "#{call} do\n #{block}\n end"
|
|
84
|
+
exp.clear
|
|
85
|
+
out
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def process_output exp
|
|
89
|
+
out = if exp[0].node_type == :str
|
|
90
|
+
""
|
|
91
|
+
else
|
|
92
|
+
res = process exp[0]
|
|
93
|
+
|
|
94
|
+
if res == ""
|
|
95
|
+
""
|
|
96
|
+
else
|
|
97
|
+
"[Output] #{res}"
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
exp.clear
|
|
101
|
+
out
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def process_escaped_output exp
|
|
105
|
+
out = if exp[0].node_type == :str
|
|
106
|
+
""
|
|
107
|
+
else
|
|
108
|
+
res = process exp[0]
|
|
109
|
+
|
|
110
|
+
if res == ""
|
|
111
|
+
""
|
|
112
|
+
else
|
|
113
|
+
"[Escaped Output] #{res}"
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
exp.clear
|
|
117
|
+
out
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def process_format exp
|
|
122
|
+
out = if exp[0].node_type == :str or exp[0].node_type == :ignore
|
|
123
|
+
""
|
|
124
|
+
else
|
|
125
|
+
res = process exp[0]
|
|
126
|
+
|
|
127
|
+
if res == ""
|
|
128
|
+
""
|
|
129
|
+
else
|
|
130
|
+
"[Format] #{res}"
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
exp.clear
|
|
134
|
+
out
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def process_format_escaped exp
|
|
138
|
+
out = if exp[0].node_type == :str or exp[0].node_type == :ignore
|
|
139
|
+
""
|
|
140
|
+
else
|
|
141
|
+
res = process exp[0]
|
|
142
|
+
|
|
143
|
+
if res == ""
|
|
144
|
+
""
|
|
145
|
+
else
|
|
146
|
+
"[Escaped] #{res}"
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
exp.clear
|
|
150
|
+
out
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def process_const exp
|
|
154
|
+
if exp[0] == Brakeman::Tracker::UNKNOWN_MODEL
|
|
155
|
+
exp.clear
|
|
156
|
+
"(Unresolved Model)"
|
|
157
|
+
else
|
|
158
|
+
out = exp[0].to_s
|
|
159
|
+
exp.clear
|
|
160
|
+
out
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def process_render exp
|
|
165
|
+
exp[1] = process exp[1] if sexp? exp[1]
|
|
166
|
+
exp[2] = process exp[2] if sexp? exp[2]
|
|
167
|
+
out = "render(#{exp[0]} => #{exp[1]}, #{exp[2]})"
|
|
168
|
+
exp.clear
|
|
169
|
+
out
|
|
170
|
+
end
|
|
171
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'brakeman/processors/base_processor'
|
|
2
|
+
require 'brakeman/processors/alias_processor'
|
|
3
|
+
require 'brakeman/processors/lib/route_helper'
|
|
4
|
+
require 'brakeman/util'
|
|
5
|
+
require 'brakeman/processors/lib/rails3_route_processor.rb'
|
|
6
|
+
require 'brakeman/processors/lib/rails2_route_processor.rb'
|
|
7
|
+
require 'set'
|
|
8
|
+
|
|
9
|
+
class Brakeman::RoutesProcessor
|
|
10
|
+
def self.new tracker
|
|
11
|
+
if tracker.options[:rails3]
|
|
12
|
+
Brakeman::Rails3RoutesProcessor.new tracker
|
|
13
|
+
else
|
|
14
|
+
Brakeman::Rails2RoutesProcessor.new tracker
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
require 'brakeman/processors/template_processor'
|
|
2
|
+
require 'brakeman/processors/lib/render_helper'
|
|
3
|
+
|
|
4
|
+
class Brakeman::SlimTemplateProcessor < Brakeman::TemplateProcessor
|
|
5
|
+
include Brakeman::RenderHelper
|
|
6
|
+
|
|
7
|
+
SAFE_BUFFER = s(:call, s(:colon2, s(:const, :ActiveSupport), :SafeBuffer), :new)
|
|
8
|
+
OUTPUT_BUFFER = s(:ivar, :@output_buffer)
|
|
9
|
+
TEMPLE_UTILS = s(:colon2, s(:colon3, :Temple), :Utils)
|
|
10
|
+
|
|
11
|
+
def process_call exp
|
|
12
|
+
target = exp.target
|
|
13
|
+
method = exp.method
|
|
14
|
+
|
|
15
|
+
if method == :safe_concat and (target == SAFE_BUFFER or target == OUTPUT_BUFFER)
|
|
16
|
+
arg = normalize_output(exp.first_arg)
|
|
17
|
+
|
|
18
|
+
if is_escaped? arg
|
|
19
|
+
make_escaped_output arg
|
|
20
|
+
elsif string? arg
|
|
21
|
+
ignore
|
|
22
|
+
elsif render? arg
|
|
23
|
+
make_output make_render_in_view arg
|
|
24
|
+
elsif string_interp? arg
|
|
25
|
+
process_inside_interp arg
|
|
26
|
+
elsif node_type? arg, :ignore
|
|
27
|
+
ignore
|
|
28
|
+
else
|
|
29
|
+
make_output arg
|
|
30
|
+
end
|
|
31
|
+
elsif is_escaped? exp
|
|
32
|
+
make_escaped_output exp.first_arg
|
|
33
|
+
elsif target == nil and method == :render
|
|
34
|
+
exp.arglist = process exp.arglist
|
|
35
|
+
make_render_in_view exp
|
|
36
|
+
else
|
|
37
|
+
exp.arglist = process exp.arglist
|
|
38
|
+
exp
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def make_output exp
|
|
43
|
+
s = Sexp.new :output, exp
|
|
44
|
+
s.line(exp.line)
|
|
45
|
+
@current_template.add_output s
|
|
46
|
+
s
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def make_escaped_output exp
|
|
50
|
+
s = Sexp.new :escaped_output, exp.first_arg
|
|
51
|
+
s.line(exp.line)
|
|
52
|
+
@current_template.add_output s
|
|
53
|
+
s
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
#Slim likes to interpolate output into strings then pass them to safe_concat.
|
|
57
|
+
#Better to pull those values out directly.
|
|
58
|
+
def process_inside_interp exp
|
|
59
|
+
exp.map! do |e|
|
|
60
|
+
if node_type? e, :evstr
|
|
61
|
+
e.value = process_interp_output e.value
|
|
62
|
+
e
|
|
63
|
+
else
|
|
64
|
+
e
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
exp
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def process_interp_output exp
|
|
72
|
+
if sexp? exp
|
|
73
|
+
if node_type? exp, :if
|
|
74
|
+
process_interp_output exp.then_clause
|
|
75
|
+
process_interp_output exp.else_clause
|
|
76
|
+
elsif exp == SAFE_BUFFER
|
|
77
|
+
ignore
|
|
78
|
+
elsif render? exp
|
|
79
|
+
make_output make_render_in_view exp
|
|
80
|
+
elsif node_type? :output, :escaped_output
|
|
81
|
+
exp
|
|
82
|
+
elsif is_escaped? exp
|
|
83
|
+
make_escaped_output exp
|
|
84
|
+
else
|
|
85
|
+
make_output exp
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def is_escaped? exp
|
|
91
|
+
call? exp and
|
|
92
|
+
exp.target == TEMPLE_UTILS and
|
|
93
|
+
(exp.method == :escape_html or exp.method == :escape_html_safe)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def render? exp
|
|
97
|
+
call? exp and
|
|
98
|
+
exp.target.nil? and
|
|
99
|
+
exp.method == :render
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def process_render exp
|
|
103
|
+
#Still confused as to why this is not needed in other template processors
|
|
104
|
+
#but is needed here
|
|
105
|
+
exp
|
|
106
|
+
end
|
|
107
|
+
end
|