# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details. # frozen_string_literal: true cs__scoped_require 'contrast/components/interface' # This module acts a trigger & propagator for Tilt::Template evaluation module TiltTemplateTrigger include Contrast::Components::Interface access_component :logging class << self NODE_HASH = { 'class_name' => 'Tilt::Template', 'instance_method' => true, 'method_name' => 'render', 'method_visibility' => 'public', 'action' => 'CUSTOM', 'source' => 'O,P0', 'target' => 'R', 'patch_class' => 'NOOP', 'patch_method' => 'track_template_evaluation' }.cs__freeze TEMPLATE_PROPAGATION_NODE = Contrast::Agent::Assess::Policy::PropagationNode.new(NODE_HASH) def render_trigger_check context, trigger_node, _source, object, ret, invoked, *args logger.debug { 'Tilt::Template Trigger - running propagation' } scope = args[0] binding_variables = scope.instance_variables erb_template_prerender = object.instance_variable_get(:@data) interpolated_inputs = [] binding_variables.each do |bound_variable_sym| bound_variable_value = scope.instance_variable_get(bound_variable_sym) next unless bound_variable_value.cs__respond_to?(:cs__tracked?) && bound_variable_value.cs__tracked? next unless erb_template_prerender.include?(bound_variable_sym.to_s) start_index = ret.index(bound_variable_value) next if start_index.nil? logger.debug('Tilt::Template Trigger - found bound_variable in erb template result') ret.cs__copy_from(bound_variable_value, start_index) interpolated_inputs << bound_variable_sym end locals = args[1] locals.each do |local_name, local_value| next unless local_value.cs__respond_to?(:cs__tracked?) && local_value.cs__tracked? next unless erb_template_prerender.include?(local_name.to_s) start_index = ret.index(local_value) next if start_index.nil? logger.debug('Tilt:Template Trigger - found local_value in erb template result') ret.cs__copy_from(local_value, start_index) interpolated_inputs << local_name end unless interpolated_inputs.empty? interpolated_inputs.each do |input| input.cs__properties.events.each do |event| ret.cs__properties.events << event end end ret.cs__properties.build_event(TEMPLATE_PROPAGATION_NODE, ret, erb_template_prerender, ret, interpolated_inputs, invoked + 1) end if ret.cs__tracked? Contrast::Agent::Assess::Policy::TriggerMethod.build_finding(context, trigger_node, ret, erb_template_prerender, ret, invoked + 1, interpolated_inputs) end ret end end end