# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details. # frozen_string_literal: true module Contrast module Agent module Telemetry module TelemetryException # Here will be all known gems to obfuscate during the building of TelemetryExceptions module Obfuscate # TODO: RUBY-1984 Re-enable/Remove Telemetry Obfuscation. # # List of known gems to be third parties not containing any # user sensitive data. # KNOWN_GEMS = %w[ # activesupport redis-activesupport redis builder dry-types rails rails-html-sanitizer rails-observers # sinatra # benchmark-ips bundler climate_control execjs factory_bot debride fake_ftp fasterer flay openssl # parallel_tests contrast contrast-agent ruby pry-byebug byebug pry resolv ougai protobuf async nokogiri # benchmark grape-order grape-activerecord newrelic newrelic-grape grape-rails-cache grape-msgpack # grape-batch rspec rake rubocop grape-jbuilder rack-test rack-protection minitest grape-instrumentation # minitest-global_expectations rack-proxy rack-attack rack-ssl grape-cancan grape-attack grape-rake-tasks # grape-route-helpers benchmark-memory grape-rabl grape-kaminari grape-path-helpers grape-swagger-entity # grape-swagger-rails grape-roar newrelic-rake grapes-wagger-representative grape-forgery_protection # grape-papertrail grape-app grape-middleware-logger rack-protection rake-compile rhino rspec-benchmark # rspec_junit_formatter rspec-rails rake-performance rubocop-rails rubocop-rake rubocop-rspec # ruby-debug-ide simplecov sqlite steep tilt tzinfo-data warning xpath sinatra-activerecord sinatra-param # sinatra-partial sinatra-flash sinatra-reloader sinatra-sinatra rake_fly rack rack-accept grape # grape-entity # sinatra-advanced-routes sinatra-warden grape_logging grape-swagger sinatra-namespace sinatra-resource # sinatra-hashfix sinatra-instrumentation sinatra-helpers redis-rack sinatra-support sinatra-assetpack # sinatra-router sinatra-cross_origin sinatra_more sinatra-jsonp faraday-rack zlib mustermann # mustermann-grape # rspec-expectations rspec-core rspec-mocks rspec-sidekiq # ].cs__freeze # KNOWN_ERRORS = %w[ # ActiveModel Error Errors Resolv Rspec ActiveRecord nil NilClass NoMemoryError ScriptError # LoadError NotImplementedError SyntaxError SecurityError SignalException Interrupt # StandardError ArgumentError UncaughtThrowError FiberError IOError EOFError IndexError KeyError # StopIteration LocalJumpError NameError NoMethodError RangeError FloatDomainError RegexpError # RuntimeError FrozenError SystemCallError ThreadError TypeError ZeroDivisionError SystemExit # SystemStackError fatal Warning buffer OpenSSL SSL SSLError Errno Timeout Exception EOFError # ECONNRESET ECONNREFUSED ETIMEDOUT EINVAL ESHUTDOWN EHOSTDOWN EHOSTUNREACH EISCONN # ECONNABORTED ENETRESET ENETUNREACH Net HTTPBadResponse HTTPHeaderSyntaxError ProtocolError # Faraday BadRequestError UnauthorizedError ForbiddenError ResourceNotFound ProxyAuthError # ConflictError UnprocessableEntityError ClientError # ].cs__freeze # CHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'.cs__freeze # # This will generate different chars for each agent startup but will be constant # # for current run and will make identical obfuscation to be compared if given type # # is the same. # CYPHER = CHARS.chars.shuffle.join # # class << self # # Returns paths for known gems. # # # # @return [Array] known paths # def known_gem_paths # @_known_gem_paths ||= KNOWN_GEMS.map do |gem_name| # to_regexp(File.join( # 'gems', gem_name.tr('-', ''), 'lib')) # end # end # # # Returns known modules names. # # # # @return [Array] known modules # def known_modules # @_known_modules ||= KNOWN_ERRORS.map { |module_name| to_regexp(module_name) } # end # # # Obfuscate a type and replace it with random characters. # # # # @param type [String] the StackFrame type to obfuscate # # @return [String] obfuscated type # def obfuscate_type type # return unless type # # check = type.tr('[^0-9].-', '') # type = cypher(type) unless match_known(known_gem_paths, check) # type # end # # # Obfuscate a type and replace it with random characters. # # # # @param exception_type [String] the exception type to obfuscate # # @return [String] obfuscated exception type # def obfuscate_exception_type exception_type # return unless exception_type # # exceptions = exception_type.split('::').each do |exception| # cypher(exception) unless match_known(known_modules, exception) # end # exceptions.join('::') # end # # private # # # Transforms string to regexp # # # # @param string [String] # def to_regexp string # /#{ string }/ # end # # # Add cypher to path to make it obscure, but unique enough for # # comparisons. Mutates original or duplicate if frozen string. # # # # @param string [String] string to be transformed. # def cypher string # string = string.dup if string.cs__frozen? # string.to_s.tr!(CHARS, CYPHER) # end # # # @param known [Array] Array of regexp to match against # # @param type [String] type to check # def match_known known, type # known.any? { |regexp| type =~ regexp } # end # end end end end end end