Class: Contrast::Agent::Assess::Policy::PropagationNode
- Inherits:
-
PolicyNode
- Object
- Patching::Policy::PolicyNode
- PolicyNode
- Contrast::Agent::Assess::Policy::PropagationNode
- Includes:
- Components::Logger::InstanceMethods
- Defined in:
- lib/contrast/agent/assess/policy/propagation_node.rb
Overview
This class functions to translate our policy.json into an actionable Ruby object, allowing for dynamic patching over hardcoded patching, specifically for those methods which result in the transformation of untrusted data (indicate points in the application where user controlled input is modified).
Constant Summary collapse
- JSON_ACTION =
'action'
- JSON_UNTAGS =
'untags'
- JSON_PATCH_CLASS =
'patch_class'
- JSON_PATCH_METHOD =
'patch_method'
- TAGGER =
'Tagger'
- PROPAGATOR =
'Propagator'
Constants inherited from PolicyNode
Contrast::Agent::Assess::Policy::PolicyNode::ALL_TYPE, Contrast::Agent::Assess::Policy::PolicyNode::JSON_DATAFLOW, Contrast::Agent::Assess::Policy::PolicyNode::JSON_SOURCE, Contrast::Agent::Assess::Policy::PolicyNode::JSON_TAGS, Contrast::Agent::Assess::Policy::PolicyNode::JSON_TARGET, Contrast::Agent::Assess::Policy::PolicyNode::ORIGINAL_OBJECT_METHODS, Contrast::Agent::Assess::Policy::PolicyNode::RESPONSE_SOURCES, Contrast::Agent::Assess::Policy::PolicyNode::TO_MARKER, Contrast::Agent::Assess::Policy::PolicyNode::TO_S
Constants inherited from Patching::Policy::PolicyNode
Patching::Policy::PolicyNode::JSON_CLASS_NAME, Patching::Policy::PolicyNode::JSON_INSTANCE_METHOD, Patching::Policy::PolicyNode::JSON_METHOD_NAME, Patching::Policy::PolicyNode::JSON_METHOD_SCOPE, Patching::Policy::PolicyNode::JSON_METHOD_VISIBILITY, Patching::Policy::PolicyNode::JSON_PROPERTIES
Instance Attribute Summary collapse
-
#action ⇒ Object
readonly
Returns the value of attribute action.
-
#patch_class ⇒ Object
Returns the value of attribute patch_class.
-
#patch_method ⇒ Object
readonly
Returns the value of attribute patch_method.
-
#untags ⇒ Object
readonly
Returns the value of attribute untags.
Attributes inherited from PolicyNode
#source_string, #sources, #tags, #target_string, #targets, #type
Attributes inherited from Patching::Policy::PolicyNode
#class_name, #instance_method, #method_name, #method_scope, #method_visibility, #properties
Instance Method Summary collapse
-
#initialize(propagation_hash = {}) ⇒ PropagationNode
constructor
Most things here carry over from PolicyNode.
- #needs_args? ⇒ Boolean
- #needs_object? ⇒ Boolean
- #node_class ⇒ Object
-
#node_type ⇒ Object
Unlike the other agents, we don’t have separate tag & propagation events.
-
#tagger? ⇒ Boolean
This is a tagger if it has a tag or an untag.
-
#validate ⇒ Object
Standard validation + TS trace version two rules: Must have source, target, and action @raise raises if any of the required propagation node field is not valid, or is missing.
-
#validate_untags ⇒ Object
@raise raises if any of the tags is invalid.
Methods included from Components::Logger::InstanceMethods
Methods inherited from PolicyNode
#add_property, #assign_on_bang_check, #build_action, #feature, #get_property, #response_source_node?, #use_original_object?, #use_original_on_bang_method?, #use_response_as_source?, #validate_tags
Methods inherited from Patching::Policy::PolicyNode
#feature, #id, #instance_method?
Methods included from Components::Scope::InstanceMethods
#contrast_enter_method_scopes!, #contrast_exit_method_scopes!, #with_app_scope, #with_contrast_scope, #with_deserialization_scope, #with_split_scope
Constructor Details
#initialize(propagation_hash = {}) ⇒ PropagationNode
Most things here carry over from PolicyNode. A couple things are new / have new rules
Source - from where the tainted data flows, cannot be nil Target - to where the tainted data flows, cannot be nil Action - how the tainted data flows from source to target, should not be nil Tags - array of tags to apply to the target, can be nil if no tags are added Untags - array of tags to remove from the target, can be nil if not tags are removed id, class_name, instance_method, method_name, source, target, action, tags = nil, untags = nil
39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/contrast/agent/assess/policy/propagation_node.rb', line 39 def initialize propagation_hash = {} super(propagation_hash) @action = propagation_hash[JSON_ACTION] @untags = Set.new(propagation_hash[JSON_UNTAGS]) @patch_class = propagation_hash[JSON_PATCH_CLASS] @patch_method = propagation_hash[JSON_PATCH_METHOD] @patch_method = @patch_method.to_sym if @patch_method validate rescue ArgumentError => e logger.error('Propagation Node Initialization failed with: ', e) nil end |
Instance Attribute Details
#action ⇒ Object (readonly)
Returns the value of attribute action.
25 26 27 |
# File 'lib/contrast/agent/assess/policy/propagation_node.rb', line 25 def action @action end |
#patch_class ⇒ Object
Returns the value of attribute patch_class.
26 27 28 |
# File 'lib/contrast/agent/assess/policy/propagation_node.rb', line 26 def patch_class @patch_class end |
#patch_method ⇒ Object (readonly)
Returns the value of attribute patch_method.
25 26 27 |
# File 'lib/contrast/agent/assess/policy/propagation_node.rb', line 25 def patch_method @patch_method end |
#untags ⇒ Object (readonly)
Returns the value of attribute untags.
25 26 27 |
# File 'lib/contrast/agent/assess/policy/propagation_node.rb', line 25 def @untags end |
Instance Method Details
#needs_args? ⇒ Boolean
113 114 115 116 117 118 119 120 121 |
# File 'lib/contrast/agent/assess/policy/propagation_node.rb', line 113 def needs_args? if @_needs_args.nil? @_needs_args = action == Contrast::Utils::Assess::PropagationMethodUtils::CUSTOM_ACTION || action == Contrast::Utils::Assess::PropagationMethodUtils::DB_WRITE_ACTION || sources.any? { |source| source.is_a?(Integer) || source.is_a?(Symbol) } || targets.any? { |target| target.is_a?(Integer) || target.is_a?(Symbol) } end @_needs_args end |
#needs_object? ⇒ Boolean
103 104 105 106 107 108 109 110 111 |
# File 'lib/contrast/agent/assess/policy/propagation_node.rb', line 103 def needs_object? if @_needs_object.nil? @_needs_object = action == Contrast::Utils::Assess::PropagationMethodUtils::CUSTOM_ACTION || action == Contrast::Utils::Assess::PropagationMethodUtils::DB_WRITE_ACTION || sources.any?(Contrast::Utils::ObjectShare::OBJECT_KEY) || targets.any?(Contrast::Utils::ObjectShare::OBJECT_KEY) end @_needs_object end |
#node_class ⇒ Object
52 53 54 |
# File 'lib/contrast/agent/assess/policy/propagation_node.rb', line 52 def node_class @_node_class ||= tagger? ? TAGGER : PROPAGATOR end |
#node_type ⇒ Object
Unlike the other agents, we don’t have separate tag & propagation events. To make TS happy, we need to have different types though. Pretty straight forward: if there’s a tag, this is a tagger
59 60 61 |
# File 'lib/contrast/agent/assess/policy/propagation_node.rb', line 59 def node_type tagger? ? :TYPE_TAG : :TYPE_PROPAGATION end |
#tagger? ⇒ Boolean
This is a tagger if it has a tag or an untag. It indicates this method is more than just a transformation, it is an interesting security event that has a meaningful change.
127 128 129 130 |
# File 'lib/contrast/agent/assess/policy/propagation_node.rb', line 127 def tagger? @_tagger = &.any? || &.any? if @_tagger.nil? @_tagger end |
#validate ⇒ Object
Standard validation + TS trace version two rules: Must have source, target, and action @raise raises if any of the required propagation node field is not valid, or is missing
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/contrast/agent/assess/policy/propagation_node.rb', line 66 def validate super raise(ArgumentError, "Propagator #{ id } did not have a proper action. Unable to create.") unless action if @action == 'CUSTOM' unless patch_class raise(ArgumentError, "Propagator #{ id } did not have a proper patch_class. Unable to create.") end unless patch_method.is_a?(Symbol) raise(ArgumentError, "Propagator #{ id } did not have a proper patch_method. Unable to create.") end else unless targets&.any? raise(ArgumentError, "Propagator #{ id } did not have a proper target. Unable to create.") end unless sources&.any? raise(ArgumentError, "Propagator #{ id } did not have a proper source. Unable to create.") end end end |
#validate_untags ⇒ Object
@raise raises if any of the tags is invalid
89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/contrast/agent/assess/policy/propagation_node.rb', line 89 def return unless .each do |tag| unless Contrast::Agent::Reporting::FindingEventTaintRangeTags::VALID_TAGS.include?(tag) raise(ArgumentError, "#{ node_type } #{ id } did not have a valid untag. #{ tag } is not a known value.") end if &.include?(tag) raise(ArgumentError, "#{ node_type } #{ id } had the same tag and untag, #{ tag }.") end end end |