contrast-agent 3.13.0 → 3.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (241) hide show
  1. checksums.yaml +4 -4
  2. data/exe/contrast_service +1 -7
  3. data/ext/cs__assess_active_record_named/cs__active_record_named.c +8 -7
  4. data/ext/cs__assess_array/cs__assess_array.c +6 -5
  5. data/ext/cs__assess_basic_object/cs__assess_basic_object.c +5 -5
  6. data/ext/cs__assess_fiber_track/cs__assess_fiber_track.c +2 -1
  7. data/ext/cs__assess_hash/cs__assess_hash.c +18 -17
  8. data/ext/cs__assess_hash/cs__assess_hash.h +2 -1
  9. data/ext/cs__assess_kernel/cs__assess_kernel.c +7 -8
  10. data/ext/cs__assess_marshal_module/cs__assess_marshal_module.c +18 -16
  11. data/ext/cs__assess_marshal_module/cs__assess_marshal_module.h +1 -0
  12. data/ext/cs__assess_module/cs__assess_module.c +6 -6
  13. data/ext/cs__assess_regexp/cs__assess_regexp.c +4 -4
  14. data/ext/cs__assess_string/cs__assess_string.c +31 -16
  15. data/ext/cs__assess_string/cs__assess_string.h +6 -1
  16. data/ext/cs__assess_string_interpolation26/cs__assess_string_interpolation26.c +4 -2
  17. data/ext/cs__assess_yield_track/cs__assess_yield_track.c +2 -2
  18. data/ext/cs__common/cs__common.c +48 -39
  19. data/ext/cs__common/cs__common.h +16 -21
  20. data/ext/cs__contrast_patch/cs__contrast_patch.c +27 -25
  21. data/ext/cs__contrast_patch/cs__contrast_patch.h +5 -7
  22. data/ext/cs__protect_kernel/cs__protect_kernel.c +11 -12
  23. data/ext/cs__protect_kernel/cs__protect_kernel.h +2 -2
  24. data/lib/contrast-agent.rb +1 -1
  25. data/lib/contrast.rb +13 -23
  26. data/lib/contrast/agent.rb +39 -46
  27. data/lib/contrast/agent/assess.rb +12 -12
  28. data/lib/contrast/agent/assess/contrast_event.rb +151 -85
  29. data/lib/contrast/agent/assess/events/event_factory.rb +2 -2
  30. data/lib/contrast/agent/assess/events/source_event.rb +3 -3
  31. data/lib/contrast/agent/assess/finalizers/freeze.rb +15 -0
  32. data/lib/contrast/agent/assess/finalizers/hash.rb +97 -0
  33. data/lib/contrast/agent/assess/policy/dynamic_source_factory.rb +11 -4
  34. data/lib/contrast/agent/assess/policy/patcher.rb +6 -6
  35. data/lib/contrast/agent/assess/policy/policy.rb +9 -11
  36. data/lib/contrast/agent/assess/policy/policy_node.rb +17 -12
  37. data/lib/contrast/agent/assess/policy/policy_scanner.rb +9 -4
  38. data/lib/contrast/agent/assess/policy/preshift.rb +13 -7
  39. data/lib/contrast/agent/assess/policy/propagation_method.rb +64 -44
  40. data/lib/contrast/agent/assess/policy/propagation_node.rb +2 -2
  41. data/lib/contrast/agent/assess/policy/propagator.rb +18 -18
  42. data/lib/contrast/agent/assess/policy/propagator/append.rb +8 -5
  43. data/lib/contrast/agent/assess/policy/propagator/base.rb +1 -1
  44. data/lib/contrast/agent/assess/policy/propagator/center.rb +9 -5
  45. data/lib/contrast/agent/assess/policy/propagator/custom.rb +1 -1
  46. data/lib/contrast/agent/assess/policy/propagator/database_write.rb +6 -4
  47. data/lib/contrast/agent/assess/policy/propagator/insert.rb +7 -4
  48. data/lib/contrast/agent/assess/policy/propagator/keep.rb +4 -1
  49. data/lib/contrast/agent/assess/policy/propagator/match_data.rb +7 -9
  50. data/lib/contrast/agent/assess/policy/propagator/next.rb +7 -5
  51. data/lib/contrast/agent/assess/policy/propagator/prepend.rb +13 -5
  52. data/lib/contrast/agent/assess/policy/propagator/remove.rb +8 -4
  53. data/lib/contrast/agent/assess/policy/propagator/replace.rb +5 -2
  54. data/lib/contrast/agent/assess/policy/propagator/reverse.rb +7 -5
  55. data/lib/contrast/agent/assess/policy/propagator/select.rb +13 -7
  56. data/lib/contrast/agent/assess/policy/propagator/splat.rb +10 -9
  57. data/lib/contrast/agent/assess/policy/propagator/split.rb +27 -22
  58. data/lib/contrast/agent/assess/policy/propagator/substitution.rb +52 -35
  59. data/lib/contrast/agent/assess/policy/propagator/trim.rb +11 -5
  60. data/lib/contrast/agent/assess/policy/rewriter_patch.rb +5 -5
  61. data/lib/contrast/agent/assess/policy/source_method.rb +90 -72
  62. data/lib/contrast/agent/assess/policy/source_validation/cross_site_validator.rb +1 -1
  63. data/lib/contrast/agent/assess/policy/source_validation/source_validation.rb +1 -1
  64. data/lib/contrast/agent/assess/policy/trigger/reflected_xss.rb +16 -12
  65. data/lib/contrast/agent/assess/policy/trigger/xpath.rb +2 -2
  66. data/lib/contrast/agent/assess/policy/trigger_method.rb +81 -33
  67. data/lib/contrast/agent/assess/policy/trigger_node.rb +41 -46
  68. data/lib/contrast/agent/assess/policy/trigger_validation/ssrf_validator.rb +2 -1
  69. data/lib/contrast/agent/assess/policy/trigger_validation/trigger_validation.rb +2 -2
  70. data/lib/contrast/agent/assess/properties.rb +15 -5
  71. data/lib/contrast/agent/assess/property/evented.rb +7 -20
  72. data/lib/contrast/agent/assess/property/tagged.rb +13 -7
  73. data/lib/contrast/agent/assess/property/updated.rb +131 -0
  74. data/lib/contrast/agent/assess/rule.rb +2 -2
  75. data/lib/contrast/agent/assess/rule/base.rb +3 -4
  76. data/lib/contrast/agent/assess/rule/provider.rb +3 -3
  77. data/lib/contrast/agent/assess/rule/provider/hardcoded_key.rb +58 -5
  78. data/lib/contrast/agent/assess/rule/provider/hardcoded_password.rb +24 -9
  79. data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +84 -16
  80. data/lib/contrast/agent/assess/tag.rb +1 -1
  81. data/lib/contrast/agent/assess/tracker.rb +66 -0
  82. data/lib/contrast/agent/at_exit_hook.rb +6 -6
  83. data/lib/contrast/agent/class_reopener.rb +14 -11
  84. data/lib/contrast/agent/deadzone/policy/deadzone_node.rb +1 -1
  85. data/lib/contrast/agent/deadzone/policy/policy.rb +2 -2
  86. data/lib/contrast/agent/disable_reaction.rb +1 -1
  87. data/lib/contrast/agent/exclusion_matcher.rb +1 -1
  88. data/lib/contrast/agent/inventory/policy/datastores.rb +2 -2
  89. data/lib/contrast/agent/inventory/policy/policy.rb +3 -3
  90. data/lib/contrast/agent/inventory/policy/trigger_node.rb +1 -1
  91. data/lib/contrast/agent/middleware.rb +32 -32
  92. data/lib/contrast/agent/patching/policy/after_load_patch.rb +9 -9
  93. data/lib/contrast/agent/patching/policy/after_load_patcher.rb +23 -22
  94. data/lib/contrast/agent/patching/policy/module_policy.rb +11 -11
  95. data/lib/contrast/agent/patching/policy/patch.rb +15 -15
  96. data/lib/contrast/agent/patching/policy/patcher.rb +43 -44
  97. data/lib/contrast/agent/patching/policy/policy.rb +23 -12
  98. data/lib/contrast/agent/patching/policy/policy_node.rb +1 -1
  99. data/lib/contrast/agent/patching/policy/trigger_node.rb +2 -2
  100. data/lib/contrast/agent/protect/policy/applies_command_injection_rule.rb +6 -8
  101. data/lib/contrast/agent/protect/policy/applies_deserialization_rule.rb +2 -2
  102. data/lib/contrast/agent/protect/policy/applies_no_sqli_rule.rb +2 -2
  103. data/lib/contrast/agent/protect/policy/applies_path_traversal_rule.rb +3 -3
  104. data/lib/contrast/agent/protect/policy/applies_sqli_rule.rb +2 -2
  105. data/lib/contrast/agent/protect/policy/applies_xxe_rule.rb +4 -4
  106. data/lib/contrast/agent/protect/policy/policy.rb +8 -8
  107. data/lib/contrast/agent/protect/policy/rule_applicator.rb +1 -1
  108. data/lib/contrast/agent/protect/policy/trigger_node.rb +1 -1
  109. data/lib/contrast/agent/protect/rule.rb +18 -18
  110. data/lib/contrast/agent/protect/rule/base.rb +4 -3
  111. data/lib/contrast/agent/protect/rule/base_service.rb +1 -1
  112. data/lib/contrast/agent/protect/rule/cmd_injection.rb +5 -5
  113. data/lib/contrast/agent/protect/rule/deserialization.rb +1 -1
  114. data/lib/contrast/agent/protect/rule/http_method_tampering.rb +1 -1
  115. data/lib/contrast/agent/protect/rule/no_sqli.rb +1 -1
  116. data/lib/contrast/agent/protect/rule/no_sqli/mongo_no_sql_scanner.rb +1 -0
  117. data/lib/contrast/agent/protect/rule/path_traversal.rb +4 -5
  118. data/lib/contrast/agent/protect/rule/sqli.rb +2 -2
  119. data/lib/contrast/agent/protect/rule/unsafe_file_upload.rb +1 -1
  120. data/lib/contrast/agent/protect/rule/xss.rb +1 -1
  121. data/lib/contrast/agent/protect/rule/xxe.rb +3 -5
  122. data/lib/contrast/agent/protect/rule/xxe/entity_wrapper.rb +2 -2
  123. data/lib/contrast/agent/railtie.rb +1 -1
  124. data/lib/contrast/agent/reaction_processor.rb +2 -2
  125. data/lib/contrast/agent/request.rb +45 -43
  126. data/lib/contrast/agent/request_context.rb +10 -6
  127. data/lib/contrast/agent/response.rb +23 -12
  128. data/lib/contrast/agent/rewriter.rb +6 -9
  129. data/lib/contrast/agent/service_heartbeat.rb +2 -2
  130. data/lib/contrast/agent/static_analysis.rb +9 -9
  131. data/lib/contrast/agent/thread.rb +1 -1
  132. data/lib/contrast/agent/thread_watcher.rb +2 -2
  133. data/lib/contrast/agent/tracepoint_hook.rb +1 -1
  134. data/lib/contrast/agent/version.rb +1 -1
  135. data/lib/contrast/api.rb +4 -4
  136. data/lib/contrast/api/communication.rb +9 -9
  137. data/lib/contrast/api/communication/messaging_queue.rb +3 -6
  138. data/lib/contrast/api/communication/response_processor.rb +1 -1
  139. data/lib/contrast/api/communication/socket_client.rb +41 -6
  140. data/lib/contrast/api/communication/speedracer.rb +1 -1
  141. data/lib/contrast/api/communication/tcp_socket.rb +1 -1
  142. data/lib/contrast/api/communication/unix_socket.rb +1 -1
  143. data/lib/contrast/api/decorators.rb +14 -14
  144. data/lib/contrast/api/decorators/address.rb +20 -19
  145. data/lib/contrast/api/decorators/application_settings.rb +3 -2
  146. data/lib/contrast/api/decorators/application_update.rb +7 -8
  147. data/lib/contrast/api/decorators/http_request.rb +13 -12
  148. data/lib/contrast/api/decorators/input_analysis.rb +3 -2
  149. data/lib/contrast/api/decorators/message.rb +4 -2
  150. data/lib/contrast/api/decorators/rasp_rule_sample.rb +2 -1
  151. data/lib/contrast/api/decorators/route_coverage.rb +3 -2
  152. data/lib/contrast/api/decorators/server_features.rb +3 -2
  153. data/lib/contrast/api/decorators/trace_event.rb +28 -25
  154. data/lib/contrast/api/decorators/trace_event_object.rb +6 -5
  155. data/lib/contrast/api/decorators/trace_event_signature.rb +5 -4
  156. data/lib/contrast/api/decorators/trace_taint_range.rb +4 -3
  157. data/lib/contrast/api/decorators/user_input.rb +4 -4
  158. data/lib/contrast/common_agent_configuration.rb +2 -2
  159. data/lib/contrast/components/agent.rb +2 -2
  160. data/lib/contrast/components/app_context.rb +50 -39
  161. data/lib/contrast/components/config.rb +7 -17
  162. data/lib/contrast/components/contrast_service.rb +10 -10
  163. data/lib/contrast/components/interface.rb +15 -15
  164. data/lib/contrast/components/logger.rb +1 -1
  165. data/lib/contrast/components/scope.rb +3 -3
  166. data/lib/contrast/components/settings.rb +20 -23
  167. data/lib/contrast/config.rb +18 -18
  168. data/lib/contrast/config/application_configuration.rb +5 -2
  169. data/lib/contrast/config/base_configuration.rb +2 -2
  170. data/lib/contrast/config/protect_rule_configuration.rb +1 -1
  171. data/lib/contrast/config/service_configuration.rb +8 -0
  172. data/lib/contrast/configuration.rb +93 -52
  173. data/lib/contrast/extension/assess.rb +21 -22
  174. data/lib/contrast/extension/assess/array.rb +18 -11
  175. data/lib/contrast/extension/assess/erb.rb +11 -3
  176. data/lib/contrast/extension/assess/eval_trigger.rb +7 -7
  177. data/lib/contrast/extension/assess/exec_trigger.rb +2 -2
  178. data/lib/contrast/extension/assess/fiber.rb +14 -14
  179. data/lib/contrast/extension/assess/hash.rb +7 -6
  180. data/lib/contrast/extension/assess/kernel.rb +34 -28
  181. data/lib/contrast/extension/assess/marshal.rb +67 -0
  182. data/lib/contrast/extension/assess/regexp.rb +10 -9
  183. data/lib/contrast/extension/assess/string.rb +23 -23
  184. data/lib/contrast/extension/inventory.rb +4 -4
  185. data/lib/contrast/extension/kernel.rb +1 -1
  186. data/lib/contrast/extension/module.rb +1 -1
  187. data/lib/contrast/extension/protect.rb +3 -3
  188. data/lib/contrast/extension/protect/kernel.rb +4 -4
  189. data/lib/contrast/extension/protect/psych.rb +2 -2
  190. data/lib/contrast/framework/base_support.rb +1 -1
  191. data/lib/contrast/framework/manager.rb +10 -11
  192. data/lib/contrast/framework/rack/patch/session_cookie.rb +22 -28
  193. data/lib/contrast/framework/rack/patch/support.rb +1 -1
  194. data/lib/contrast/framework/rack/support.rb +2 -2
  195. data/lib/contrast/framework/rails/patch/action_controller_live_buffer.rb +13 -13
  196. data/lib/contrast/framework/rails/patch/assess_configuration.rb +6 -12
  197. data/lib/contrast/framework/rails/patch/rails_application_configuration.rb +11 -11
  198. data/lib/contrast/framework/rails/patch/support.rb +4 -4
  199. data/lib/contrast/framework/rails/rewrite/action_controller_railties_helper_inherited.rb +11 -11
  200. data/lib/contrast/framework/rails/rewrite/active_record_attribute_methods_read.rb +12 -12
  201. data/lib/contrast/framework/rails/rewrite/active_record_named.rb +4 -4
  202. data/lib/contrast/framework/rails/rewrite/active_record_time_zone_inherited.rb +12 -12
  203. data/lib/contrast/framework/rails/support.rb +64 -14
  204. data/lib/contrast/framework/sinatra/patch/base.rb +12 -12
  205. data/lib/contrast/framework/sinatra/patch/support.rb +1 -1
  206. data/lib/contrast/framework/sinatra/support.rb +6 -6
  207. data/lib/contrast/funchook/funchook.rb +1 -1
  208. data/lib/contrast/logger/application.rb +13 -5
  209. data/lib/contrast/logger/format.rb +22 -9
  210. data/lib/contrast/logger/log.rb +17 -10
  211. data/lib/contrast/logger/request.rb +30 -0
  212. data/lib/contrast/tasks/config.rb +1 -1
  213. data/lib/contrast/tasks/service.rb +2 -2
  214. data/lib/contrast/utils/assess/sampling_util.rb +2 -2
  215. data/lib/contrast/utils/assess/tracking_util.rb +49 -4
  216. data/lib/contrast/utils/boolean_util.rb +1 -1
  217. data/lib/contrast/utils/class_util.rb +2 -2
  218. data/lib/contrast/utils/duck_utils.rb +0 -10
  219. data/lib/contrast/utils/env_configuration_item.rb +2 -1
  220. data/lib/contrast/utils/gemfile_reader.rb +5 -5
  221. data/lib/contrast/utils/hash_digest.rb +2 -1
  222. data/lib/contrast/utils/heap_dump_util.rb +2 -2
  223. data/lib/contrast/utils/invalid_configuration_util.rb +21 -22
  224. data/lib/contrast/utils/inventory_util.rb +4 -4
  225. data/lib/contrast/utils/io_util.rb +1 -1
  226. data/lib/contrast/utils/os.rb +1 -1
  227. data/lib/contrast/utils/ruby_ast_rewriter.rb +1 -1
  228. data/lib/contrast/utils/sha256_builder.rb +2 -2
  229. data/lib/contrast/utils/stack_trace_utils.rb +2 -2
  230. data/lib/contrast/utils/string_utils.rb +11 -6
  231. data/resources/assess/policy.json +31 -22
  232. data/resources/deadzone/policy.json +5 -0
  233. data/ruby-agent.gemspec +21 -19
  234. data/service_executables/VERSION +1 -1
  235. data/service_executables/linux/contrast-service +0 -0
  236. data/service_executables/mac/contrast-service +0 -0
  237. metadata +67 -29
  238. data/lib/contrast/agent/assess/insulator.rb +0 -49
  239. data/lib/contrast/agent/require_state.rb +0 -61
  240. data/lib/contrast/extension/assess/assess_extension.rb +0 -147
  241. data/lib/contrast/utils/freeze_util.rb +0 -32
