# Copyright (c) 2023 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/agent/reporting/reporting_events/reportable_hash' 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 < Contrast::Agent::Reporting::ReportableHash # @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 # @param policy_node [Contrast::Agent::Assess::Policy::PolicyNode] the node that governs this event. # @param args[Array] the safe representation of the Arguments with # which the method was invoked # @param ret [Contrast::Agent::Assess::ContrastObject] the safe representation of the Return of the # invoked method def initialize policy_node, args, ret node = policy_node @arg_types = [] args&.each { |arg| arg_types << type_name(arg) } @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.to_s @return_type = type_name(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 = ret.nil? || ret.object.nil? || ret.object == Contrast::Utils::ObjectShare::NIL_STRING super() 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 validate { 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