提交 35bc224a 编写于 作者: J Justin

Merge pull request #690 from presidentbeef/use_real_objects_in_tracker

Add Model, Controller, Template, Config classes
......@@ -39,8 +39,9 @@ class Brakeman::BaseCheck < Brakeman::SexpProcessor
#Add result to result list, which is used to check for duplicates
def add_result result, location = nil
location ||= (@current_template && @current_template[:name]) || @current_class || @current_module || @current_set || result[:location][:class] || result[:location][:template]
location ||= (@current_template && @current_template.name) || @current_class || @current_module || @current_set || result[:location][:class] || result[:location][:template]
location = location[:name] if location.is_a? Hash
location = location.name if location.is_a? Brakeman::Collection
location = location.to_sym
if result.is_a? Hash
......@@ -138,36 +139,6 @@ class Brakeman::BaseCheck < Brakeman::SexpProcessor
Brakeman::OutputProcessor.new.format(exp).gsub(/\r|\n/, "")
end
#Checks if the model inherits from parent,
def ancestor? model, parent, seen={}
return false unless model
seen[model[:name]] = true
if model[:parent] == parent || seen[model[:parent]]
true
elsif model[:parent]
ancestor? tracker.models[model[:parent]], parent, seen
else
false
end
end
def unprotected_model? model
model[:attr_accessible].nil? and !parent_classes_protected?(model) and ancestor?(model, :"ActiveRecord::Base")
end
# go up the chain of parent classes to see if any have attr_accessible
def parent_classes_protected? model, seen={}
seen[model] = true
if model[:attr_accessible] or model[:includes].include? :"ActiveModel::ForbiddenAttributesProtection"
true
elsif parent = tracker.models[model[:parent]] and !seen[parent]
parent_classes_protected? parent, seen
else
false
end
end
#Checks if mass assignment is disabled globally in an initializer.
def mass_assign_disabled?
return @mass_assign_disabled unless @mass_assign_disabled.nil?
......@@ -175,12 +146,10 @@ class Brakeman::BaseCheck < Brakeman::SexpProcessor
@mass_assign_disabled = false
if version_between?("3.1.0", "3.9.9") and
tracker.config[:rails][:active_record] and
tracker.config[:rails][:active_record][:whitelist_attributes] == Sexp.new(:true)
tracker.config.whitelist_attributes?
@mass_assign_disabled = true
elsif tracker.options[:rails4] && (!tracker.config[:gems][:protected_attributes] || (tracker.config[:rails][:active_record] &&
tracker.config[:rails][:active_record][:whitelist_attributes] == Sexp.new(:true)))
elsif tracker.options[:rails4] && (!tracker.config.has_gem?(:protected_attributes) || tracker.config.whitelist_attributes?)
@mass_assign_disabled = true
else
......@@ -231,7 +200,7 @@ class Brakeman::BaseCheck < Brakeman::SexpProcessor
#gem and still using hack above, so this is a separate check for
#including ActiveModel::ForbiddenAttributesProtection in
#ActiveRecord::Base in an initializer.
if not @mass_assign_disabled and version_between?("3.1.0", "3.9.9") and tracker.config[:gems][:strong_parameters]
if not @mass_assign_disabled and version_between?("3.1.0", "3.9.9") and tracker.config.has_gem? :strong_parameters
matches = tracker.check_initializers([], :include)
forbidden_protection = Sexp.new(:colon2, Sexp.new(:const, :ActiveModel), :ForbiddenAttributesProtection)
......@@ -267,9 +236,10 @@ class Brakeman::BaseCheck < Brakeman::SexpProcessor
raise ArgumentError
end
location ||= (@current_template && @current_template[:name]) || @current_class || @current_module || @current_set || result[:location][:class] || result[:location][:template]
location ||= (@current_template && @current_template.name) || @current_class || @current_module || @current_set || result[:location][:class] || result[:location][:template]
location = location[:name] if location.is_a? Hash
location = location.name if location.is_a? Brakeman::Collection
location = location.to_sym
@results.each do |r|
......@@ -456,7 +426,7 @@ class Brakeman::BaseCheck < Brakeman::SexpProcessor
#
#If the Rails version is unknown, returns false.
def version_between? low_version, high_version, current_version = nil
current_version ||= tracker.config[:rails_version]
current_version ||= rails_version
return false unless current_version
version = current_version.split(".").map! { |n| n.to_i }
......@@ -483,12 +453,12 @@ class Brakeman::BaseCheck < Brakeman::SexpProcessor
end
def lts_version? version
tracker.config[:gems][:'railslts-version'] and
version_between? version, "2.3.18.99", tracker.config[:gems][:'railslts-version'][:version]
tracker.config.has_gem? :'railslts-version' and
version_between? version, "2.3.18.99", tracker.config.gem_version(:'railslts-version')
end
def gemfile_or_environment gem_name = :rails
if gem_name and info = tracker.config[:gems][gem_name]
if gem_name and info = tracker.config.get_gem(gem_name)
info
elsif @app_tree.exists?("Gemfile")
"Gemfile"
......@@ -507,7 +477,7 @@ class Brakeman::BaseCheck < Brakeman::SexpProcessor
@active_record_models = {}
tracker.models.each do |name, model|
if ancestor? model, :"ActiveRecord::Base"
if model.ancestor? :"ActiveRecord::Base"
@active_record_models[name] = model
end
end
......
......@@ -18,11 +18,11 @@ class Brakeman::CheckBasicAuth < Brakeman::BaseCheck
def check_basic_auth_filter
controllers = tracker.controllers.select do |name, c|
c[:options][:http_basic_authenticate_with]
c.options[:http_basic_authenticate_with]
end
Hash[controllers].each do |name, controller|
controller[:options][:http_basic_authenticate_with].each do |call|
controller.options[:http_basic_authenticate_with].each do |call|
if pass = get_password(call) and string? pass
warn :controller => name,
......@@ -31,7 +31,7 @@ class Brakeman::CheckBasicAuth < Brakeman::BaseCheck
:message => "Basic authentication password stored in source code",
:code => call,
:confidence => 0,
:file => controller[:files].first
:file => controller.file
break
end
end
......
......@@ -42,7 +42,7 @@ class Brakeman::CheckCrossSiteScripting < Brakeman::BaseCheck
@current_template = template
template[:outputs].each do |out|
template.each_output do |out|
unless check_for_immediate_xss out
@matched = false
@mark = false
......@@ -314,9 +314,7 @@ class Brakeman::CheckCrossSiteScripting < Brakeman::BaseCheck
initializers = tracker.check_initializers :ActiveSupport, :escape_html_entities_in_json=
initializers.each {|result| json_escape_on = true?(result.call.first_arg) }
if tracker.config[:rails][:active_support] and
true? tracker.config[:rails][:active_support][:escape_html_entities_in_json]
if tracker.config.escape_html_entities_in_json?
json_escape_on = true
elsif version_between? "4.0.0", "5.0.0"
json_escape_on = true
......
......@@ -74,7 +74,7 @@ class Brakeman::CheckDefaultRoutes < Brakeman::BaseCheck
warn :warning_type => "Remote Code Execution",
:warning_code => :CVE_2014_0130,
:message => "Rails #{tracker.config[:rails_version]} with globbing routes is vulnerable to directory traversal and remote code execution. Patch or upgrade to #{upgrade}",
:message => "Rails #{rails_version} with globbing routes is vulnerable to directory traversal and remote code execution. Patch or upgrade to #{upgrade}",
:confidence => confidence,
:file => "#{tracker.app_path}/config/routes.rb",
:link => "http://matasano.com/research/AnatomyOfRailsVuln-CVE-2014-0130.pdf"
......
......@@ -14,7 +14,7 @@ class Brakeman::CheckDetailedExceptions < Brakeman::BaseCheck
end
def check_local_request_config
if true? tracker.config[:rails][:consider_all_requests_local]
if true? tracker.config.rails[:consider_all_requests_local]
warn :warning_type => "Information Disclosure",
:warning_code => :local_request_config,
:message => "Detailed exceptions are enabled in production",
......@@ -25,7 +25,7 @@ class Brakeman::CheckDetailedExceptions < Brakeman::BaseCheck
def check_detailed_exceptions
tracker.controllers.each do |name, controller|
controller[:public].each do |name, definition|
controller.methods_public.each do |name, definition|
src = definition[:src]
body = src.body.last
next unless body
......
......@@ -22,7 +22,7 @@ class Brakeman::CheckFileDisclosure < Brakeman::BaseCheck
if fix_version and serves_static_assets?
warn :warning_type => "File Access",
:warning_code => :CVE_2014_7829,
:message => "Rails #{tracker.config[:rails_version]} has a file existence disclosure. Upgrade to #{fix_version} or disable serving static assets",
:message => "Rails #{rails_version} has a file existence disclosure. Upgrade to #{fix_version} or disable serving static assets",
:confidence => CONFIDENCE[:high],
:gem_info => gemfile_or_environment,
:link_path => "https://groups.google.com/d/msg/rubyonrails-security/23fiuwb1NBA/MQVM1-5GkPMJ"
......@@ -30,6 +30,6 @@ class Brakeman::CheckFileDisclosure < Brakeman::BaseCheck
end
def serves_static_assets?
true? tracker.config[:rails][:serve_static_assets]
true? tracker.config.rails[:serve_static_assets]
end
end
......@@ -11,34 +11,31 @@ class Brakeman::CheckForgerySetting < Brakeman::BaseCheck
def run_check
app_controller = tracker.controllers[:ApplicationController]
return unless app_controller and app_controller.ancestor? :"ActionController::Base"
return unless ancestor? app_controller, :"ActionController::Base"
if tracker.config[:rails][:action_controller] and
tracker.config[:rails][:action_controller][:allow_forgery_protection] == Sexp.new(:false)
if tracker.config.allow_forgery_protection?
warn :controller => :ApplicationController,
:warning_type => "Cross-Site Request Forgery",
:warning_code => :csrf_protection_disabled,
:message => "Forgery protection is disabled",
:confidence => CONFIDENCE[:high],
:file => app_controller[:files].first
:file => app_controller.file
elsif app_controller and not app_controller[:options][:protect_from_forgery]
elsif app_controller and not app_controller.protect_from_forgery?
warn :controller => :ApplicationController,
:warning_type => "Cross-Site Request Forgery",
:warning_code => :csrf_protection_missing,
:message => "'protect_from_forgery' should be called in ApplicationController",
:confidence => CONFIDENCE[:high],
:file => app_controller[:files].first
:file => app_controller.file
elsif version_between? "2.1.0", "2.3.10"
warn :controller => :ApplicationController,
:warning_type => "Cross-Site Request Forgery",
:warning_code => :CVE_2011_0447,
:message => "CSRF protection is flawed in unpatched versions of Rails #{tracker.config[:rails_version]} (CVE-2011-0447). Upgrade to 2.3.11 or apply patches as needed",
:message => "CSRF protection is flawed in unpatched versions of Rails #{rails_version} (CVE-2011-0447). Upgrade to 2.3.11 or apply patches as needed",
:confidence => CONFIDENCE[:high],
:gem_info => gemfile_or_environment,
:link_path => "https://groups.google.com/d/topic/rubyonrails-security/LZWjzCPgNmU/discussion"
......@@ -48,11 +45,11 @@ class Brakeman::CheckForgerySetting < Brakeman::BaseCheck
warn :controller => :ApplicationController,
:warning_type => "Cross-Site Request Forgery",
:warning_code => :CVE_2011_0447,
:message => "CSRF protection is flawed in unpatched versions of Rails #{tracker.config[:rails_version]} (CVE-2011-0447). Upgrade to 3.0.4 or apply patches as needed",
:message => "CSRF protection is flawed in unpatched versions of Rails #{rails_version} (CVE-2011-0447). Upgrade to 3.0.4 or apply patches as needed",
:confidence => CONFIDENCE[:high],
:gem_info => gemfile_or_environment,
:link_path => "https://groups.google.com/d/topic/rubyonrails-security/LZWjzCPgNmU/discussion"
elsif version_between? "4.0.0", "100.0.0" and forgery_opts = app_controller[:options][:protect_from_forgery]
elsif version_between? "4.0.0", "100.0.0" and forgery_opts = app_controller.options[:protect_from_forgery]
unless forgery_opts.is_a?(Array) and sexp?(forgery_opts.first) and
access_arg = hash_access(forgery_opts.first.first_arg, :with) and access_arg.value == :exception
......@@ -63,7 +60,7 @@ class Brakeman::CheckForgerySetting < Brakeman::BaseCheck
:warning_code => :csrf_not_protected_by_raising_exception,
:message => "protect_from_forgery should be configured with 'with: :exception'",
:confidence => CONFIDENCE[:med],
:file => app_controller[:files].first
:file => app_controller.file
}
args.merge!(:code => forgery_opts.first) if forgery_opts.is_a?(Array)
......
......@@ -7,7 +7,7 @@ class Brakeman::CheckHeaderDoS < Brakeman::BaseCheck
def run_check
if (version_between? "3.0.0", "3.2.15" or version_between? "4.0.0", "4.0.1") and not has_workaround?
message = "Rails #{tracker.config[:rails_version]} has a denial of service vulnerability (CVE-2013-6414). Upgrade to Rails version "
message = "Rails #{rails_version} has a denial of service vulnerability (CVE-2013-6414). Upgrade to Rails version "
if version_between? "3.0.0", "3.2.15"
message << "3.2.16"
......
......@@ -7,8 +7,8 @@ class Brakeman::CheckI18nXSS < Brakeman::BaseCheck
def run_check
if (version_between? "3.0.6", "3.2.15" or version_between? "4.0.0", "4.0.1") and not has_workaround?
message = "Rails #{tracker.config[:rails_version]} has an XSS vulnerability in i18n (CVE-2013-4491). Upgrade to Rails version "
i18n_gem = tracker.config[:gems][:i18n][:version] if tracker.config[:gems][:i18n]
message = "Rails #{rails_version} has an XSS vulnerability in i18n (CVE-2013-4491). Upgrade to Rails version "
i18n_gem = tracker.config.gem_version :i18n
if version_between? "3.0.6", "3.1.99" and version_before i18n_gem, "0.5.1"
message << "3.2.16 or i18n 0.5.1"
......
......@@ -30,7 +30,7 @@ class Brakeman::CheckJRubyXML < Brakeman::BaseCheck
warn :warning_type => "File Access",
:warning_code => :CVE_2013_1856,
:message => "Rails #{tracker.config[:rails_version]} with JRuby has a vulnerability in XML parser: upgrade to #{fix_version} or patch",
:message => "Rails #{rails_version} with JRuby has a vulnerability in XML parser: upgrade to #{fix_version} or patch",
:confidence => CONFIDENCE[:high],
:gem_info => gemfile_or_environment,
:link => "https://groups.google.com/d/msg/rubyonrails-security/KZwsQbYsOiI/5kUV7dSCJGwJ"
......
......@@ -7,7 +7,7 @@ class Brakeman::CheckJSONEncoding < Brakeman::BaseCheck
def run_check
if (version_between? "4.1.0", "4.1.10" or version_between? "4.2.0", "4.2.1") and not has_workaround?
message = "Rails #{tracker.config[:rails_version]} does not encode JSON keys (CVE-2015-3226). Upgrade to Rails version "
message = "Rails #{rails_version} does not encode JSON keys (CVE-2015-3226). Upgrade to Rails version "
if version_between? "4.1.0", "4.1.10"
message << "4.1.11"
......
......@@ -20,7 +20,7 @@ class Brakeman::CheckJSONParsing < Brakeman::BaseCheck
"3.0.20"
end
message = "Rails #{tracker.config[:rails_version]} has a serious JSON parsing vulnerability: upgrade to #{new_version} or patch"
message = "Rails #{rails_version} has a serious JSON parsing vulnerability: upgrade to #{new_version} or patch"
if uses_yajl?
gem_info = gemfile_or_environment(:yajl)
else
......@@ -38,7 +38,7 @@ class Brakeman::CheckJSONParsing < Brakeman::BaseCheck
#Check if `yajl` is included in Gemfile
def uses_yajl?
tracker.config[:gems][:yajl]
tracker.config.has_gem? :yajl
end
#Check for `ActiveSupport::JSON.backend = "JSONGem"`
......@@ -60,7 +60,7 @@ class Brakeman::CheckJSONParsing < Brakeman::BaseCheck
def check_cve_2013_0269
[:json, :json_pure].each do |name|
gem_hash = tracker.config[:gems][name] if tracker.config[:gems]
gem_hash = tracker.config.get_gem name
check_json_version name, gem_hash[:version] if gem_hash and gem_hash[:version]
end
end
......
......@@ -10,7 +10,7 @@ class Brakeman::CheckLinkTo < Brakeman::CheckCrossSiteScripting
@description = "Checks for XSS in link_to in versions before 3.0"
def run_check
return unless version_between?("2.0.0", "2.9.9") and not tracker.config[:escape_html]
return unless version_between?("2.0.0", "2.9.9") and not tracker.config.escape_html?
@ignore_methods = Set[:button_to, :check_box, :escapeHTML, :escape_once,
:field_field, :fields_for, :h, :hidden_field,
......
......@@ -19,7 +19,10 @@ class Brakeman::CheckMassAssignment < Brakeman::BaseCheck
models = []
tracker.models.each do |name, m|
if unprotected_model? m
if m.is_a? Hash
p m
end
if m.unprotected_model?
models << name
end
end
......@@ -62,7 +65,7 @@ class Brakeman::CheckMassAssignment < Brakeman::BaseCheck
model = tracker.models[res[:chain].first]
attr_protected = (model and model[:options][:attr_protected])
attr_protected = (model and model.attr_protected)
if attr_protected and tracker.options[:ignore_attr_protected]
return
......
......@@ -20,13 +20,13 @@ class Brakeman::CheckModelAttrAccessible < Brakeman::BaseCheck
def run_check
check_models do |name, model|
model[:attr_accessible].each do |attribute|
model.attr_accessible.each do |attribute|
next if role_limited? model, attribute
SUSP_ATTRS.each do |susp_attr, confidence|
if susp_attr.is_a?(Regexp) and susp_attr =~ attribute.to_s or susp_attr == attribute
warn :model => name,
:file => model[:files].first,
:file => model.file,
:warning_type => "Mass Assignment",
:warning_code => :dangerous_attr_accessible,
:message => "Potentially dangerous attribute available for mass assignment",
......@@ -40,14 +40,14 @@ class Brakeman::CheckModelAttrAccessible < Brakeman::BaseCheck
end
def role_limited? model, attribute
role_accessible = model[:options][:role_accessible]
role_accessible = model.role_accessible
return if role_accessible.nil?
role_accessible.include? attribute
end
def check_models
tracker.models.each do |name, model|
if !model[:attr_accessible].nil?
if !model.attr_accessible.nil?
yield name, model
end
end
......
......@@ -19,7 +19,7 @@ class Brakeman::CheckModelAttributes < Brakeman::BaseCheck
protected_names = []
check_models do |name, model|
if model[:options][:attr_protected].nil?
if model.attr_protected.nil?
no_accessible_names << name.to_s
elsif not tracker.options[:ignore_attr_protected]
protected_names << name.to_s
......@@ -53,9 +53,9 @@ class Brakeman::CheckModelAttributes < Brakeman::BaseCheck
else #Output one warning per model
check_models do |name, model|
if model[:options][:attr_protected].nil?
if model.attr_protected.nil?
warn :model => name,
:file => model[:files].first,
:file => model.file,
:warning_type => "Attribute Restriction",
:warning_code => :no_attr_accessible,
:message => "Mass assignment is not restricted using attr_accessible",
......@@ -70,8 +70,8 @@ class Brakeman::CheckModelAttributes < Brakeman::BaseCheck
end
warn :model => name,
:file => model[:files].first,
:line => model[:options][:attr_protected].first.line,
:file => model.file,
:line => model.attr_protected.first.line,
:warning_type => "Attribute Restriction",
:warning_code => warning_code,
:message => message,
......@@ -83,7 +83,7 @@ class Brakeman::CheckModelAttributes < Brakeman::BaseCheck
def check_models
tracker.models.each do |name, model|
if unprotected_model? model
if model.unprotected_model?
yield name, model
end
end
......@@ -104,7 +104,7 @@ class Brakeman::CheckModelAttributes < Brakeman::BaseCheck
end
if upgrade_version
message = "attr_protected is bypassable in #{tracker.config[:rails_version]}, use attr_accessible or upgrade to #{upgrade_version}"
message = "attr_protected is bypassable in #{rails_version}, use attr_accessible or upgrade to #{upgrade_version}"
confidence = CONFIDENCE[:high]
link = "https://groups.google.com/d/topic/rubyonrails-security/AFBKNY7VSH8/discussion"
else
......
......@@ -25,7 +25,7 @@ class Brakeman::CheckModelSerialize < Brakeman::BaseCheck
#High confidence warning on serialized, unprotected attributes.
#Medium confidence warning for serialized, protected attributes.
def check_for_serialize model
if serialized_attrs = model[:options] && model[:options][:serialize]
if serialized_attrs = model.options[:serialize]
attrs = Set.new
serialized_attrs.each do |arglist|
......@@ -34,9 +34,9 @@ class Brakeman::CheckModelSerialize < Brakeman::BaseCheck
end
end
if unsafe_attrs = model[:attr_accessible]
if unsafe_attrs = model.attr_accessible
attrs.delete_if { |attr| not unsafe_attrs.include? attr.value }
elsif protected_attrs = model[:options][:attr_protected]
elsif protected_attrs = model.attr_protected
safe_attrs = Set.new
protected_attrs.each do |arglist|
......@@ -54,13 +54,13 @@ class Brakeman::CheckModelSerialize < Brakeman::BaseCheck
confidence = CONFIDENCE[:high]
end
warn :model => model[:name],
warn :model => model.name,
:warning_type => "Remote Code Execution",
:warning_code => :CVE_2013_0277,
:message => "Serialized attributes are vulnerable in Rails #{tracker.config[:rails_version]}, upgrade to #{@upgrade_version} or patch.",
:message => "Serialized attributes are vulnerable in Rails #{rails_version}, upgrade to #{@upgrade_version} or patch.",
:confidence => confidence,
:link => "https://groups.google.com/d/topic/rubyonrails-security/KtmwSbEpzrU/discussion",
:file => model[:files].first
:file => model.file
end
end
end
......@@ -8,7 +8,7 @@ class Brakeman::CheckNestedAttributes < Brakeman::BaseCheck
@description = "Checks for nested attributes vulnerability in Rails 2.3.9 and 3.0.0"
def run_check
version = tracker.config[:rails_version]
version = rails_version
if (version == "2.3.9" or version == "3.0.0") and uses_nested_attributes?
message = "Vulnerability in nested attributes (CVE-2010-3933). Upgrade to Rails version "
......@@ -30,7 +30,7 @@ class Brakeman::CheckNestedAttributes < Brakeman::BaseCheck
def uses_nested_attributes?
active_record_models.each do |name, model|
return true if model[:options][:accepts_nested_attributes_for]
return true if model.options[:accepts_nested_attributes_for]
end
false
......
......@@ -18,7 +18,7 @@ class Brakeman::CheckNumberToCurrency < Brakeman::BaseCheck
end
def generic_warning
message = "Rails #{tracker.config[:rails_version]} has a vulnerability in number helpers (CVE-2014-0081). Upgrade to Rails version "
message = "Rails #{rails_version} has a vulnerability in number helpers (CVE-2014-0081). Upgrade to Rails version "
if version_between? "2.3.0", "3.2.16"
message << "3.2.17"
......@@ -62,7 +62,7 @@ class Brakeman::CheckNumberToCurrency < Brakeman::BaseCheck
warn :result => result,
:warning_type => "Cross Site Scripting",
:warning_code => :CVE_2014_0081_call,
:message => "Format options in #{result[:call].method} are not safe in Rails #{@tracker.config[:rails_version]}",
:message => "Format options in #{result[:call].method} are not safe in Rails #{rails_version}",
:confidence => CONFIDENCE[:high],
:link_path => "https://groups.google.com/d/msg/ruby-security-ann/9WiRn2nhfq0/2K2KRB4LwCMJ",
:user_input => match
......
......@@ -17,7 +17,7 @@ class Brakeman::CheckQuoteTableName < Brakeman::BaseCheck
confidence = CONFIDENCE[:med]
end
if tracker.config[:rails_version] =~ /^3/
if rails_version =~ /^3/
message = "Versions before 3.0.10 have a vulnerability in quote_table_name: CVE-2011-2930"
else
message = "Versions before 2.3.14 have a vulnerability in quote_table_name: CVE-2011-2930"
......
......@@ -184,7 +184,7 @@ class Brakeman::CheckRedirect < Brakeman::BaseCheck
if node_type? exp, :or
decorated_model? exp.lhs or decorated_model? exp.rhs
else
tracker.config[:gems][:draper] and
tracker.config.has_gem? :draper and
call? exp and
node_type?(exp.target, :const) and
exp.target.value.to_s.match(/Decorator$/) and
......@@ -204,14 +204,6 @@ class Brakeman::CheckRedirect < Brakeman::BaseCheck
return false unless model
model[:associations].each do |name, args|
args.each do |arg|
if symbol? arg and arg.value == meth
return true
end
end
end
false
model.association? meth
end
end
......@@ -25,7 +25,7 @@ class Brakeman::CheckRenderDoS < Brakeman::BaseCheck
end
def warn_about_text_render
message = "Rails #{tracker.config[:rails_version]} has a denial of service vulnerability (CVE-2014-0082). Upgrade to Rails version 3.2.17"
message = "Rails #{rails_version} has a denial of service vulnerability (CVE-2014-0082). Upgrade to Rails version 3.2.17"
warn :warning_type => "Denial of Service",
:warning_code => :CVE_2014_0082,
......
......@@ -20,7 +20,7 @@ class Brakeman::CheckSafeBufferManipulation < Brakeman::BaseCheck
return
end
message = "Rails #{tracker.config[:rails_version]} has a vulnerabilty in SafeBuffer. Upgrade to #{suggested_version} or apply patches."
message = "Rails #{rails_version} has a vulnerabilty in SafeBuffer. Upgrade to #{suggested_version} or apply patches."
warn :warning_type => "Cross Site Scripting",
:warning_code => :safe_buffer_vuln,
......
......@@ -38,7 +38,7 @@ class Brakeman::CheckSanitizeMethods < Brakeman::BaseCheck
next if duplicate? result
add_result result
message = "Rails #{tracker.config[:rails_version]} has a vulnerability in #{method}: upgrade to #{@fix_version} or patch"
message = "Rails #{rails_version} has a vulnerability in #{method}: upgrade to #{@fix_version} or patch"
if include_user_input? result[:call]
confidence = CONFIDENCE[:high]
......
......@@ -21,7 +21,7 @@ class Brakeman::CheckSelectTag < Brakeman::BaseCheck
@ignore_methods = Set[:escapeHTML, :escape_once, :h].merge tracker.options[:safe_methods]
@message = "Upgrade to Rails #{suggested_version}, #{tracker.config[:rails_version]} select_tag is vulnerable (CVE-2012-3463)"
@message = "Upgrade to Rails #{suggested_version}, #{rails_version} select_tag is vulnerable (CVE-2012-3463)"
calls = tracker.find_call(:target => nil, :method => :select_tag).select do |result|
result[:location][:type] == :template
......
......@@ -23,7 +23,7 @@ class Brakeman::CheckSelectVulnerability < Brakeman::BaseCheck
return
end
@message = "Upgrade to Rails #{suggested_version}, #{tracker.config[:rails_version]} select() helper is vulnerable"
@message = "Upgrade to Rails #{suggested_version}, #{rails_version} select() helper is vulnerable"
calls = tracker.find_call(:target => nil, :method => :select).select do |result|
result[:location][:type] == :template
......
......@@ -17,8 +17,7 @@ class Brakeman::CheckSessionSettings < Brakeman::BaseCheck
end
def run_check
settings = tracker.config[:rails][:action_controller] &&
tracker.config[:rails][:action_controller][:session]
settings = tracker.config.session_settings
check_for_issues settings, "#{tracker.app_path}/config/environment.rb"
......
......@@ -16,7 +16,7 @@ class Brakeman::CheckSimpleFormat < Brakeman::CheckCrossSiteScripting
end
def generic_warning
message = "Rails #{tracker.config[:rails_version]} has a vulnerability in simple_format (CVE-2013-6416). Upgrade to Rails version 4.0.2"
message = "Rails #{rails_version} has a vulnerability in simple_format (CVE-2013-6416). Upgrade to Rails version 4.0.2"
warn :warning_type => "Cross Site Scripting",
:warning_code => :CVE_2013_6416,
......@@ -51,7 +51,7 @@ class Brakeman::CheckSimpleFormat < Brakeman::CheckCrossSiteScripting
warn :result => result,
:warning_type => "Cross Site Scripting",
:warning_code => :CVE_2013_6416_call,
:message => "Values passed to simple_format are not safe in Rails #{@tracker.config[:rails_version]}",
:message => "Values passed to simple_format are not safe in Rails #{rails_version}",
:confidence => CONFIDENCE[:high],
:link_path => "https://groups.google.com/d/msg/ruby-security-ann/5ZI1-H5OoIM/ZNq4FoR2GnIJ",
:user_input => match.match
......
......@@ -20,11 +20,11 @@ class Brakeman::CheckSingleQuotes < Brakeman::BaseCheck
when version_between?('2.0.0', '2.3.14')
message = "All Rails 2.x versions do not escape single quotes (CVE-2012-3464)"
when version_between?('3.0.0', '3.0.16')
message = "Rails #{tracker.config[:rails_version]} does not escape single quotes (CVE-2012-3464). Upgrade to 3.0.17"
message = "Rails #{rails_version} does not escape single quotes (CVE-2012-3464). Upgrade to 3.0.17"
when version_between?('3.1.0', '3.1.7')
message = "Rails #{tracker.config[:rails_version]} does not escape single quotes (CVE-2012-3464). Upgrade to 3.1.8"
message = "Rails #{rails_version} does not escape single quotes (CVE-2012-3464). Upgrade to 3.1.8"
when version_between?('3.2.0', '3.2.7')
message = "Rails #{tracker.config[:rails_version]} does not escape single quotes (CVE-2012-3464). Upgrade to 3.2.8"
message = "Rails #{rails_version} does not escape single quotes (CVE-2012-3464). Upgrade to 3.2.8"
else
return
end
......
......@@ -14,9 +14,7 @@ class Brakeman::CheckSkipBeforeFilter < Brakeman::BaseCheck
def run_check
tracker.controllers.each do |name, controller|
filter_skips = controller[:options][:skip_filters]
filter_skips.each do |filter|
controller.skip_filters.each do |filter|
process_skip_filter filter, controller
end
end
......@@ -25,23 +23,23 @@ class Brakeman::CheckSkipBeforeFilter < Brakeman::BaseCheck
def process_skip_filter filter, controller
case skip_except_value filter
when :verify_authenticity_token
warn :class => controller[:name], #ugh this should be a controller warning, too
warn :class => controller.name, #ugh this should be a controller warning, too
:warning_type => "Cross-Site Request Forgery",
:warning_code => :csrf_blacklist,
:message => "Use whitelist (:only => [..]) when skipping CSRF check",
:code => filter,
:confidence => CONFIDENCE[:med],
:file => controller[:files].first
:file => controller.file
when :login_required, :authenticate_user!, :require_user
warn :controller => controller[:name],
warn :controller => controller.name,
:warning_code => :auth_blacklist,
:warning_type => "Authentication",
:message => "Use whitelist (:only => [..]) when skipping authentication",
:code => filter,
:confidence => CONFIDENCE[:med],
:link => "authentication_whitelist",
:file => controller[:files].first
:file => controller.file
end
end
......
......@@ -14,8 +14,6 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
@description = "Check for SQL injection"
def run_check
@rails_version = tracker.config[:rails_version]
@sql_targets = [:all, :average, :calculate, :count, :count_by_sql, :exists?, :delete_all, :destroy_all,
:find, :find_by_sql, :first, :last, :maximum, :minimum, :pluck, :sum, :update_all]
@sql_targets.concat [:from, :group, :having, :joins, :lock, :order, :reorder, :select, :where] if tracker.options[:rails3]
......@@ -84,7 +82,7 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
def ar_scope_calls(symbol_name = :named_scope, &block)
return_array = []
active_record_models.each do |name, model|
model_args = model[:options][symbol_name]
model_args = model.options[symbol_name]
if model_args
model_args.each do |args|
yield name, args
......@@ -614,7 +612,7 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
#
#http://www.rorsecurity.info/2008/09/08/sql-injection-issue-in-limit-and-offset-parameter/
def check_for_limit_or_offset_vulnerability options
return false if @rails_version.nil? or @rails_version >= "2.1.1" or not hash?(options)
return false if rails_version.nil? or rails_version >= "2.1.1" or not hash?(options)
return true if hash_access(options, :limit) or hash_access(options, :offset)
......
......@@ -48,7 +48,7 @@ class Brakeman::CheckSQLCVEs < Brakeman::BaseCheck
}
end
if tracker.config[:gems][:pg]
if tracker.config.has_gem? :pg
issues << {
:cve => "CVE-2014-3482",
:versions => [%w[2.0.0 2.9.9 3.2.19], %w[3.0.0 3.2.18 3.2.19], %w[4.0.0 4.0.6 4.0.7], %w[4.1.0 4.1.2 4.1.3]],
......@@ -73,7 +73,7 @@ class Brakeman::CheckSQLCVEs < Brakeman::BaseCheck
warn :warning_type => 'SQL Injection',
:warning_code => code,
:message => "Rails #{tracker.config[:rails_version]} contains a SQL injection vulnerability (#{cve}). Upgrade to #{upgrade_version}",
:message => "Rails #{rails_version} contains a SQL injection vulnerability (#{cve}). Upgrade to #{upgrade_version}",
:confidence => CONFIDENCE[:high],
:gem_info => gemfile_or_environment,
:link_path => link
......@@ -89,11 +89,11 @@ class Brakeman::CheckSQLCVEs < Brakeman::BaseCheck
def check_cve_2014_0080
return unless version_between? "4.0.0", "4.0.2" and
@tracker.config[:gems].include? :pg
@tracker.config.has_gem? :pg
warn :warning_type => 'SQL Injection',
:warning_code => :CVE_2014_0080,
:message => "Rails #{tracker.config[:rails_version]} contains a SQL injection vulnerability (CVE-2014-0080) with PostgreSQL. Upgrade to 4.0.3",
:message => "Rails #{rails_version} contains a SQL injection vulnerability (CVE-2014-0080) with PostgreSQL. Upgrade to 4.0.3",
:confidence => CONFIDENCE[:high],
:gem_info => gemfile_or_environment(:pg),
:link_path => "https://groups.google.com/d/msg/rubyonrails-security/Wu96YkTUR6s/pPLBMZrlwvYJ"
......
......@@ -19,7 +19,7 @@ class Brakeman::CheckStripTags < Brakeman::BaseCheck
def cve_2011_2931
if version_between?('2.0.0', '2.3.12') or version_between?('3.0.0', '3.0.9')
if tracker.config[:rails_version] =~ /^3/
if rails_version =~ /^3/
message = "Versions before 3.0.10 have a vulnerability in strip_tags (CVE-2011-2931)"
else
message = "Versions before 2.3.13 have a vulnerability in strip_tags (CVE-2011-2931)"
......@@ -36,14 +36,14 @@ class Brakeman::CheckStripTags < Brakeman::BaseCheck
def cve_2012_3465
case
when (version_between?('2.0.0', '2.3.14') and tracker.config[:escape_html])
when (version_between?('2.0.0', '2.3.14') and tracker.config.escape_html?)
message = "All Rails 2.x versions have a vulnerability in strip_tags (CVE-2012-3465)"
when version_between?('3.0.10', '3.0.16')
message = "Rails #{tracker.config[:rails_version]} has a vulnerability in strip_tags (CVE-2012-3465). Upgrade to 3.0.17"
message = "Rails #{rails_version} has a vulnerability in strip_tags (CVE-2012-3465). Upgrade to 3.0.17"
when version_between?('3.1.0', '3.1.7')
message = "Rails #{tracker.config[:rails_version]} has a vulnerability in strip_tags (CVE-2012-3465). Upgrade to 3.1.8"
message = "Rails #{rails_version} has a vulnerability in strip_tags (CVE-2012-3465). Upgrade to 3.1.8"
when version_between?('3.2.0', '3.2.7')
message = "Rails #{tracker.config[:rails_version]} has a vulnerability in strip_tags (CVE-2012-3465). Upgrade to 3.2.8"
message = "Rails #{rails_version} has a vulnerability in strip_tags (CVE-2012-3465). Upgrade to 3.2.8"
else
return
end
......
......@@ -20,7 +20,7 @@ class Brakeman::CheckSymbolDoSCVE < Brakeman::BaseCheck
if fix_version && active_record_models.any?
warn :warning_type => "Denial of Service",
:warning_code => :CVE_2013_1854,
:message => "Rails #{tracker.config[:rails_version]} has a denial of service vulnerability in ActiveRecord: upgrade to #{fix_version} or patch",
:message => "Rails #{rails_version} has a denial of service vulnerability in ActiveRecord: upgrade to #{fix_version} or patch",
:confidence => CONFIDENCE[:med],
:gem_info => gemfile_or_environment,
:link => "https://groups.google.com/d/msg/rubyonrails-security/jgJ4cjjS8FE/BGbHRxnDRTIJ"
......
......@@ -8,7 +8,7 @@ class Brakeman::CheckTranslateBug < Brakeman::BaseCheck
def run_check
return if lts_version? '2.3.18.6'
if (version_between?('2.3.0', '2.3.99') and tracker.config[:escape_html]) or
if (version_between?('2.3.0', '2.3.99') and tracker.config.escape_html?) or
version_between?('3.0.0', '3.0.10') or
version_between?('3.1.0', '3.1.1')
......@@ -18,12 +18,11 @@ class Brakeman::CheckTranslateBug < Brakeman::BaseCheck
CONFIDENCE[:med]
end
version = tracker.config[:rails_version]
description = "have a vulnerability in the translate helper with keys ending in _html"
message = if version =~ /^3\.1/
message = if rails_version =~ /^3\.1/
"Versions before 3.1.2 #{description}."
elsif version =~ /^3\.0/
elsif rails_version =~ /^3\.0/
"Versions before 3.0.11 #{description}."
else
"Rails 2.3.x using the rails_xss plugin #{description}."
......
......@@ -10,7 +10,7 @@ class Brakeman::CheckUnscopedFind < Brakeman::BaseCheck
Brakeman.debug("Finding instances of #find on models with associations")
associated_model_names = active_record_models.keys.select do |name|
active_record_models[name][:associations][:belongs_to]
active_record_models[name].associations[:belongs_to]
end
calls = tracker.find_call :method => [:find, :find_by_id, :find_by_id!],
......
......@@ -18,7 +18,7 @@ class Brakeman::CheckValidationRegex < Brakeman::BaseCheck
def run_check
active_record_models.each do |name, model|
@current_model = name
format_validations = model[:options][:validates_format_of]
format_validations = model.options[:validates_format_of]
if format_validations
format_validations.each do |v|
......@@ -26,7 +26,7 @@ class Brakeman::CheckValidationRegex < Brakeman::BaseCheck
end
end
validates = model[:options][:validates]
validates = model.options[:validates]
if validates
validates.each do |v|
......
......@@ -6,7 +6,7 @@ class Brakeman::CheckXMLDoS < Brakeman::BaseCheck
@description = "Checks for XML denial of service (CVE-2015-3227)"
def run_check
version = tracker.config[:rails_version]
version = rails_version
fix_version = case
when version_between?("2.0.0", "3.2.21")
......
......@@ -22,7 +22,7 @@ class Brakeman::CheckYAMLParsing < Brakeman::BaseCheck
"3.2.11"
end
message = "Rails #{tracker.config[:rails_version]} has a remote code execution vulnerability: upgrade to #{new_version} or disable XML parsing"
message = "Rails #{rails_version} has a remote code execution vulnerability: upgrade to #{new_version} or disable XML parsing"
warn :warning_type => "Remote Code Execution",
:warning_code => :CVE_2013_0156,
......
......@@ -47,7 +47,7 @@ module Brakeman
end
def parse_erb text
if tracker.config[:escape_html]
if tracker.config.escape_html?
if tracker.options[:rails3]
require 'brakeman/parsers/rails3_erubis'
Brakeman::Rails3Erubis.new(text).src
......@@ -55,7 +55,7 @@ module Brakeman
require 'brakeman/parsers/rails2_xss_plugin_erubis'
Brakeman::Rails2XSSPluginErubis.new(text).src
end
elsif tracker.config[:erubis]
elsif tracker.config.erubis?
require 'brakeman/parsers/rails2_erubis'
Brakeman::ScannerErubis.new(text).src
else
......@@ -67,8 +67,8 @@ module Brakeman
end
def erubis?
tracker.config[:escape_html] or
tracker.config[:erubis]
tracker.config.escape_html? or
tracker.config.erubis?
end
def parse_haml text
......@@ -76,7 +76,7 @@ module Brakeman
Brakeman.load_brakeman_dependency 'sass'
Haml::Engine.new(text,
:escape_html => !!tracker.config[:escape_html]).precompiled.gsub(/([^\\])\\n/, '\1')
:escape_html => tracker.config.escape_html?).precompiled.gsub(/([^\\])\\n/, '\1')
end
def parse_slim text
......
......@@ -78,13 +78,13 @@ module Brakeman
name = ("#{name}.#{called_from}").to_sym
end
@tracker.templates[name][:src] = result
@tracker.templates[name][:type] = type
@tracker.templates[name].src = result
@tracker.templates[name].type = type
end
#Process any calls to render() within a template
def process_template_alias template
TemplateAliasProcessor.new(@tracker, template).process_safely template[:src]
TemplateAliasProcessor.new(@tracker, template).process_safely template.src
end
#Process source for initializing files
......
......@@ -9,7 +9,7 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
include Brakeman::ProcessorHelper
include Brakeman::Util
attr_reader :result
attr_reader :result, :tracker
#Returns a new AliasProcessor with an empty environment.
#
......
......@@ -37,19 +37,19 @@ class Brakeman::ControllerAliasProcessor < Brakeman::AliasProcessor
def process_mixins
controller = @tracker.controllers[@current_class]
controller[:includes].each do |i|
controller.includes.each do |i|
mixin = @tracker.libs[i]
next unless mixin
#Process methods in alphabetical order for consistency
methods = mixin[:public].keys.map { |n| n.to_s }.sort.map { |n| n.to_sym }
methods = mixin.methods_public.keys.map { |n| n.to_s }.sort.map { |n| n.to_sym }
methods.each do |name|
#Need to process the method like it was in a controller in order
#to get the renders set
processor = Brakeman::ControllerProcessor.new(@app_tree, @tracker)
method = mixin[:public][name][:src].deep_clone
method = mixin.get_method(name)[:src].deep_clone
if node_type? method, :methdef
method = processor.process_defn method
......@@ -192,12 +192,12 @@ class Brakeman::ControllerAliasProcessor < Brakeman::AliasProcessor
def layout_name
controller = @tracker.controllers[@current_class]
return controller[:layout] if controller[:layout]
return false if controller[:layout] == false
return controller.layout if controller.layout
return false if controller.layout == false
app_controller = @tracker.controllers[:ApplicationController]
return app_controller[:layout] if app_controller and app_controller[:layout]
return app_controller.layout if app_controller and app_controller.layout
nil
end
......@@ -215,120 +215,12 @@ class Brakeman::ControllerAliasProcessor < Brakeman::AliasProcessor
#Get list of filters, including those that are inherited
def before_filter_list method, klass
controller = @tracker.controllers[klass]
filters = []
while controller
filters = get_before_filters(method, controller) + filters
controller = @tracker.controllers[controller[:parent]] ||
@tracker.libs[controller[:parent]]
end
remove_skipped_filters filters, method, klass
end
def remove_skipped_filters filters, method, klass
controller = @tracker.controllers[klass]
while controller
filters = filters - get_skipped_filters(method, controller)
controller = @tracker.controllers[controller[:parent]] ||
@tracker.libs[controller[:parent]]
end
filters
end
def get_skipped_filters method, controller
return [] unless controller[:options] and controller[:options][:skip_filters]
filters = []
if controller[:skip_filter_cache].nil?
controller[:skip_filter_cache] = controller[:options][:skip_filters].map do |filter|
before_filter_to_hash(filter.args)
end
end
controller[:skip_filter_cache].each do |f|
if f[:all] or
(f[:only] == method) or
(f[:only].is_a? Array and f[:only].include? method) or
(f[:except].is_a? Symbol and f[:except] != method) or
(f[:except].is_a? Array and not f[:except].include? method)
filters.concat f[:methods]
end
end
filters
end
#Returns an array of filter names
def get_before_filters method, controller
return [] unless controller[:options] and controller[:options][:before_filters]
filters = []
if controller[:before_filter_cache].nil?
filter_cache = []
controller[:options][:before_filters].each do |filter|
filter_cache << before_filter_to_hash(filter.args)
end
controller[:before_filter_cache] = filter_cache
end
controller[:before_filter_cache].each do |f|
if f[:all] or
(f[:only] == method) or
(f[:only].is_a? Array and f[:only].include? method) or
(f[:except].is_a? Symbol and f[:except] != method) or
(f[:except].is_a? Array and not f[:except].include? method)
filters.concat f[:methods]
end
end
filters
end
#Returns a before filter as a hash table
def before_filter_to_hash args
filter = {}
#Process args for the uncommon but possible situation
#in which some variables are used in the filter.
args.each do |a|
if sexp? a
a = process_default a
end
end
filter[:methods] = [args[0][1]]
args[1..-1].each do |a|
filter[:methods] << a[1] if a.node_type == :lit
end
if args[-1].node_type == :hash
option = args[-1][1][1]
value = args[-1][2]
case value.node_type
when :array
filter[option] = value[1..-1].map {|v| v[1] }
when :lit, :str
filter[option] = value[1]
else
Brakeman.debug "[Notice] Unknown before_filter value: #{option} => #{value}"
end
if controller
controller.before_filter_list self, method
else
filter[:all] = true
[]
end
filter
end
#Finds a method in the given class or a parent class
......@@ -348,12 +240,10 @@ class Brakeman::ControllerAliasProcessor < Brakeman::AliasProcessor
controller ||= @tracker.libs[klass]
if klass and controller
method = controller[:public][method_name]
method ||= controller[:private][method_name]
method ||= controller[:protected][method_name]
method = controller.get_method method_name
if method.nil?
controller[:includes].each do |included|
controller.includes.each do |included|
method = find_method method_name, included
if method
@method_cache[method_name] = method
......@@ -361,9 +251,9 @@ class Brakeman::ControllerAliasProcessor < Brakeman::AliasProcessor
end
end
@method_cache[method_name] = find_method method_name, controller[:parent]
@method_cache[method_name] = find_method method_name, controller.parent
else
@method_cache[method_name] = { :controller => controller[:name], :method => method[:src] }
@method_cache[method_name] = { :controller => controller.name, :method => method[:src] }
end
else
nil
......
require 'brakeman/processors/base_processor'
require 'brakeman/tracker/controller'
#Processes controller. Results are put in tracker.controllers
class Brakeman::ControllerProcessor < Brakeman::BaseProcessor
......@@ -28,7 +29,7 @@ class Brakeman::ControllerProcessor < Brakeman::BaseProcessor
#If inside a real controller, treat any other classes as libraries.
#But if not inside a controller already, then the class may include
#a real controller, so we can't take this shortcut.
if @current_class and @current_class[:name].to_s.end_with? "Controller"
if @current_class and @current_class.name.to_s.end_with? "Controller"
Brakeman.debug "[Notice] Treating inner class as library: #{name}"
Brakeman::LibraryProcessor.new(@tracker).process_library exp, @file_name
return exp
......@@ -48,30 +49,18 @@ class Brakeman::ControllerProcessor < Brakeman::BaseProcessor
if @current_class
outer_class = @current_class
name = (outer_class[:name].to_s + "::" + name.to_s).to_sym
name = (outer_class.name.to_s + "::" + name.to_s).to_sym
end
if @current_module
name = (@current_module[:name].to_s + "::" + name.to_s).to_sym
name = (@current_module.name.to_s + "::" + name.to_s).to_sym
end
if @tracker.controllers[name]
@current_class = @tracker.controllers[name]
@current_class[:files] << @file_name unless @current_class[:files].include? @file_name
@current_class[:src][@file_name] = exp
@current_class.add_file @file_name, exp
else
@current_class = {
:name => name,
:parent => parent,
:includes => [],
:public => {},
:private => {},
:protected => {},
:options => {:before_filters => [], :skip_filters => []},
:src => { @file_name => exp },
:files => [ @file_name ]
}
@current_class = Brakeman::Controller.new name, parent, @file_name, exp, @tracker
@tracker.controllers[name] = @current_class
end
......@@ -92,30 +81,18 @@ class Brakeman::ControllerProcessor < Brakeman::BaseProcessor
if @current_module
outer_module = @current_module
name = (outer_module[:name].to_s + "::" + name.to_s).to_sym
name = (outer_module.name.to_s + "::" + name.to_s).to_sym
end
if @current_class
name = (@current_class[:name].to_s + "::" + name.to_s).to_sym
name = (@current_class.name.to_s + "::" + name.to_s).to_sym
end
if @tracker.libs[name]
@current_module = @tracker.libs[name]
@current_module[:files] << @file_name unless @current_module[:files].include? @file_name
@current_module[:src][@file_name] = exp
@current_module.add_file @file_name, exp
else
@current_module = {
:name => name,
:parent => parent,
:includes => [],
:public => {},
:private => {},
:protected => {},
:options => {:before_filters => []},
:src => { @file_name => exp },
:files => [ @file_name ]
}
@current_module = Brakeman::Controller.new name, parent, @file_name, exp, @tracker
@tracker.libs[name] = @current_module
end
......@@ -149,45 +126,44 @@ class Brakeman::ControllerProcessor < Brakeman::BaseProcessor
when :private, :protected, :public
@visibility = method
when :protect_from_forgery
@current_class[:options][:protect_from_forgery] = true
@current_class.options[:protect_from_forgery] = true
else
#??
end
else
case method
when :include
@current_class[:includes] << class_name(first_arg) if @current_class
@current_class.add_include class_name(first_arg) if @current_class
when :before_filter, :append_before_filter, :before_action, :append_before_action
if node_type? exp.first_arg, :iter
add_lambda_filter exp
else
@current_class[:options][:before_filters] << exp
@current_class.add_before_filter exp
end
when :prepend_before_filter, :prepend_before_action
if node_type? exp.first_arg, :iter
add_lambda_filter exp
else
@current_class[:options][:before_filters].unshift exp
@current_class.prepend_before_filter exp
end
when :skip_before_filter, :skip_filter, :skip_before_action, :skip_action_callback
@current_class[:options][:skip_filters] << exp
@current_class.skip_filter exp
when :layout
if string? last_arg
#layout "some_layout"
name = last_arg.value.to_s
if @app_tree.layout_exists?(name)
@current_class[:layout] = "layouts/#{name}"
@current_class.layout = "layouts/#{name}"
else
Brakeman.debug "[Notice] Layout not found: #{name}"
end
elsif node_type? last_arg, :nil, :false
#layout :false or layout nil
@current_class[:layout] = false
@current_class.layout = false
end
else
@current_class[:options][method] ||= []
@current_class[:options][method] << exp
@current_class.add_option method, exp
end
end
......@@ -218,9 +194,9 @@ class Brakeman::ControllerProcessor < Brakeman::BaseProcessor
@current_method = nil
if @current_class
@current_class[@visibility][name] = { :src => res, :file => @file_name }
@current_class.add_method @visibility, name, res, @file_name
elsif @current_module
@current_module[@visibility][name] = { :src => res, :file => @file_name }
@current_module.add_method @visibility, name, res, @file_name
end
res
......@@ -232,7 +208,7 @@ class Brakeman::ControllerProcessor < Brakeman::BaseProcessor
if exp[1].node_type == :self
if @current_class
target = @current_class[:name]
target = @current_class.name
elsif @current_module
target = @current_module
else
......@@ -248,9 +224,9 @@ class Brakeman::ControllerProcessor < Brakeman::BaseProcessor
@current_method = nil
if @current_class
@current_class[@visibility][name] = { :src => res, :file => @file_name }
@current_class.add_method @visibility, name, res, @file_name
elsif @current_module
@current_module[@visibility][name] = { :src => res, :file => @file_name }
@current_module.add_method @visibility, name, res, @file_name
end
res
......@@ -268,13 +244,13 @@ class Brakeman::ControllerProcessor < Brakeman::BaseProcessor
#Sets default layout for renders inside Controller
def set_layout_name
return if @current_class[:layout]
return if @current_class.layout
name = underscore(@current_class[:name].to_s.split("::")[-1].gsub("Controller", ''))
name = underscore(@current_class.name.to_s.split("::")[-1].gsub("Controller", ''))
#There is a layout for this Controller
if @app_tree.layout_exists?(name)
@current_class[:layout] = "layouts/#{name}"
@current_class.layout = "layouts/#{name}"
end
end
......@@ -308,7 +284,7 @@ class Brakeman::ControllerProcessor < Brakeman::BaseProcessor
#Build Sexp for filter method
body = Sexp.new(:lasgn,
block_variable,
Sexp.new(:call, Sexp.new(:const, @current_class[:name]), :new))
Sexp.new(:call, Sexp.new(:const, @current_class.name), :new))
filter_method = Sexp.new(:defn, filter_name, Sexp.new(:args), body).concat(block_inner).line(exp.line)
......
......@@ -34,7 +34,7 @@ class Brakeman::ErbTemplateProcessor < Brakeman::TemplateProcessor
else
s = Sexp.new :output, arg
s.line(exp.line)
@current_template[:outputs] << s
@current_template.add_output s
s
end
elsif method == :force_encoding
......
......@@ -30,12 +30,12 @@ class Brakeman::ErubisTemplateProcessor < Brakeman::TemplateProcessor
elsif node_type? target, :ivar and target.value == :@output_buffer
s = Sexp.new :escaped_output, arg
s.line(exp.line)
@current_template[:outputs] << s
@current_template.add_output s
s
else
s = Sexp.new :output, arg
s.line(exp.line)
@current_template[:outputs] << s
@current_template.add_output s
s
end
elsif method == :to_s
......@@ -80,12 +80,12 @@ class Brakeman::ErubisTemplateProcessor < Brakeman::TemplateProcessor
elsif exp.method == :safe_append=
s = Sexp.new :output, arg
s.line(exp.line)
@current_template[:outputs] << s
@current_template.add_output s
s
else
s = Sexp.new :escaped_output, arg
s.line(exp.line)
@current_template[:outputs] << s
@current_template.add_output s
s
end
else
......
......@@ -6,7 +6,6 @@ class Brakeman::GemProcessor < Brakeman::BasicProcessor
def initialize *args
super
@gem_name_version = /^\s*([-_+.A-Za-z0-9]+) \((\w(\.\w+)*)\)/
@tracker.config[:gems] ||= {}
end
def process_gems src, gem_lock = nil
......@@ -14,29 +13,9 @@ class Brakeman::GemProcessor < Brakeman::BasicProcessor
if gem_lock
process_gem_lock gem_lock
@tracker.config[:rails_version] = @tracker.config[:gems][:rails][:version] if @tracker.config[:gems][:rails]
elsif @tracker.config[:gems] && @tracker.config[:gems][:rails] && @tracker.config[:gems][:rails][:version] =~ /(\d+.\d+.\d+)/
@tracker.config[:rails_version] = $1
else
@tracker.config[:rails_version] = nil
end
if @tracker.options[:rails3].nil? and @tracker.options[:rails4].nil? and @tracker.config[:rails_version]
if @tracker.config[:rails_version].start_with? "3"
@tracker.options[:rails3] = true
Brakeman.notify "[Notice] Detected Rails 3 application"
elsif @tracker.config[:rails_version].start_with? "4"
@tracker.options[:rails3] = true
@tracker.options[:rails4] = true
Brakeman.notify "[Notice] Detected Rails 4 application"
end
end
if @tracker.config[:gems][:rails_xss]
@tracker.config[:escape_html] = true
Brakeman.notify "[Notice] Escaping HTML by default"
end
@tracker.config.set_rails_version
end
def process_call exp
......@@ -46,11 +25,13 @@ class Brakeman::GemProcessor < Brakeman::BasicProcessor
gem_version = exp.second_arg
if string? gem_version
@tracker.config[:gems][gem_name.value.to_sym] = { :version => gem_version.value.to_s, :file => 'Gemfile', :line => exp.line }
else
@tracker.config[:gems][gem_name.value.to_sym] = { :version => nil, :file => 'Gemfile' , :line => exp.line }
end
version = if string? gem_version
gem_version.value
else
nil
end
@tracker.config.add_gem gem_name.value, version, 'Gemfile', exp.line
end
exp
......@@ -67,7 +48,7 @@ class Brakeman::GemProcessor < Brakeman::BasicProcessor
# Supports .rc2 but not ~>, >=, or <=
def set_gem_version_and_file line, file, line_num
if line =~ @gem_name_version
@tracker.config[:gems][$1.to_sym] = { :version => $2, :file => file, :line => line_num }
@tracker.config.add_gem $1, $2, file, line_num
end
end
end
......@@ -67,7 +67,7 @@ class Brakeman::HamlTemplateProcessor < Brakeman::TemplateProcessor
ignore
else
s = Sexp.new(:output, out)
@current_template[:outputs] << s
@current_template.add_output s
s.line(exp.line)
s
end
......@@ -140,11 +140,11 @@ class Brakeman::HamlTemplateProcessor < Brakeman::TemplateProcessor
case exp.node_type
when :format
exp.node_type = :output
@current_template[:outputs] << exp
@current_template.add_output exp
exp
when :format_escaped
exp.node_type = :escaped_output
@current_template[:outputs] << exp
@current_template.add_output exp
exp
when :str, :ignore, :output, :escaped_output
exp
......@@ -158,7 +158,7 @@ class Brakeman::HamlTemplateProcessor < Brakeman::TemplateProcessor
end
s.line(exp.line)
@current_template[:outputs] << s
@current_template.add_output s
s
end
end
......
......@@ -2,7 +2,7 @@ require 'brakeman/processors/lib/basic_processor'
#Processes configuration. Results are put in tracker.config.
#
#Configuration of Rails via Rails::Initializer are stored in tracker.config[:rails].
#Configuration of Rails via Rails::Initializer are stored in tracker.config.rails.
#For example:
#
# Rails::Initializer.run |config|
......@@ -13,7 +13,7 @@ require 'brakeman/processors/lib/basic_processor'
#
# tracker.config[:rails][:action_controller][:session_store]
#
#Values for tracker.config[:rails] will still be Sexps.
#Values for tracker.config.rails will still be Sexps.
class Brakeman::Rails2ConfigProcessor < Brakeman::BasicProcessor
#Replace block variable in
#
......@@ -24,7 +24,6 @@ class Brakeman::Rails2ConfigProcessor < Brakeman::BasicProcessor
def initialize *args
super
@tracker.config[:rails] ||= {}
end
#Use this method to process configuration file
......@@ -40,7 +39,7 @@ class Brakeman::Rails2ConfigProcessor < Brakeman::BasicProcessor
if exp.method == :gem and exp.first_arg.value == "erubis"
Brakeman.notify "[Notice] Using Erubis for ERB templates"
@tracker.config[:erubis] = true
@tracker.config.erubis = true
end
exp
......@@ -53,13 +52,13 @@ class Brakeman::Rails2ConfigProcessor < Brakeman::BasicProcessor
attribute = exp.method.to_s[0..-2].to_sym
if exp.args.length > 1
#Multiple arguments?...not sure if this will ever happen
@tracker.config[:rails][attribute] = exp.args
@tracker.config.rails[attribute] = exp.args
else
@tracker.config[:rails][attribute] = exp.first_arg
@tracker.config.rails[attribute] = exp.first_arg
end
elsif include_rails_config? exp
options = get_rails_config exp
level = @tracker.config[:rails]
level = @tracker.config.rails
options[0..-2].each do |o|
level[o] ||= {}
level = level[o]
......@@ -75,7 +74,7 @@ class Brakeman::Rails2ConfigProcessor < Brakeman::BasicProcessor
def process_cdecl exp
#Set Rails version required
if exp.lhs == :RAILS_GEM_VERSION
@tracker.config[:rails_version] = exp.rhs.value
@tracker.config.rails_version = exp.rhs.value
end
exp
......
......@@ -3,7 +3,7 @@ require 'brakeman/processors/lib/basic_processor'
#Processes configuration. Results are put in tracker.config.
#
#Configuration of Rails via Rails::Initializer are stored in tracker.config[:rails].
#Configuration of Rails via Rails::Initializer are stored in tracker.config.rails.
#For example:
#
# MyApp::Application.configure do
......@@ -12,15 +12,14 @@ require 'brakeman/processors/lib/basic_processor'
#
#will be stored in
#
# tracker.config[:rails][:active_record][:whitelist_attributes]
# tracker.config.rails[:active_record][:whitelist_attributes]
#
#Values for tracker.config[:rails] will still be Sexps.
#Values for tracker.config.rails will still be Sexps.
class Brakeman::Rails3ConfigProcessor < Brakeman::BasicProcessor
RAILS_CONFIG = Sexp.new(:call, nil, :config)
def initialize *args
super
@tracker.config[:rails] ||= {}
@inside_config = false
end
......@@ -66,13 +65,13 @@ class Brakeman::Rails3ConfigProcessor < Brakeman::BasicProcessor
attribute = exp.method.to_s[0..-2].to_sym
if exp.args.length > 1
#Multiple arguments?...not sure if this will ever happen
@tracker.config[:rails][attribute] = exp.args
@tracker.config.rails[attribute] = exp.args
else
@tracker.config[:rails][attribute] = exp.first_arg
@tracker.config.rails[attribute] = exp.first_arg
end
elsif include_rails_config? exp
options = get_rails_config exp
level = @tracker.config[:rails]
level = @tracker.config.rails
options[0..-2].each do |o|
level[o] ||= {}
......
......@@ -84,7 +84,7 @@ module Brakeman::RenderHelper
process_template "layouts/#{options[:layout][1]}", nil
elsif node_type? options[:layout], :false
#nothing
elsif not template[:name].to_s.match(/[^\/_][^\/]+$/)
elsif not template.name.to_s.match(/[^\/_][^\/]+$/)
#Don't do this for partials
process_layout
......@@ -100,7 +100,7 @@ module Brakeman::RenderHelper
#The collection name is the name of the partial without the leading
#underscore.
variable = template[:name].to_s.match(/[^\/_][^\/]+$/)[0].to_sym
variable = template.name.to_s.match(/[^\/_][^\/]+$/)[0].to_sym
#Unless the :as => :variable_name option is used
if options[:as]
......@@ -127,7 +127,7 @@ module Brakeman::RenderHelper
#Run source through AliasProcessor with instance variables from the
#current environment.
#TODO: Add in :locals => { ... } to environment
src = Brakeman::TemplateAliasProcessor.new(@tracker, template, called_from).process_safely(template[:src], template_env)
src = Brakeman::TemplateAliasProcessor.new(@tracker, template, called_from).process_safely(template.src, template_env)
digest = Digest::SHA1.new.update(name + src.to_s).to_s.to_sym
......@@ -142,7 +142,7 @@ module Brakeman::RenderHelper
#This information will be stored in tracker.templates, but with a name
#specifying this particular route. The original source should remain
#pristine (so it can be processed within other environments).
@tracker.processor.process_template name, src, template[:type], called_from
@tracker.processor.process_template name, src, template.type, called_from
end
end
......
require 'brakeman/processors/base_processor'
require 'brakeman/processors/alias_processor'
require 'brakeman/tracker/library'
#Process generic library and stores it in Tracker.libs
class Brakeman::LibraryProcessor < Brakeman::BaseProcessor
......@@ -23,29 +24,18 @@ class Brakeman::LibraryProcessor < Brakeman::BaseProcessor
if @current_class
outer_class = @current_class
name = (outer_class[:name].to_s + "::" + name.to_s).to_sym
name = (outer_class.name.to_s + "::" + name.to_s).to_sym
end
if @current_module
name = (@current_module[:name].to_s + "::" + name.to_s).to_sym
name = (@current_module.name.to_s + "::" + name.to_s).to_sym
end
if @tracker.libs[name]
@current_class = @tracker.libs[name]
@current_class[:files] << @file_name unless @current_class[:files].include? @file_name
@current_class[:src][@file_name] = exp
@current_class.add_file @file_name, exp
else
@current_class = {
:name => name,
:parent => parent,
:includes => [],
:public => {},
:private => {},
:protected => {},
:src => { @file_name => exp },
:files => [ @file_name ]
}
@current_class = Brakeman::Library.new name, parent, @file_name, exp, @tracker
@tracker.libs[name] = @current_class
end
......@@ -65,28 +55,18 @@ class Brakeman::LibraryProcessor < Brakeman::BaseProcessor
if @current_module
outer_module = @current_module
name = (outer_module[:name].to_s + "::" + name.to_s).to_sym
name = (outer_module.name.to_s + "::" + name.to_s).to_sym
end
if @current_class
name = (@current_class[:name].to_s + "::" + name.to_s).to_sym
name = (@current_class.name.to_s + "::" + name.to_s).to_sym
end
if @tracker.libs[name]
@current_module = @tracker.libs[name]
@current_module[:files] << @file_name unless @current_module[:files].include? @file_name
@current_module[:src][@file_name] = exp
@current_module.add_file @file_name, exp
else
@current_module = {
:name => name,
:includes => [],
:public => {},
:private => {},
:protected => {},
:src => { @file_name => exp },
:files => [ @file_name ]
}
@current_module = Brakeman::Library.new name, nil, @file_name, exp, @tracker
@tracker.libs[name] = @current_module
end
......@@ -107,10 +87,10 @@ class Brakeman::LibraryProcessor < Brakeman::BaseProcessor
if @current_class
exp.body = process_all! exp.body
@current_class[:public][exp.method_name] = { :src => exp, :file => @file_name }
@current_class.add_method :public, exp.method_name, exp, @file_name
elsif @current_module
exp.body = process_all! exp.body
@current_module[:public][exp.method_name] = { :src => exp, :file => @file_name }
@current_module.add_method :public, exp.method_name, exp, @file_name
end
exp
......@@ -122,10 +102,10 @@ class Brakeman::LibraryProcessor < Brakeman::BaseProcessor
if @current_class
exp.body = process_all! exp.body
@current_class[:public][exp.method_name] = { :src => exp, :file => @file_name }
@current_class.add_method :public, exp.method_name, exp, @file_name
elsif @current_module
exp.body = process_all! exp.body
@current_module[:public][exp.method_name] = { :src => exp, :file => @file_name }
@current_module.add_method :public, exp.method_name, exp, @file_name
end
exp
......
require 'brakeman/processors/base_processor'
require 'brakeman/tracker/model'
#Processes models. Puts results in tracker.models
class Brakeman::ModelProcessor < Brakeman::BaseProcessor
ASSOCIATIONS = Set[:belongs_to, :has_one, :has_many, :has_and_belongs_to_many]
def initialize tracker
super
@current_class = nil
......@@ -34,31 +33,18 @@ class Brakeman::ModelProcessor < Brakeman::BaseProcessor
if @current_class
outer_class = @current_class
name = (outer_class[:name].to_s + "::" + name.to_s).to_sym
name = (outer_class.name.to_s + "::" + name.to_s).to_sym
end
if @current_module
name = (@current_module[:name].to_s + "::" + name.to_s).to_sym
name = (@current_module.name.to_s + "::" + name.to_s).to_sym
end
if @tracker.models[name]
@current_class = @tracker.models[name]
@current_class[:files] << @file_name unless @current_class[:files].include? @file_name
@current_class[:src][@file_name] = exp
@current_class.add_file @file_name, exp
else
@current_class = {
:name => name,
:parent => parent,
:includes => [],
:public => {},
:private => {},
:protected => {},
:options => {},
:src => { @file_name => exp },
:associations => {},
:files => [ @file_name ]
}
@current_class = Brakeman::Model.new name, parent, @file_name, exp, @tracker
@tracker.models[name] = @current_class
end
......@@ -78,30 +64,18 @@ class Brakeman::ModelProcessor < Brakeman::BaseProcessor
if @current_module
outer_module = @current_module
name = (outer_module[:name].to_s + "::" + name.to_s).to_sym
name = (outer_module.name.to_s + "::" + name.to_s).to_sym
end
if @current_class
name = (@current_class[:name].to_s + "::" + name.to_s).to_sym
name = (@current_class.name.to_s + "::" + name.to_s).to_sym
end
if @tracker.libs[name]
@current_module = @tracker.libs[name]
@current_module[:files] << @file_name unless @current_module[:files].include? @file_name
@current_module[:src][@file_name] = exp
@current_module.add_file @file_name, exp
else
@current_module = {
:name => name,
:includes => [],
:public => {},
:private => {},
:protected => {},
:options => {},
:src => { @file_name => exp },
:associations => {},
:files => [ @file_name ]
}
@current_module = Brakeman::Model.new name, nil, @file_name, exp, @tracker
@tracker.libs[name] = @current_module
end
......@@ -136,37 +110,21 @@ class Brakeman::ModelProcessor < Brakeman::BaseProcessor
when :private, :protected, :public
@visibility = method
when :attr_accessible
@current_class[:attr_accessible] ||= []
@current_class.set_attr_accessible
else
#??
end
else
case method
when :include
@current_class[:includes] << class_name(first_arg) if @current_class
@current_class.add_include class_name(first_arg) if @current_class
when :attr_accessible
@current_class[:attr_accessible] ||= []
args = []
exp.each_arg do |e|
if node_type? e, :lit
args << e.value
elsif hash? e
@current_class[:options][:role_accessible] ||= []
@current_class[:options][:role_accessible].concat args
end
end
@current_class[:attr_accessible].concat args
@current_class.set_attr_accessible exp
when :attr_protected
@current_class.set_attr_protected exp
else
if @current_class
if ASSOCIATIONS.include? method
@current_class[:associations][method] ||= []
@current_class[:associations][method].concat exp.args
else
@current_class[:options][method] ||= []
@current_class[:options][method] << exp.arglist.line(exp.line)
end
@current_class.add_option method, exp
end
end
end
......@@ -190,9 +148,9 @@ class Brakeman::ModelProcessor < Brakeman::BaseProcessor
@current_method = nil
if @current_class
@current_class[@visibility][name] = { :src => res, :file => @file_name }
@current_class.add_method @visibility, name, res, @file_name
elsif @current_module
@current_module[@visibility][name] = { :src => res, :file => @file_name }
@current_module.add_method @visibility, name, res, @file_name
end
res
......@@ -205,7 +163,7 @@ class Brakeman::ModelProcessor < Brakeman::BaseProcessor
if exp[1].node_type == :self
if @current_class
target = @current_class[:name]
target = @current_class.name
elsif @current_module
target = @current_module
else
......@@ -221,9 +179,9 @@ class Brakeman::ModelProcessor < Brakeman::BaseProcessor
@current_method = nil
if @current_class
@current_class[@visibility][name] = { :src => res, :file => @file_name }
@current_class.add_method @visibility, name, res, @file_name
elsif @current_module
@current_module[@visibility][name] = { :src => res, :file => @file_name }
@current_module.add_method @visibility, name, res, @file_name
end
res
end
......
......@@ -46,14 +46,14 @@ class Brakeman::SlimTemplateProcessor < Brakeman::TemplateProcessor
def make_output exp
s = Sexp.new :output, exp
s.line(exp.line)
@current_template[:outputs] << s
@current_template.add_output s
s
end
def make_escaped_output exp
s = Sexp.new :escaped_output, exp.first_arg
s.line(exp.line)
@current_template[:outputs] << s
@current_template.add_output s
s
end
......
......@@ -21,20 +21,20 @@ class Brakeman::TemplateAliasProcessor < Brakeman::AliasProcessor
def process_template name, args
if @called_from
if @called_from.include_template? name
Brakeman.debug "Skipping circular render from #{@template[:name]} to #{name}"
Brakeman.debug "Skipping circular render from #{@template.name} to #{name}"
return
end
super name, args, @called_from.dup.add_template_render(@template[:name])
super name, args, @called_from.dup.add_template_render(@template.name)
else
super name, args, Brakeman::RenderPath.new.add_template_render(@template[:name])
super name, args, Brakeman::RenderPath.new.add_template_render(@template.name)
end
end
#Determine template name
def template_name name
if !name.to_s.include?('/') && @template[:name].to_s.include?('/')
name = "#{@template[:name].to_s.match(/^(.*\/).*$/)[1]}#{name}"
if !name.to_s.include?('/') && @template.name.to_s.include?('/')
name = "#{@template.name.to_s.match(/^(.*\/).*$/)[1]}#{name}"
end
name
end
......
require 'brakeman/processors/base_processor'
require 'brakeman/tracker/template'
#Base Processor for templates/views
class Brakeman::TemplateProcessor < Brakeman::BaseProcessor
......@@ -6,13 +7,8 @@ class Brakeman::TemplateProcessor < Brakeman::BaseProcessor
#Initializes template information.
def initialize tracker, template_name, called_from = nil, file_name = nil
super(tracker)
@current_template = { :name => template_name,
:caller => called_from,
:partial => template_name.to_s[0,1] == "_",
:outputs => [],
:src => nil, #set in Processor
:type => nil, #set in Processor
:file => file_name }
@current_template = Brakeman::Template.new template_name, called_from, file_name, tracker
if called_from
template_name = (template_name.to_s + "." + called_from.to_s).to_sym
end
......@@ -27,7 +23,7 @@ class Brakeman::TemplateProcessor < Brakeman::BaseProcessor
begin
super
rescue => e
except = e.exception("Error when processing #{@current_template[:name]}: #{e.message}")
except = e.exception("Error when processing #{@current_template.name}: #{e.message}")
except.set_backtrace(e.backtrace)
raise except
end
......@@ -48,7 +44,7 @@ class Brakeman::TemplateProcessor < Brakeman::BaseProcessor
#Adds output to the list of outputs.
def process_output exp
exp.value = process exp.value
@current_template[:outputs] << exp unless exp.original_line
@current_template.add_output exp unless exp.original_line
exp
end
......
......@@ -40,7 +40,7 @@ class Brakeman::Report::Base
c = tracker.controllers[name]
if tracker.routes.include? :allow_all_actions or (tracker.routes[name] and tracker.routes[name].include? :allow_all_actions)
routes = c[:public].keys.map{|e| e.to_s}.sort.join(", ")
routes = c.methods_public.keys.map{|e| e.to_s}.sort.join(", ")
elsif tracker.routes[name].nil?
#No routes defined for this controller.
#This can happen when it is only a parent class
......@@ -48,7 +48,7 @@ class Brakeman::Report::Base
routes = "[None]"
else
routes = (Set.new(c[:public].keys) & tracker.routes[name.to_sym]).
routes = (Set.new(c.methods_public.keys) & tracker.routes[name.to_sym]).
to_a.
map {|e| e.to_s}.
sort.
......@@ -60,8 +60,8 @@ class Brakeman::Report::Base
end
controller_rows << { "Name" => name.to_s,
"Parent" => c[:parent].to_s,
"Includes" => c[:includes].join(", "),
"Parent" => c.parent.to_s,
"Includes" => c.includes.join(", "),
"Routes" => routes
}
end
......@@ -248,7 +248,7 @@ class Brakeman::Report::Base
end
def number_of_templates tracker
Set.new(tracker.templates.map {|k,v| v[:name].to_s[/[^.]+/]}).length
Set.new(tracker.templates.map {|k,v| v.name.to_s[/[^.]+/]}).length
end
def warning_file warning, absolute = @tracker.options[:absolute_paths]
......@@ -263,8 +263,8 @@ class Brakeman::Report::Base
def rails_version
case
when tracker.config[:rails_version]
tracker.config[:rails_version]
when tracker.config.rails_version
tracker.config.rails_version
when tracker.options[:rails4]
"4.x"
when tracker.options[:rails3]
......
......@@ -47,12 +47,10 @@ class Brakeman::Report::HTML < Brakeman::Report::Base
out_processor = Brakeman::OutputProcessor.new
template_rows = {}
tracker.templates.each do |name, template|
unless template[:outputs].empty?
template[:outputs].each do |out|
out = CGI.escapeHTML(out_processor.format(out))
template_rows[name] ||= []
template_rows[name] << out.gsub("\n", ";").gsub(/\s+/, " ")
end
template.each_output do |out|
out = CGI.escapeHTML(out_processor.format(out))
template_rows[name] ||= []
template_rows[name] << out.gsub("\n", ";").gsub(/\s+/, " ")
end
end
......@@ -83,7 +81,7 @@ class Brakeman::Report::HTML < Brakeman::Report::Base
warning["Message"] = with_context original, warning["Message"]
warning["Warning Type"] = with_link original, warning["Warning Type"]
warning["Called From"] = original.called_from
warning["Template Name"] = original.template[:name]
warning["Template Name"] = original.template.name
warning
end
......
......@@ -99,12 +99,10 @@ class Brakeman::Report::Markdown < Brakeman::Report::Base
out_processor = Brakeman::OutputProcessor.new
template_rows = {}
tracker.templates.each do |name, template|
unless template[:outputs].empty?
template[:outputs].each do |out|
out = out_processor.format out
template_rows[name] ||= []
template_rows[name] << out.gsub("\n", ";").gsub(/\s+/, " ")
end
template.each_output do |out|
out = out_processor.format out
template_rows[name] ||= []
template_rows[name] << out.gsub("\n", ";").gsub(/\s+/, " ")
end
end
......
......@@ -57,12 +57,10 @@ class Brakeman::Report::Table < Brakeman::Report::Base
out_processor = Brakeman::OutputProcessor.new
template_rows = {}
tracker.templates.each do |name, template|
unless template[:outputs].empty?
template[:outputs].each do |out|
out = out_processor.format out
template_rows[name] ||= []
template_rows[name] << out.gsub("\n", ";").gsub(/\s+/, " ")
end
template.each_output do |out|
out = out_processor.format out
template_rows[name] ||= []
template_rows[name] << out.gsub("\n", ";").gsub(/\s+/, " ")
end
end
......
......@@ -88,8 +88,8 @@ class Brakeman::Rescanner < Brakeman::Scanner
when :routes
rescan_routes
when :gemfile
if tracker.config[:gems][:rails_xss] and tracker.config[:escape_html]
tracker.config[:escape_html] = false
if tracker.config.has_gem? :rails_xss and tracker.config.escape_html?
tracker.config.escape_html = false
end
process_gems
......@@ -102,7 +102,7 @@ class Brakeman::Rescanner < Brakeman::Scanner
def rescan_controller path
controller = tracker.reset_controller path
paths = controller.nil? ? [path] : controller[:files]
paths = controller.nil? ? [path] : controller.files
parse_ruby_files(paths).each do |astfile|
process_controller astfile
end
......@@ -110,16 +110,16 @@ class Brakeman::Rescanner < Brakeman::Scanner
#Process data flow and template rendering
#from the controller
tracker.controllers.each do |name, controller|
if controller[:files].include?(path)
if controller.files.include?(path)
tracker.templates.each do |template_name, template|
next unless template[:caller]
if template[:caller].include_controller? name
next unless template.render_path
if template.render_path.include_controller? name
tracker.reset_template template_name
end
end
controller[:src].each_value do |src|
@processor.process_controller_alias controller[:name], src
controller.src.each_value do |src|
@processor.process_controller_alias controller.name, src
end
end
end
......@@ -145,10 +145,10 @@ class Brakeman::Rescanner < Brakeman::Scanner
#Search for processed template and process it.
#Search for rendered versions of template and re-render (if necessary)
tracker.templates.each do |name, template|
if template[:file] == path or template[:file].nil?
next unless template[:caller] and template[:name].to_sym == template_name.to_sym
if template.file == path or template.file.nil?
next unless template.render_path and template.name.to_sym == template_name.to_sym
template[:caller].each do |from|
template.render_path.each do |from|
case from[:type]
when :template
rescan << [:template, from[:name]]
......@@ -163,15 +163,15 @@ class Brakeman::Rescanner < Brakeman::Scanner
if r[0] == :controller
controller = tracker.controllers[r[1]]
controller[:src].each do |file, src|
controller.src.each do |file, src|
unless @paths.include? file
@processor.process_controller_alias controller[:name], src, r[2]
@processor.process_controller_alias controller.name, src, r[2]
end
end
elsif r[0] == :template
template = tracker.templates[r[1]]
rescan_template template[:file]
rescan_template template.file
end
end
......@@ -181,7 +181,7 @@ class Brakeman::Rescanner < Brakeman::Scanner
def rescan_model path
num_models = tracker.models.length
model = tracker.reset_model path
paths = model.nil? ? [path] : model[:files]
paths = model.nil? ? [path] : model.files
parse_ruby_files(paths).each do |astfile|
process_model astfile.path, astfile.ast
end
......@@ -198,7 +198,7 @@ class Brakeman::Rescanner < Brakeman::Scanner
def rescan_lib path
lib = tracker.reset_lib path
paths = lib.nil? ? [path] : lib[:files]
paths = lib.nil? ? [path] : lib.files
parse_ruby_files(paths).each do |astfile|
process_lib astfile
end
......@@ -206,7 +206,7 @@ class Brakeman::Rescanner < Brakeman::Scanner
lib = nil
tracker.libs.each do |name, library|
if library[:files].include?(path)
if library.files.include?(path)
lib = library
break
end
......@@ -269,7 +269,7 @@ class Brakeman::Rescanner < Brakeman::Scanner
#Remove any rendered versions, or partials rendered from it
tracker.templates.delete_if do |name, template|
template[:file] == path or template[:name].to_sym == template_name.to_sym
template.file == path or template.name.to_sym == template_name.to_sym
end
end
......@@ -277,7 +277,7 @@ class Brakeman::Rescanner < Brakeman::Scanner
deleted_lib = nil
tracker.libs.delete_if do |name, lib|
if lib[:files].include?(path)
if lib.files.include?(path)
deleted_lib = lib
true
end
......@@ -297,7 +297,7 @@ class Brakeman::Rescanner < Brakeman::Scanner
[:controllers, :models, :libs].each do |collection|
tracker.send(collection).delete_if do |name, data|
if data[:files].include?(path)
if data.files.include?(path)
deleted = true
true
end
......@@ -305,7 +305,7 @@ class Brakeman::Rescanner < Brakeman::Scanner
end
tracker.templates.delete_if do |name, data|
if data[:file] == path
if data.file == path
deleted = true
true
end
......@@ -341,18 +341,16 @@ class Brakeman::Rescanner < Brakeman::Scanner
def rescan_mixin lib
method_names = []
[:public, :private, :protected].each do |access|
lib[access].each do |name, meth|
method_names << name
end
lib.each_method do |name, meth|
method_names << name
end
to_rescan = []
#Rescan controllers that mixed in library
tracker.controllers.each do |name, controller|
if controller[:includes].include? lib[:name]
controller[:files].each do |path|
if controller.includes.include? lib.name
controller.files.each do |path|
unless @paths.include? path
to_rescan << path
end
......@@ -371,15 +369,15 @@ class Brakeman::Rescanner < Brakeman::Scanner
#This is not precise, because a different controller might have the
#same method...
tracker.templates.each do |name, template|
next unless template[:caller]
next unless template.render_path
if template[:caller].include_any_method? method_names
if template.render_path.include_any_method? method_names
name.to_s.match /^([^.]+)/
original = tracker.templates[$1.to_sym]
if original
to_rescan << [name, original[:file]]
to_rescan << [name, original.file]
end
end
end
......
......@@ -107,7 +107,7 @@ class Brakeman::Scanner
if @app_tree.exists?("vendor/plugins/rails_xss") or
options[:rails3] or options[:escape_html]
tracker.config[:escape_html] = true
tracker.config.escape_html = true
Brakeman.notify "[Notice] Escaping HTML by default"
end
end
......@@ -221,7 +221,7 @@ class Brakeman::Scanner
track_progress controllers, "controllers" do |name, controller|
Brakeman.debug "Processing #{name}"
controller[:src].each_value do |src|
controller.src.each_value do |src|
@processor.process_controller_alias name, src
end
end
......
......@@ -4,6 +4,7 @@ require 'brakeman/checks'
require 'brakeman/report'
require 'brakeman/processors/lib/find_call'
require 'brakeman/processors/lib/find_all_calls'
require 'brakeman/tracker/config'
#The Tracker keeps track of all the processed information.
class Brakeman::Tracker
......@@ -25,20 +26,14 @@ class Brakeman::Tracker
@processor = processor
@options = options
@config = { :rails => {}, :gems => {} }
@config = Brakeman::Config.new(self)
@templates = {}
@controllers = {}
#Initialize models with the unknown model so
#we can match models later without knowing precisely what
#class they are.
@models = { UNKNOWN_MODEL => { :name => UNKNOWN_MODEL,
:parent => nil,
:includes => [],
:public => {},
:private => {},
:protected => {},
:options => {},
:files => [] } }
@models = {}
@models[UNKNOWN_MODEL] = Brakeman::Model.new(UNKNOWN_MODEL, nil, nil, nil, self)
@routes = {}
@initializers = {}
@errors = []
......@@ -90,17 +85,15 @@ class Brakeman::Tracker
end
classes.each do |set|
set.each do |set_name, info|
[:private, :public, :protected].each do |visibility|
info[visibility].each do |method_name, definition|
src = definition[:src]
if src.node_type == :selfdef
method_name = "#{src[1]}.#{method_name}"
end
set.each do |set_name, collection|
collection.each_method do |method_name, definition|
src = definition[:src]
if src.node_type == :selfdef
method_name = "#{src[1]}.#{method_name}"
end
yield src, set_name, method_name, definition[:file]
yield src, set_name, method_name, definition[:file]
end
end
end
end
......@@ -186,7 +179,7 @@ class Brakeman::Tracker
end
self.each_template do |name, template|
finder.process_source template[:src], :template => template, :file => template[:file]
finder.process_source template.src, :template => template, :file => template.file
end
@call_index = Brakeman::CallIndex.new finder.calls
......@@ -228,23 +221,20 @@ class Brakeman::Tracker
method_sets.each do |set|
set.each do |set_name, info|
[:private, :public, :protected].each do |visibility|
info[visibility].each do |method_name, definition|
src = definition[:src]
if src.node_type == :selfdef
method_name = "#{src[1]}.#{method_name}"
end
finder.process_source src, :class => set_name, :method => method_name, :file => definition[:file]
info.each_method do |method_name, definition|
src = definition[:src]
if src.node_type == :selfdef
method_name = "#{src[1]}.#{method_name}"
end
finder.process_source src, :class => set_name, :method => method_name, :file => definition[:file]
end
end
end
if locations.include? :templates
self.each_template do |name, template|
finder.process_source template[:src], :template => template, :file => template[:file]
finder.process_source template.src, :template => template, :file => template.file
end
end
......@@ -257,7 +247,7 @@ class Brakeman::Tracker
def reset_templates options = { :only_rendered => false }
if options[:only_rendered]
@templates.delete_if do |name, template|
template[:caller] and template[:caller].rendered_from_controller?
template.rendered_from_controller?
end
else
@templates = {}
......@@ -281,7 +271,7 @@ class Brakeman::Tracker
model_name = nil
@models.each do |name, model|
if model[:files].include?(path)
if model.files.include?(path)
model_name = name
break
end
......@@ -295,7 +285,7 @@ class Brakeman::Tracker
lib_name = nil
@libs.each do |name, lib|
if lib[:files].include?(path)
if lib.files.include?(path)
lib_name = name
break
end
......@@ -309,12 +299,12 @@ class Brakeman::Tracker
#Remove from controller
@controllers.each do |name, controller|
if controller[:files].include?(path)
if controller.files.include?(path)
controller_name = name
#Remove templates rendered from this controller
@templates.each do |template_name, template|
if template[:caller] and template[:caller].include_controller? name
if template.render_path and template.render_path.include_controller? name
reset_template template_name
@call_index.remove_template_indexes template_name
end
......
require 'brakeman/util'
module Brakeman
class Collection
include Brakeman::Util
attr_reader :collection, :files, :includes, :name, :options, :parent, :src, :tracker
def initialize name, parent, file_name, src, tracker
@name = name
@parent = parent
@file_name = file_name
@files = [ file_name ]
@src = { file_name => src }
@includes = []
@methods = { :public => {}, :private => {}, :protected => {} }
@options = {}
@tracker = tracker
end
def ancestor? parent, seen={}
seen[self.name] = true
if self.parent == parent or seen[self.parent]
true
elsif parent_model = collection[self.parent]
parent_model.ancestor? parent, seen
else
false
end
end
def add_file file_name, src
@files << file_name unless @files.include? file_name
@src[file_name] = src
end
def add_include class_name
@includes << class_name
end
def add_option name, exp
@options[name] ||= []
@options[name] << exp
end
def add_method visibility, name, src, file_name
@methods[visibility][name] = { :src => src, :file => file_name }
end
def each_method
@methods.each do |vis, meths|
meths.each do |name, info|
yield name, info
end
end
end
def get_method name
each_method do |n, info|
if n == name
return info
end
end
nil
end
def file
@files.first
end
def methods_public
@methods[:public]
end
end
end
require 'brakeman/util'
module Brakeman
class Config
include Util
attr_reader :rails, :tracker
attr_accessor :rails_version
attr_writer :erubis, :escape_html
def initialize tracker
@tracker = tracker
@rails = {}
@gems = {}
@settings = {}
end
def allow_forgery_protection?
@rails[:action_controller] and
@rails[:action_controller][:allow_forgery_protection] == Sexp.new(:false)
end
def erubis?
@erubis
end
def escape_html?
@escape_html
end
def escape_html_entities_in_json?
#TODO add version-specific information here
@rails[:active_support] and
true? @rails[:active_support][:escape_html_entities_in_json]
end
def whitelist_attributes?
@rails[:active_record] and
@rails[:active_record][:whitelist_attributes] == Sexp.new(:true)
end
def gem_version name
@gems[name] and @gems[name][:version]
end
def add_gem name, version, file, line
name = name.to_sym
@gems[name] = {
:version => version,
:file => file,
:line => line
}
end
def has_gem? name
!!@gems[name]
end
def get_gem name
@gems[name]
end
def set_rails_version
# Ignore ~>, etc. when using values from Gemfile
version = gem_version(:rails)
if version and version.match(/(\d+\.\d+\.\d+.*)/)
@rails_version = $1
if tracker.options[:rails3].nil? and tracker.options[:rails4].nil?
if @rails_version.start_with? "3"
tracker.options[:rails3] = true
Brakeman.notify "[Notice] Detected Rails 3 application"
elsif @rails_version.start_with? "4"
tracker.options[:rails3] = true
tracker.options[:rails4] = true
Brakeman.notify "[Notice] Detected Rails 4 application"
end
end
end
if get_gem :rails_xss
@escape_html = true
Brakeman.notify "[Notice] Escaping HTML by default"
end
end
def session_settings
@rails[:action_controller] &&
@rails[:action_controller][:session]
end
end
end
require 'brakeman/tracker/collection'
module Brakeman
module ControllerMethods
attr_accessor :layout
def initialize_controller
@options[:before_filters] = []
@options[:skip_filters] = []
@layout = nil
@skip_filter_cache = nil
@before_filter_cache = nil
end
def protect_from_forgery?
@options[:protect_from_forgery]
end
def add_before_filter exp
@options[:before_filters] << exp
end
def prepend_before_filter exp
@options[:before_filters].unshift exp
end
def before_filters
@options[:before_filters]
end
def skip_filter exp
@options[:skip_filters] << exp
end
def skip_filters
@options[:skip_filters]
end
def before_filter_list processor, method
controller = self
filters = []
while controller
filters = controller.get_before_filters(processor, method) + filters
controller = tracker.controllers[controller.parent] ||
tracker.libs[controller.parent]
end
remove_skipped_filters processor, filters, method
end
def get_skipped_filters processor, method
filters = []
if @skip_filter_cache.nil?
@skip_filter_cache = skip_filters.map do |filter|
before_filter_to_hash(processor, filter.args)
end
end
@skip_filter_cache.each do |f|
if f[:all] or
(f[:only] == method) or
(f[:only].is_a? Array and f[:only].include? method) or
(f[:except].is_a? Symbol and f[:except] != method) or
(f[:except].is_a? Array and not f[:except].include? method)
filters.concat f[:methods]
else
end
end
filters
end
def remove_skipped_filters processor, filters, method
controller = self
while controller
filters = filters - controller.get_skipped_filters(processor, method)
controller = tracker.controllers[controller.parent] ||
tracker.libs[controller.parent]
end
filters
end
def get_before_filters processor, method
filters = []
if @before_filter_cache.nil?
@before_filter_cache = []
before_filters.each do |filter|
@before_filter_cache << before_filter_to_hash(processor, filter.args)
end
end
@before_filter_cache.each do |f|
if f[:all] or
(f[:only] == method) or
(f[:only].is_a? Array and f[:only].include? method) or
(f[:except].is_a? Symbol and f[:except] != method) or
(f[:except].is_a? Array and not f[:except].include? method)
filters.concat f[:methods]
end
end
filters
end
def before_filter_to_hash processor, args
filter = {}
#Process args for the uncommon but possible situation
#in which some variables are used in the filter.
args.each do |a|
if sexp? a
a = processor.process_default a
end
end
filter[:methods] = [args[0][1]]
args[1..-1].each do |a|
filter[:methods] << a[1] if a.node_type == :lit
end
if args[-1].node_type == :hash
option = args[-1][1][1]
value = args[-1][2]
case value.node_type
when :array
filter[option] = value[1..-1].map {|v| v[1] }
when :lit, :str
filter[option] = value[1]
else
Brakeman.debug "[Notice] Unknown before_filter value: #{option} => #{value}"
end
else
filter[:all] = true
end
filter
end
end
class Controller < Brakeman::Collection
include ControllerMethods
def initialize name, parent, file_name, src, tracker
super
initialize_controller
@collection = tracker.controllers
end
end
end
require 'brakeman/tracker/collection'
require 'brakeman/tracker/controller'
require 'brakeman/tracker/model'
module Brakeman
class Library < Brakeman::Collection
include ControllerMethods
include ModelMethods
def initialize name, parent, file_name, src, tracker
super
initialize_controller
initialize_model
@collection = tracker.libs
end
end
end
require 'brakeman/tracker/collection'
module Brakeman
module ModelMethods
attr_reader :associations, :attr_accessible, :role_accessible
def initialize_model
@associations = {}
@role_accessible = []
@attr_accessible = nil
end
def association? method_name
@associations.each do |name, args|
args.each do |arg|
if symbol? arg and arg.value == method_name
return true
end
end
end
false
end
def unprotected_model?
@attr_accessible.nil? and !parent_classes_protected? and ancestor?(:"ActiveRecord::Base")
end
# go up the chain of parent classes to see if any have attr_accessible
def parent_classes_protected? seen={}
seen[self.name] = true
if @attr_accessible or self.includes.include? :"ActiveModel::ForbiddenAttributesProtection"
true
elsif parent = tracker.models[self.parent] and !seen[self.parent]
parent.parent_classes_protected? seen
else
false
end
end
def set_attr_accessible exp = nil
if exp
args = []
exp.each_arg do |e|
if node_type? e, :lit
args << e.value
elsif hash? e
@role_accessible.concat args
end
end
@attr_accessible ||= []
@attr_accessible.concat args
else
@attr_accessible ||= []
end
end
def set_attr_protected exp
add_option :attr_protected, exp
end
def attr_protected
@options[:attr_protected]
end
end
class Model < Brakeman::Collection
include ModelMethods
ASSOCIATIONS = Set[:belongs_to, :has_one, :has_many, :has_and_belongs_to_many]
def initialize name, parent, file_name, src, tracker
super
initialize_model
@collection = tracker.models
end
def add_option name, exp
if ASSOCIATIONS.include? name
@associations[name] ||= []
@associations[name].concat exp.args
else
super name, exp.arglist.line(exp.line)
end
end
end
end
require 'brakeman/tracker/collection'
module Brakeman
class Template < Brakeman::Collection
attr_accessor :type
attr_reader :render_path
attr_writer :src
def initialize name, called_from, file_name, tracker
super name, nil, file_name, nil, tracker
@render_path = called_from
@outputs = []
end
def add_output exp
@outputs << exp
end
def each_output
@outputs.each do |o|
yield o
end
end
def rendered_from_controller?
if @render_path
@render_path.rendered_from_controller?
else
false
end
end
end
end
......@@ -267,6 +267,10 @@ module Brakeman::Util
call
end
def rails_version
@tracker.config.rails_version
end
#Return file name related to given warning. Uses +warning.file+ if it exists
def file_for warning, tracker = nil
if tracker.nil?
......@@ -275,14 +279,14 @@ module Brakeman::Util
if warning.file
File.expand_path warning.file, tracker.app_path
elsif warning.template.is_a? Hash and warning.template[:file]
warning.template[:file]
elsif warning.template and warning.template.file
warning.template.file
else
case warning.warning_set
when :controller
file_by_name warning.controller, :controller, tracker
when :template
file_by_name warning.template[:name], :template, tracker
file_by_name warning.template.name, :template, tracker
when :model
file_by_name warning.model, :model, tracker
when :warning
......@@ -318,20 +322,20 @@ module Brakeman::Util
case type
when :controller
if tracker.controllers[name] and tracker.controllers[name][:files]
path = tracker.controllers[name][:files].first
if tracker.controllers[name]
path = tracker.controllers[name].file
else
path += "/app/controllers/#{underscore(string_name)}.rb"
end
when :model
if tracker.models[name] and tracker.models[name][:files]
path = tracker.models[name][:files].first
if tracker.models[name]
path = tracker.models[name].file
else
path += "/app/models/#{underscore(string_name)}.rb"
end
when :template
if tracker.templates[name] and tracker.templates[name][:file]
path = tracker.templates[name][:file]
if tracker.templates[name] and tracker.templates[name].file
path = tracker.templates[name].file
elsif string_name.include? " "
name = string_name.split[0].to_sym
path = file_for tracker, name, :template
......
......@@ -62,7 +62,7 @@ class Brakeman::Warning
@warning_set = :model
elsif self.template
@warning_set = :template
@called_from = self.template[:caller]
@called_from = self.template.render_path
elsif self.controller
@warning_set = :controller
else
......@@ -92,9 +92,9 @@ class Brakeman::Warning
def view_name
return @view_name if @view_name
if called_from
@view_name = "#{template[:name]} (#{called_from.last})"
@view_name = "#{template.name} (#{called_from.last})"
else
@view_name = template[:name]
@view_name = template.name
end
end
......
......@@ -42,7 +42,7 @@ module BrakemanTester::FindWarning
def assert_no_warning opts
warnings = find opts
assert_equal 0, warnings.length, "Unexpected warning found"
assert_equal 0, warnings.length
end
def find opts = {}, &block
......@@ -85,7 +85,7 @@ module BrakemanTester::CheckExpected
end
def test_zero_errors
assert_equal 0, report[:errors].length
assert_equal 0, report[:errors].length, "Unexpected warning found: #{report[:errors].inspect}"
end
end
......
......@@ -91,17 +91,20 @@ class BaseCheckTests < Test::Unit::TestCase
def setup
@tracker = FakeTracker.new
@tracker.config = Brakeman::Config.new(@tracker)
app_tree = FakeAppTree.new
@check = Brakeman::BaseCheck.new app_tree, @tracker
end
def version_between? version, low, high
@tracker.config = { :rails_version => version }
@tracker.config.rails_version = version
@check.send(:version_between?, low, high)
end
def lts_version? version, low
@tracker.config = { :gems => { :"railslts-version" => { :version => version, :file => nil, :line => nil} } }
if version
@tracker.config.add_gem :"railslts-version", version, nil, nil
end
@check.send(:lts_version?, low)
end
......@@ -126,7 +129,7 @@ class BaseCheckTests < Test::Unit::TestCase
end
def test_lts_version
@tracker.config = { :rails_version => "2.3.18" }
@tracker.config.rails_version = "2.3.18"
assert lts_version? '2.3.18.6', '2.3.18.6'
assert !lts_version?('2.3.18.1', '2.3.18.6')
assert !lts_version?(nil, '2.3.18.6')
......@@ -281,11 +284,13 @@ class GemProcessorTests < Test::Unit::TestCase
FakeTracker = Struct.new(:config, :options)
def assert_version version, name, msg = nil
assert_equal version, @tracker[:config][:gems][name][:version], msg
assert_equal version, @tracker.config.gem_version(name), msg
end
def setup
@tracker = FakeTracker.new({}, {})
@tracker = FakeTracker.new
@tracker.options = {}
@tracker.config = Brakeman::Config.new(@tracker)
@gem_processor = Brakeman::GemProcessor.new @tracker
@eol_representations = ["\r\n", "\n"]
@gem_locks = @eol_representations.inject({}) {|h, eol|
......
......@@ -10,9 +10,9 @@ class CVETests < Test::Unit::TestCase
def assert_version version, gem = :rails
if gem == :rails
assert_equal version, @rescanner.tracker.config[:rails_version]
assert_equal version, @rescanner.tracker.config.rails_version
else
assert_equal version, @rescanner.tracker.config[:gems][gem][:version]
assert_equal version, @rescanner.tracker.config.gem_version(gem)
end
end
......
......@@ -34,7 +34,7 @@ class Rails2Tests < Test::Unit::TestCase
end
def test_config_sanity
assert_equal 'UTC', report[:config][:rails][:time_zone].value
assert_equal 'UTC', report[:config].rails[:time_zone].value
end
def test_eval
......
......@@ -29,7 +29,7 @@ class Rails3Tests < Test::Unit::TestCase
end
def test_config_sanity
assert_equal 'utf-8', report[:config][:rails][:encoding].value
assert_equal 'utf-8', report[:config].rails[:encoding].value
end
def test_eval_params
......
......@@ -28,7 +28,7 @@ class Rails32Tests < Test::Unit::TestCase
end
def test_rc_version_number
assert_equal "3.2.9.rc2", report[:config][:rails_version]
assert_equal "3.2.9.rc2", report[:config].rails_version
end
def test_sql_injection_CVE_2012_5664
......
......@@ -11,7 +11,7 @@ class RailsLTSTests < Test::Unit::TestCase
end
#@original is actually modified
assert @original.config[:gems][:"railslts-version"], "2.3.18.6"
assert @original.config.gem_version(:'railslts-version'), "2.3.18.6"
assert_reindex :none
assert_changes
assert_new 0
......@@ -26,7 +26,7 @@ class RailsLTSTests < Test::Unit::TestCase
end
#@original is actually modified
assert @original.config[:gems][:"railslts-version"], "2.3.18.7"
assert @original.config.gem_version(:'railslts-version'), "2.3.18.7"
assert_reindex :none
assert_changes
assert_new 0
......@@ -41,7 +41,7 @@ class RailsLTSTests < Test::Unit::TestCase
end
#@original is actually modified
assert @original.config[:gems][:"railslts-version"], "2.3.18.8"
assert @original.config.gem_version(:'railslts-version'), "2.3.18.8"
assert_reindex :none
assert_changes
assert_new 0
......@@ -56,7 +56,7 @@ class RailsLTSTests < Test::Unit::TestCase
end
#@original is actually modified
assert @original.config[:gems][:"railslts-version"], "2.3.18.9"
assert @original.config.gem_version(:'railslts-version'), "2.3.18.9"
assert_reindex :none
assert_changes
assert_new 0
......
......@@ -273,7 +273,7 @@ class RescannerTests < Test::Unit::TestCase
end
#@original is actually modified
assert @original.config[:rails_version], "3.2.6"
assert @original.config.rails_version, "3.2.6"
assert_reindex :none
assert_changes
assert_new 1
......@@ -288,7 +288,7 @@ class RescannerTests < Test::Unit::TestCase
end
#@original is actually modified
assert @original.config[:rails_version], "3.2.17"
assert @original.config.rails_version, "3.2.17"
assert_reindex :none
assert_changes
assert_new 0
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册