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,192 @@
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/core_extensions/object'
5
+
6
+ module Contrast
7
+ module Agent
8
+ module Patching
9
+ module Policy
10
+ # This indicates the status of the Module into which Contrast is being
11
+ # woven
12
+ class PatchStatus
13
+ class << self
14
+ # Gives the current status for the provided module, setting one if
15
+ # one does not exist.
16
+ #
17
+ # @param mod [Module] the Module for which the status is asked
18
+ # @return [Contrast::Agent::Patching::Policy::PolicyStatus]
19
+ def get_status mod
20
+ if mod.cs__const_defined?(status_key, false)
21
+ mod.cs__const_get(status_key, false)
22
+ else
23
+ s = new
24
+ mod.cs__const_set(status_key, s)
25
+ s
26
+ end
27
+ end
28
+
29
+ # Allows our C patches to look up the :MethodPolicy for a given
30
+ # Module and method
31
+ #
32
+ # @param mod [Module or Class] the entity on which the patch has
33
+ # been placed
34
+ # @param method [Symbol] the name of the method to which the patch
35
+ # applies
36
+ # @param is_instance_method [Boolean] is the method being patched
37
+ # an instance method or not (not implying class method).
38
+ # @return [Contrast::Agent::Patching::Policy::MethodPolicy]
39
+ def info_for mod, method, is_instance_method
40
+ mod = mod.cs__class unless mod.cs__is_a?(Module)
41
+ method_key = method_name_key(method, is_instance_method)
42
+ # Ideally, we'll get to a point where this is all that is needed
43
+ ret = find_info_for_one(mod, method_key)
44
+ return ret if ret
45
+
46
+ # But to start, the lookup will be on the ancestor, not the
47
+ # calling class. We need to traverse the ancestors, included
48
+ # modules, and Module itself the first time a method is called in
49
+ # a given class. Then we save that lookup to the class
50
+ ret = find_info_for(mod.ancestors, method_key)
51
+ ret ||= find_info_for(mod.cs__singleton_class.included_modules, method_key)
52
+ ret ||= find_info_for(MOD_ARRAY, method_key)
53
+ update_holder(mod, method_key, ret) if ret
54
+ ret
55
+ end
56
+
57
+ # Allows our C patches to set the :MethodPolicy for a given
58
+ # Module and method
59
+ #
60
+ # @param mod [Module or Class] the entity on which the patch will
61
+ # be placed
62
+ # @param method [Symbol] the name of the method to which the patch
63
+ # applies
64
+ # @param method_policy [:MethodPolicy] the policy that applies to
65
+ # the given mod & method
66
+ # @param is_instance_method [Boolean] is the method being patched
67
+ # an instance method or not (not implying class method).
68
+ # @param cs_method [Symbol] the name to which the original method
69
+ # was aliased, cached for performance reasons
70
+ def set_info_for mod, method, method_policy, is_instance_method, cs_method
71
+ mod.instance_variable_set(method_info_key, {}) unless mod.instance_variable_defined?(method_info_key)
72
+ holder = mod.instance_variable_get(method_info_key)
73
+ holder[method_name_key(method, is_instance_method)] = [method_policy, cs_method] unless holder.key?(method)
74
+ end
75
+
76
+ private
77
+
78
+ def method_info_key
79
+ :@cs__patched_method_info
80
+ end
81
+
82
+ # holder for each method - instance combination we've seen, done to
83
+ # avoid rebuilding the key on every method invocation.
84
+ def translated_names
85
+ @_translated_names ||= {}
86
+ end
87
+
88
+ # @param method [Symbol] the name of the method to which the patch
89
+ # applies
90
+ # @param is_instance_method [Boolean] is the method being patched
91
+ # an instance method or not (not implying class method).
92
+ # @return [Symbol] :"method[true|false]"
93
+ def method_name_key method, is_instance_method
94
+ translated_names[method] = [] unless translated_names.key?(method)
95
+ pre_built = translated_names[method]
96
+ idx = is_instance_method ? 0 : 1
97
+ pre_built[idx] = :"#{ method }#{ is_instance_method }" unless pre_built[idx]
98
+ pre_built[idx]
99
+ end
100
+
101
+ def status_key
102
+ :CONTRAST_PATCH_POLICY_STATUS
103
+ end
104
+
105
+ def update_holder mod, method, ret
106
+ mod.instance_variable_set(method_info_key, {}) unless mod.instance_variable_defined?(method_info_key)
107
+ holder = mod.instance_variable_get(method_info_key)
108
+ holder[method] = ret
109
+ end
110
+
111
+ def find_info_for candidates, method
112
+ candidates.each do |candidate|
113
+ new_ret = find_info_for_one(candidate, method)
114
+ return new_ret if new_ret
115
+ end
116
+ nil
117
+ end
118
+
119
+ def find_info_for_one mod, method
120
+ return unless mod.instance_variable_defined?(method_info_key)
121
+
122
+ holder = mod.instance_variable_get(method_info_key)
123
+ return unless holder&.key?(method)
124
+
125
+ holder[method]
126
+ end
127
+
128
+ MOD_ARRAY = [Module].cs__freeze
129
+ end
130
+
131
+ attr_reader :patch_status, :rewrite_status
132
+
133
+ def patching!
134
+ @patch_status = :PATCHING
135
+ end
136
+
137
+ def partial_patch!
138
+ @patch_status = :PARTIAL
139
+ end
140
+
141
+ def no_patch!
142
+ @patch_status = :NONE
143
+ end
144
+
145
+ def patched!
146
+ @patch_status = :PATCHED
147
+ end
148
+
149
+ def failed_patch!
150
+ @patch_status = :FAILED
151
+ end
152
+
153
+ def patching?
154
+ @patch_status == :PATCHING
155
+ end
156
+
157
+ def patched?
158
+ @patch_status == :PATCHED ||
159
+ @patch_status == :NONE ||
160
+ @patch_status == :FAILED
161
+ end
162
+
163
+ def rewriting!
164
+ @rewrite_status = :REWRITING
165
+ end
166
+
167
+ def no_rewrite!
168
+ @rewrite_status = :NO_REWRITE
169
+ end
170
+
171
+ def rewritten!
172
+ @rewrite_status = :REWRITTEN
173
+ end
174
+
175
+ def failed_rewrite!
176
+ @rewrite_status = :FAILED_REWRITE
177
+ end
178
+
179
+ def rewriting?
180
+ @rewrite_status == :REWRITING
181
+ end
182
+
183
+ def rewritten?
184
+ @rewrite_status == :REWRITTEN ||
185
+ @rewrite_status == :NO_REWRITE ||
186
+ @rewrite_status == :FAILED_REWRITE
187
+ end
188
+ end
189
+ end
190
+ end
191
+ end
192
+ end
@@ -0,0 +1,310 @@
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 'monitor'
5
+
6
+ # base
7
+ cs__scoped_require 'contrast/agent/patching/policy/patch_status'
8
+ cs__scoped_require 'contrast/agent/patching/policy/method_policy'
9
+ cs__scoped_require 'contrast/agent/patching/policy/module_policy'
10
+ cs__scoped_require 'contrast/agent/patching/policy/policy_unpatcher'
11
+ cs__scoped_require 'contrast/components/interface'
12
+ cs__scoped_require 'contrast/utils/class_util'
13
+ cs__scoped_require 'contrast/utils/scope_util'
14
+
15
+ # assess
16
+ cs__scoped_require 'contrast/agent/assess/policy/policy'
17
+ cs__scoped_require 'contrast/agent/assess/policy/policy_scanner'
18
+ cs__scoped_require 'contrast/agent/assess/policy/rewriter_patch'
19
+ cs__scoped_require 'contrast/agent/assess/policy/source_method'
20
+ cs__scoped_require 'contrast/agent/assess/policy/trigger_method'
21
+
22
+ # deadzone
23
+ cs__scoped_require 'contrast/agent/deadzone/policy/policy'
24
+
25
+ # inventory
26
+ cs__scoped_require 'contrast/agent/inventory/policy/policy'
27
+
28
+ # protect
29
+ cs__scoped_require 'contrast/agent/protect/policy/policy'
30
+
31
+ # patch
32
+ cs__scoped_require 'contrast/agent/patching/policy/patch'
33
+
34
+ # after load patched
35
+ cs__scoped_require 'contrast/agent/patching/policy/after_load_patcher'
36
+
37
+ module Contrast
38
+ module Agent
39
+ module Patching
40
+ module Policy
41
+ # This is how we patch into our customer's code. It provides a way to
42
+ # track which classes we need to patch into and, once we've woven,
43
+ # provides a map for which methods our renamed functions need to call
44
+ # and how.
45
+ module Patcher
46
+ extend Contrast::Utils::ScopeUtil
47
+ extend Contrast::Agent::Patching::Policy::AfterLoadPatcher
48
+
49
+ include Contrast::Components::Interface
50
+ access_component :logging, :analysis, :agent, :scope
51
+
52
+ class << self
53
+ # Hook to install the Contrast changes needed to allow for the
54
+ # instrumentation of the application - this only occurs once, during
55
+ # startup to catchup on everything we didn't see get loaded
56
+ def patch
57
+ logger.debug_with_time("\tPatching") do
58
+ catchup_after_load_patches
59
+ patch_methods
60
+ Contrast::Agent::Assess::Policy::RewriterPatch.rewrite_interpolations
61
+ Contrast::Agent::Patching::Policy::PolicyUnpatcher.revert_conflicting_patches
62
+ end
63
+ end
64
+
65
+ # Hook to only monkeypatch Contrast. This will not trigger any
66
+ # other functions, like rewriting or scanning. Exposed for those
67
+ # situations, like ActiveRecord dynamically defining functions,
68
+ # where only a subset of the Assess changes are needed.
69
+ PATCH_MONITOR = Monitor.new
70
+
71
+ def patch_methods
72
+ PATCH_MONITOR.synchronize do
73
+ t = Contrast::Agent::Thread.new do
74
+ synchronized_patch_methods
75
+ end
76
+ # aborting on exception makes exceptions propagate.
77
+ t.abort_on_exception = true
78
+ t.priority = Thread.current.priority + 1
79
+ t.join
80
+ end
81
+ end
82
+
83
+ # This method is called by TracePointHook to instrument a specific class during a require
84
+ # or eval of dynamic class definition
85
+ def patch_specific_module mod
86
+ mod_name = mod.cs__name
87
+ return unless Module.cs__truly_defined?(mod_name)
88
+
89
+ load_patches_for_module(mod_name)
90
+
91
+ return unless all_module_names.any? { |name| name == mod_name }
92
+
93
+ module_data = Contrast::Agent::ModuleData.new(mod, mod_name)
94
+ patch_into_module(module_data)
95
+ all_module_names.delete(mod_name) if status_type.get_status(mod).patched?
96
+ rescue StandardError => e
97
+ logger.error("Unable to patch into #{ mod_name }", e)
98
+ end
99
+
100
+ # We did it, team. We found a patcher(s) that applies to the given
101
+ # class (or module) and the given method. Time to do some tracking.
102
+ #
103
+ # @param mod [Module] the module in which the patch should be
104
+ # placed.
105
+ # @param methods [Array(Symbol)] all the instance or singleton
106
+ # methods in this clazz.
107
+ # @param method_policy [Contrast::Agent::Patching::Policy::MethodPolicy]
108
+ # the policy that applies to the given method_name.
109
+ # @return [Boolean] if patched, either by this invocation or a
110
+ # previous, or not
111
+ def patch_method mod, methods, method_policy
112
+ return false unless methods&.any? # don't even build the name if there are no methods
113
+
114
+ if Contrast::Utils::ClassUtil.prepended_method?(mod, method_policy)
115
+ Contrast::Agent::Patching::Policy::Patch.instrument_with_prepend(mod, method_policy)
116
+ else
117
+ Contrast::Agent::Patching::Policy::Patch.instrument_with_alias(mod, methods, method_policy)
118
+ end
119
+ end
120
+
121
+ private
122
+
123
+ POLICIES = [
124
+ Contrast::Agent::Assess::Policy::Policy,
125
+ Contrast::Agent::Inventory::Policy::Policy,
126
+ Contrast::Agent::Protect::Policy::Policy,
127
+ Contrast::Agent::Deadzone::Policy::Policy
128
+ ].cs__freeze
129
+
130
+ def status_type
131
+ Contrast::Agent::Patching::Policy::PatchStatus
132
+ end
133
+
134
+ # Find, and return, the constant with the given name. If none
135
+ # exists, return nil.
136
+ #
137
+ # @param name [String] the constant whose value should be retrieved
138
+ # @return [Object, nil]
139
+ def patchable name
140
+ return unless Module.cs__truly_defined?(name)
141
+
142
+ Module.cs__const_get(name)
143
+ end
144
+
145
+ # @return [Array<String>] the names of all the Modules for which
146
+ # there patches in our policies
147
+ def all_module_names
148
+ @_all_module_names ||= POLICIES.each_with_object(Set.new) { |policy, set| set.merge(policy.instance.module_names) }
149
+ end
150
+
151
+ # Hook to only monkeypatch Contrast. This will not trigger any
152
+ # other functions, like rewriting or scanning. This method should
153
+ # only be invoked by the patch_methods method above in order to
154
+ # ensure it is wrapped in a synchronize call
155
+ def synchronized_patch_methods
156
+ # logger.trace_with_time("\t\tRunning patching") do # TODO: RUBY-547
157
+ patched = []
158
+ all_module_names.each do |patchable_name|
159
+ patchable_mod = patchable(patchable_name)
160
+ next unless patchable_mod
161
+
162
+ module_data = Contrast::Agent::ModuleData.new(patchable_mod, patchable_name)
163
+ patch_into_module(module_data)
164
+ patched << patchable_name if status_type.get_status(patchable_mod).patched?
165
+ end
166
+ all_module_names.subtract(patched)
167
+ # end
168
+ end
169
+
170
+ # Given the patchers that apply to this class that may apply, patch
171
+ # Contrast method calls into the methods for which we have rules.
172
+ #
173
+ # @param module_data [Contrast::Agent::ModuleData] the module, and
174
+ # its name, that's being patched into
175
+ # @param redo_patch [Boolean] a trigger to force patching
176
+ # regardless of the state of the
177
+ # Contrast::Agent::Patching::Policy::PatchStatus status on the
178
+ # Module
179
+ def patch_into_module module_data, redo_patch = false
180
+ status = status_type.get_status(module_data.mod)
181
+ return if (status&.patched? || status&.patching?) && !redo_patch
182
+
183
+ # Begin patching our sources into the given clazz (or module)
184
+ # Any patcher that has the name of the clazz will be evaluated for
185
+ # patching.
186
+ # Find all the patchers that apply to this class, sorted by type.
187
+ module_policy = Contrast::Agent::Patching::Policy::ModulePolicy.create_module_policy(module_data.name)
188
+
189
+ clazz = module_data.mod
190
+
191
+ status = status_type.get_status(clazz)
192
+ return if (status.patched? || status.patching?) && !redo_patch
193
+
194
+ status.patching!
195
+ patched = include_module(module_data)
196
+
197
+ counts = 0
198
+ # Monkey patch any methods in this class that have matching nodes in the policy
199
+ unless module_policy.empty?
200
+ instance_methods = all_instance_methods(clazz, true)
201
+ singleton_methods = clazz.singleton_methods(false)
202
+ counts += patch_into_methods(clazz, instance_methods, module_policy, true)
203
+ counts += patch_into_methods(clazz, singleton_methods, module_policy, false)
204
+ counts = module_policy.num_expected_patches if adjust_for_prepend(clazz)
205
+ patched = true
206
+ end
207
+
208
+ if patched
209
+ if module_policy.num_expected_patches == counts
210
+ status.patched!
211
+ else
212
+ status.partial_patch!
213
+ end
214
+ else
215
+ status.no_patch!
216
+ end
217
+ rescue StandardError => e
218
+ status ||= status_type.get_status(module_data.mod)
219
+ status.failed_patch!
220
+ logger.warn(e, "Unable to patch into #{ module_data.name }")
221
+ ensure
222
+ logger.debug(nil, "Patching #{ module_data.name } resulted in #{ status_type.get_status(module_data.mod).patch_status }")
223
+ end
224
+
225
+ # Includes the given module with the
226
+ # Contrast::CoreExtensions::Assess::AssessExtension
227
+ # @param module_data [Contrast::Agent::ModuleData] the module, and
228
+ # its name, that's being patched into
229
+ def include_module module_data
230
+ return false unless Contrast::Agent::Assess::Policy::Policy.instance.tracked_classes.include?(module_data.name)
231
+
232
+ module_data.mod.send(:include, Contrast::CoreExtensions::Assess::AssessExtension)
233
+ true
234
+ end
235
+
236
+ # Get all of the instance methods on the given module, excluding
237
+ # those from super classes. this list will always include the
238
+ # initialize method
239
+ #
240
+ # @param mod [Module] The module from which to retrieve instance
241
+ # methods.
242
+ # @param private [Boolean] Indicate if the query should include
243
+ # private, as well as public, instance methods
244
+ # @return [Array<Symbol>]
245
+ def all_instance_methods mod, private = false
246
+ instance_methods = mod.instance_methods(false)
247
+ # C magic rb_define_global_function creates private instance
248
+ # methods. We need to instrument those dudes
249
+ # https://www.thecodingforums.com/threads/object-private_instance_methods-kernel-singleton_methods.843013/
250
+ instance_methods.concat(mod.private_instance_methods(false)) if private
251
+ # initialize is an exception to the inheritance rule.
252
+ instance_methods << :initialize unless instance_methods.include?(:initialize)
253
+ instance_methods
254
+ end
255
+
256
+ # We've found the patchers that apply to this class (or module). Now we'll
257
+ # filter on the given method.
258
+ #
259
+ # @param mod [Module] The module from which to retrieve instance
260
+ # methods.
261
+ # @param methods [Array<Symbol>] The names of all the methods in
262
+ # in this module
263
+ # @param module_policy [Contrast::Agent::Patching::Policy::ModulePolicy]
264
+ # All the patchers that apply to this class, sorted by type.
265
+ # @param is_instance_method [Boolean] Indicates if these methods
266
+ # are the instance or singleton methods for this module.
267
+ # @return [Integer] number of methods patched
268
+ def patch_into_methods mod, methods, module_policy, is_instance_method
269
+ count = 0
270
+ methods.each do |method|
271
+ method_policy = Contrast::Agent::Patching::Policy::MethodPolicy.build_method_policy(method, module_policy, is_instance_method)
272
+ next if method_policy.empty?
273
+
274
+ patched = patch_method(mod, methods, method_policy)
275
+ count += 1 if patched
276
+ end
277
+ count
278
+ end
279
+
280
+ # CGI falls pray to the weirdness that is the history of a
281
+ # previously included Module being prepended - the class that has
282
+ # already included the Module does not learn about the prepend and
283
+ # it has to be reapplied.
284
+ # TODO: RUBY-620 should remove the need for this
285
+ #
286
+ # @param mod[Module] the Module for which a prepend action needs to
287
+ # be accounted
288
+ # @return [Boolean] if an adjustment was made or not
289
+ def adjust_for_prepend mod
290
+ return false unless mod.cs__name == 'CGI::Util'
291
+
292
+ CGI.include(CGI::Util)
293
+ CGI.extend(CGI::Util)
294
+ true
295
+ end
296
+ end
297
+ end
298
+ end
299
+ end
300
+ end
301
+ end
302
+
303
+ # core extensions
304
+ cs__scoped_require 'contrast/core_extensions/module'
305
+ cs__scoped_require 'contrast/core_extensions/assess'
306
+ cs__scoped_require 'contrast/core_extensions/inventory'
307
+ cs__scoped_require 'contrast/core_extensions/protect'
308
+ cs__scoped_require 'contrast/core_extensions/protect/kernel'
309
+
310
+ cs__scoped_require 'cs__contrast_patch/cs__contrast_patch'