@@ -38,7 +38,8 @@ module Contrast
38
38
  finish = match.begin(:path)
39
39
  finish ||= url.length
40
40
 
41
- args[0].cs__properties.any_tags_between?(start, finish)
41
+ properties = Contrast::Agent::Assess::Tracker.properties(args[0])
42
+ properties.any_tags_between?(start, finish)
42
43
  end
43
44
  end
44
45
  end
@@ -1,8 +1,8 @@
1
1
  # Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
- cs__scoped_require 'contrast/agent/assess/policy/trigger_validation/ssrf_validator'
5
- cs__scoped_require 'contrast/agent/assess/policy/trigger_validation/xss_validator'
4
+ require 'contrast/agent/assess/policy/trigger_validation/ssrf_validator'
5
+ require 'contrast/agent/assess/policy/trigger_validation/xss_validator'
6
6
 
7
7
  module Contrast
8
8
  module Agent
@@ -1,11 +1,12 @@
1
1
  # Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
- cs__scoped_require 'set'
5
- cs__scoped_require 'base64'
6
- cs__scoped_require 'contrast/utils/prevent_serialization'
7
- cs__scoped_require 'contrast/agent/assess/property/evented'
8
- cs__scoped_require 'contrast/agent/assess/property/tagged'
4
+ require 'base64'
5
+ require 'set'
6
+ require 'contrast/agent/assess/property/evented'
7
+ require 'contrast/agent/assess/property/tagged'
8
+ require 'contrast/agent/assess/property/updated'
9
+ require 'contrast/utils/prevent_serialization'
9
10
 
