lib/roda/plugins/render.rb in roda-2.12.0 vs lib/roda/plugins/render.rb in roda-2.13.0

- old
+ new

@@ -26,14 +26,18 @@ # # = Plugin Options # # The following plugin options are supported: # + # :allowed_paths :: Set the template paths to allow if +:check_paths+ is true. + # Defaults to the +:views+ directory. # :cache :: nil/false to not cache templates (useful for development), defaults # to true unless RACK_ENV is development to automatically use the # default template cache. # :cache_class :: A class to use as the template cache instead of the default. + # :check_paths :: Check template paths start with one of the entries in +:allowed_paths+, + # and raise a RodaError if the path doesn't. # :engine :: The tilt engine to use for rendering, also the default file extension for # templates, defaults to 'erb'. # :escape :: Use Roda's Erubis escaping support, which makes <tt><%= %></tt> escape output, # <tt><%== %></tt> not escape output, and handles postfix conditions inside # <tt><%= %></tt> tags. @@ -135,10 +139,12 @@ app.opts[:render][:orig_opts] = opts opts = app.opts[:render] opts[:engine] = (opts[:engine] || opts[:ext] || "erb").dup.freeze opts[:views] = File.expand_path(opts[:views]||"views", app.opts[:root]).freeze + opts[:allowed_paths] ||= [opts[:views]].freeze + opts[:allowed_paths] = opts[:allowed_paths].map{|f| ::File.expand_path(f)}.uniq.freeze if opts.fetch(:cache, ENV['RACK_ENV'] != 'development') if cache_class = opts[:cache_class] opts[:cache] = cache_class.new else @@ -350,10 +356,17 @@ opts[:template].to_s end # The template path for the given options. def template_path(opts) - "#{opts[:views]}/#{template_name(opts)}.#{opts[:engine]}" + path = "#{opts[:views]}/#{template_name(opts)}.#{opts[:engine]}" + if opts.fetch(:check_paths){render_opts[:check_paths]} + full_path = ::File.expand_path(path) + unless render_opts[:allowed_paths].any?{|f| full_path.start_with?(f)} + raise RodaError, "attempt to render path not in allowed_paths: #{path} (allowed: #{render_opts[:allowed_paths].join(', ')})" + end + end + path end # If a layout should be used, return a hash of options for # rendering the layout template. If a layout should not be # used, return nil.