# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details. # frozen_string_literal: true require 'contrast/utils/object_share' require 'contrast/components/logger' module Contrast module Agent module Reporting # This is the new FindingEventSignature class which will include all the needed information for the new reporting # system to relay this information in the Finding/Trace messages. These FindingEventSignatures are used by # TeamServer to construct the method signature for the assess feature. They represent the method invoked when the # FindingEvent was generated. class FindingEventSignature include Contrast::Components::Logger::InstanceMethods # @return [String] the types of the arguments in this event; may be different for each invocation of the # method. attr_reader :arg_types # @return [String] the name of the class of this object or the name itself if of Module type. attr_reader :class_name # @return [Boolean] if the method is a constructor or not. attr_reader :constructor # @return [String] unused. attr_reader :expression_type # @return [Integer] the Java flags; static or not. attr_reader :flags # @return [String] the name of the method. attr_reader :method_name # @return [String] unused. attr_reader :operator # @return [String] the type of the return in this event; may be different for each invocation of the method. attr_reader :return_type # @return [String] unused. attr_reader :signature # @return [Boolean] if the method is void or not; may be different for each invocation of the method. attr_reader :void_method class << self # @param event [Contrast::Agent::Assess::ContrastEvent] the event to build a signature for # @return [Contrast::Agent::Reporting::FindingEventSignature] def convert event report = new report.attach_data(event) report end end # Parse the data from a Contrast::Agent::Assess::ContrastEvent to attach what is required for reporting to # TeamServer to this Contrast::Agent::Reporting::FindingEventSignature # # @param event [Contrast::Agent::Assess::ContrastEvent] def attach_data event node = event.policy_node @arg_types = [] event.args&.each do |arg| arg_types << type_name(arg) end @class_name = node.class_name @constructor = node.method_name == :new || node.method_name == :initialize # 8 is STATIC in Java... we have to placate them for now it has been requested that flags be removed since it # isn't used @flags = 8 unless node.instance_method? @method_name = node.method_name @return_type = type_name(event.ret) # if there's a ret, then this method isn't nil. not 100% full proof since you can return nil, but this is the # best we've got currently. @void_method = event.ret.nil? || event.ret.object.nil? || event.ret.object == Contrast::Utils::ObjectShare::NIL_STRING end # Convert the instance variables on the class, and other information, into the identifiers required for # TeamServer to process the JSON form of this message. # # @return [Hash] # @raise [ArgumentError] def to_controlled_hash begin validate rescue ArgumentError => e logger.error('FindingEventSignature validation failed with: ', e) return end { argTypes: arg_types, className: class_name, constructor: constructor, # expressionType: expression_type, # This is unused by the Ruby agent flags: flags.to_i, methodName: method_name, # operator: operator, # This is unused by the Ruby agent returnType: return_type, # signature: signature, # This is unused by the Ruby agent voidMethod: void_method } end def validate raise(ArgumentError, "#{ self } did not have a proper argTypes. Unable to continue.") unless arg_types raise(ArgumentError, "#{ self } did not have a proper constructor. Unable to continue.") if constructor.nil? end private # While Ruby signatures do not require neither a return type and can return anything depending on inputs, code # paths, etc, nor constant parameter types, TeamServer was designed with strongly typed languages (Java) in # mind, so we need types in our signatures. # # @param contrast_object [Contrast::Agent::Assess::ContrastObject, nil] the object to find the type of # @return [String] the name of the module of the ret_obj, or `nil` def type_name contrast_object contrast_object ? contrast_object.object_type : Contrast::Utils::ObjectShare::NIL_STRING end end end end end