10
11
  module Contrast
11
12
  module Agent
@@ -20,6 +21,9 @@ module Contrast
20
21
  include Contrast::Utils::PreventSerialization
21
22
  include Contrast::Agent::Assess::Property::Evented
22
23
  include Contrast::Agent::Assess::Property::Tagged
24
+ include Contrast::Agent::Assess::Property::Updated
25
+
26
+ attr_accessor :dupped_from
23
27
 
24
28
  # CONTRAST-36937
25
29
  # Creating these on Properties is expensive. We want to delay this for
@@ -39,6 +43,12 @@ module Contrast
39
43
 
40
44
  properties[name] = value
41
45
  end
46
+
47
+ def dup
48
+ ret = super
49
+ ret.dupped_from = __id__
50
+ ret
51
+ end
42
52
  end
43
53
  end
44
54
  end
@@ -1,8 +1,8 @@
1
1
  # Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
- cs__scoped_require 'contrast/agent/assess/events/event_factory'
5
- cs__scoped_require 'contrast/agent/assess/events/source_event'
4
+ require 'contrast/agent/assess/events/event_factory'
5
+ require 'contrast/agent/assess/events/source_event'
6
6
 
7
7
  module Contrast
8
8
  module Agent
@@ -10,23 +10,11 @@ module Contrast
10
10
  module Property
