# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details. # frozen_string_literal: true require 'contrast/components/logger' module Contrast module Agent # This class is responsible for holding our ruleset and performing filtering operations on all # rules when asked by the middleware. class RuleSet < Set include Contrast::Components::Logger::InstanceMethods # The filtering that needs to happen before the application gets access to the request object. # The main action here is snapshotting the request as provided to the application from the # user before any application code has acted upon it. Additionally, this is where Protect will # terminate requests on attack detection if set to block at perimeter # # @raise [Contrast::SecurityException] raises error if security exception is thrown in prefilter def prefilter context = Contrast::Agent::REQUEST_TRACKER.current return unless context&.analyze_request? logger.trace_with_time('Running prefilter...') do map { |rule| rule.prefilter(context) } end rescue Contrast::SecurityException => e logger.warn('RASP threw security exception in prefilter', e) raise(e) rescue StandardError => e logger.error('Unexpected exception during prefilter', e) end # The filtering that needs occur after the application has acted on the request and the response # has been created. The main actions here are analyzing the response for unsafe state or actions. # # @raise [Contrast::SecurityException] raises error if security exception is thrown in postfilter def postfilter context = Contrast::Agent::REQUEST_TRACKER.current return unless context&.analyze_response? logger.trace_with_time('Running postfilter...') do map { |rule| rule.postfilter(context) } end rescue Contrast::SecurityException => e logger.warn('RASP threw security exception in postfilter', e) raise(e) rescue StandardError => e logger.error('Unexpected exception during postfilter', e) end end end end