contrast-agent 3.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (500) hide show
  1. checksums.yaml +7 -0
  2. data/.clang-format +5 -0
  3. data/.dockerignore +10 -0
  4. data/.gitignore +58 -0
  5. data/.gitmodules +6 -0
  6. data/.rspec +6 -0
  7. data/.simplecov +4 -0
  8. data/Gemfile +7 -0
  9. data/LICENSE.txt +12 -0
  10. data/Rakefile +15 -0
  11. data/exe/contrast_service +29 -0
  12. data/ext/build_funchook.rb +48 -0
  13. data/ext/cs__assess_active_record_named/cs__active_record_named.c +47 -0
  14. data/ext/cs__assess_active_record_named/cs__active_record_named.h +10 -0
  15. data/ext/cs__assess_active_record_named/extconf.rb +2 -0
  16. data/ext/cs__assess_array/cs__assess_array.c +38 -0
  17. data/ext/cs__assess_array/cs__assess_array.h +9 -0
  18. data/ext/cs__assess_array/extconf.rb +2 -0
  19. data/ext/cs__assess_basic_object/cs__assess_basic_object.c +50 -0
  20. data/ext/cs__assess_basic_object/cs__assess_basic_object.h +17 -0
  21. data/ext/cs__assess_basic_object/extconf.rb +2 -0
  22. data/ext/cs__assess_fiber_track/cs__assess_fiber_track.c +86 -0
  23. data/ext/cs__assess_fiber_track/cs__assess_fiber_track.h +34 -0
  24. data/ext/cs__assess_fiber_track/extconf.rb +2 -0
  25. data/ext/cs__assess_hash/cs__assess_hash.c +64 -0
  26. data/ext/cs__assess_hash/cs__assess_hash.h +24 -0
  27. data/ext/cs__assess_hash/extconf.rb +2 -0
  28. data/ext/cs__assess_kernel/cs__assess_kernel.c +36 -0
  29. data/ext/cs__assess_kernel/cs__assess_kernel.h +10 -0
  30. data/ext/cs__assess_kernel/extconf.rb +2 -0
  31. data/ext/cs__assess_marshal_module/cs__assess_marshal_module.c +47 -0
  32. data/ext/cs__assess_marshal_module/cs__assess_marshal_module.h +18 -0
  33. data/ext/cs__assess_marshal_module/extconf.rb +2 -0
  34. data/ext/cs__assess_module/cs__assess_module.c +78 -0
  35. data/ext/cs__assess_module/cs__assess_module.h +25 -0
  36. data/ext/cs__assess_module/extconf.rb +2 -0
  37. data/ext/cs__assess_regexp/cs__assess_regexp.c +48 -0
  38. data/ext/cs__assess_regexp/cs__assess_regexp.h +22 -0
  39. data/ext/cs__assess_regexp/extconf.rb +2 -0
  40. data/ext/cs__assess_regexp_track/cs__assess_regexp_track.c +63 -0
  41. data/ext/cs__assess_regexp_track/cs__assess_regexp_track.h +29 -0
  42. data/ext/cs__assess_regexp_track/extconf.rb +2 -0
  43. data/ext/cs__assess_string/cs__assess_string.c +38 -0
  44. data/ext/cs__assess_string/cs__assess_string.h +19 -0
  45. data/ext/cs__assess_string/extconf.rb +2 -0
  46. data/ext/cs__assess_string_interpolation26/cs__assess_string_interpolation26.c +31 -0
  47. data/ext/cs__assess_string_interpolation26/cs__assess_string_interpolation26.h +13 -0
  48. data/ext/cs__assess_string_interpolation26/extconf.rb +2 -0
  49. data/ext/cs__common/cs__common.c +60 -0
  50. data/ext/cs__common/cs__common.h +28 -0
  51. data/ext/cs__common/extconf.rb +20 -0
  52. data/ext/cs__contrast_patch/cs__contrast_patch.c +445 -0
  53. data/ext/cs__contrast_patch/cs__contrast_patch.h +196 -0
  54. data/ext/cs__contrast_patch/extconf.rb +2 -0
  55. data/ext/cs__protect_kernel/cs__protect_kernel.c +37 -0
  56. data/ext/cs__protect_kernel/cs__protect_kernel.h +11 -0
  57. data/ext/cs__protect_kernel/extconf.rb +2 -0
  58. data/ext/cs__scope/cs__scope.c +96 -0
  59. data/ext/cs__scope/cs__scope.h +33 -0
  60. data/ext/cs__scope/extconf.rb +2 -0
  61. data/ext/extconf_common.rb +49 -0
  62. data/funchook/LICENSE +360 -0
  63. data/funchook/Makefile +29 -0
  64. data/funchook/Makefile.in +29 -0
  65. data/funchook/README.md +121 -0
  66. data/funchook/appveyor.yml +42 -0
  67. data/funchook/autogen.sh +3 -0
  68. data/funchook/autom4te.cache/output.0 +4976 -0
  69. data/funchook/autom4te.cache/requests +78 -0
  70. data/funchook/autom4te.cache/traces.0 +364 -0
  71. data/funchook/config.guess +1530 -0
  72. data/funchook/config.log +490 -0
  73. data/funchook/config.status +1016 -0
  74. data/funchook/config.sub +1773 -0
  75. data/funchook/configure +4976 -0
  76. data/funchook/configure.ac +59 -0
  77. data/funchook/distorm/COPYING +26 -0
  78. data/funchook/distorm/MANIFEST +25 -0
  79. data/funchook/distorm/MANIFEST.in +4 -0
  80. data/funchook/distorm/README.md +12 -0
  81. data/funchook/distorm/disOps/disOps.py +795 -0
  82. data/funchook/distorm/disOps/x86db.py +404 -0
  83. data/funchook/distorm/disOps/x86header.py +247 -0
  84. data/funchook/distorm/disOps/x86sets.py +1664 -0
  85. data/funchook/distorm/examples/cs/TestdiStorm/Program.cs +79 -0
  86. data/funchook/distorm/examples/cs/TestdiStorm/Properties/AssemblyInfo.cs +36 -0
  87. data/funchook/distorm/examples/cs/TestdiStorm/TestdiStorm.csproj +69 -0
  88. data/funchook/distorm/examples/cs/distorm-net.sln +26 -0
  89. data/funchook/distorm/examples/cs/distorm-net/CodeInfo.cs +23 -0
  90. data/funchook/distorm/examples/cs/distorm-net/DecodedInst.cs +15 -0
  91. data/funchook/distorm/examples/cs/distorm-net/DecodedResult.cs +14 -0
  92. data/funchook/distorm/examples/cs/distorm-net/DecomposedInst.cs +36 -0
  93. data/funchook/distorm/examples/cs/distorm-net/DecomposedResult.cs +14 -0
  94. data/funchook/distorm/examples/cs/distorm-net/Opcodes.cs +1268 -0
  95. data/funchook/distorm/examples/cs/distorm-net/Opcodes.tt +37 -0
  96. data/funchook/distorm/examples/cs/distorm-net/Operand.cs +25 -0
  97. data/funchook/distorm/examples/cs/distorm-net/Properties/AssemblyInfo.cs +36 -0
  98. data/funchook/distorm/examples/cs/distorm-net/diStorm3.cs +411 -0
  99. data/funchook/distorm/examples/cs/distorm-net/distorm-net.csproj +80 -0
  100. data/funchook/distorm/examples/cs/readme +3 -0
  101. data/funchook/distorm/examples/ddk/README +48 -0
  102. data/funchook/distorm/examples/ddk/distorm.ini +11 -0
  103. data/funchook/distorm/examples/ddk/dummy.c +15 -0
  104. data/funchook/distorm/examples/ddk/main.c +91 -0
  105. data/funchook/distorm/examples/ddk/makefile +1 -0
  106. data/funchook/distorm/examples/ddk/sources +10 -0
  107. data/funchook/distorm/examples/java/Makefile +23 -0
  108. data/funchook/distorm/examples/java/distorm/src/Main.java +43 -0
  109. data/funchook/distorm/examples/java/distorm/src/diStorm3/CodeInfo.java +27 -0
  110. data/funchook/distorm/examples/java/distorm/src/diStorm3/DecodedInst.java +32 -0
  111. data/funchook/distorm/examples/java/distorm/src/diStorm3/DecodedResult.java +11 -0
  112. data/funchook/distorm/examples/java/distorm/src/diStorm3/DecomposedInst.java +89 -0
  113. data/funchook/distorm/examples/java/distorm/src/diStorm3/DecomposedResult.java +11 -0
  114. data/funchook/distorm/examples/java/distorm/src/diStorm3/OpcodeEnum.java +131 -0
  115. data/funchook/distorm/examples/java/distorm/src/diStorm3/Opcodes.java +1123 -0
  116. data/funchook/distorm/examples/java/distorm/src/diStorm3/Operand.java +24 -0
  117. data/funchook/distorm/examples/java/distorm/src/diStorm3/distorm3.java +41 -0
  118. data/funchook/distorm/examples/java/jdistorm.c +405 -0
  119. data/funchook/distorm/examples/java/jdistorm.h +40 -0
  120. data/funchook/distorm/examples/java/jdistorm.sln +20 -0
  121. data/funchook/distorm/examples/java/jdistorm.vcproj +208 -0
  122. data/funchook/distorm/examples/linux/Makefile +15 -0
  123. data/funchook/distorm/examples/linux/main.c +181 -0
  124. data/funchook/distorm/examples/tests/Makefile +15 -0
  125. data/funchook/distorm/examples/tests/main.cpp +42 -0
  126. data/funchook/distorm/examples/tests/main.py +66 -0
  127. data/funchook/distorm/examples/tests/test_distorm3.py +1672 -0
  128. data/funchook/distorm/examples/tests/tests.sln +20 -0
  129. data/funchook/distorm/examples/tests/tests.vcxproj +82 -0
  130. data/funchook/distorm/examples/tests/tests.vcxproj.filters +22 -0
  131. data/funchook/distorm/examples/win32/disasm.sln +25 -0
  132. data/funchook/distorm/examples/win32/disasm.vcxproj +201 -0
  133. data/funchook/distorm/examples/win32/disasm.vcxproj.filters +14 -0
  134. data/funchook/distorm/examples/win32/main.cpp +163 -0
  135. data/funchook/distorm/include/distorm.h +482 -0
  136. data/funchook/distorm/include/mnemonics.h +301 -0
  137. data/funchook/distorm/make/linux/Makefile +28 -0
  138. data/funchook/distorm/make/mac/Makefile +24 -0
  139. data/funchook/distorm/make/win32/cdistorm.vcxproj +239 -0
  140. data/funchook/distorm/make/win32/cdistorm.vcxproj.filters +80 -0
  141. data/funchook/distorm/make/win32/distorm.sln +25 -0
  142. data/funchook/distorm/make/win32/resource.h +14 -0
  143. data/funchook/distorm/make/win32/resource.rc +99 -0
  144. data/funchook/distorm/python/distorm3/__init__.py +957 -0
  145. data/funchook/distorm/python/distorm3/sample.py +51 -0
  146. data/funchook/distorm/setup.cfg +10 -0
  147. data/funchook/distorm/setup.py +266 -0
  148. data/funchook/distorm/src/config.h +169 -0
  149. data/funchook/distorm/src/decoder.c +641 -0
  150. data/funchook/distorm/src/decoder.h +33 -0
  151. data/funchook/distorm/src/distorm.c +413 -0
  152. data/funchook/distorm/src/instructions.c +597 -0
  153. data/funchook/distorm/src/instructions.h +463 -0
  154. data/funchook/distorm/src/insts.c +7939 -0
  155. data/funchook/distorm/src/insts.h +64 -0
  156. data/funchook/distorm/src/mnemonics.c +284 -0
  157. data/funchook/distorm/src/operands.c +1290 -0
  158. data/funchook/distorm/src/operands.h +28 -0
  159. data/funchook/distorm/src/prefix.c +368 -0
  160. data/funchook/distorm/src/prefix.h +64 -0
  161. data/funchook/distorm/src/textdefs.c +172 -0
  162. data/funchook/distorm/src/textdefs.h +57 -0
  163. data/funchook/distorm/src/wstring.c +47 -0
  164. data/funchook/distorm/src/wstring.h +35 -0
  165. data/funchook/distorm/src/x86defs.h +82 -0
  166. data/funchook/include/funchook.h +123 -0
  167. data/funchook/install-sh +527 -0
  168. data/funchook/src/Makefile +70 -0
  169. data/funchook/src/Makefile.in +70 -0
  170. data/funchook/src/__strerror.h +109 -0
  171. data/funchook/src/config.h +101 -0
  172. data/funchook/src/config.h.in +100 -0
  173. data/funchook/src/decoder.o +0 -0
  174. data/funchook/src/distorm.o +0 -0
  175. data/funchook/src/funchook.c +440 -0
  176. data/funchook/src/funchook.o +0 -0
  177. data/funchook/src/funchook_internal.h +155 -0
  178. data/funchook/src/funchook_io.c +182 -0
  179. data/funchook/src/funchook_io.h +64 -0
  180. data/funchook/src/funchook_io.o +0 -0
  181. data/funchook/src/funchook_syscall.S +134 -0
  182. data/funchook/src/funchook_syscall.o +0 -0
  183. data/funchook/src/funchook_unix.c +480 -0
  184. data/funchook/src/funchook_unix.o +0 -0
  185. data/funchook/src/funchook_windows.c +397 -0
  186. data/funchook/src/funchook_x86.c +622 -0
  187. data/funchook/src/funchook_x86.o +0 -0
  188. data/funchook/src/instructions.o +0 -0
  189. data/funchook/src/insts.o +0 -0
  190. data/funchook/src/libfunchook.so +0 -0
  191. data/funchook/src/mnemonics.o +0 -0
  192. data/funchook/src/operands.o +0 -0
  193. data/funchook/src/os_func.c +115 -0
  194. data/funchook/src/os_func.h +75 -0
  195. data/funchook/src/os_func.o +0 -0
  196. data/funchook/src/os_func_unix.c +94 -0
  197. data/funchook/src/os_func_unix.o +0 -0
  198. data/funchook/src/os_func_windows.c +32 -0
  199. data/funchook/src/prefix.o +0 -0
  200. data/funchook/src/printf_base.c +1688 -0
  201. data/funchook/src/printf_base.h +46 -0
  202. data/funchook/src/printf_base.o +0 -0
  203. data/funchook/src/textdefs.o +0 -0
  204. data/funchook/src/wstring.o +0 -0
  205. data/funchook/test/Makefile +43 -0
  206. data/funchook/test/Makefile.in +43 -0
  207. data/funchook/test/funchook_test +0 -0
  208. data/funchook/test/libfunchook_test.c +25 -0
  209. data/funchook/test/libfunchook_test.so +0 -0
  210. data/funchook/test/libfunchook_test2.c +18 -0
  211. data/funchook/test/suffix.list +600 -0
  212. data/funchook/test/test_main.c +430 -0
  213. data/funchook/test/test_main.o +0 -0
  214. data/funchook/test/x86_64_test.S +10 -0
  215. data/funchook/test/x86_64_test.o +0 -0
  216. data/funchook/test/x86_test.S +339 -0
  217. data/funchook/win32/config.h +1 -0
  218. data/funchook/win32/funchook.sln +52 -0
  219. data/funchook/win32/funchook.vcxproj +188 -0
  220. data/funchook/win32/funchook.vcxproj.filters +84 -0
  221. data/funchook/win32/funchook_test.vcxproj +170 -0
  222. data/funchook/win32/funchook_test.vcxproj.filters +22 -0
  223. data/funchook/win32/funchook_test_dll.vcxproj +184 -0
  224. data/funchook/win32/funchook_test_dll.vcxproj.filters +30 -0
  225. data/funchook/win32/funchook_test_exe.def +3 -0
  226. data/lib/contrast-agent.rb +8 -0
  227. data/lib/contrast.rb +57 -0
  228. data/lib/contrast/agent.rb +80 -0
  229. data/lib/contrast/agent/assess.rb +45 -0
  230. data/lib/contrast/agent/assess/adjusted_span.rb +25 -0
  231. data/lib/contrast/agent/assess/class_reverter.rb +82 -0
  232. data/lib/contrast/agent/assess/contrast_event.rb +398 -0
  233. data/lib/contrast/agent/assess/frozen_properties.rb +41 -0
  234. data/lib/contrast/agent/assess/insulator.rb +53 -0
  235. data/lib/contrast/agent/assess/policy/dynamic_source_factory.rb +78 -0
  236. data/lib/contrast/agent/assess/policy/patcher.rb +85 -0
  237. data/lib/contrast/agent/assess/policy/policy.rb +116 -0
  238. data/lib/contrast/agent/assess/policy/policy_node.rb +289 -0
  239. data/lib/contrast/agent/assess/policy/policy_scanner.rb +44 -0
  240. data/lib/contrast/agent/assess/policy/preshift.rb +94 -0
  241. data/lib/contrast/agent/assess/policy/propagation_method.rb +260 -0
  242. data/lib/contrast/agent/assess/policy/propagation_node.rb +127 -0
  243. data/lib/contrast/agent/assess/policy/propagator.rb +35 -0
  244. data/lib/contrast/agent/assess/policy/propagator/append.rb +54 -0
  245. data/lib/contrast/agent/assess/policy/propagator/base.rb +37 -0
  246. data/lib/contrast/agent/assess/policy/propagator/center.rb +73 -0
  247. data/lib/contrast/agent/assess/policy/propagator/custom.rb +36 -0
  248. data/lib/contrast/agent/assess/policy/propagator/database_write.rb +62 -0
  249. data/lib/contrast/agent/assess/policy/propagator/insert.rb +55 -0
  250. data/lib/contrast/agent/assess/policy/propagator/keep.rb +26 -0
  251. data/lib/contrast/agent/assess/policy/propagator/next.rb +42 -0
  252. data/lib/contrast/agent/assess/policy/propagator/prepend.rb +50 -0
  253. data/lib/contrast/agent/assess/policy/propagator/remove.rb +76 -0
  254. data/lib/contrast/agent/assess/policy/propagator/replace.rb +27 -0
  255. data/lib/contrast/agent/assess/policy/propagator/reverse.rb +38 -0
  256. data/lib/contrast/agent/assess/policy/propagator/select.rb +86 -0
  257. data/lib/contrast/agent/assess/policy/propagator/splat.rb +60 -0
  258. data/lib/contrast/agent/assess/policy/propagator/split.rb +49 -0
  259. data/lib/contrast/agent/assess/policy/propagator/substitution.rb +169 -0
  260. data/lib/contrast/agent/assess/policy/propagator/trim.rb +81 -0
  261. data/lib/contrast/agent/assess/policy/rewriter_patch.rb +79 -0
  262. data/lib/contrast/agent/assess/policy/source_method.rb +209 -0
  263. data/lib/contrast/agent/assess/policy/source_node.rb +62 -0
  264. data/lib/contrast/agent/assess/policy/trigger_method.rb +209 -0
  265. data/lib/contrast/agent/assess/policy/trigger_node.rb +198 -0
  266. data/lib/contrast/agent/assess/policy/trigger_validation/ssrf_validator.rb +77 -0
  267. data/lib/contrast/agent/assess/policy/trigger_validation/trigger_validation.rb +31 -0
  268. data/lib/contrast/agent/assess/policy/trigger_validation/xss_validator.rb +40 -0
  269. data/lib/contrast/agent/assess/properties.rb +392 -0
  270. data/lib/contrast/agent/assess/rule.rb +18 -0
  271. data/lib/contrast/agent/assess/rule/base.rb +72 -0
  272. data/lib/contrast/agent/assess/rule/csrf.rb +66 -0
  273. data/lib/contrast/agent/assess/rule/csrf/csrf_action.rb +28 -0
  274. data/lib/contrast/agent/assess/rule/csrf/csrf_applicator.rb +69 -0
  275. data/lib/contrast/agent/assess/rule/csrf/csrf_watcher.rb +132 -0
  276. data/lib/contrast/agent/assess/rule/provider.rb +21 -0
  277. data/lib/contrast/agent/assess/rule/provider/hardcoded_key.rb +62 -0
  278. data/lib/contrast/agent/assess/rule/provider/hardcoded_password.rb +73 -0
  279. data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +121 -0
  280. data/lib/contrast/agent/assess/rule/redos.rb +68 -0
  281. data/lib/contrast/agent/assess/rule/response_scanning_rule.rb +47 -0
  282. data/lib/contrast/agent/assess/rule/response_watcher.rb +36 -0
  283. data/lib/contrast/agent/assess/rule/watcher.rb +36 -0
  284. data/lib/contrast/agent/assess/tag.rb +151 -0
  285. data/lib/contrast/agent/at_exit_hook.rb +33 -0
  286. data/lib/contrast/agent/class_reopener.rb +195 -0
  287. data/lib/contrast/agent/deadzone/policy/deadzone_node.rb +26 -0
  288. data/lib/contrast/agent/deadzone/policy/policy.rb +57 -0
  289. data/lib/contrast/agent/disable_reaction.rb +24 -0
  290. data/lib/contrast/agent/exclusion_matcher.rb +190 -0
  291. data/lib/contrast/agent/feature_state.rb +379 -0
  292. data/lib/contrast/agent/inventory/policy/policy.rb +32 -0
  293. data/lib/contrast/agent/inventory/policy/trigger_node.rb +22 -0
  294. data/lib/contrast/agent/logger_manager.rb +116 -0
  295. data/lib/contrast/agent/middleware.rb +352 -0
  296. data/lib/contrast/agent/module_data.rb +16 -0
  297. data/lib/contrast/agent/patching/policy/after_load_patch.rb +37 -0
  298. data/lib/contrast/agent/patching/policy/after_load_patcher.rb +58 -0
  299. data/lib/contrast/agent/patching/policy/method_policy.rb +94 -0
  300. data/lib/contrast/agent/patching/policy/module_policy.rb +116 -0
  301. data/lib/contrast/agent/patching/policy/patch.rb +312 -0
  302. data/lib/contrast/agent/patching/policy/patch_status.rb +192 -0
  303. data/lib/contrast/agent/patching/policy/patcher.rb +310 -0
  304. data/lib/contrast/agent/patching/policy/policy.rb +138 -0
  305. data/lib/contrast/agent/patching/policy/policy_node.rb +80 -0
  306. data/lib/contrast/agent/patching/policy/policy_unpatcher.rb +28 -0
  307. data/lib/contrast/agent/patching/policy/trigger_node.rb +81 -0
  308. data/lib/contrast/agent/protect/policy/policy.rb +37 -0
  309. data/lib/contrast/agent/protect/policy/trigger_node.rb +23 -0
  310. data/lib/contrast/agent/protect/rule.rb +58 -0
  311. data/lib/contrast/agent/protect/rule/base.rb +300 -0
  312. data/lib/contrast/agent/protect/rule/base_service.rb +88 -0
  313. data/lib/contrast/agent/protect/rule/cmd_injection.rb +156 -0
  314. data/lib/contrast/agent/protect/rule/csrf.rb +118 -0
  315. data/lib/contrast/agent/protect/rule/csrf/csrf_evaluator.rb +103 -0
  316. data/lib/contrast/agent/protect/rule/csrf/csrf_token_injector.rb +85 -0
  317. data/lib/contrast/agent/protect/rule/default_scanner.rb +300 -0
  318. data/lib/contrast/agent/protect/rule/deserialization.rb +193 -0
  319. data/lib/contrast/agent/protect/rule/http_method_tampering.rb +80 -0
  320. data/lib/contrast/agent/protect/rule/no_sqli.rb +101 -0
  321. data/lib/contrast/agent/protect/rule/no_sqli/mongo_no_sql_scanner.rb +40 -0
  322. data/lib/contrast/agent/protect/rule/path_traversal.rb +143 -0
  323. data/lib/contrast/agent/protect/rule/sqli.rb +101 -0
  324. data/lib/contrast/agent/protect/rule/sqli/default_sql_scanner.rb +16 -0
  325. data/lib/contrast/agent/protect/rule/sqli/mysql_sql_scanner.rb +38 -0
  326. data/lib/contrast/agent/protect/rule/sqli/postgres_sql_scanner.rb +22 -0
  327. data/lib/contrast/agent/protect/rule/sqli/sqlite_sql_scanner.rb +19 -0
  328. data/lib/contrast/agent/protect/rule/unsafe_file_upload.rb +20 -0
  329. data/lib/contrast/agent/protect/rule/xss.rb +24 -0
  330. data/lib/contrast/agent/protect/rule/xxe.rb +120 -0
  331. data/lib/contrast/agent/protect/rule/xxe/entity_wrapper.rb +82 -0
  332. data/lib/contrast/agent/railtie.rb +30 -0
  333. data/lib/contrast/agent/reaction_processor.rb +47 -0
  334. data/lib/contrast/agent/request.rb +493 -0
  335. data/lib/contrast/agent/request_context.rb +225 -0
  336. data/lib/contrast/agent/require_state.rb +61 -0
  337. data/lib/contrast/agent/response.rb +215 -0
  338. data/lib/contrast/agent/rewriter.rb +244 -0
  339. data/lib/contrast/agent/scope.rb +28 -0
  340. data/lib/contrast/agent/service_heartbeat.rb +37 -0
  341. data/lib/contrast/agent/settings_state.rb +148 -0
  342. data/lib/contrast/agent/socket_client.rb +125 -0
  343. data/lib/contrast/agent/thread.rb +26 -0
  344. data/lib/contrast/agent/tracepoint_hook.rb +51 -0
  345. data/lib/contrast/agent/version.rb +8 -0
  346. data/lib/contrast/api.rb +17 -0
  347. data/lib/contrast/api/.gitkeep +0 -0
  348. data/lib/contrast/api/connection_status.rb +49 -0
  349. data/lib/contrast/api/socket.rb +43 -0
  350. data/lib/contrast/api/speedracer.rb +206 -0
  351. data/lib/contrast/api/tcp_socket.rb +31 -0
  352. data/lib/contrast/api/unix_socket.rb +25 -0
  353. data/lib/contrast/common_agent_configuration.rb +86 -0
  354. data/lib/contrast/components/agent.rb +85 -0
  355. data/lib/contrast/components/app_context.rb +188 -0
  356. data/lib/contrast/components/assess.rb +67 -0
  357. data/lib/contrast/components/config.rb +135 -0
  358. data/lib/contrast/components/contrast_service.rb +113 -0
  359. data/lib/contrast/components/heap_dump.rb +34 -0
  360. data/lib/contrast/components/interface.rb +178 -0
  361. data/lib/contrast/components/inventory.rb +23 -0
  362. data/lib/contrast/components/logger.rb +92 -0
  363. data/lib/contrast/components/protect.rb +38 -0
  364. data/lib/contrast/components/sampling.rb +41 -0
  365. data/lib/contrast/components/scope.rb +106 -0
  366. data/lib/contrast/components/settings.rb +140 -0
  367. data/lib/contrast/config.rb +33 -0
  368. data/lib/contrast/config/agent_configuration.rb +24 -0
  369. data/lib/contrast/config/application_configuration.rb +27 -0
  370. data/lib/contrast/config/assess_configuration.rb +22 -0
  371. data/lib/contrast/config/assess_rules_configuration.rb +18 -0
  372. data/lib/contrast/config/base_configuration.rb +105 -0
  373. data/lib/contrast/config/default_value.rb +16 -0
  374. data/lib/contrast/config/exception_configuration.rb +21 -0
  375. data/lib/contrast/config/heap_dump_configuration.rb +23 -0
  376. data/lib/contrast/config/inventory_configuration.rb +20 -0
  377. data/lib/contrast/config/logger_configuration.rb +20 -0
  378. data/lib/contrast/config/protect_configuration.rb +20 -0
  379. data/lib/contrast/config/protect_rule_configuration.rb +37 -0
  380. data/lib/contrast/config/protect_rules_configuration.rb +30 -0
  381. data/lib/contrast/config/root_configuration.rb +26 -0
  382. data/lib/contrast/config/ruby_configuration.rb +39 -0
  383. data/lib/contrast/config/sampling_configuration.rb +22 -0
  384. data/lib/contrast/config/server_configuration.rb +23 -0
  385. data/lib/contrast/config/service_configuration.rb +22 -0
  386. data/lib/contrast/configuration.rb +214 -0
  387. data/lib/contrast/core_extensions/assess.rb +51 -0
  388. data/lib/contrast/core_extensions/assess/array.rb +58 -0
  389. data/lib/contrast/core_extensions/assess/assess_extension.rb +145 -0
  390. data/lib/contrast/core_extensions/assess/basic_object.rb +15 -0
  391. data/lib/contrast/core_extensions/assess/erb.rb +42 -0
  392. data/lib/contrast/core_extensions/assess/exec_trigger.rb +48 -0
  393. data/lib/contrast/core_extensions/assess/fiber.rb +125 -0
  394. data/lib/contrast/core_extensions/assess/hash.rb +22 -0
  395. data/lib/contrast/core_extensions/assess/kernel.rb +95 -0
  396. data/lib/contrast/core_extensions/assess/module.rb +14 -0
  397. data/lib/contrast/core_extensions/assess/regexp.rb +206 -0
  398. data/lib/contrast/core_extensions/assess/string.rb +75 -0
  399. data/lib/contrast/core_extensions/assess/tilt_template_trigger.rb +73 -0
  400. data/lib/contrast/core_extensions/delegator.rb +14 -0
  401. data/lib/contrast/core_extensions/eval_trigger.rb +52 -0
  402. data/lib/contrast/core_extensions/inventory.rb +22 -0
  403. data/lib/contrast/core_extensions/inventory/datastores.rb +37 -0
  404. data/lib/contrast/core_extensions/module.rb +42 -0
  405. data/lib/contrast/core_extensions/object.rb +27 -0
  406. data/lib/contrast/core_extensions/protect.rb +20 -0
  407. data/lib/contrast/core_extensions/protect/applies_command_injection_rule.rb +70 -0
  408. data/lib/contrast/core_extensions/protect/applies_deserialization_rule.rb +58 -0
  409. data/lib/contrast/core_extensions/protect/applies_no_sqli_rule.rb +81 -0
  410. data/lib/contrast/core_extensions/protect/applies_path_traversal_rule.rb +119 -0
  411. data/lib/contrast/core_extensions/protect/applies_sqli_rule.rb +63 -0
  412. data/lib/contrast/core_extensions/protect/applies_xxe_rule.rb +141 -0
  413. data/lib/contrast/core_extensions/protect/kernel.rb +30 -0
  414. data/lib/contrast/core_extensions/protect/psych.rb +7 -0
  415. data/lib/contrast/core_extensions/thread.rb +31 -0
  416. data/lib/contrast/internal_exception.rb +8 -0
  417. data/lib/contrast/rails_extensions/assess/action_controller_inheritance.rb +48 -0
  418. data/lib/contrast/rails_extensions/assess/active_record.rb +32 -0
  419. data/lib/contrast/rails_extensions/assess/active_record_named.rb +61 -0
  420. data/lib/contrast/rails_extensions/assess/configuration.rb +26 -0
  421. data/lib/contrast/rails_extensions/buffer.rb +30 -0
  422. data/lib/contrast/rails_extensions/rack.rb +45 -0
  423. data/lib/contrast/security_exception.rb +14 -0
  424. data/lib/contrast/sinatra_extensions/assess/cookie.rb +26 -0
  425. data/lib/contrast/sinatra_extensions/inventory/sinatra_base.rb +59 -0
  426. data/lib/contrast/tasks/service.rb +95 -0
  427. data/lib/contrast/utils/assess/sampling_util.rb +96 -0
  428. data/lib/contrast/utils/assess/tracking_util.rb +39 -0
  429. data/lib/contrast/utils/boolean_util.rb +33 -0
  430. data/lib/contrast/utils/cache.rb +69 -0
  431. data/lib/contrast/utils/class_util.rb +58 -0
  432. data/lib/contrast/utils/comment_range.rb +19 -0
  433. data/lib/contrast/utils/data_store_util.rb +23 -0
  434. data/lib/contrast/utils/duck_utils.rb +58 -0
  435. data/lib/contrast/utils/env_configuration_item.rb +52 -0
  436. data/lib/contrast/utils/environment_util.rb +152 -0
  437. data/lib/contrast/utils/freeze_util.rb +36 -0
  438. data/lib/contrast/utils/gemfile_reader.rb +191 -0
  439. data/lib/contrast/utils/hash_digest.rb +148 -0
  440. data/lib/contrast/utils/heap_dump_util.rb +113 -0
  441. data/lib/contrast/utils/invalid_configuration_util.rb +88 -0
  442. data/lib/contrast/utils/inventory_util.rb +126 -0
  443. data/lib/contrast/utils/io_util.rb +61 -0
  444. data/lib/contrast/utils/object_share.rb +117 -0
  445. data/lib/contrast/utils/operating_environment.rb +38 -0
  446. data/lib/contrast/utils/os.rb +49 -0
  447. data/lib/contrast/utils/path_util.rb +151 -0
  448. data/lib/contrast/utils/performs_logging.rb +152 -0
  449. data/lib/contrast/utils/preflight_util.rb +13 -0
  450. data/lib/contrast/utils/prevent_serialization.rb +52 -0
  451. data/lib/contrast/utils/rack_assess_session_cookie.rb +104 -0
  452. data/lib/contrast/utils/rails_assess_configuration.rb +95 -0
  453. data/lib/contrast/utils/random_util.rb +22 -0
  454. data/lib/contrast/utils/resource_loader.rb +23 -0
  455. data/lib/contrast/utils/ruby_ast_rewriter.rb +74 -0
  456. data/lib/contrast/utils/scope_util.rb +99 -0
  457. data/lib/contrast/utils/service_response_util.rb +116 -0
  458. data/lib/contrast/utils/service_sender_util.rb +98 -0
  459. data/lib/contrast/utils/sha256_builder.rb +69 -0
  460. data/lib/contrast/utils/sinatra_helper.rb +49 -0
  461. data/lib/contrast/utils/stack_trace_utils.rb +209 -0
  462. data/lib/contrast/utils/string_utils.rb +72 -0
  463. data/lib/contrast/utils/tag_util.rb +139 -0
  464. data/lib/contrast/utils/thread_tracker.rb +54 -0
  465. data/lib/contrast/utils/timer.rb +78 -0
  466. data/resources/assess/policy.json +1673 -0
  467. data/resources/csrf/inject.js +44 -0
  468. data/resources/deadzone/policy.json +55 -0
  469. data/resources/factory-bot-spec/spec_helper.rb +30 -0
  470. data/resources/inventory/policy.json +110 -0
  471. data/resources/protect/policy.json +417 -0
  472. data/resources/rubocops/kernel/catch_cop.rb +37 -0
  473. data/resources/rubocops/kernel/require_cop.rb +37 -0
  474. data/resources/rubocops/kernel/require_relative_cop.rb +33 -0
  475. data/resources/rubocops/module/autoload_cop.rb +37 -0
  476. data/resources/rubocops/module/const_defined_cop.rb +37 -0
  477. data/resources/rubocops/module/const_get_cop.rb +37 -0
  478. data/resources/rubocops/module/const_set_cop.rb +37 -0
  479. data/resources/rubocops/module/constants_cop.rb +37 -0
  480. data/resources/rubocops/module/name_cop.rb +37 -0
  481. data/resources/rubocops/object/class_cop.rb +37 -0
  482. data/resources/rubocops/object/freeze_cop.rb +37 -0
  483. data/resources/rubocops/object/frozen_cop.rb +37 -0
  484. data/resources/rubocops/object/is_a_cop.rb +37 -0
  485. data/resources/rubocops/object/method_cop.rb +37 -0
  486. data/resources/rubocops/object/respond_to_cop.rb +37 -0
  487. data/resources/rubocops/object/singleton_class_cop.rb +37 -0
  488. data/resources/rubocops/regexp/spelling_cop.rb +44 -0
  489. data/resources/rubocops/thread/new_cop.rb +39 -0
  490. data/resources/ruby-spec/ancestors_spec.rb +70 -0
  491. data/resources/ruby-spec/modulo_spec.rb +831 -0
  492. data/resources/ruby-spec/parameters_spec.rb +261 -0
  493. data/resources/ruby-spec/ruby_spec_spec_helper.rb +35 -0
  494. data/resources/test_marker.txt +1 -0
  495. data/ruby-agent.gemspec +129 -0
  496. data/service_executables/.gitkeep +0 -0
  497. data/service_executables/VERSION +1 -0
  498. data/service_executables/linux/contrast-service +0 -0
  499. data/service_executables/mac/contrast-service +0 -0
  500. metadata +945 -0