11
11
  # This module serves to hold the functionality required for the
12
12
  # management of our dataflow events.
13
+ #
14
+ # @attr_reader event [Contrast::Agent::Assess::ContrastEvent] the
15
+ # latest event to track
13
16
  module Evented
14
- # The events for this object.
15
- #
16
- # @return [Array<Contrast::Agent::Assess::ContrastEvent>]
17
- def events
18
- @_events ||= []
19
- end
20
-
21
- # Add an event to these properties. It will be used to build
22
- # a trace if this object ends up in a trigger.
23
- #
24
- # @param event [Contrast::Agent::Assess::ContrastEvent] the latest
25
- # event to track
26
- def add_event event
27
- events << event
28
- self
29
- end
17
+ attr_accessor :event
30
18
 
31
19
  # Create a new event and add it to the event set.
32
20
  #
@@ -43,8 +31,7 @@ module Contrast
43
31
  # the key used to accessed if from a map or nil if a type like
44
32
  # BODY
45
33
  def build_event policy_node, tagged, object, ret, args, source_type = nil, source_name = nil
46
- event = Contrast::Agent::Assess::Events::EventFactory.build(policy_node, tagged, object, ret, args, source_type, source_name)
47
- add_event(event)
34
+ @event = Contrast::Agent::Assess::Events::EventFactory.build(policy_node, tagged, object, ret, args, source_type, source_name)
48
35
  report_sources(tagged, event)
