# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details. # frozen_string_literal: true require 'contrast/agent/assess/contrast_event' require 'contrast/agent/reporting/reporting_events/trace_event_source' 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. # # @attr_reader request [Contrast::Agent::Request] our wrapper around the Rack::Request at the time this source # was created # @attr_reader source_name [String] the name of the source if it comes from a map-like entity # @attr_reader source_type [String] the TeamServer understood type of source; i.e. parameter class SourceEvent < Contrast::Agent::Assess::ContrastEvent attr_reader :request, :source_name, :source_type # @param event_data [Contrast::Agent::Assess::Events::EventData] # @param source_type [String] the type of this source, from the # source_node, or a KEY_TYPE if invoked for a map, # @param source_name [String, nil] the name of this source, i.e. # the key used to accessed if from a map or nil if a type like, def initialize event_data, source_type = nil, source_name = nil super(event_data) @source_type = source_type @source_name = source_name @request = Contrast::Agent::REQUEST_TRACKER.current&.request end def parent_events 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 # 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 # You can have a source w/o a name, but not w/o a type return unless source_type trace_event_source = Contrast::Agent::Reporting::TraceEventSource.new trace_event_source.type = forced_source_type trace_event_source.name = forced_source_name trace_event_source 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) I'll set the event's source and target to TS values. # 2) Return the first source/target as the taint target. def determine_taint_target event_dtm return unless @policy_node&.targets&.any? event_dtm.source = @policy_node.source_string if @policy_node.source_string event_dtm.target = @policy_node.target_string @policy_node.targets[0] end end end end end end