@@ -0,0 +1,22 @@
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
+ module Contrast
5
+ module Config
6
+ # Common Configuration settings. Those in this section pertain to the
7
+ # sampling functionality of the Agent.
8
+ class SamplingConfiguration < BaseConfiguration
9
+ KEYS = {
10
+ enable: EMPTY_VALUE,
11
+ baseline: EMPTY_VALUE,
12
+ request_frequency: EMPTY_VALUE,
13
+ response_frequency: EMPTY_VALUE,
14
+ window_ms: EMPTY_VALUE
15
+ }.cs__freeze
16
+
17
+ def initialize hsh
18
+ super(hsh, KEYS)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,23 @@
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
+ module Contrast
5
+ module Config
6
+ # Common Configuration settings. Those in this section pertain to the
7
+ # server identification functionality of the Agent.
8
+ class ServerConfiguration < BaseConfiguration
9
+ KEYS = {
10
+ name: EMPTY_VALUE,
11
+ path: EMPTY_VALUE,
12
+ type: EMPTY_VALUE,
13
+ tags: EMPTY_VALUE,
14
+ environment: EMPTY_VALUE,
15
+ version: EMPTY_VALUE
16
+ }.cs__freeze
17
+
18
+ def initialize hsh
19
+ super(hsh, KEYS)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,22 @@
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
+ module Contrast
5
+ module Config
6
+ # Common Configuration settings. Those in this section pertain to the
7
+ # communication between the Agent & the Service.
8
+ class ServiceConfiguration < BaseConfiguration
9
+ KEYS = {
10
+ enable: EMPTY_VALUE,
11
+ host: EMPTY_VALUE,
12
+ port: EMPTY_VALUE,
13
+ socket: EMPTY_VALUE,
14
+ logger: Contrast::Config::LoggerConfiguration
15
+ }.cs__freeze
16
+
17
+ def initialize hsh
18
+ super(hsh, KEYS)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,214 @@
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
+ cs__scoped_require 'yaml'
5
+ cs__scoped_require 'fileutils'
6
+
7
+ cs__scoped_require 'contrast/config'
8
+ cs__scoped_require 'contrast/utils/object_share'
9
+ cs__scoped_require 'contrast/components/interface'
10
+
11
+ module Contrast
12
+ # This is how we read in the local settings for the Agent, both ENV/ CMD line
13
+ # and from properties files, in order to determine which settings, if any,
14
+ # the user has overridden.
15
+ class Configuration
16
+ extend Forwardable
17
+
18
+ include Contrast::Components::Interface
19
+
20
+ access_component :scope
21
+
22
+ def_delegator :root, :assign_value_to_path_array
23
+
24
+ attr_reader :default_name, :root
25
+
26
+ DEFAULT_YAML_PATH = 'contrast_security.yaml'
27
+ DEFAULT_HOST = '127.0.0.1'
28
+ DEFAULT_PORT = '30555'
29
+ MILLISECOND_MARKER = '_ms'
30
+ CONVERSION = {
31
+ 'agent.service.enable' => 'agent.start_bundled_service'
32
+ }.cs__freeze
33
+ CONFIG_BASE_PATHS = [
34
+ '',
35
+ 'config/',
36
+ '/etc/contrast/ruby/',
37
+ '/etc/contrast/',
38
+ '/etc/'
39
+ ].cs__freeze
40
+ REMOVE_FIELDS = [
41
+ 'contrast'
42
+ ].cs__freeze
43
+
44
+ def initialize cli_options = nil, default_name = DEFAULT_YAML_PATH
45
+ @default_name = default_name
46
+
47
+ # Load config_kv from file
48
+ config_kv = deep_stringify_all_keys(load_config)
49
+
50
+ # Overlay CLI options - they take precedence over config file
51
+ cli_options = deep_stringify_all_keys(cli_options)
52
+ config_kv = deep_merge(cli_options, config_kv) if cli_options
53
+
54
+ # Some in-flight rewrites to maintain backwards compatibility
55
+ config_kv = update_prop_keys(config_kv)
56
+ config_kv = deprecate_fields(config_kv)
57
+
58
+ @root = Contrast::Config::RootConfiguration.new(config_kv)
59
+ end
60
+
61
+ # Because we call this method to determine the need for scoping, it itself
62
+ # must be executed inside a Contrast scope. Failure to do so could result
63
+ # in an infinite loop on the to_sym method used later.
64
+ def method_missing symbol, *args
65
+ with_contrast_scope do
66
+ begin
67
+ root.public_send(symbol, *args)
68
+ rescue NoMethodError => _e
69
+ super
70
+ end
71
+ end
72
+ end
73
+
74
+ def respond_to_missing? method_name, *args
75
+ root&.cs__respond_to?(method_name) || super
76
+ end
77
+
78
+ protected
79
+
80
+ # TODO: RUBY-546 move utility methods to auxiliary classes
81
+
82
+ def load_config
83
+ config = {}
84
+ configuration_paths.find do |path|
85
+ found = File.exist?(path)
86
+ next unless found
87
+
88
+ readable = File.readable?(path)
89
+ unless readable
90
+ puts "!!! Contrast - Configuration file at #{ path } is not readable by current user"
91
+ next
92
+ end
93
+ config = yaml_to_hash(path)
94
+ break
95
+ end
96
+
97
+ if config.empty?
98
+ puts "!!! Contrast - working directory: #{ Dir.pwd }"
99
+ puts '!!! Contrast - configuration file could not be found at any of the search paths'
100
+ puts 'Valid configuration paths are: '
101
+ configuration_paths.each do |path|
102
+ puts(path)
103
+ end
104
+ end
105
+ config
106
+ end
107
+
108
+ def yaml_to_hash path
109
+ if path && File.readable?(path)
110
+ begin
111
+ yaml = IO.read(path)
112
+ yaml = ERB.new(yaml).result if defined?(ERB)
113
+ return YAML.safe_load(yaml)
114
+ rescue RuntimeError => e
115
+ puts "ERROR: unable to load configuration from path due to #{ e }"
116
+ puts "ERROR: path=#{ path } pwd=#{ Dir.pwd }"
117
+ end
118
+ end
119
+
120
+ {}
121
+ end
122
+
123
+ # We're updating properties loaded from the configuration
124
+ # files to match the new agreed upon standard configuration
125
+ # names, so that one file works for all agents
126
+ def update_prop_keys config
127
+ converted = false
128
+ CONVERSION.each_pair do |old_method, new_method|
129
+ # See if the old value was set and needs to be translated
130
+ deprecated_keys = old_method.split('.')
131
+
132
+ old_value = config
133
+ deprecated_keys.each do |key|
134
+ old_value = old_value[key]
135
+ break if old_value.nil?
136
+ end
137
+
138
+ next if old_value.nil?
139
+
140
+ converted = true
141
+
142
+ puts "The deprecated property #{ old_method } is being set."
143
+ puts "Please update your config to use the property #{ new_method } instead."
144
+
145
+ new_keys = new_method.split('.')
146
+
147
+ # We changed the seconds values into ms values. Multiply them accordingly
148
+ old_value = old_value.to_i * 1000 if new_method.end_with?(MILLISECOND_MARKER)
149
+
150
+ new_value = config
151
+ end_idx = new_keys.length - 1
152
+ new_keys.each_with_index do |new_key, index|
153
+ if index == end_idx
154
+ new_value[new_key] = old_value if new_value[new_key].nil?
155
+ else
156
+ new_value = {} if new_value.nil?
157
+ new_value[new_key] = {} if new_value[new_key].nil?
158
+ new_value = new_value[new_key]
159
+ end
160
+ end
161
+ end
162
+
163
+ config
164
+ end
165
+
166
+ def deprecate_fields hash
167
+ REMOVE_FIELDS.each do |field|
168
+ path = field.split('.')
169
+ active_path = hash
170
+ path.each_with_index do |delete_path, index|
171
+ if index == path.length - 1 && active_path
172
+ active_path.delete(delete_path)
173
+ elsif active_path
174
+ active_path = active_path[delete_path]
175
+ end
176
+ end
177
+ end
178
+ hash
179
+ end
180
+
181
+ # Base paths to check for the contrast configuration file, sorted by
182
+ # reverse order of precedence (first is most important).
183
+ def configuration_paths
184
+ @_configuration_paths ||= begin
185
+ basename = default_name.split('.').first
186
+ names = %w[yml yaml].map { |suffix| "#{ basename }.#{ suffix }" }
187
+
188
+ paths = []
189
+ paths << ENV['CONTRAST_CONFIG_PATH'] if ENV['CONTRAST_CONFIG_PATH']
190
+ paths << ENV['CONTRAST_SECURITY_CONFIG'] if ENV['CONTRAST_SECURITY_CONFIG']
191
+
192
+ tmp = CONFIG_BASE_PATHS.product(names)
193
+ paths += tmp.map!(&:join)
194
+ paths
195
+ end
196
+ end
197
+
198
+ def deep_merge cli_config, file_config
199
+ cli_config.merge(file_config) do |_key, cli_value, file_value|
200
+ cli_value.is_a?(Hash) && file_value.is_a?(Hash) ? deep_merge(cli_value, file_value) : cli_value
201
+ end
202
+ end
203
+
204
+ def deep_stringify_all_keys hash
205
+ return if hash.nil?
206
+
207
+ new_hash = {}
208
+ hash.each do |key, value|
209
+ new_hash[key.to_s] = value.is_a?(Hash) ? deep_stringify_all_keys(value) : value
210
+ end
211
+ new_hash
212
+ end
213
+ end
214
+ end
@@ -0,0 +1,51 @@
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
+ module Contrast
5
+ module CoreExtensions
6
+ # Our top level Protect namespace in the Core Extensions section of our
7
+ # code. These patches are those that are invoked directly from a patched
8
+ # Class.
9
+ #
10
+ # @deprecated This is one of our earliest designs and is not nearly as
11
+ # relevant given the move to C based patching and the lessons learned
12
+ # therein.
13
+ module Assess
14
+ cs__scoped_require 'contrast/agent/patching/policy/patcher'
15
+
16
+ cs__scoped_require 'contrast/utils/tag_util'
17
+
18
+ # provider rules - have to come before policy
19
+ cs__scoped_require 'contrast/agent/assess/rule/provider'
20
+
21
+ # tagging / dataflow
22
+ cs__scoped_require 'contrast/agent/assess/adjusted_span'
23
+ cs__scoped_require 'contrast/agent/assess/policy/policy_node'
24
+ cs__scoped_require 'contrast/agent/assess/policy/source_node'
25
+ cs__scoped_require 'contrast/agent/assess/policy/source_method'
26
+ cs__scoped_require 'contrast/agent/assess/policy/propagation_node'
27
+ cs__scoped_require 'contrast/agent/assess/policy/propagation_method'
28
+ cs__scoped_require 'contrast/agent/assess/policy/trigger_node'
29
+ cs__scoped_require 'contrast/agent/assess/policy/trigger_method'
30
+ cs__scoped_require 'contrast/agent/assess/policy/policy'
31
+ cs__scoped_require 'contrast/agent/assess/policy/patcher'
32
+
33
+ # classes that don't play nice w/ our standard propagation
34
+ cs__scoped_require 'contrast/agent/assess/frozen_properties'
35
+ cs__scoped_require 'contrast/core_extensions/assess/assess_extension'
36
+ # this needs to come first b/c array and others work on strings and
37
+ # expect them to be trackable
38
+ cs__scoped_require 'contrast/core_extensions/assess/string'
39
+
40
+ cs__scoped_require 'contrast/core_extensions/assess/array'
41
+ cs__scoped_require 'contrast/core_extensions/assess/erb'
42
+ cs__scoped_require 'contrast/core_extensions/assess/fiber'
43
+ cs__scoped_require 'contrast/core_extensions/assess/hash'
44
+ cs__scoped_require 'contrast/core_extensions/assess/kernel'
45
+ cs__scoped_require 'contrast/core_extensions/assess/regexp'
46
+ cs__scoped_require 'contrast/core_extensions/assess/module'
47
+ cs__scoped_require 'contrast/core_extensions/assess/basic_object'
48
+ cs__scoped_require 'contrast/core_extensions/assess/tilt_template_trigger'
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,58 @@
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
+ cs__scoped_require 'contrast/agent/patching/policy/patcher'
5
+ cs__scoped_require 'contrast/components/interface'
6
+
7
+ # This is our patch of the Array class required to handle propagation
8
+ # Disclaimer: there may be a better way, but we're in a 'get it work' state.
9
+ # Hopefully, we'll be in a 'get it right' state soon.
10
+ class Array
11
+ include Contrast::Components::Interface
12
+
13
+ access_component :scope
14
+
15
+ ARRAY_JOIN_HASH = {
16
+ 'class_name' => 'Array',
17
+ 'instance_method' => true,
18
+ 'method_visibility' => 'public',
19
+ 'method_name' => 'join',
20
+ 'action' => 'CUSTOM',
21
+ 'source' => 'O',
22
+ 'target' => 'R',
23
+ 'patch_class' => 'NOOP',
24
+ 'patch_method' => '__cs_track_join'
25
+ }.cs__freeze
26
+ ARRAY_JOIN_NODE = Contrast::Agent::Assess::Policy::PropagationNode.new(ARRAY_JOIN_HASH)
27
+
28
+ # When you call join, they use an internal thing, so there's no good way to get at the thing being returned.
29
+ # Multiple Strings are appended with the #join method. Because that
30
+ # operation happens in C, we have to do it here rather than rely on the
31
+ # patch of our String append or concat methods.
32
+ def __cs_track_join separator, ret
33
+ return ret if Contrast::Agent::Patching::Policy::Patcher.skip_assess_analysis?
34
+
35
+ with_contrast_scope do
36
+ shift = 0
37
+ separator_length = separator.nil? ? 0 : separator.to_s.length
38
+ each do |obj|
39
+ if obj # skip nil here
40
+ ret.cs__copy_from(obj, shift)
41
+ shift += obj.to_s.length
42
+ end
43
+ shift += separator_length
44
+ end
45
+ return ret unless ret.cs__tracked?
46
+
47
+ ret.cs__properties.cleanup_tags
48
+ ret.cs__properties.build_event(
49
+ ARRAY_JOIN_NODE,
50
+ ret,
51
+ self,
52
+ ret,
53
+ [separator])
54
+ ret
55
+ end
56
+ end
57
+ end
58
+ cs__scoped_require 'cs__assess_array/cs__assess_array'
@@ -0,0 +1,145 @@
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
+ cs__scoped_require 'contrast/agent/assess/properties'
5
+ cs__scoped_require 'contrast/agent/assess/frozen_properties'
6
+ cs__scoped_require 'contrast/agent/assess/insulator'
7
+
8
+ module Contrast
9
+ module CoreExtensions
10
+ module Assess
11
+ # This module is responsible for maintaining the data we need to
12
+ # construct a trace event for the object in which it is included. Rather
13
+ # than have this code all over the place, any class that wants to use
14
+ # dataflow features should be sent
15
+ # 'include Contrast::CoreExtensions::Assess::AssessExtension'
16
+ module AssessExtension
17
+ include Contrast::Utils::ScopeUtil
18
+
19
+ # Lazily build properties object. Only objects that have been tracked
20
+ # will have the @_cs__properties, but all will respond to the
21
+ # cs__properties method call. You should only call this method if you
22
+ # either intend to start tracking an object or you have already checked
23
+ # cs__tracked? and it is true.
24
+ def cs__properties
25
+ # If this object was tracked before being frozen, it'll have
26
+ # mutable properties we need inside of the insulator @_cs__properties
27
+ if cs__frozen?
28
+ if instance_variable_defined?(:@_cs__properties)
29
+ @_cs__properties.properties
30
+ else
31
+ Contrast::Agent::Assess::Insulator.generate_frozen.properties
32
+ end
33
+ else
34
+ @_cs__properties ||= Contrast::Agent::Assess::Insulator.generate
35
+ @_cs__properties.properties
36
+ end
37
+ end
38
+
39
+ def cs__properties?
40
+ instance_variable_defined?(:@_cs__properties)
41
+ end
42
+
43
+ # This is a way to check if we are already tracking an object without
44
+ # adding tracking to it. If the object already has been tracked we will
45
+ # return the tracking state of its properties. If the object hasn't
46
+ # already been tracked we will return false without starting to track
47
+ # it
48
+ def cs__tracked?
49
+ cs__properties? && cs__properties.tracked?
50
+ end
51
+
52
+ def cs__reset_properties
53
+ return unless cs__properties?
54
+
55
+ @_cs__properties = nil
56
+ end
57
+
58
+ # copy tags and info from object to self if object support methods
59
+ # obj: the object from which to copy tags and events
60
+ # shift: how far to shift the tags, negative moves left
61
+ # skip_tags: array of tags to skip copying
62
+ def cs__copy_from obj, shift = 0, skip_tags = nil
63
+ return if obj.equal?(self)
64
+ return unless Contrast::Utils::DuckUtils.quacks_to?(obj,
65
+ :cs__tracked?)
66
+ return unless obj.cs__tracked?
67
+ return if cs__properties == Contrast::Agent::Assess::Insulator.generate_frozen.properties
68
+
69
+ # This was fun to find...
70
+ # the clone and dup methods don't apply to instance variables in the
71
+ # cloned/ duped thing, so the arrays in the properties were the same.
72
+ # The most infinite of infinite loops ensued.
73
+ # DO NOT TAKE THIS OUT!
74
+ cs__reset_properties if obj.cs__properties == cs__properties
75
+
76
+ obj.cs__properties.events.each do |event|
77
+ cs__properties.events << event
78
+ end
79
+
80
+ obj.cs__properties.tag_keys.each do |key|
81
+ next if skip_tags&.include?(key)
82
+
83
+ new_tags = []
84
+ value = obj.cs__properties.fetch_tag(key)
85
+ value.each do |tag|
86
+ new_tags << tag.copy_modified(shift)
87
+ end
88
+ existing = cs__properties.fetch_tag(key)
89
+ if existing
90
+ existing.concat(new_tags)
91
+ else
92
+ cs__properties.set_tags(key, new_tags)
93
+ end
94
+ end
95
+ end
96
+
97
+ # Some propagation occurred, but we're not sure what the
98
+ # exact transformation was. To be safe, we just explode
99
+ # all the tags from the source to the return.
100
+ #
101
+ # If the return already had that tag, the existing tag
102
+ # range is recycled to save us an object.
103
+ def cs__splat_tags ret, source = self
104
+ return unless Contrast::Utils::DuckUtils.quacks_to?(
105
+ ret,
106
+ :cs__tracked?)
107
+
108
+ splat_source = Contrast::Utils::DuckUtils.quacks_to?(
109
+ source,
110
+ :cs__tracked?)
111
+ splat_source &&= source.cs__tracked?
112
+ if splat_source
113
+ length = Contrast::Utils::StringUtils.ret_length(ret)
114
+ source.cs__properties.tag_keys.each do |key|
115
+ existing = ret.cs__properties.fetch_tag(key)
116
+ # if the tag already exists, drop all but the first range
117
+ # then change that range to cover the entire return
118
+ if existing
119
+ existing.drop(existing.length - 1)
120
+ range = existing[0]
121
+ range.repurpose(0, length)
122
+ else
123
+ span = Contrast::Agent::Assess::AdjustedSpan.new(0, length)
124
+ ret.cs__properties.add_tag(key, span)
125
+ end
126
+ end
127
+ end
128
+ return unless ret.cs__tracked?
129
+
130
+ length ||= Contrast::Utils::StringUtils.ret_length(ret)
131
+ ret.cs__properties.tag_keys.each do |key|
132
+ next unless key
133
+
134
+ existing = ret.cs__properties.fetch_tag(key)
135
+ next unless existing
136
+
137
+ existing.each do |range|
138
+ range.update_end(length) if range.end_idx > length
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
145
+ end