49
36
  end
50
37
 
@@ -1,10 +1,10 @@
1
1
  # Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
- cs__scoped_require 'contrast/agent/assess/tag'
5
- cs__scoped_require 'contrast/utils/object_share'
6
- cs__scoped_require 'contrast/utils/string_utils'
7
- cs__scoped_require 'contrast/utils/tag_util'
4
+ require 'contrast/agent/assess/tag'
5
+ require 'contrast/utils/object_share'
6
+ require 'contrast/utils/string_utils'
7
+ require 'contrast/utils/tag_util'
8
8
 
9
9
  module Contrast
10
10
  module Agent
@@ -162,15 +162,21 @@ module Contrast
162
162
  end
163
163
 
164
164
  # We'll use this as a helper method to retrieve tags from the hash.
165
- # Because the hash auto-populates an empty array when we try to access
166
- # a tag in it, we cannot use the [] method without side effect. To get
167
- # around this, we'll use a fetch work around.
165
+ # Because the hash auto-populates an empty array when we try to
166
+ # access a tag in it, we cannot use the [] method without side
167
+ # effect. To get around this, we'll use a fetch work around.
168
+ #
169
+ # @param label [Symbol] the label to look up
170
+ # @return [Array<Contrast::Agent::Assess::Tag>] all the tags with
171
+ # that label
168
172
  def fetch_tag label
