# 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/agent/assess/contrast_event' cs__scoped_require 'contrast/utils/string_utils' module Contrast module Agent module Assess module Events # This class holds the data about an event in the application # We'll use it to build an event that TeamServer can consume if # the object to which this event belongs ends in a trigger. class SourceEvent < Contrast::Agent::Assess::ContrastEvent attr_reader :source_name, :source_type, :request def initialize policy_node, tagged, object, ret, args, source_type = nil, source_name = nil super(policy_node, tagged, object, ret, args) @source_type = source_type @source_name = source_name @request = Contrast::Agent::REQUEST_TRACKER.current&.request end def find_parent_ids _policy_node, _object, _ret, _args nil end # Convert this event into a DTM that TeamServer can consume def to_dtm_event event = super event.field_name = Contrast::Utils::StringUtils.force_utf8(source_name) event_source_dtm = build_event_source_dtm event.event_sources << event_source_dtm if event_source_dtm event.object_id = event_id.to_i event end def forced_source_type @_forced_source_type ||= Contrast::Utils::StringUtils.force_utf8(source_type) end def forced_source_name @_forced_source_name ||= Contrast::Utils::StringUtils.force_utf8(source_name) end # Probably only for source events, but we'll go # with source_type instead. java & .net support source_type # in propagation events, so we'll future proof this def build_event_source_dtm # You can have a source w/o a name, but not w/o a type return unless source_type dtm = Contrast::Api::Dtm::TraceEventSource.new dtm.type = forced_source_type dtm.name = forced_source_name dtm end # We have to do a little work to figure out what our TS appropriate # target is. To break this down, the logic is as follows: # 1) If I have a highlight, it means that I have a P target that is # not in integer form (it was a named / keyword type for which I had # to find the index). I need to address this so that TS can process # it. # 2) I'll set the event's source and target to TS values. # 3) Return the highlight or the first source/target as the taint # target. def determine_taint_target event return unless @policy_node&.targets&.any? event.source = @policy_node.source_string if @policy_node.source_string event.target = if @highlight "P#{ @highlight }" else @policy_node.target_string end @highlight || @policy_node.targets[0] end end end end end end