lib/contrast/agent/assess/contrast_event.rb in contrast-agent-3.10.2 vs lib/contrast/agent/assess/contrast_event.rb in contrast-agent-3.11.0

- old
+ new

@@ -1,10 +1,16 @@ # 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/utils/assess/tracking_util' cs__scoped_require 'contrast/utils/class_util' +cs__scoped_require 'contrast/utils/duck_utils' +cs__scoped_require 'contrast/utils/object_share' cs__scoped_require 'contrast/utils/prevent_serialization' +cs__scoped_require 'contrast/utils/stack_trace_utils' +cs__scoped_require 'contrast/utils/string_utils' +cs__scoped_require 'contrast/utils/timer' module Contrast module Agent module Assess # This class holds the data about an event in the application @@ -51,12 +57,11 @@ original end end end - attr_accessor :source_name - attr_reader :event_id, :source_type, :parent_ids + attr_reader :event_id, :parent_ids # We need this to track the parent id's of events to build up a flow # chart of the finding @atomic_id = 0 @atomic_mutex = Mutex.new @@ -67,29 +72,27 @@ rescue StandardError @atomic_id = 1 end end - def initialize policy_node, tagged, object, ret, args, invoked = 0, source_type = nil, source_name = nil - @caller = caller_locations(get_call_start(policy_node, invoked), 10) + def initialize policy_node, tagged, object, ret, args @policy_node = policy_node + # so long as this event is built in a factory, we know Contrast Code + # will be the first three events + @caller = caller(3, 20) @time = Contrast::Utils::Timer.now_ms @thread = Thread.current.object_id - @source_type = source_type - @source_name = source_name # These methods rely on the above being set. Don't move them! @event_id = Contrast::Agent::Assess::ContrastEvent.next_atomic_id @parent_ids = find_parent_ids(policy_node, object, ret, args) snapshot(tagged, object, ret, args) end # Parent IDs are the event ids of all the sources of this event which # were tracked prior to this event occurring def find_parent_ids policy_node, object, ret, args - return if policy_node.is_a?(Contrast::Agent::Assess::Policy::SourceNode) - mapped = policy_node.sources.map do |source| value_of_source(source, object, ret, args) end selected = mapped.select do |source| source && @@ -135,10 +138,12 @@ # I know we're creating an extra string here since we replace the safe # one w/ a dup, but good enough for now. Trying not to make this too # complicated. - HM 8/8/19 def save_target_arg target, tagged + return if @args.cs__frozen? + if target.is_a?(Integer) @args[target] = cs__class.safe_dup(tagged) return end @@ -170,31 +175,10 @@ end end end end - # each policy_node has a certain number of levels down it calls - # before getting here. since we know them, we can skip - # right to the part of the stack we care about. - # - # Note: if our callstack changes, this number has to change - def get_call_start policy_node, invoked - # TODO: RUBY-440 audit these numbers to get stacktraces to render - # properly - base = case policy_node - when Contrast::Agent::Assess::Policy::SourceNode - 6 - when Contrast::Agent::Assess::Policy::PropagationNode - 7 - when Contrast::Agent::Assess::Policy::TriggerNode - 7 - else - 2 - end - base + invoked - end - # Convert this event into a DTM that TeamServer can consume def to_dtm_event event = Contrast::Api::Dtm::TraceEvent.new # Figure out what the target of this event was. It's a little @@ -218,53 +202,23 @@ taint_ranges.each do |range| event.taint_ranges << range end # We delayed doing this as long as possible b/c it's expensive - stack = Contrast::Utils::StackTraceUtils.to_dtm_stack( - stack_locations: @caller, - rasp_element: false) - stack.each do |frame| - event.stack << frame - end + stack = Contrast::Utils::StackTraceUtils.build_assess_stack_array(@caller) + event.stack += stack - 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 - @parent_ids&.each do |id| + parent_ids&.each do |id| parent = Contrast::Api::Dtm::ParentObjectId.new parent.id = id.to_i event.parent_object_ids << parent end # not to be confused w/ the partial signature build_complete_signature(event) 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're not going to build the signature string here, b/c we have all # the composite pieces of it. Instead, we're going to let TeamServer # render this for us.