169
173
  tags.fetch(label, nil) if tracked?
170
174
  end
171
175
 
172
176
  # Convert the tags of this object into the TraceTaintRange required
173
177
  # to be sent to the service
178
+ #
179
+ # @return [Array<Contrast::Api::Dtm::TraceTaintRange>]
174
180
  def tags_to_dtm
175
181
  Contrast::Api::Dtm::TraceTaintRange.build_for_event(tags)
176
182
  end
@@ -0,0 +1,131 @@
1
+ # Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
+ # frozen_string_literal: true
3
+
4
+ require 'contrast/utils/duck_utils'
5
+
6
+ module Contrast
7
+ module Agent
8
+ module Assess
9
+ module Property
10
+ # This module serves to hold the functionality required for the
11
+ # update of properties as they go through dataflow.
12
+ module Updated
13
+ # copy tags and info from source's properties to self
14
+ # @param source [Object] the object from which existing properties
15
+ # should be copied.
16
+ # @param owner [Object] the object to which these properties apply.
17
+ # @param shift [Integer] (0) how far to shift the tags during copy,
18
+ # useful for insert and append operations.
19
+ # @param skip_tags [Set<String>] (nil) the tags to not copy over,
20
+ # useful for propagation events that have 'untags'.
21
+ def copy_from source, owner, shift = 0, skip_tags = nil
22
+ return if owner.equal?(source)
23
+ return unless Contrast::Agent::Assess::Tracker.tracked?(source)
24
+
25
+ original = Contrast::Agent::Assess::Tracker.properties(source)
26
+ return unless original
27
+
28
+ adjust_duplicate(original)
29
+ original.tag_keys.each do |key|
30
+ next if skip_tags&.include?(key)
31
+
32
+ existing = tags[key]
33
+ had_existing = existing.any?
34
+ value = original.fetch_tag(key)
35
+ value.each do |tag|
36
+ existing << tag.copy_modified(shift)
37
+ end
38
+ Contrast::Utils::TagUtil.size_aware_merge(owner, existing) if had_existing
39
+ end
40
+ end
41
+
42
+ # Some propagation occurred, but we're not sure what the
43
+ # exact transformation was. To be safe, we just explode
44
+ # all the tags from the source to the return.
45
+ #
46
+ # If the return already had that tag, the existing tag
47
+ # range is recycled to save us an object.
48
+ #
49
+ # @param source [Object] the object from which existing properties
50
+ # should be copied.
51
+ # @param owner [Object] the object to which these properties apply.
52
+ def splat_from source, owner
53
+ splat_length = Contrast::Utils::StringUtils.ret_length(owner)
54
+ return if splat_length.zero?
55
+
56
+ splat_from_ret(splat_length)
57
+ splat_from_source(source, splat_length)
58
+ cleanup_tags
59
+ end
60
+
61
+ private
62
+
63
+ # Because of how our tracking works now, sometimes the Source and
64
+ # Target are the same, but their IDs in our map will be different due
65
+ # to PreShift duplication. To account for this, we have to ensure that
66
+ # the Object we're copying from does not have the same Properties
67
+ # that the Object we're copying to does. If they are the same, wipe the
68
+ # Target so that the copy method can update events and ranges as
69
+ # necessary.
70
+ # DO NOT TAKE THIS OUT!
71
+ def adjust_duplicate original
72
+ reset_properties if original == self
73
+ reset_properties if original.__id__ == dupped_from
74
+ reset_properties if original.dupped_from == __id__
75
+ end
76
+
77
+ # Wipe out the instance variables on this Properties instance,
78
+ # allowing them to be rebuilt.
79
+ def reset_properties
80
+ @_tags = nil
81
+ @_events = nil
82
+ @_properties = nil
83
+ end
84
+
85
+ # Splat all the tags from the source to this set of Properties
86
+ #
87
+ # @param source [Object] the object from which tags will be copied
88
+ # and splatted.
89
+ # @param splat_length [Integer] the length to which to to set all
90
+ # tags.
91
+ def splat_from_source source, splat_length
92
+ properties = Contrast::Agent::Assess::Tracker.properties(source)
93
+ return unless properties
94
+
95
+ properties.tag_keys.each do |key|
96
+ existing = fetch_tag(key)
97
+ # if the tag already exists, drop all but the first range
98
+ # then change that range to cover the entire return
99
+ if existing
100
+ existing.drop(existing.length - 1)
101
+ range = existing[0]
102
+ range.repurpose(0, splat_length)
103
+ else
104
+ add_tag(key, 0...splat_length)
105
+ end
106
+ end
107
+ end
108
+
109
+ # Splat all the tags existing on this set of Properties
110
+ #
111
+ # @param splat_length [Integer] the length to which to to set all
112
+ # tags.
113
+ def splat_from_ret splat_length
114
+ return unless tracked?
115
+
116
+ tag_keys.each do |key|
117
+ next unless key
118
+
119
+ existing = fetch_tag(key)
120
+ next unless existing
121
+
122
+ existing.each do |range|
123
+ range.repurpose(0, splat_length)
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
@@ -14,5 +14,5 @@ module Contrast
14
14
  end
15
15
  end
16
16
 
17
- cs__scoped_require 'contrast/agent/assess/rule/base'
18
- cs__scoped_require 'contrast/agent/assess/rule/provider'
17
+ require 'contrast/agent/assess/rule/base'
18
+ require 'contrast/agent/assess/rule/provider'
@@ -1,10 +1,9 @@
1
1
  # Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
- cs__scoped_require 'contrast/components/interface'
5
-
6
- cs__scoped_require 'zlib'
7
- cs__scoped_require 'digest'
4
+ require 'digest'
5
+ require 'zlib'
6
+ require 'contrast/components/interface'
8
7
 
9
8
  module Contrast
10
9
  module Agent
@@ -16,6 +16,6 @@ module Contrast
16
16
  end
17
17
  end
18
18
 
19
- cs__scoped_require 'contrast/agent/assess/rule/provider/hardcoded_value_rule'
20
- cs__scoped_require 'contrast/agent/assess/rule/provider/hardcoded_key'
21
- cs__scoped_require 'contrast/agent/assess/rule/provider/hardcoded_password'
19
+ require 'contrast/agent/assess/rule/provider/hardcoded_value_rule'
20
+ require 'contrast/agent/assess/rule/provider/hardcoded_key'
21
+ require 'contrast/agent/assess/rule/provider/hardcoded_password'
@@ -33,6 +33,64 @@ module Contrast
33
33
  NON_KEY_PARTIAL_NAMES.none? { |name| constant_string.index(name) }
34
34
  end
35
35
 
36
+ BYTE_HOLDERS = %i[ARRAY LIST].cs__freeze
37
+ # Determine if the given value node violates the hardcode key rule
38
+ # @param value_node [RubyVM::AbstractSyntaxTree::Node] the node to
39
+ # evaluate
40
+ # @return [Boolean]
41
+ def value_node_passes? value_node
42
+ # If it's a freeze call, then evaluate the entity being frozen
43
+ value_node = value_node.children[0] if freeze_call?(value_node)
44
+ # If it's a String being turned into bytes, then it matches key
45
+ # expectations
46
+ return true if bytes_call?(value_node)
47
+
48
+ type = value_node.type
49
+ return false unless BYTE_HOLDERS.include?(type)
50
+ return false unless value_node.children.any?
51
+
52
+ # Unless this is an array of literal numerics, we don't match.
53
+ # That array seems to always end in a nil value, so we allow
54
+ # those as well.
55
+ value_node.children.each do |child|
56
+ next unless child
57
+
58
+ return false unless child.cs__is_a?(RubyVM::AbstractSyntaxTree::Node) &&
59
+ child.type == :LIT &&
60
+ child.children[0]&.cs__is_a?(Integer)
61
+ end
62
+
63
+ true
64
+ end
65
+
66
+ REDACTED_MARKER = ' = [**REDACTED**]'
67
+ def redacted_marker
68
+ REDACTED_MARKER
69
+ end
70
+
71
+ # A node is a bytes_call if it's the Node for String#bytes. We care
72
+ # about this specifically as it's likely to be a common way to
73
+ # generate a key constant, rather than directly declaring an
74
+ # integer array.
75
+ #
76
+ # @param value_node [RubyVM::AbstractSyntaxTree::Node] the node to
77
+ # evaluate
78
+ # @return [Boolean] is this a node for String#bytes or not
79
+ def bytes_call? value_node
80
+ return false unless value_node.type == :CALL
81
+
82
+ children = value_node.children
83
+ return false unless children
84
+ return false unless children.length >= 2
85
+
86
+ potential_string_node = children[0]
87
+ return false unless potential_string_node.cs__is_a?(RubyVM::AbstractSyntaxTree::Node) &&
88
+ potential_string_node.type == :STR
89
+
90
+ children[1] == :bytes
91
+ end
92
+
93
+ # TODO: RUBY-1014 remove `#value_type_passes?` and `#value_passes?`
36
94
  # If the value is a byte array, or at least an array of numbers, it
37
95
  # passes for this rule
38
96
  def value_type_passes? value
@@ -49,11 +107,6 @@ module Contrast
49
107
  def value_passes? _value
50
108
  true
51
109
  end
52
-
53
- REDACTED_MARKER = ' = [**REDACTED**]'
54
- def redacted_marker
55
- REDACTED_MARKER
56
- end
57
110
  end
58
111
  end
59
112
  end
@@ -38,15 +38,18 @@ module Contrast
38
38
  NON_PASSWORD_PARTIAL_NAMES.none? { |name| constant_string.index(name) }
39
39
  end
40
40
 
41
- # If the value is a string, it passes for this rule
42
- def value_type_passes? value
43
- value.is_a?(String)
44
- end
41
+ # Determine if the given value node violates the hardcode key rule
42
+ # @param value_node [RubyVM::AbstractSyntaxTree::Node] the node to
43
+ # evaluate
44
+ # @return [Boolean]
45
+ def value_node_passes? value_node
46
+ # If it's a freeze call, then evaluate the entity being frozen
47
+ value_node = value_node.children[0] if freeze_call?(value_node)
48
+ return false unless value_node.type == :STR
45
49
 
46
- # If the value probably isn't a property name, it passes for this
47
- # rule
48
- def value_passes? value
49
- !probably_property_name?(value)
50
+ # https://www.rubydoc.info/gems/ruby-internal/Node/STR
51
+ string = value_node.children[0]
52
+ !probably_property_name?(string)
50
53
  end
51
54
 
52
55
  # If a field name matches an expected password field, we'll check it's
@@ -56,7 +59,7 @@ module Contrast
56
59
  # characters are probably more likely to appear together in a
57
60
  # default placeholder than in a password. Note this is opposite of
58
61
  # the behavior in Java
59
- PROPERTY_NAME_PATTERN = /^[a-z]+[\.\_][\.\_a-z]*[a-z]+$/.cs__freeze
62
+ PROPERTY_NAME_PATTERN = /^[a-z]+[._][._a-z]*[a-z]+$/.cs__freeze
60
63
  def probably_property_name? value
61
64
  value.match?(PROPERTY_NAME_PATTERN)
62
65
  end
@@ -65,6 +68,18 @@ module Contrast
65
68
  def redacted_marker
66
69
  REDACTED_MARKER
67
70
  end
71
+
72
+ # TODO: RUBY-1014 remove `#value_type_passes?` and `#value_passes?`
73
+ # If the value is a string, it passes for this rule
74
+ def value_type_passes? value
75
+ value.is_a?(String)
76
+ end
77
+
78
+ # If the value probably isn't a property name, it passes for this
79
+ # rule
80
+ def value_passes? value
81
+ !probably_property_name?(value)
82
+ end
68
83
  end
69
84
  end
70
85
  end