arachni 1.3.2 → 1.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 (727) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +108 -0
  3. data/Gemfile +2 -6
  4. data/LICENSE.md +1 -1
  5. data/README.md +34 -16
  6. data/Rakefile +1 -1
  7. data/arachni.gemspec +28 -20
  8. data/bin/arachni +1 -1
  9. data/bin/arachni_console +1 -1
  10. data/bin/arachni_multi +1 -1
  11. data/bin/arachni_reporter +1 -1
  12. data/bin/arachni_rest_server +13 -0
  13. data/bin/arachni_restore +1 -1
  14. data/bin/arachni_rpc +1 -1
  15. data/bin/arachni_rpcd +1 -1
  16. data/bin/arachni_rpcd_monitor +1 -1
  17. data/bin/arachni_script +1 -1
  18. data/components/checks/active/code_injection.rb +8 -10
  19. data/components/checks/active/code_injection_php_input_wrapper.rb +5 -6
  20. data/components/checks/active/code_injection_timing.rb +1 -1
  21. data/components/checks/active/csrf.rb +1 -1
  22. data/components/checks/active/file_inclusion.rb +20 -26
  23. data/components/checks/active/ldap_injection.rb +4 -5
  24. data/components/checks/active/no_sql_injection.rb +11 -20
  25. data/components/checks/active/no_sql_injection/substrings/mongodb +1 -0
  26. data/components/checks/active/no_sql_injection_differential.rb +3 -4
  27. data/components/checks/active/os_cmd_injection.rb +5 -9
  28. data/components/checks/active/os_cmd_injection_timing.rb +1 -1
  29. data/components/checks/active/path_traversal.rb +4 -17
  30. data/components/checks/active/response_splitting.rb +8 -2
  31. data/components/checks/active/rfi.rb +4 -5
  32. data/components/checks/active/session_fixation.rb +9 -3
  33. data/components/checks/active/source_code_disclosure.rb +5 -20
  34. data/components/checks/active/sql_injection.rb +30 -18
  35. data/components/checks/active/sql_injection/{regexp_ignore.txt → ignore_substrings} +0 -0
  36. data/components/checks/active/sql_injection/regexps/db2.yaml +2 -0
  37. data/components/checks/active/sql_injection/regexps/frontbase.yaml +1 -0
  38. data/components/checks/active/sql_injection/regexps/informix.yaml +1 -0
  39. data/components/checks/active/sql_injection/regexps/ingres.yaml +2 -0
  40. data/components/checks/active/sql_injection/regexps/maxdb.yaml +2 -0
  41. data/components/checks/active/sql_injection/regexps/mssql.yaml +8 -0
  42. data/components/checks/active/sql_injection/regexps/mysql.yaml +4 -0
  43. data/components/checks/active/sql_injection/regexps/oracle.yaml +4 -0
  44. data/components/checks/active/sql_injection/regexps/pgsql.yaml +3 -0
  45. data/components/checks/active/sql_injection/regexps/sqlite.yaml +2 -0
  46. data/components/checks/active/sql_injection/regexps/sybase.yaml +2 -0
  47. data/components/checks/active/sql_injection/substrings/access +3 -0
  48. data/components/checks/active/sql_injection/substrings/db2 +2 -0
  49. data/components/checks/active/sql_injection/{patterns → substrings}/emc +1 -1
  50. data/components/checks/active/sql_injection/{patterns → substrings}/firebird +0 -1
  51. data/components/checks/active/sql_injection/substrings/hsqldb +1 -0
  52. data/components/checks/active/sql_injection/{patterns → substrings}/informix +1 -2
  53. data/components/checks/active/sql_injection/substrings/ingres +1 -0
  54. data/components/checks/active/sql_injection/{patterns → substrings}/interbase +0 -0
  55. data/components/checks/active/sql_injection/substrings/mssql +17 -0
  56. data/components/checks/active/sql_injection/{patterns → substrings}/mysql +3 -6
  57. data/components/checks/active/sql_injection/substrings/oracle +2 -0
  58. data/components/checks/active/sql_injection/{patterns → substrings}/pgsql +3 -6
  59. data/components/checks/active/sql_injection/substrings/sqlite +3 -0
  60. data/components/checks/active/sql_injection/substrings/sybase +1 -0
  61. data/components/checks/active/sql_injection_differential.rb +5 -7
  62. data/components/checks/active/sql_injection_differential/payloads.txt +1 -1
  63. data/components/checks/active/sql_injection_timing.rb +1 -1
  64. data/components/checks/active/trainer.rb +5 -4
  65. data/components/checks/active/unvalidated_redirect.rb +1 -1
  66. data/components/checks/active/unvalidated_redirect_dom.rb +1 -1
  67. data/components/checks/active/xpath_injection.rb +3 -4
  68. data/components/checks/active/xss.rb +33 -12
  69. data/components/checks/active/xss_dom.rb +7 -4
  70. data/components/checks/active/xss_dom_script_context.rb +1 -1
  71. data/components/checks/active/xss_event.rb +43 -20
  72. data/components/checks/active/xss_path.rb +5 -4
  73. data/components/checks/active/xss_script_context.rb +41 -11
  74. data/components/checks/active/xss_tag.rb +14 -15
  75. data/components/checks/active/xxe.rb +5 -16
  76. data/components/checks/passive/allowed_methods.rb +1 -1
  77. data/components/checks/passive/backdoors.rb +4 -2
  78. data/components/checks/passive/backup_directories.rb +4 -2
  79. data/components/checks/passive/backup_files.rb +4 -2
  80. data/components/checks/passive/common_admin_interfaces.rb +4 -3
  81. data/components/checks/passive/common_directories.rb +3 -1
  82. data/components/checks/passive/common_files.rb +3 -1
  83. data/components/checks/passive/directory_listing.rb +4 -4
  84. data/components/checks/passive/grep/captcha.rb +1 -1
  85. data/components/checks/passive/grep/cookie_set_for_parent_domain.rb +1 -1
  86. data/components/checks/passive/grep/credit_card.rb +5 -7
  87. data/components/checks/passive/grep/cvs_svn_users.rb +1 -1
  88. data/components/checks/passive/grep/emails.rb +135 -8
  89. data/components/checks/passive/grep/form_upload.rb +1 -1
  90. data/components/checks/passive/grep/hsts.rb +4 -3
  91. data/components/checks/passive/grep/html_objects.rb +1 -1
  92. data/components/checks/passive/grep/http_only_cookies.rb +5 -3
  93. data/components/checks/passive/grep/insecure_cookies.rb +5 -3
  94. data/components/checks/passive/grep/insecure_cors_policy.rb +1 -1
  95. data/components/checks/passive/grep/mixed_resource.rb +1 -1
  96. data/components/checks/passive/grep/password_autocomplete.rb +1 -1
  97. data/components/checks/passive/grep/private_ip.rb +1 -1
  98. data/components/checks/passive/grep/ssn.rb +6 -3
  99. data/components/checks/passive/grep/unencrypted_password_forms.rb +1 -1
  100. data/components/checks/passive/grep/x_frame_options.rb +4 -3
  101. data/components/checks/passive/htaccess_limit.rb +1 -1
  102. data/components/checks/passive/http_put.rb +1 -1
  103. data/components/checks/passive/insecure_client_access_policy.rb +2 -2
  104. data/components/checks/passive/insecure_cross_domain_policy_access.rb +2 -2
  105. data/components/checks/passive/insecure_cross_domain_policy_headers.rb +2 -2
  106. data/components/checks/passive/interesting_responses.rb +1 -1
  107. data/components/checks/passive/localstart_asp.rb +1 -1
  108. data/components/checks/passive/origin_spoof_access_restriction_bypass.rb +1 -1
  109. data/components/checks/passive/webdav.rb +1 -1
  110. data/components/checks/passive/xst.rb +1 -1
  111. data/components/fingerprinters/frameworks/aspx_mvc.rb +1 -1
  112. data/components/fingerprinters/frameworks/cakephp.rb +1 -1
  113. data/components/fingerprinters/frameworks/cherrypy.rb +1 -1
  114. data/components/fingerprinters/frameworks/django.rb +1 -1
  115. data/components/fingerprinters/frameworks/jsf.rb +1 -1
  116. data/components/fingerprinters/frameworks/nette.rb +1 -1
  117. data/components/fingerprinters/frameworks/rack.rb +1 -1
  118. data/components/fingerprinters/frameworks/rails.rb +1 -1
  119. data/components/fingerprinters/frameworks/symfony.rb +1 -1
  120. data/components/fingerprinters/languages/asp.rb +1 -1
  121. data/components/fingerprinters/languages/aspx.rb +1 -1
  122. data/components/fingerprinters/languages/java.rb +1 -1
  123. data/components/fingerprinters/languages/php.rb +1 -1
  124. data/components/fingerprinters/languages/python.rb +1 -1
  125. data/components/fingerprinters/languages/ruby.rb +1 -1
  126. data/components/fingerprinters/os/bsd.rb +1 -1
  127. data/components/fingerprinters/os/linux.rb +1 -1
  128. data/components/fingerprinters/os/solaris.rb +1 -1
  129. data/components/fingerprinters/os/unix.rb +1 -1
  130. data/components/fingerprinters/os/windows.rb +1 -1
  131. data/components/fingerprinters/servers/apache.rb +1 -1
  132. data/components/fingerprinters/servers/gunicorn.rb +1 -1
  133. data/components/fingerprinters/servers/iis.rb +1 -1
  134. data/components/fingerprinters/servers/jetty.rb +1 -1
  135. data/components/fingerprinters/servers/nginx.rb +1 -1
  136. data/components/fingerprinters/servers/tomcat.rb +1 -1
  137. data/components/path_extractors/anchors.rb +1 -1
  138. data/components/path_extractors/areas.rb +1 -1
  139. data/components/path_extractors/comments.rb +1 -1
  140. data/components/path_extractors/data_url.rb +1 -1
  141. data/components/path_extractors/forms.rb +1 -1
  142. data/components/path_extractors/frames.rb +1 -1
  143. data/components/path_extractors/generic.rb +1 -1
  144. data/components/path_extractors/links.rb +1 -1
  145. data/components/path_extractors/meta_refresh.rb +3 -3
  146. data/components/path_extractors/scripts.rb +1 -1
  147. data/components/plugins/autologin.rb +16 -24
  148. data/components/plugins/beep_notify.rb +1 -1
  149. data/components/plugins/content_types.rb +1 -1
  150. data/components/plugins/cookie_collector.rb +1 -1
  151. data/components/plugins/defaults/autothrottle.rb +1 -1
  152. data/components/plugins/defaults/healthmap.rb +1 -1
  153. data/components/plugins/defaults/meta/remedies/discovery.rb +10 -9
  154. data/components/plugins/defaults/meta/remedies/timing_attacks.rb +1 -1
  155. data/components/plugins/defaults/meta/uniformity.rb +1 -1
  156. data/components/plugins/email_notify.rb +3 -5
  157. data/components/plugins/exec.rb +1 -1
  158. data/components/plugins/form_dicattack.rb +1 -1
  159. data/components/plugins/headers_collector.rb +1 -1
  160. data/components/plugins/http_dicattack.rb +1 -1
  161. data/components/plugins/login_script.rb +47 -22
  162. data/components/plugins/metrics.rb +1 -1
  163. data/components/plugins/proxy.rb +69 -44
  164. data/components/plugins/proxy/panel/help.html.erb +1 -18
  165. data/components/plugins/proxy/panel/inspect.html.erb +4 -3
  166. data/components/plugins/proxy/panel/page_accordion.html.erb +78 -43
  167. data/components/plugins/proxy/panel/panel.html.erb +2 -7
  168. data/components/plugins/proxy/template_scope.rb +1 -1
  169. data/components/plugins/restrict_to_dom_state.rb +3 -15
  170. data/components/plugins/script.rb +1 -1
  171. data/components/plugins/uncommon_headers.rb +1 -1
  172. data/components/plugins/vector_collector.rb +1 -1
  173. data/components/plugins/vector_feed.rb +3 -11
  174. data/components/plugins/waf_detector.rb +1 -1
  175. data/components/reporters/ap.rb +1 -1
  176. data/components/reporters/html.rb +2 -2
  177. data/components/reporters/json.rb +1 -1
  178. data/components/reporters/marshal.rb +1 -1
  179. data/components/reporters/plugin_formatters/html/autologin.rb +1 -1
  180. data/components/reporters/plugin_formatters/html/content_types.rb +1 -1
  181. data/components/reporters/plugin_formatters/html/cookie_collector.rb +1 -1
  182. data/components/reporters/plugin_formatters/html/exec.rb +1 -1
  183. data/components/reporters/plugin_formatters/html/form_dicattack.rb +1 -1
  184. data/components/reporters/plugin_formatters/html/healthmap.rb +1 -1
  185. data/components/reporters/plugin_formatters/html/http_dicattack.rb +1 -1
  186. data/components/reporters/plugin_formatters/html/login_script.rb +1 -1
  187. data/components/reporters/plugin_formatters/html/metrics.rb +1 -1
  188. data/components/reporters/plugin_formatters/html/uncommon_headers.rb +1 -1
  189. data/components/reporters/plugin_formatters/html/uniformity.rb +1 -1
  190. data/components/reporters/plugin_formatters/html/vector_collector.rb +1 -1
  191. data/components/reporters/plugin_formatters/html/waf_detector.rb +1 -1
  192. data/components/reporters/plugin_formatters/stdout/autologin.rb +1 -1
  193. data/components/reporters/plugin_formatters/stdout/content_types.rb +1 -1
  194. data/components/reporters/plugin_formatters/stdout/cookie_collector.rb +1 -1
  195. data/components/reporters/plugin_formatters/stdout/exec.rb +1 -1
  196. data/components/reporters/plugin_formatters/stdout/form_dicattack.rb +1 -1
  197. data/components/reporters/plugin_formatters/stdout/healthmap.rb +1 -1
  198. data/components/reporters/plugin_formatters/stdout/http_dicattack.rb +1 -1
  199. data/components/reporters/plugin_formatters/stdout/login_script.rb +1 -1
  200. data/components/reporters/plugin_formatters/stdout/metrics.rb +1 -1
  201. data/components/reporters/plugin_formatters/stdout/uncommon_headers.rb +1 -1
  202. data/components/reporters/plugin_formatters/stdout/uniformity.rb +1 -1
  203. data/components/reporters/plugin_formatters/stdout/vector_collector.rb +1 -1
  204. data/components/reporters/plugin_formatters/stdout/waf_detector.rb +1 -1
  205. data/components/reporters/plugin_formatters/xml/autologin.rb +1 -1
  206. data/components/reporters/plugin_formatters/xml/content_types.rb +1 -1
  207. data/components/reporters/plugin_formatters/xml/cookie_collector.rb +1 -1
  208. data/components/reporters/plugin_formatters/xml/exec.rb +1 -1
  209. data/components/reporters/plugin_formatters/xml/form_dicattack.rb +1 -1
  210. data/components/reporters/plugin_formatters/xml/healthmap.rb +1 -1
  211. data/components/reporters/plugin_formatters/xml/http_dicattack.rb +1 -1
  212. data/components/reporters/plugin_formatters/xml/login_script.rb +1 -1
  213. data/components/reporters/plugin_formatters/xml/metrics.rb +1 -1
  214. data/components/reporters/plugin_formatters/xml/uncommon_headers.rb +1 -1
  215. data/components/reporters/plugin_formatters/xml/uniformity.rb +1 -1
  216. data/components/reporters/plugin_formatters/xml/vector_collector.rb +1 -1
  217. data/components/reporters/plugin_formatters/xml/waf_detector.rb +1 -1
  218. data/components/reporters/stdout.rb +1 -1
  219. data/components/reporters/txt.rb +1 -1
  220. data/components/reporters/xml.rb +29 -4
  221. data/components/reporters/yaml.rb +1 -1
  222. data/lib/arachni.rb +48 -3
  223. data/lib/arachni/banner.rb +1 -1
  224. data/lib/arachni/browser.rb +601 -358
  225. data/lib/arachni/browser/element_locator.rb +25 -6
  226. data/lib/arachni/browser/javascript.rb +103 -35
  227. data/lib/arachni/browser/javascript/dom_monitor.rb +1 -1
  228. data/lib/arachni/browser/javascript/proxy.rb +28 -16
  229. data/lib/arachni/browser/javascript/proxy/stub.rb +1 -1
  230. data/lib/arachni/browser/javascript/scripts/dom_monitor.js +138 -67
  231. data/lib/arachni/browser/javascript/scripts/polyfills.js +28 -0
  232. data/lib/arachni/browser/javascript/scripts/taint_tracer.js +27 -6
  233. data/lib/arachni/browser/javascript/taint_tracer.rb +1 -1
  234. data/lib/arachni/browser/javascript/taint_tracer/frame.rb +1 -1
  235. data/lib/arachni/browser/javascript/taint_tracer/frame/called_function.rb +1 -1
  236. data/lib/arachni/browser/javascript/taint_tracer/sink/base.rb +1 -1
  237. data/lib/arachni/browser/javascript/taint_tracer/sink/data_flow.rb +1 -1
  238. data/lib/arachni/browser/javascript/taint_tracer/sink/execution_flow.rb +1 -1
  239. data/lib/arachni/browser_cluster.rb +10 -14
  240. data/lib/arachni/browser_cluster/job.rb +1 -1
  241. data/lib/arachni/browser_cluster/job/result.rb +1 -1
  242. data/lib/arachni/browser_cluster/jobs/browser_provider.rb +1 -1
  243. data/lib/arachni/browser_cluster/jobs/{resource_exploration.rb → dom_exploration.rb} +5 -5
  244. data/lib/arachni/browser_cluster/jobs/{resource_exploration → dom_exploration}/event_trigger.rb +7 -4
  245. data/lib/arachni/browser_cluster/jobs/{resource_exploration → dom_exploration}/event_trigger/result.rb +3 -3
  246. data/lib/arachni/browser_cluster/jobs/{resource_exploration → dom_exploration}/result.rb +2 -2
  247. data/lib/arachni/browser_cluster/jobs/taint_trace.rb +3 -3
  248. data/lib/arachni/browser_cluster/jobs/taint_trace/event_trigger.rb +2 -2
  249. data/lib/arachni/browser_cluster/jobs/taint_trace/event_trigger/result.rb +2 -2
  250. data/lib/arachni/browser_cluster/jobs/taint_trace/result.rb +1 -1
  251. data/lib/arachni/browser_cluster/worker.rb +12 -40
  252. data/lib/arachni/check.rb +1 -1
  253. data/lib/arachni/check/auditor.rb +15 -1
  254. data/lib/arachni/check/base.rb +1 -1
  255. data/lib/arachni/check/manager.rb +1 -1
  256. data/lib/arachni/component.rb +1 -1
  257. data/lib/arachni/component/base.rb +5 -5
  258. data/lib/arachni/component/manager.rb +39 -13
  259. data/lib/arachni/component/options.rb +1 -1
  260. data/lib/arachni/component/options/address.rb +1 -1
  261. data/lib/arachni/component/options/base.rb +1 -1
  262. data/lib/arachni/component/options/bool.rb +1 -1
  263. data/lib/arachni/component/options/float.rb +1 -1
  264. data/lib/arachni/component/options/int.rb +1 -1
  265. data/lib/arachni/component/options/multiple_choice.rb +1 -1
  266. data/lib/arachni/component/options/object.rb +1 -1
  267. data/lib/arachni/component/options/path.rb +1 -1
  268. data/lib/arachni/component/options/port.rb +1 -1
  269. data/lib/arachni/component/options/string.rb +1 -1
  270. data/lib/arachni/component/options/url.rb +1 -1
  271. data/lib/arachni/component/output.rb +1 -1
  272. data/lib/arachni/component/utilities.rb +1 -1
  273. data/lib/arachni/data.rb +1 -1
  274. data/lib/arachni/data/framework.rb +1 -1
  275. data/lib/arachni/data/framework/rpc.rb +1 -1
  276. data/lib/arachni/data/issues.rb +1 -1
  277. data/lib/arachni/data/plugins.rb +1 -1
  278. data/lib/arachni/data/session.rb +1 -1
  279. data/lib/arachni/element/base.rb +19 -5
  280. data/lib/arachni/element/body.rb +1 -1
  281. data/lib/arachni/element/capabilities/analyzable.rb +1 -1
  282. data/lib/arachni/element/capabilities/analyzable/differential.rb +15 -5
  283. data/lib/arachni/element/capabilities/analyzable/signature.rb +147 -89
  284. data/lib/arachni/element/capabilities/analyzable/timeout.rb +43 -16
  285. data/lib/arachni/element/capabilities/auditable.rb +20 -15
  286. data/lib/arachni/element/capabilities/dom_only.rb +5 -4
  287. data/lib/arachni/element/capabilities/inputtable.rb +62 -12
  288. data/lib/arachni/element/capabilities/mutable.rb +74 -13
  289. data/lib/arachni/element/capabilities/refreshable.rb +1 -1
  290. data/lib/arachni/element/capabilities/submittable.rb +5 -2
  291. data/lib/arachni/element/capabilities/with_auditor.rb +1 -1
  292. data/lib/arachni/element/capabilities/with_auditor/output.rb +5 -5
  293. data/lib/arachni/element/capabilities/with_dom.rb +1 -1
  294. data/lib/arachni/element/capabilities/with_node.rb +2 -2
  295. data/lib/arachni/element/capabilities/with_scope.rb +1 -1
  296. data/lib/arachni/element/capabilities/with_scope/scope.rb +1 -1
  297. data/lib/arachni/element/capabilities/with_source.rb +4 -4
  298. data/lib/arachni/element/cookie.rb +57 -34
  299. data/lib/arachni/element/cookie/capabilities/inputtable.rb +1 -1
  300. data/lib/arachni/element/cookie/capabilities/mutable.rb +10 -1
  301. data/lib/arachni/element/cookie/capabilities/with_dom.rb +1 -1
  302. data/lib/arachni/element/cookie/dom.rb +1 -1
  303. data/lib/arachni/element/dom.rb +1 -15
  304. data/lib/arachni/element/dom/capabilities/auditable.rb +1 -1
  305. data/lib/arachni/element/dom/capabilities/inputtable.rb +1 -1
  306. data/lib/arachni/element/dom/capabilities/locatable.rb +29 -0
  307. data/lib/arachni/element/dom/capabilities/mutable.rb +11 -1
  308. data/lib/arachni/element/dom/capabilities/submittable.rb +2 -2
  309. data/lib/arachni/element/form.rb +33 -14
  310. data/lib/arachni/element/form/capabilities/auditable.rb +1 -1
  311. data/lib/arachni/element/form/capabilities/mutable.rb +18 -17
  312. data/lib/arachni/element/form/capabilities/submittable.rb +1 -1
  313. data/lib/arachni/element/form/capabilities/with_dom.rb +2 -1
  314. data/lib/arachni/element/form/dom.rb +3 -2
  315. data/lib/arachni/element/generic_dom.rb +1 -1
  316. data/lib/arachni/element/header.rb +16 -4
  317. data/lib/arachni/element/header/capabilities/inputtable.rb +1 -1
  318. data/lib/arachni/element/header/capabilities/mutable.rb +11 -1
  319. data/lib/arachni/element/json.rb +2 -2
  320. data/lib/arachni/element/json/capabilities/inputtable.rb +1 -1
  321. data/lib/arachni/element/json/capabilities/mutable.rb +8 -2
  322. data/lib/arachni/element/link.rb +14 -7
  323. data/lib/arachni/element/link/capabilities/auditable.rb +1 -1
  324. data/lib/arachni/element/link/capabilities/submittable.rb +1 -1
  325. data/lib/arachni/element/link/capabilities/with_dom.rb +8 -1
  326. data/lib/arachni/element/link/dom.rb +2 -1
  327. data/lib/arachni/element/link/dom/capabilities/submittable.rb +1 -1
  328. data/lib/arachni/element/link_template.rb +8 -3
  329. data/lib/arachni/element/link_template/capabilities/auditable.rb +1 -1
  330. data/lib/arachni/element/link_template/capabilities/inputtable.rb +1 -1
  331. data/lib/arachni/element/link_template/capabilities/with_dom.rb +1 -1
  332. data/lib/arachni/element/link_template/dom.rb +2 -1
  333. data/lib/arachni/element/link_template/dom/capabilities/submittable.rb +1 -1
  334. data/lib/arachni/element/path.rb +1 -1
  335. data/lib/arachni/element/server.rb +3 -3
  336. data/lib/arachni/element/ui_form.rb +24 -21
  337. data/lib/arachni/element/ui_form/dom.rb +12 -3
  338. data/lib/arachni/element/ui_input.rb +17 -11
  339. data/lib/arachni/element/{input → ui_input}/dom.rb +11 -2
  340. data/lib/arachni/element/xml.rb +3 -3
  341. data/lib/arachni/element/xml/capabilities/inputtable.rb +7 -1
  342. data/lib/arachni/element/xml/capabilities/mutable.rb +7 -13
  343. data/lib/arachni/element_filter.rb +1 -1
  344. data/lib/arachni/error.rb +1 -1
  345. data/lib/arachni/ethon/easy.rb +1 -1
  346. data/lib/arachni/framework.rb +2 -5
  347. data/lib/arachni/framework/parts/audit.rb +8 -2
  348. data/lib/arachni/framework/parts/browser.rb +8 -9
  349. data/lib/arachni/framework/parts/check.rb +2 -6
  350. data/lib/arachni/framework/parts/data.rb +23 -8
  351. data/lib/arachni/framework/parts/platform.rb +1 -1
  352. data/lib/arachni/framework/parts/plugin.rb +2 -8
  353. data/lib/arachni/framework/parts/report.rb +3 -9
  354. data/lib/arachni/framework/parts/scope.rb +1 -1
  355. data/lib/arachni/framework/parts/state.rb +8 -8
  356. data/lib/arachni/http.rb +1 -1
  357. data/lib/arachni/http/client.rb +72 -68
  358. data/lib/arachni/http/client/dynamic_404_handler.rb +85 -60
  359. data/lib/arachni/http/cookie_jar.rb +48 -27
  360. data/lib/arachni/http/headers.rb +4 -3
  361. data/lib/arachni/http/message.rb +17 -3
  362. data/lib/arachni/http/message/scope.rb +1 -1
  363. data/lib/arachni/http/proxy_server.rb +46 -344
  364. data/lib/arachni/http/proxy_server/connection.rb +316 -0
  365. data/lib/arachni/http/proxy_server/ssl_interceptor.rb +102 -0
  366. data/lib/arachni/http/proxy_server/tunnel.rb +54 -0
  367. data/lib/arachni/http/request.rb +126 -29
  368. data/lib/arachni/http/request/scope.rb +1 -1
  369. data/lib/arachni/http/response.rb +42 -12
  370. data/lib/arachni/http/response/scope.rb +1 -1
  371. data/lib/arachni/issue.rb +2 -2
  372. data/lib/arachni/issue/severity.rb +1 -1
  373. data/lib/arachni/issue/severity/base.rb +1 -1
  374. data/lib/arachni/option_group.rb +1 -1
  375. data/lib/arachni/option_groups.rb +1 -1
  376. data/lib/arachni/option_groups/audit.rb +20 -4
  377. data/lib/arachni/option_groups/browser_cluster.rb +8 -4
  378. data/lib/arachni/option_groups/datastore.rb +1 -1
  379. data/lib/arachni/option_groups/dispatcher.rb +1 -1
  380. data/lib/arachni/option_groups/http.rb +2 -2
  381. data/lib/arachni/option_groups/input.rb +6 -3
  382. data/lib/arachni/option_groups/output.rb +1 -1
  383. data/lib/arachni/option_groups/paths.rb +10 -3
  384. data/lib/arachni/option_groups/rpc.rb +1 -1
  385. data/lib/arachni/option_groups/scope.rb +35 -6
  386. data/lib/arachni/option_groups/session.rb +1 -1
  387. data/lib/arachni/option_groups/snapshot.rb +1 -1
  388. data/lib/arachni/options.rb +1 -1
  389. data/lib/arachni/page.rb +26 -12
  390. data/lib/arachni/page/dom.rb +29 -22
  391. data/lib/arachni/page/dom/transition.rb +2 -2
  392. data/lib/arachni/page/scope.rb +1 -1
  393. data/lib/arachni/parser.rb +42 -5
  394. data/lib/arachni/platform.rb +1 -1
  395. data/lib/arachni/platform/fingerprinter.rb +1 -1
  396. data/lib/arachni/platform/list.rb +1 -1
  397. data/lib/arachni/platform/manager.rb +2 -2
  398. data/lib/arachni/plugin.rb +1 -1
  399. data/lib/arachni/plugin/base.rb +1 -1
  400. data/lib/arachni/plugin/formatter.rb +1 -1
  401. data/lib/arachni/plugin/manager.rb +7 -13
  402. data/lib/arachni/processes.rb +1 -1
  403. data/lib/arachni/processes/dispatchers.rb +2 -2
  404. data/lib/arachni/processes/executables/base.rb +45 -4
  405. data/lib/arachni/processes/executables/browser.rb +91 -0
  406. data/lib/arachni/processes/executables/rest_service.rb +14 -0
  407. data/lib/arachni/processes/helpers.rb +1 -1
  408. data/lib/arachni/processes/helpers/dispatchers.rb +1 -1
  409. data/lib/arachni/processes/helpers/instances.rb +1 -1
  410. data/lib/arachni/processes/helpers/processes.rb +1 -1
  411. data/lib/arachni/processes/instances.rb +5 -5
  412. data/lib/arachni/processes/manager.rb +68 -9
  413. data/lib/arachni/report.rb +1 -1
  414. data/lib/arachni/reporter.rb +1 -1
  415. data/lib/arachni/reporter/base.rb +1 -1
  416. data/lib/arachni/reporter/formatter_manager.rb +4 -2
  417. data/lib/arachni/reporter/manager.rb +3 -2
  418. data/lib/arachni/reporter/options.rb +1 -1
  419. data/lib/arachni/rest/server.rb +231 -0
  420. data/lib/arachni/rest/server/instance_helpers.rb +37 -0
  421. data/lib/arachni/rpc/client/base.rb +1 -1
  422. data/lib/arachni/rpc/client/dispatcher.rb +1 -1
  423. data/lib/arachni/rpc/client/instance.rb +1 -1
  424. data/lib/arachni/rpc/client/instance/framework.rb +1 -1
  425. data/lib/arachni/rpc/client/instance/service.rb +1 -1
  426. data/lib/arachni/rpc/serializer.rb +1 -1
  427. data/lib/arachni/rpc/server/active_options.rb +20 -3
  428. data/lib/arachni/rpc/server/base.rb +1 -1
  429. data/lib/arachni/rpc/server/check/manager.rb +1 -1
  430. data/lib/arachni/rpc/server/dispatcher.rb +4 -4
  431. data/lib/arachni/rpc/server/dispatcher/node.rb +1 -1
  432. data/lib/arachni/rpc/server/dispatcher/service.rb +1 -1
  433. data/lib/arachni/rpc/server/framework.rb +3 -1
  434. data/lib/arachni/rpc/server/framework/distributor.rb +1 -1
  435. data/lib/arachni/rpc/server/framework/master.rb +1 -1
  436. data/lib/arachni/rpc/server/framework/multi_instance.rb +1 -1
  437. data/lib/arachni/rpc/server/framework/slave.rb +1 -1
  438. data/lib/arachni/rpc/server/instance.rb +1 -3
  439. data/lib/arachni/rpc/server/output.rb +1 -1
  440. data/lib/arachni/rpc/server/plugin/manager.rb +1 -1
  441. data/lib/arachni/ruby.rb +1 -2
  442. data/lib/arachni/ruby/array.rb +1 -1
  443. data/lib/arachni/ruby/hash.rb +1 -1
  444. data/lib/arachni/ruby/object.rb +15 -1
  445. data/lib/arachni/ruby/set.rb +1 -1
  446. data/lib/arachni/ruby/string.rb +23 -4
  447. data/lib/arachni/ruby/webrick.rb +1 -1
  448. data/lib/arachni/ruby/webrick/cookie.rb +1 -1
  449. data/lib/arachni/ruby/webrick/httprequest.rb +1 -1
  450. data/lib/arachni/scope.rb +1 -1
  451. data/lib/arachni/{watir → selenium/webdriver}/element.rb +12 -13
  452. data/lib/arachni/session.rb +19 -4
  453. data/lib/arachni/snapshot.rb +9 -5
  454. data/lib/arachni/state.rb +1 -1
  455. data/lib/arachni/state/audit.rb +1 -1
  456. data/lib/arachni/state/element_filter.rb +1 -1
  457. data/lib/arachni/state/framework.rb +1 -1
  458. data/lib/arachni/state/framework/rpc.rb +1 -1
  459. data/lib/arachni/state/http.rb +1 -1
  460. data/lib/arachni/state/options.rb +1 -1
  461. data/lib/arachni/state/plugins.rb +1 -1
  462. data/lib/arachni/support.rb +2 -1
  463. data/lib/arachni/support/buffer.rb +1 -1
  464. data/lib/arachni/support/buffer/autoflush.rb +1 -1
  465. data/lib/arachni/support/buffer/base.rb +1 -1
  466. data/lib/arachni/support/cache.rb +1 -1
  467. data/lib/arachni/support/cache/base.rb +20 -8
  468. data/lib/arachni/support/cache/least_cost_replacement.rb +1 -1
  469. data/lib/arachni/support/cache/least_recently_pushed.rb +1 -1
  470. data/lib/arachni/support/cache/least_recently_used.rb +8 -9
  471. data/lib/arachni/support/cache/preference.rb +7 -20
  472. data/lib/arachni/support/cache/random_replacement.rb +1 -1
  473. data/lib/arachni/support/crypto.rb +1 -1
  474. data/lib/arachni/support/crypto/rsa_aes_cbc.rb +1 -1
  475. data/lib/arachni/support/database.rb +1 -1
  476. data/lib/arachni/support/database/base.rb +2 -2
  477. data/lib/arachni/support/database/hash.rb +1 -1
  478. data/lib/arachni/support/database/queue.rb +1 -1
  479. data/lib/arachni/support/glob.rb +35 -0
  480. data/lib/arachni/support/lookup.rb +1 -1
  481. data/lib/arachni/support/lookup/base.rb +1 -1
  482. data/lib/arachni/support/lookup/hash_set.rb +1 -1
  483. data/lib/arachni/support/lookup/moolb.rb +1 -1
  484. data/lib/arachni/support/mixins.rb +1 -1
  485. data/lib/arachni/support/mixins/observable.rb +1 -1
  486. data/lib/arachni/support/mixins/terminal.rb +1 -1
  487. data/lib/arachni/support/profiler.rb +12 -10
  488. data/lib/arachni/support/signature.rb +12 -5
  489. data/lib/arachni/trainer.rb +18 -4
  490. data/lib/arachni/ui/foo/output.rb +17 -1
  491. data/lib/arachni/uri.rb +285 -203
  492. data/lib/arachni/uri/scope.rb +13 -2
  493. data/lib/arachni/utilities.rb +22 -5
  494. data/lib/arachni/version.rb +1 -1
  495. data/lib/version +1 -1
  496. data/spec/arachni/browser/element_locator_spec.rb +42 -14
  497. data/spec/arachni/browser/javascript/dom_monitor_spec.rb +34 -304
  498. data/spec/arachni/browser/javascript/polyfills_spec.rb +35 -0
  499. data/spec/arachni/browser/javascript/taint_tracer_spec.rb +24 -4
  500. data/spec/arachni/browser/javascript_spec.rb +92 -65
  501. data/spec/arachni/browser_cluster/job_spec.rb +3 -3
  502. data/spec/arachni/browser_cluster/jobs/{resource_exploration → dom_exploration}/event_trigger/result_spec.rb +1 -1
  503. data/spec/arachni/browser_cluster/jobs/{resource_exploration → dom_exploration}/event_trigger_spec.rb +4 -4
  504. data/spec/arachni/browser_cluster/jobs/{resource_exploration → dom_exploration}/result_spec.rb +1 -1
  505. data/spec/arachni/browser_cluster/jobs/{resource_exploration_spec.rb → dom_exploration_spec.rb} +4 -4
  506. data/spec/arachni/browser_cluster/jobs/taint_tracer_spec.rb +9 -9
  507. data/spec/arachni/browser_cluster/worker_spec.rb +46 -67
  508. data/spec/arachni/browser_cluster_spec.rb +19 -17
  509. data/spec/arachni/browser_spec.rb +506 -183
  510. data/spec/arachni/check/auditor_spec.rb +70 -25
  511. data/spec/arachni/component/manager_spec.rb +19 -20
  512. data/spec/arachni/data/framework/rpc_spec.rb +1 -1
  513. data/spec/arachni/data/framework_spec.rb +1 -1
  514. data/spec/arachni/data/issues_spec.rb +3 -3
  515. data/spec/arachni/element/capabilities/analyzable/differential_spec.rb +44 -0
  516. data/spec/arachni/element/capabilities/analyzable/signature_spec.rb +33 -162
  517. data/spec/arachni/element/capabilities/analyzable/timeout_spec.rb +4 -4
  518. data/spec/arachni/element/cookie_spec.rb +98 -49
  519. data/spec/arachni/element/form/dom_spec.rb +1 -22
  520. data/spec/arachni/element/form_spec.rb +7 -7
  521. data/spec/arachni/element/header_spec.rb +2 -2
  522. data/spec/arachni/element/json_spec.rb +2 -2
  523. data/spec/arachni/element/link/dom_spec.rb +1 -22
  524. data/spec/arachni/element/link_spec.rb +17 -1
  525. data/spec/arachni/element/link_template/dom_spec.rb +1 -22
  526. data/spec/arachni/element/link_template_spec.rb +3 -3
  527. data/spec/arachni/element/ui_form/{ui_form_dom_spec.rb → dom_spec.rb} +72 -22
  528. data/spec/arachni/element/ui_form_spec.rb +1 -0
  529. data/spec/arachni/element/ui_input/dom_spec.rb +64 -22
  530. data/spec/arachni/element/ui_input_spec.rb +1 -0
  531. data/spec/arachni/element/xml_spec.rb +1 -0
  532. data/spec/arachni/framework/parts/audit_spec.rb +7 -5
  533. data/spec/arachni/framework/parts/browser_spec.rb +8 -8
  534. data/spec/arachni/framework/parts/check_spec.rb +1 -1
  535. data/spec/arachni/framework/parts/data_spec.rb +4 -4
  536. data/spec/arachni/framework/parts/scope_spec.rb +2 -2
  537. data/spec/arachni/framework_spec.rb +1 -1
  538. data/spec/arachni/http/client/dynamic_404_handlers_spec.rb +26 -13
  539. data/spec/arachni/http/client_spec.rb +80 -45
  540. data/spec/arachni/http/cookie_jar_spec.rb +6 -6
  541. data/spec/arachni/http/proxy_server_spec.rb +69 -66
  542. data/spec/arachni/http/request_spec.rb +147 -23
  543. data/spec/arachni/http/response/scope_spec.rb +12 -12
  544. data/spec/arachni/http/response_spec.rb +62 -4
  545. data/spec/arachni/issue_spec.rb +6 -6
  546. data/spec/arachni/option_groups/audit_spec.rb +25 -8
  547. data/spec/arachni/option_groups/browser_cluster_spec.rb +27 -1
  548. data/spec/arachni/option_groups/dispatcher_spec.rb +3 -3
  549. data/spec/arachni/option_groups/input_spec.rb +9 -9
  550. data/spec/arachni/option_groups/paths_spec.rb +2 -2
  551. data/spec/arachni/option_groups/scope_spec.rb +32 -16
  552. data/spec/arachni/options_spec.rb +4 -4
  553. data/spec/arachni/page/dom/transition_spec.rb +17 -10
  554. data/spec/arachni/page/dom_spec.rb +19 -0
  555. data/spec/arachni/page/scope_spec.rb +4 -4
  556. data/spec/arachni/page_spec.rb +15 -15
  557. data/spec/arachni/platform/manager_spec.rb +2 -2
  558. data/spec/arachni/plugin/base_spec.rb +1 -0
  559. data/spec/arachni/reporter/base_spec.rb +2 -2
  560. data/spec/arachni/reporter/manager_spec.rb +2 -2
  561. data/spec/arachni/rest/server_spec.rb +495 -0
  562. data/spec/arachni/rpc/server/active_options_spec.rb +63 -12
  563. data/spec/arachni/rpc/server/base_spec.rb +1 -1
  564. data/spec/arachni/rpc/server/framework/distributor_spec.rb +2 -2
  565. data/spec/arachni/rpc/server/framework_multi_spec.rb +6 -6
  566. data/spec/arachni/rpc/server/framework_spec.rb +4 -4
  567. data/spec/arachni/rpc/server/instance_spec.rb +24 -24
  568. data/spec/arachni/ruby/array_spec.rb +2 -2
  569. data/spec/arachni/ruby/string_spec.rb +52 -0
  570. data/spec/arachni/session_spec.rb +19 -2
  571. data/spec/arachni/snapshot_spec.rb +1 -1
  572. data/spec/arachni/state/audit_spec.rb +1 -1
  573. data/spec/arachni/state/framework_spec.rb +2 -2
  574. data/spec/arachni/support/cache/least_recently_used_spec.rb +0 -2
  575. data/spec/arachni/support/glob_spec.rb +75 -0
  576. data/spec/arachni/support/lookup/hash_set_spec.rb +1 -1
  577. data/spec/arachni/support/lookup/moolb_spec.rb +2 -2
  578. data/spec/arachni/support/signature_spec.rb +4 -4
  579. data/spec/arachni/trainer_spec.rb +48 -4
  580. data/spec/arachni/uri/scope_spec.rb +54 -10
  581. data/spec/arachni/uri_spec.rb +110 -89
  582. data/spec/arachni/utilities_spec.rb +8 -8
  583. data/spec/components/checks/active/code_injection_spec.rb +9 -9
  584. data/spec/components/checks/active/file_inclusion_spec.rb +20 -20
  585. data/spec/components/checks/active/ldap_injection_spec.rb +1 -1
  586. data/spec/components/checks/active/no_sql_injection_spec.rb +1 -1
  587. data/spec/components/checks/active/os_cmd_injection_spec.rb +3 -3
  588. data/spec/components/checks/active/path_traversal_spec.rb +11 -11
  589. data/spec/components/checks/active/response_splitting_spec.rb +2 -2
  590. data/spec/components/checks/active/rfi_spec.rb +3 -3
  591. data/spec/components/checks/active/session_fixation_spec.rb +1 -1
  592. data/spec/components/checks/active/source_code_disclosure_spec.rb +4 -4
  593. data/spec/components/checks/active/sql_injection_spec.rb +58 -59
  594. data/spec/components/checks/active/unvalidated_redirect_spec.rb +2 -2
  595. data/spec/components/checks/active/xpath_injection_spec.rb +3 -3
  596. data/spec/components/checks/active/xss_dom_script_context_spec.rb +1 -1
  597. data/spec/components/checks/active/xss_dom_spec.rb +1 -1
  598. data/spec/components/checks/active/xss_script_context_spec.rb +5 -5
  599. data/spec/components/checks/active/xss_spec.rb +5 -5
  600. data/spec/components/checks/passive/grep/credit_card_spec.rb +1 -1
  601. data/spec/components/checks/passive/grep/emails_spec.rb +12 -2
  602. data/spec/components/checks/passive/grep/ssn_spec.rb +1 -1
  603. data/spec/components/path_extractors/meta_refresh_spec.rb +3 -1
  604. data/spec/components/plugins/exec_spec.rb +2 -2
  605. data/spec/components/plugins/login_script_spec.rb +22 -2
  606. data/spec/components/plugins/vector_feed_spec.rb +3 -3
  607. data/spec/spec_helper.rb +10 -4
  608. data/spec/support/factories/browser_cluster/job.rb +1 -0
  609. data/spec/support/fixtures/check_with_invalid_platforms/with_invalid_platforms.rb +1 -1
  610. data/spec/support/fixtures/checks/test.rb +1 -1
  611. data/spec/support/fixtures/checks/test2.rb +1 -1
  612. data/spec/support/fixtures/checks/test3.rb +1 -1
  613. data/spec/support/fixtures/fingerprinters/test.rb +1 -1
  614. data/spec/support/fixtures/plugins/bad.rb +1 -1
  615. data/spec/support/fixtures/plugins/defaults/default.rb +1 -1
  616. data/spec/support/fixtures/plugins/distributable.rb +1 -1
  617. data/spec/support/fixtures/plugins/loop.rb +1 -1
  618. data/spec/support/fixtures/plugins/suspendable.rb +1 -1
  619. data/spec/support/fixtures/plugins/wait.rb +1 -1
  620. data/spec/support/fixtures/plugins/with_options.rb +1 -1
  621. data/spec/support/fixtures/plugins_with_priorities/p0.rb +1 -1
  622. data/spec/support/fixtures/plugins_with_priorities/p00.rb +1 -1
  623. data/spec/support/fixtures/plugins_with_priorities/p1.rb +1 -1
  624. data/spec/support/fixtures/plugins_with_priorities/p2.rb +1 -1
  625. data/spec/support/fixtures/plugins_with_priorities/p22.rb +1 -1
  626. data/spec/support/fixtures/plugins_with_priorities/p222.rb +1 -1
  627. data/spec/support/fixtures/plugins_with_priorities/p_nil.rb +1 -1
  628. data/spec/support/fixtures/plugins_with_priorities/p_nil2.rb +1 -1
  629. data/spec/support/fixtures/report.afr +0 -0
  630. data/spec/support/fixtures/reporters/base_spec/plugin_formatters/with_formatters/foobar.rb +1 -1
  631. data/spec/support/fixtures/reporters/base_spec/with_formatters.rb +1 -1
  632. data/spec/support/fixtures/reporters/base_spec/with_outfile.rb +1 -1
  633. data/spec/support/fixtures/reporters/base_spec/without_outfile.rb +1 -1
  634. data/spec/support/fixtures/reporters/manager_spec/afr.rb +1 -1
  635. data/spec/support/fixtures/reporters/manager_spec/error.rb +1 -1
  636. data/spec/support/fixtures/reporters/manager_spec/foo.rb +1 -1
  637. data/spec/support/fixtures/run_check/body.rb +1 -1
  638. data/spec/support/fixtures/run_check/cookies.rb +1 -1
  639. data/spec/support/fixtures/run_check/empty.rb +1 -1
  640. data/spec/support/fixtures/run_check/flch.rb +1 -1
  641. data/spec/support/fixtures/run_check/forms.rb +1 -1
  642. data/spec/support/fixtures/run_check/headers.rb +1 -1
  643. data/spec/support/fixtures/run_check/links.rb +1 -1
  644. data/spec/support/fixtures/run_check/nil.rb +1 -1
  645. data/spec/support/fixtures/run_check/path.rb +1 -1
  646. data/spec/support/fixtures/run_check/server.rb +1 -1
  647. data/spec/support/fixtures/signature_check/signature.rb +1 -1
  648. data/spec/support/fixtures/wait_check/wait.rb +1 -1
  649. data/spec/support/helpers/framework.rb +1 -1
  650. data/spec/support/helpers/misc.rb +1 -1
  651. data/spec/support/helpers/paths.rb +1 -1
  652. data/spec/support/helpers/request_helpers.rb +38 -0
  653. data/spec/support/helpers/requires.rb +1 -1
  654. data/spec/support/helpers/resets.rb +1 -1
  655. data/spec/support/helpers/web_server.rb +1 -1
  656. data/spec/support/lib/factory.rb +1 -1
  657. data/spec/support/lib/web_server_client.rb +1 -1
  658. data/spec/support/lib/web_server_dispatcher.rb +1 -1
  659. data/spec/support/lib/web_server_manager.rb +2 -2
  660. data/spec/support/servers/arachni/browser.rb +182 -15
  661. data/spec/support/servers/arachni/browser/javascript/angular-1.2.8.js +1 -1
  662. data/spec/support/servers/arachni/browser/javascript/angular-route.js +1 -1
  663. data/spec/support/servers/arachni/browser/javascript/dom_monitor.rb +27 -4
  664. data/spec/support/servers/arachni/element/capabilities/analyzable/differential.rb +103 -0
  665. data/spec/support/servers/arachni/element/capabilities/analyzable/timeout.rb +5 -2
  666. data/spec/support/servers/arachni/element/header.rb +1 -1
  667. data/spec/support/servers/arachni/http/client.rb +46 -0
  668. data/spec/support/servers/arachni/http/client/dynamic_404_handler.rb +7 -1
  669. data/spec/support/servers/checks/active/code_injection.rb +5 -5
  670. data/spec/support/servers/checks/active/no_sql_injection.rb +0 -6
  671. data/spec/support/servers/checks/active/no_sql_injection_differential.rb +1 -1
  672. data/spec/support/servers/checks/active/sql_injection.rb +5 -2
  673. data/spec/support/servers/checks/active/sql_injection_differential.rb +1 -1
  674. data/spec/support/servers/checks/active/trainer_check.rb +6 -6
  675. data/spec/support/servers/checks/passive/backdoors.rb +1 -0
  676. data/spec/support/servers/checks/passive/backup_directories.rb +2 -0
  677. data/spec/support/servers/checks/passive/backup_files.rb +2 -0
  678. data/spec/support/servers/checks/passive/grep/emails.rb +6 -6
  679. data/spec/support/shared/check.rb +28 -0
  680. data/spec/support/shared/element/capabilities/auditable.rb +76 -13
  681. data/spec/support/shared/element/capabilities/dom_only.rb +5 -6
  682. data/spec/support/shared/element/capabilities/inputtable.rb +74 -4
  683. data/spec/support/shared/element/capabilities/mutable.rb +86 -14
  684. data/spec/support/shared/element/capabilities/submittable.rb +12 -0
  685. data/spec/support/shared/element/capabilities/with_dom.rb +13 -4
  686. data/spec/support/shared/element/capabilities/with_node.rb +1 -1
  687. data/spec/support/shared/element/capabilities/with_source.rb +1 -6
  688. data/spec/support/shared/element/dom/locatable.rb +20 -0
  689. data/spec/support/shared/element/dom/submittable.rb +4 -17
  690. data/spec/support/shared/http/message.rb +37 -5
  691. data/spec/support/shared/support/cache.rb +5 -4
  692. data/ui/cli/framework.rb +4 -3
  693. data/ui/cli/framework/option_parser.rb +20 -8
  694. data/ui/cli/option_parser.rb +1 -1
  695. data/ui/cli/output.rb +40 -4
  696. data/ui/cli/reporter.rb +1 -1
  697. data/ui/cli/reporter/option_parser.rb +4 -4
  698. data/ui/cli/rest/server.rb +43 -0
  699. data/ui/cli/rest/server/option_parser.rb +115 -0
  700. data/ui/cli/restored_framework.rb +1 -1
  701. data/ui/cli/restored_framework/option_parser.rb +1 -1
  702. data/ui/cli/rpc/client/dispatcher_monitor.rb +1 -1
  703. data/ui/cli/rpc/client/dispatcher_monitor/option_parser.rb +1 -1
  704. data/ui/cli/rpc/client/instance.rb +1 -1
  705. data/ui/cli/rpc/client/local.rb +1 -1
  706. data/ui/cli/rpc/client/local/option_parser.rb +1 -1
  707. data/ui/cli/rpc/client/remote.rb +1 -1
  708. data/ui/cli/rpc/client/remote/option_parser.rb +1 -1
  709. data/ui/cli/rpc/server/dispatcher.rb +1 -1
  710. data/ui/cli/rpc/server/dispatcher/option_parser.rb +1 -1
  711. data/ui/cli/utilities.rb +1 -1
  712. metadata +197 -84
  713. data/components/checks/active/no_sql_injection/patterns/mongodb +0 -1
  714. data/components/checks/active/no_sql_injection/regexp_ignore.txt +0 -0
  715. data/components/checks/active/sql_injection/patterns/access +0 -3
  716. data/components/checks/active/sql_injection/patterns/db2 +0 -5
  717. data/components/checks/active/sql_injection/patterns/frontbase +0 -1
  718. data/components/checks/active/sql_injection/patterns/hsqldb +0 -1
  719. data/components/checks/active/sql_injection/patterns/ingres +0 -3
  720. data/components/checks/active/sql_injection/patterns/maxdb +0 -2
  721. data/components/checks/active/sql_injection/patterns/mssql +0 -25
  722. data/components/checks/active/sql_injection/patterns/oracle +0 -6
  723. data/components/checks/active/sql_injection/patterns/sqlite +0 -5
  724. data/components/checks/active/sql_injection/patterns/sybase +0 -3
  725. data/lib/arachni/ruby/io.rb +0 -39
  726. data/lib/arachni/selenium/webdriver/remote/http/typhoeus.rb +0 -63
  727. data/spec/arachni/ruby/io_spec.rb +0 -26
@@ -47,7 +47,7 @@ describe Arachni::BrowserCluster::Jobs::TaintTrace do
47
47
  end
48
48
 
49
49
  context 'and the resource is a' do
50
- context String do
50
+ context 'String' do
51
51
  it 'loads the URL and traces the taint' do
52
52
  test_data_flow described_class.new(
53
53
  resource: url,
@@ -56,7 +56,7 @@ describe Arachni::BrowserCluster::Jobs::TaintTrace do
56
56
  end
57
57
  end
58
58
 
59
- context Arachni::HTTP::Response do
59
+ context 'Arachni::HTTP::Response' do
60
60
  it 'loads it and traces the taint' do
61
61
  test_data_flow described_class.new(
62
62
  resource: Arachni::HTTP::Client.get( url, mode: :sync ),
@@ -65,7 +65,7 @@ describe Arachni::BrowserCluster::Jobs::TaintTrace do
65
65
  end
66
66
  end
67
67
 
68
- context Arachni::Page do
68
+ context 'Arachni::Page' do
69
69
  it 'loads it and traces the taint' do
70
70
  test_data_flow described_class.new(
71
71
  resource: Arachni::Page.from_url( url ),
@@ -83,7 +83,7 @@ describe Arachni::BrowserCluster::Jobs::TaintTrace do
83
83
  end
84
84
 
85
85
  context 'and the resource is a' do
86
- context String do
86
+ context 'String' do
87
87
  it 'loads the URL and traces the taint' do
88
88
  test_data_flow_with_injector described_class.new(
89
89
  resource: url,
@@ -93,7 +93,7 @@ describe Arachni::BrowserCluster::Jobs::TaintTrace do
93
93
  end
94
94
  end
95
95
 
96
- context Arachni::HTTP::Response do
96
+ context 'Arachni::HTTP::Response' do
97
97
  it 'loads it and traces the taint' do
98
98
  test_data_flow_with_injector described_class.new(
99
99
  resource: Arachni::HTTP::Client.get( url, mode: :sync ),
@@ -103,7 +103,7 @@ describe Arachni::BrowserCluster::Jobs::TaintTrace do
103
103
  end
104
104
  end
105
105
 
106
- context Arachni::Page do
106
+ context 'Arachni::Page' do
107
107
  it 'loads it and traces the taint' do
108
108
  test_data_flow_with_injector described_class.new(
109
109
  resource: Arachni::Page.from_url( url ),
@@ -123,13 +123,13 @@ describe Arachni::BrowserCluster::Jobs::TaintTrace do
123
123
  end
124
124
 
125
125
  context 'and the resource is a' do
126
- context String do
126
+ context 'String' do
127
127
  it 'loads the URL and traces the taint' do
128
128
  test_execution_flow described_class.new( resource: url )
129
129
  end
130
130
  end
131
131
 
132
- context Arachni::HTTP::Response do
132
+ context 'Arachni::HTTP::Response' do
133
133
  it 'loads it and traces the taint' do
134
134
  test_execution_flow described_class.new(
135
135
  resource: Arachni::HTTP::Client.get( url, mode: :sync )
@@ -137,7 +137,7 @@ describe Arachni::BrowserCluster::Jobs::TaintTrace do
137
137
  end
138
138
  end
139
139
 
140
- context Arachni::Page do
140
+ context 'Arachni::Page' do
141
141
  it 'loads it and traces the taint' do
142
142
  test_execution_flow described_class.new(
143
143
  resource: Arachni::Page.from_url( url )
@@ -17,7 +17,7 @@ describe Arachni::BrowserCluster::Worker do
17
17
 
18
18
  let(:url) { Arachni::Utilities.normalize_url( web_server_url_for( :browser ) ) }
19
19
  let(:job) do
20
- Arachni::BrowserCluster::Jobs::ResourceExploration.new(
20
+ Arachni::BrowserCluster::Jobs::DOMExploration.new(
21
21
  resource: Arachni::HTTP::Client.get( url + 'explore', mode: :sync )
22
22
  )
23
23
  end
@@ -26,7 +26,7 @@ describe Arachni::BrowserCluster::Worker do
26
26
  let(:subject) { @cluster.workers.first }
27
27
 
28
28
  describe '#initialize' do
29
- describe :job_timeout do
29
+ describe ':job_timeout' do
30
30
  it 'sets how much time to allow each job to run' do
31
31
  @worker = described_class.new( job_timeout: 10 )
32
32
  expect(@worker.job_timeout).to eq(10)
@@ -39,7 +39,7 @@ describe Arachni::BrowserCluster::Worker do
39
39
  end
40
40
  end
41
41
 
42
- describe :max_time_to_live do
42
+ describe ':max_time_to_live' do
43
43
  it 'sets how many jobs should be run before respawning' do
44
44
  @worker = described_class.new( max_time_to_live: 10 )
45
45
  expect(@worker.max_time_to_live).to eq(10)
@@ -70,16 +70,41 @@ describe Arachni::BrowserCluster::Worker do
70
70
  end
71
71
 
72
72
  context 'before running the job' do
73
- it 'ensures that there is a live PhantomJS process' do
74
- Arachni::Processes::Manager.kill subject.pid
75
- expect{ Process.getpgid( subject.pid ) }.to raise_error Errno::ESRCH
76
- dead_pid = subject.pid
73
+ context 'when PhantomJS is dead' do
74
+ it 'spawns a new one' do
75
+ Arachni::Processes::Manager.kill subject.browser_pid
77
76
 
78
- @cluster.queue( custom_job ){}
79
- @cluster.wait
77
+ dead_lifeline_pid = subject.lifeline_pid
78
+ dead_browser_pid = subject.browser_pid
79
+
80
+ @cluster.queue( custom_job ){}
81
+ @cluster.wait
82
+
83
+ expect(subject.browser_pid).not_to eq(dead_browser_pid)
84
+ expect(subject.lifeline_pid).not_to eq(dead_lifeline_pid)
85
+
86
+ expect(Arachni::Processes::Manager.alive?( subject.lifeline_pid )).to be_truthy
87
+ expect(Arachni::Processes::Manager.alive?( subject.browser_pid )).to be_truthy
88
+ end
89
+ end
90
+
91
+ context 'when the lifeline is dead' do
92
+ it 'spawns a new one' do
93
+ Arachni::Processes::Manager << subject.browser_pid
94
+ Arachni::Processes::Manager.kill subject.lifeline_pid
95
+
96
+ dead_lifeline_pid = subject.lifeline_pid
97
+ dead_browser_pid = subject.browser_pid
80
98
 
81
- expect(subject.pid).not_to eq(dead_pid)
82
- expect(Process.getpgid( subject.pid )).to be_truthy
99
+ @cluster.queue( custom_job ){}
100
+ @cluster.wait
101
+
102
+ expect(subject.browser_pid).not_to eq(dead_browser_pid)
103
+ expect(subject.lifeline_pid).not_to eq(dead_lifeline_pid)
104
+
105
+ expect(Arachni::Processes::Manager.alive?( subject.lifeline_pid )).to be_truthy
106
+ expect(Arachni::Processes::Manager.alive?( subject.browser_pid )).to be_truthy
107
+ end
83
108
  end
84
109
  end
85
110
 
@@ -89,23 +114,23 @@ describe Arachni::BrowserCluster::Worker do
89
114
  expect(subject.run_job( custom_job )).to be_truthy
90
115
  end
91
116
 
92
- context Selenium::WebDriver::Error::WebDriverError do
117
+ context 'Selenium::WebDriver::Error::WebDriverError' do
93
118
  it 'respawns' do
94
- allow(subject.watir).to receive(:cookies) do
119
+ expect(custom_job).to receive(:configure_and_run) do
95
120
  raise Selenium::WebDriver::Error::WebDriverError
96
121
  end
97
122
 
98
- allow(subject.watir).to receive(:close) do
123
+ expect(subject.watir).to receive(:close) do
99
124
  raise Selenium::WebDriver::Error::WebDriverError
100
125
  end
101
126
 
102
127
  watir = subject.watir
103
- pid = subject.pid
128
+ pid = subject.browser_pid
104
129
 
105
130
  subject.run_job( custom_job )
106
131
 
107
132
  expect(watir).not_to eq(subject.watir)
108
- expect(pid).not_to eq(subject.pid)
133
+ expect(pid).not_to eq(subject.browser_pid)
109
134
  end
110
135
  end
111
136
  end
@@ -122,19 +147,6 @@ describe Arachni::BrowserCluster::Worker do
122
147
  expect(subject.javascript.taint).to be_nil
123
148
  end
124
149
 
125
- it 'clears #cookies' do
126
- subject.preload page
127
- expect(subject.preloads).to be_any
128
-
129
- @cluster.with_browser do |browser|
130
- browser.load page
131
- expect(subject.cookies).to be_any
132
- end
133
- @cluster.wait
134
-
135
- expect(subject.cookies).to be_empty
136
- end
137
-
138
150
  it 'clears #preloads' do
139
151
  subject.preload page
140
152
  expect(subject.preloads).to be_any
@@ -236,39 +248,6 @@ describe Arachni::BrowserCluster::Worker do
236
248
  expect(custom_job.time).to be > 0
237
249
  end
238
250
 
239
- context 'when there are 5 or more windows open' do
240
- before(:each) do
241
- 5.times do
242
- subject.javascript.run( 'window.open()' )
243
- end
244
- end
245
-
246
- it 'respawns PhantomJS' do
247
- watir = subject.watir
248
- pid = subject.pid
249
-
250
- expect(subject.watir.windows.size).to be > 5
251
- @cluster.explore( page ) {}
252
- @cluster.wait
253
-
254
- expect(watir).not_to eq(subject.watir)
255
- expect(pid).not_to eq(subject.pid)
256
- expect(subject.watir.windows.size).to eq(2)
257
- end
258
-
259
- it 'clears the cached HTTP responses' do
260
- subject.preload page
261
- expect(subject.preloads).to be_any
262
- subject.instance_variable_get(:@window_responses)
263
-
264
- expect(subject.watir.windows.size).to be > 5
265
- @cluster.queue( custom_job ) {}
266
- @cluster.wait
267
-
268
- expect(subject.instance_variable_get(:@window_responses)).to be_empty
269
- end
270
- end
271
-
272
251
  context 'when #time_to_live reaches 0' do
273
252
  it 'respawns the browser' do
274
253
  @cluster.shutdown
@@ -279,30 +258,30 @@ describe Arachni::BrowserCluster::Worker do
279
258
  subject.max_time_to_live = 1
280
259
 
281
260
  watir = subject.watir
282
- pid = subject.pid
261
+ pid = subject.browser_pid
283
262
 
284
263
  @cluster.queue( custom_job ) {}
285
264
  @cluster.wait
286
265
 
287
266
  expect(watir).not_to eq(subject.watir)
288
- expect(pid).not_to eq(subject.pid)
267
+ expect(pid).not_to eq(subject.browser_pid)
289
268
  end
290
269
  end
291
270
 
292
271
  context 'when cookie clearing raises' do
293
- context Selenium::WebDriver::Error::NoSuchWindowError do
272
+ context 'Selenium::WebDriver::Error::NoSuchWindowError' do
294
273
  it 'respawns' do
295
274
  allow(subject.watir).to receive(:cookies) do
296
275
  raise Selenium::WebDriver::Error::NoSuchWindowError
297
276
  end
298
277
 
299
278
  watir = subject.watir
300
- pid = subject.pid
279
+ pid = subject.browser_pid
301
280
 
302
281
  subject.run_job( custom_job )
303
282
 
304
283
  expect(watir).not_to eq(subject.watir)
305
- expect(pid).not_to eq(subject.pid)
284
+ expect(pid).not_to eq(subject.browser_pid)
306
285
  end
307
286
  end
308
287
  end
@@ -4,7 +4,7 @@ describe Arachni::BrowserCluster do
4
4
 
5
5
  let(:url) { Arachni::Utilities.normalize_url( web_server_url_for( :browser ) ) }
6
6
  let(:job) do
7
- Arachni::BrowserCluster::Jobs::ResourceExploration.new(
7
+ Arachni::BrowserCluster::Jobs::DOMExploration.new(
8
8
  resource: Arachni::HTTP::Client.get( url + 'explore', mode: :sync )
9
9
  )
10
10
  end
@@ -23,6 +23,7 @@ describe Arachni::BrowserCluster do
23
23
 
24
24
  @cluster = described_class.new
25
25
  @cluster.workers.each do |browser|
26
+ browser.load url
26
27
  expect(browser.javascript.run('return window.innerWidth')).to eq(100)
27
28
  end
28
29
  end
@@ -32,11 +33,12 @@ describe Arachni::BrowserCluster do
32
33
 
33
34
  @cluster = described_class.new
34
35
  @cluster.workers.each do |browser|
36
+ browser.load url
35
37
  expect(browser.javascript.run('return window.innerHeight')).to eq(200)
36
38
  end
37
39
  end
38
40
 
39
- describe :pool_size do
41
+ describe ':pool_size' do
40
42
  it 'sets the amount of browsers to instantiate' do
41
43
  @cluster = described_class.new( pool_size: 3 )
42
44
  expect(@cluster.workers.size).to eq(3)
@@ -49,7 +51,7 @@ describe Arachni::BrowserCluster do
49
51
  end
50
52
  end
51
53
 
52
- describe :on_pop do
54
+ describe ':on_pop' do
53
55
  it 'assigns blocks to be passed each poped job' do
54
56
  cj = nil
55
57
  @cluster = described_class.new(
@@ -65,7 +67,7 @@ describe Arachni::BrowserCluster do
65
67
  end
66
68
  end
67
69
 
68
- describe :on_queue do
70
+ describe ':on_queue' do
69
71
  it 'assigns blocks to be passed each queued job' do
70
72
  cj = nil
71
73
  @cluster = described_class.new(
@@ -81,7 +83,7 @@ describe Arachni::BrowserCluster do
81
83
  end
82
84
  end
83
85
 
84
- describe :on_job_done do
86
+ describe ':on_job_done' do
85
87
  it 'assigns blocks to be passed each finished job' do
86
88
  cj = nil
87
89
  @cluster = described_class.new(
@@ -261,7 +263,7 @@ describe Arachni::BrowserCluster do
261
263
  end
262
264
 
263
265
  context 'when the resource is a' do
264
- context String do
266
+ context 'String' do
265
267
  it 'loads the URL and explores the DOM' do
266
268
  pages = []
267
269
 
@@ -274,7 +276,7 @@ describe Arachni::BrowserCluster do
274
276
  end
275
277
  end
276
278
 
277
- context Arachni::HTTP::Response do
279
+ context 'Arachni::HTTP::Response' do
278
280
  it 'loads it and explores the DOM' do
279
281
  pages = []
280
282
 
@@ -287,7 +289,7 @@ describe Arachni::BrowserCluster do
287
289
  end
288
290
  end
289
291
 
290
- context Arachni::Page do
292
+ context 'Arachni::Page' do
291
293
  it 'loads it and explores the DOM' do
292
294
  pages = []
293
295
 
@@ -313,7 +315,7 @@ describe Arachni::BrowserCluster do
313
315
  end
314
316
 
315
317
  context 'and the resource is a' do
316
- context String do
318
+ context 'String' do
317
319
  it 'loads the URL and traces the taint' do
318
320
  pages = []
319
321
  @cluster.trace_taint( url, taint: taint ) do |result|
@@ -325,7 +327,7 @@ describe Arachni::BrowserCluster do
325
327
  end
326
328
  end
327
329
 
328
- context Arachni::HTTP::Response do
330
+ context 'Arachni::HTTP::Response' do
329
331
  it 'loads it and traces the taint' do
330
332
  pages = []
331
333
 
@@ -339,7 +341,7 @@ describe Arachni::BrowserCluster do
339
341
  end
340
342
  end
341
343
 
342
- context Arachni::Page do
344
+ context 'Arachni::Page' do
343
345
  it 'loads it and traces the taint' do
344
346
  pages = []
345
347
 
@@ -362,7 +364,7 @@ describe Arachni::BrowserCluster do
362
364
  end
363
365
 
364
366
  context 'and the resource is a' do
365
- context String do
367
+ context 'String' do
366
368
  it 'loads the URL and traces the taint' do
367
369
  pages = []
368
370
  @cluster.trace_taint( url,
@@ -376,7 +378,7 @@ describe Arachni::BrowserCluster do
376
378
  end
377
379
  end
378
380
 
379
- context Arachni::HTTP::Response do
381
+ context 'Arachni::HTTP::Response' do
380
382
  it 'loads it and traces the taint' do
381
383
  pages = []
382
384
  @cluster.trace_taint( Arachni::HTTP::Client.get( url, mode: :sync ),
@@ -390,7 +392,7 @@ describe Arachni::BrowserCluster do
390
392
  end
391
393
  end
392
394
 
393
- context Arachni::Page do
395
+ context 'Arachni::Page' do
394
396
  it 'loads it and traces the taint' do
395
397
  pages = []
396
398
  @cluster.trace_taint( Arachni::Page.from_url( url ),
@@ -414,7 +416,7 @@ describe Arachni::BrowserCluster do
414
416
  end
415
417
 
416
418
  context 'and the resource is a' do
417
- context String do
419
+ context 'String' do
418
420
  it 'loads the URL and traces the taint' do
419
421
  pages = []
420
422
  @cluster.trace_taint( url ) do |result|
@@ -426,7 +428,7 @@ describe Arachni::BrowserCluster do
426
428
  end
427
429
  end
428
430
 
429
- context Arachni::HTTP::Response do
431
+ context 'Arachni::HTTP::Response' do
430
432
  it 'loads it and traces the taint' do
431
433
  pages = []
432
434
  @cluster.trace_taint( Arachni::HTTP::Client.get( url, mode: :sync ) ) do |result|
@@ -438,7 +440,7 @@ describe Arachni::BrowserCluster do
438
440
  end
439
441
  end
440
442
 
441
- context Arachni::Page do
443
+ context 'Arachni::Page' do
442
444
  it 'loads it and traces the taint' do
443
445
  pages = []
444
446
  @cluster.trace_taint( Arachni::Page.from_url( url ) ) do |result|
@@ -14,7 +14,8 @@ describe Arachni::Browser do
14
14
  after( :each ) do
15
15
  Arachni::Options.reset
16
16
  Arachni::Framework.reset
17
- @browser.shutdown
17
+ @browser.shutdown if @browser
18
+ described_class.asset_domains.clear
18
19
  clear_hit_count
19
20
  end
20
21
 
@@ -27,7 +28,7 @@ describe Arachni::Browser do
27
28
 
28
29
  options = {}
29
30
  if element == :page && event == :load
30
- options.merge!( url: @browser.watir.url, cookies: {} )
31
+ options.merge!( url: @browser.dom_url, cookies: {} )
31
32
  end
32
33
 
33
34
  if element.is_a? Hash
@@ -60,6 +61,46 @@ describe Arachni::Browser do
60
61
  pages_should_have_form_with_input( pages, 'by-ajax' )
61
62
  end
62
63
 
64
+ context 'when the browser dies' do
65
+ it 'kills the lifeline too' do
66
+ Arachni::Processes::Manager.kill subject.browser_pid
67
+ expect(Arachni::Processes::Manager.alive?(subject.lifeline_pid)).to be_falsey
68
+ end
69
+ end
70
+
71
+ context 'when the lifeline dies' do
72
+ it 'kills the browser too' do
73
+ Arachni::Processes::Manager.kill subject.lifeline_pid
74
+ expect(Arachni::Processes::Manager.alive?(subject.browser_pid)).to be_falsey
75
+ end
76
+ end
77
+
78
+ describe '#alive?' do
79
+ context 'when the lifeline is alive' do
80
+ it 'returns true' do
81
+ expect(Arachni::Processes::Manager.alive?(subject.lifeline_pid)).to be_truthy
82
+ expect(subject).to be_alive
83
+ end
84
+ end
85
+
86
+ context 'when the browser is dead' do
87
+ it 'returns false' do
88
+ Arachni::Processes::Manager.kill subject.browser_pid
89
+
90
+ expect(subject).to_not be_alive
91
+ end
92
+ end
93
+
94
+ context 'when the lifeline is dead' do
95
+ it 'returns false' do
96
+ Arachni::Processes::Manager << subject.browser_pid
97
+ Arachni::Processes::Manager.kill subject.lifeline_pid
98
+
99
+ expect(subject).to_not be_alive
100
+ end
101
+ end
102
+ end
103
+
63
104
  describe '.has_executable?' do
64
105
  context 'when there is no executable browser' do
65
106
  it 'returns false' do
@@ -85,12 +126,12 @@ describe Arachni::Browser do
85
126
  end
86
127
 
87
128
  describe '#initialize' do
88
- describe :concurrency do
129
+ describe ':concurrency' do
89
130
  it 'sets the HTTP request concurrency'
90
131
  end
91
132
 
92
- describe :ignore_scope do
93
- context true do
133
+ describe ':ignore_scope' do
134
+ context 'true' do
94
135
  it 'ignores scope restrictions' do
95
136
  @browser.shutdown
96
137
 
@@ -103,7 +144,7 @@ describe Arachni::Browser do
103
144
  end
104
145
  end
105
146
 
106
- context false do
147
+ context 'false' do
107
148
  it 'enforces scope restrictions' do
108
149
  @browser.shutdown
109
150
 
@@ -116,7 +157,7 @@ describe Arachni::Browser do
116
157
  end
117
158
  end
118
159
 
119
- context :default do
160
+ context ':default' do
120
161
  it 'enforces scope restrictions' do
121
162
  @browser.shutdown
122
163
 
@@ -130,35 +171,45 @@ describe Arachni::Browser do
130
171
  end
131
172
  end
132
173
 
133
- describe :width do
174
+ describe ':width' do
134
175
  it 'sets the window width' do
135
176
  @browser.shutdown
136
177
 
137
178
  width = 100
138
179
  @browser = described_class.new( width: width )
180
+
181
+ subject.load @url
182
+
139
183
  expect(subject.javascript.run('return window.innerWidth')).to eq(width)
140
184
  end
141
185
 
142
186
  it 'defaults to 1600' do
187
+ subject.load @url
188
+
143
189
  expect(subject.javascript.run('return window.innerWidth')).to eq(1600)
144
190
  end
145
191
  end
146
192
 
147
- describe :height do
193
+ describe ':height' do
148
194
  it 'sets the window height' do
149
195
  @browser.shutdown
150
196
 
151
197
  height = 100
152
198
  @browser = described_class.new( height: height )
199
+
200
+ subject.load @url
201
+
153
202
  expect(subject.javascript.run('return window.innerHeight')).to eq(height)
154
203
  end
155
204
 
156
205
  it 'defaults to 1200' do
206
+ subject.load @url
207
+
157
208
  expect(subject.javascript.run('return window.innerHeight')).to eq(1200)
158
209
  end
159
210
  end
160
211
 
161
- describe :store_pages do
212
+ describe ':store_pages' do
162
213
  describe 'default' do
163
214
  it 'stores snapshot pages' do
164
215
  @browser.shutdown
@@ -174,7 +225,7 @@ describe Arachni::Browser do
174
225
  end
175
226
  end
176
227
 
177
- describe true do
228
+ describe 'true' do
178
229
  it 'stores snapshot pages' do
179
230
  @browser.shutdown
180
231
  @browser = described_class.new( store_pages: true )
@@ -189,7 +240,7 @@ describe Arachni::Browser do
189
240
  end
190
241
  end
191
242
 
192
- describe false do
243
+ describe 'false' do
193
244
  it 'stores snapshot pages' do
194
245
  @browser.shutdown
195
246
  @browser = described_class.new( store_pages: false )
@@ -292,7 +343,7 @@ describe Arachni::Browser do
292
343
  end
293
344
 
294
345
  context '#store_pages?' do
295
- context true do
346
+ context 'true' do
296
347
  subject { @browser.shutdown; @browser = described_class.new( store_pages: true )}
297
348
 
298
349
  it 'stores it in #page_snapshots' do
@@ -307,7 +358,7 @@ describe Arachni::Browser do
307
358
  end
308
359
  end
309
360
 
310
- context false do
361
+ context 'false' do
311
362
  subject { @browser.shutdown; @browser = described_class.new( store_pages: false ) }
312
363
 
313
364
  it 'does not store it' do
@@ -365,7 +416,7 @@ describe Arachni::Browser do
365
416
  end
366
417
 
367
418
  context '#store_pages?' do
368
- context true do
419
+ context 'true' do
369
420
  subject { @browser.shutdown; @browser = described_class.new( store_pages: true )}
370
421
 
371
422
  it 'stores it in #page_snapshots_with_sinks' do
@@ -374,7 +425,7 @@ describe Arachni::Browser do
374
425
  end
375
426
  end
376
427
 
377
- context false do
428
+ context 'false' do
378
429
  subject { @browser.shutdown; @browser = described_class.new( store_pages: false )}
379
430
 
380
431
  it 'does not store it in #page_snapshots_with_sinks' do
@@ -399,24 +450,21 @@ describe Arachni::Browser do
399
450
  end
400
451
 
401
452
  context 'when there are multiple windows open' do
402
- before :each do
403
- subject.load( ajax_url, take_snapshot: false )
404
- end
405
453
 
406
454
  it 'captures snapshots from all windows' do
407
- subject.javascript.run( 'window.open()' )
408
- subject.watir.windows.last.use
409
- subject.load sink_url, take_snapshot: false
455
+ url = "#{@url}open-new-window"
456
+
457
+ subject.load url, take_snapshot: false
410
458
 
411
459
  expect(subject.capture_snapshot.map(&:url).sort).to eq(
412
- [ajax_url, sink_url].sort
460
+ [url, "#{@url}with-ajax"].sort
413
461
  )
414
462
  end
415
463
  end
416
464
 
417
465
  context 'when an error occurs' do
418
466
  it 'ignores it' do
419
- allow(subject.watir).to receive(:windows) { raise }
467
+ allow(subject).to receive(:to_page) { raise }
420
468
  expect(subject.capture_snapshot( blah: :stuff )).to be_empty
421
469
  end
422
470
  end
@@ -496,8 +544,8 @@ describe Arachni::Browser do
496
544
  calls << [element.opening_tag, event]
497
545
  end
498
546
 
499
- @browser.fire_event @browser.watir.div( id: 'my-div' ), :click
500
- @browser.fire_event @browser.watir.div( id: 'my-div' ), :mouseover
547
+ @browser.fire_event @browser.selenium.find_element( id: 'my-div' ), :click
548
+ @browser.fire_event @browser.selenium.find_element( id: 'my-div' ), :mouseover
501
549
 
502
550
  expect(calls).to eq([
503
551
  [ "<div id=\"my-div\" onclick=\"addForm();\">", :click ],
@@ -590,7 +638,7 @@ describe Arachni::Browser do
590
638
  tag_name: 'a',
591
639
  attributes: {
592
640
  'onmouseover' => 'writeButton();',
593
- 'href' => 'javascript:level3();'
641
+ 'href' => '#'
594
642
  }
595
643
  } => :mouseover
596
644
  }
@@ -603,11 +651,11 @@ describe Arachni::Browser do
603
651
  {
604
652
  tag_name: 'a',
605
653
  attributes: {
606
- 'onmouseover' => 'writeButton();',
607
654
  'href' => 'javascript:level3();'
608
655
  }
609
656
  } => :click
610
657
  },
658
+ { "#{@url}level4" => :request },
611
659
  { "#{@url}level4" => :request }
612
660
  ],
613
661
  [
@@ -619,7 +667,7 @@ describe Arachni::Browser do
619
667
  tag_name: 'a',
620
668
  attributes: {
621
669
  'onmouseover' => 'writeButton();',
622
- 'href' => 'javascript:level3();'
670
+ 'href' => '#'
623
671
  }
624
672
  } => :mouseover
625
673
  },
@@ -640,12 +688,12 @@ describe Arachni::Browser do
640
688
  {
641
689
  tag_name: 'a',
642
690
  attributes: {
643
- 'onmouseover' => 'writeButton();',
644
691
  'href' => 'javascript:level3();'
645
692
  }
646
693
  } => :click
647
694
  },
648
695
  { "#{@url}level4" => :request },
696
+ { "#{@url}level4" => :request },
649
697
  {
650
698
  {
651
699
  tag_name: 'div',
@@ -680,7 +728,7 @@ describe Arachni::Browser do
680
728
  tag_name: 'a',
681
729
  attributes: {
682
730
  'onmouseover' => 'writeButton();',
683
- 'href' => 'javascript:level3();'
731
+ 'href' => '#'
684
732
  }
685
733
  } => :mouseover
686
734
  }
@@ -693,11 +741,11 @@ describe Arachni::Browser do
693
741
  {
694
742
  tag_name: 'a',
695
743
  attributes: {
696
- 'onmouseover' => 'writeButton();',
697
744
  'href' => 'javascript:level3();'
698
745
  }
699
746
  } => :click
700
747
  },
748
+ { "#{@url}level4" => :request },
701
749
  { "#{@url}level4" => :request }
702
750
  ]
703
751
  ].map { |transitions| transitions_from_array( transitions ) })
@@ -991,15 +1039,62 @@ describe Arachni::Browser do
991
1039
  it 'returns nil'
992
1040
  end
993
1041
 
994
- context 'when the resource is out-of-scope' do
1042
+ context 'when the resource is out of scope' do
995
1043
  it 'returns nil' do
996
1044
  Arachni::Options.url = @url
997
- @browser.load 'http://google.com/'
1045
+ @browser.load @url
1046
+
1047
+ subject.javascript.run( 'window.location = "http://google.com/";' )
1048
+ sleep 1
1049
+
998
1050
  expect(@browser.response).to be_nil
999
1051
  end
1000
1052
  end
1001
1053
  end
1002
1054
 
1055
+ describe '#state' do
1056
+ it 'returns a Page::DOM with enough info to reproduce the current state' do
1057
+ @browser.load "#{web_server_url_for( :taint_tracer )}/debug" <<
1058
+ "?input=#{@browser.javascript.log_execution_flow_sink_stub(1)}"
1059
+
1060
+ dom = subject.to_page.dom
1061
+ state = subject.state
1062
+
1063
+ expect(state.page).to be_nil
1064
+ expect(state.url).to eq dom.url
1065
+ expect(state.digest).to eq dom.digest
1066
+ expect(state.transitions).to eq dom.transitions
1067
+ expect(state.skip_states).to eq dom.skip_states
1068
+ expect(state.data_flow_sinks).to be_empty
1069
+ expect(state.execution_flow_sinks).to be_empty
1070
+ end
1071
+
1072
+ context 'when the URL is about:blank' do
1073
+ it 'returns nil' do
1074
+ Arachni::Options.url = @url
1075
+ subject.load @url
1076
+
1077
+ subject.javascript.run( 'window.location = "about:blank";' )
1078
+ sleep 1
1079
+
1080
+ expect(subject.state).to be_nil
1081
+ end
1082
+ end
1083
+
1084
+ context 'when the resource is out-of-scope' do
1085
+ it 'returns an empty page' do
1086
+ Arachni::Options.url = @url
1087
+ subject.load @url
1088
+
1089
+ subject.javascript.run( 'window.location = "http://google.com/";' )
1090
+ sleep 1
1091
+
1092
+ expect(subject.state).to be_nil
1093
+ end
1094
+ end
1095
+
1096
+ end
1097
+
1003
1098
  describe '#to_page' do
1004
1099
  it "converts the working window to an #{Arachni::Page}" do
1005
1100
  ua = Arachni::Options.http.user_agent
@@ -1017,10 +1112,12 @@ describe Arachni::Browser do
1017
1112
  it "assigns the proper #{Arachni::Page::DOM}#digest" do
1018
1113
  @browser.load( @url )
1019
1114
  expect(@browser.to_page.dom.instance_variable_get(:@digest)).to eq(
1020
- '<HTML><HEAD><SCRIPT src=http://javascript.browser.arachni/' <<
1021
- 'taint_tracer.js><SCRIPT src=http://javascript.' <<
1022
- 'browser.arachni/dom_monitor.js><SCRIPT><TITLE><BODY><' <<
1023
- 'DIV><SCRIPT type=text/javascript><SCRIPT type=text/javascript>'
1115
+ '<HTML><HEAD><SCRIPT src=http://' <<
1116
+ 'javascript.browser.arachni/polyfills.js><SCRIPT src=http://' <<
1117
+ 'javascript.browser.arachni/' <<
1118
+ 'taint_tracer.js><SCRIPT src=http://javascript.' <<
1119
+ 'browser.arachni/dom_monitor.js><SCRIPT><TITLE><BODY><' <<
1120
+ 'DIV><SCRIPT type=text/javascript><SCRIPT type=text/javascript>'
1024
1121
  )
1025
1122
  end
1026
1123
 
@@ -1078,7 +1175,7 @@ describe Arachni::Browser do
1078
1175
  context 'when the page has' do
1079
1176
  context "#{Arachni::Element::UIForm} elements" do
1080
1177
  context "and #{Arachni::OptionGroups::Audit}#inputs is" do
1081
- context true do
1178
+ context 'true' do
1082
1179
  before do
1083
1180
  Arachni::Options.audit.elements :ui_forms
1084
1181
  end
@@ -1126,7 +1223,7 @@ describe Arachni::Browser do
1126
1223
  end
1127
1224
  end
1128
1225
 
1129
- context false do
1226
+ context 'false' do
1130
1227
  before do
1131
1228
  Arachni::Options.audit.skip_elements :ui_forms
1132
1229
  end
@@ -1141,7 +1238,7 @@ describe Arachni::Browser do
1141
1238
 
1142
1239
  context "#{Arachni::Element::UIInput} elements" do
1143
1240
  context "and #{Arachni::OptionGroups::Audit}#inputs is" do
1144
- context true do
1241
+ context 'true' do
1145
1242
  before do
1146
1243
  Arachni::Options.audit.elements :ui_inputs
1147
1244
  end
@@ -1189,7 +1286,7 @@ describe Arachni::Browser do
1189
1286
  end
1190
1287
  end
1191
1288
 
1192
- context false do
1289
+ context 'false' do
1193
1290
  before do
1194
1291
  Arachni::Options.audit.skip_elements :ui_inputs
1195
1292
  end
@@ -1204,7 +1301,7 @@ describe Arachni::Browser do
1204
1301
 
1205
1302
  context "#{Arachni::Element::Form::DOM} elements" do
1206
1303
  context "and #{Arachni::OptionGroups::Audit}#forms is" do
1207
- context true do
1304
+ context 'true' do
1208
1305
  before do
1209
1306
  Arachni::Options.audit.elements :forms
1210
1307
  end
@@ -1231,7 +1328,7 @@ describe Arachni::Browser do
1231
1328
  end
1232
1329
  end
1233
1330
 
1234
- context false do
1331
+ context 'false' do
1235
1332
  before do
1236
1333
  Arachni::Options.audit.skip_elements :forms
1237
1334
  end
@@ -1248,7 +1345,7 @@ describe Arachni::Browser do
1248
1345
  let(:cookies) { @browser.to_page.cookies }
1249
1346
 
1250
1347
  context "and #{Arachni::OptionGroups::Audit}#cookies is" do
1251
- context true do
1348
+ context 'true' do
1252
1349
  before do
1253
1350
  Arachni::Options.audit.elements :cookies
1254
1351
 
@@ -1261,8 +1358,16 @@ describe Arachni::Browser do
1261
1358
  let(:page) { 'dom-cookies-names' }
1262
1359
 
1263
1360
  it 'does not set #skip_dom' do
1264
- expect(cookies.find { |c| c.name == 'my-cookie' }.skip_dom).to be_nil
1265
- expect(cookies.find { |c| c.name == 'my-cookie2' }.skip_dom).to be_nil
1361
+ expect(cookies.find { |c| c.name == 'js_cookie1' }.skip_dom).to be_nil
1362
+ expect(cookies.find { |c| c.name == 'js_cookie2' }.skip_dom).to be_nil
1363
+ end
1364
+
1365
+ it 'does not track HTTP-only cookies' do
1366
+ expect(cookies.find { |c| c.name == 'http_only_cookie' }.skip_dom).to be true
1367
+ end
1368
+
1369
+ it 'does not track cookies for other paths' do
1370
+ expect(cookies.find { |c| c.name == 'other_path' }.skip_dom).to be true
1266
1371
  end
1267
1372
  end
1268
1373
 
@@ -1270,8 +1375,16 @@ describe Arachni::Browser do
1270
1375
  let(:page) { 'dom-cookies-values' }
1271
1376
 
1272
1377
  it 'does not set #skip_dom' do
1273
- expect(cookies.find { |c| c.name == 'my-cookie' }.skip_dom).to be_nil
1274
- expect(cookies.find { |c| c.name == 'my-cookie2' }.skip_dom).to be_nil
1378
+ expect(cookies.find { |c| c.name == 'js_cookie1' }.skip_dom).to be_nil
1379
+ expect(cookies.find { |c| c.name == 'js_cookie2' }.skip_dom).to be_nil
1380
+ end
1381
+
1382
+ it 'does not track HTTP-only cookies' do
1383
+ expect(cookies.find { |c| c.name == 'http_only_cookie' }.skip_dom).to be true
1384
+ end
1385
+
1386
+ it 'does not track cookies for other paths' do
1387
+ expect(cookies.find { |c| c.name == 'other_path' }.skip_dom).to be true
1275
1388
  end
1276
1389
  end
1277
1390
  end
@@ -1281,7 +1394,7 @@ describe Arachni::Browser do
1281
1394
  let(:page) { 'dom-cookies-names' }
1282
1395
 
1283
1396
  it 'does not set #skip_dom' do
1284
- expect(cookies.find { |c| c.name == 'my-cookie3' }.skip_dom).to be_truthy
1397
+ expect(cookies.find { |c| c.name == 'js_cookie3' }.skip_dom).to be_truthy
1285
1398
  end
1286
1399
  end
1287
1400
 
@@ -1289,13 +1402,13 @@ describe Arachni::Browser do
1289
1402
  let(:page) { 'dom-cookies-values' }
1290
1403
 
1291
1404
  it 'does not set #skip_dom' do
1292
- expect(cookies.find { |c| c.name == 'my-cookie3' }.skip_dom).to be_truthy
1405
+ expect(cookies.find { |c| c.name == 'js_cookie3' }.skip_dom).to be_truthy
1293
1406
  end
1294
1407
  end
1295
1408
  end
1296
1409
  end
1297
1410
 
1298
- context false do
1411
+ context 'false' do
1299
1412
  before do
1300
1413
  Arachni::Options.audit.skip_elements :cookies
1301
1414
 
@@ -1319,13 +1432,17 @@ describe Arachni::Browser do
1319
1432
  context 'when the resource is out-of-scope' do
1320
1433
  it 'returns an empty page' do
1321
1434
  Arachni::Options.url = @url
1322
- subject.load 'http://google.com/'
1435
+ subject.load @url
1436
+
1437
+ subject.javascript.run( 'window.location = "http://google.com/";' )
1438
+ sleep 1
1439
+
1323
1440
  page = subject.to_page
1324
1441
 
1325
1442
  expect(page.code).to eq(0)
1326
- expect(page.url).to eq(subject.url)
1443
+ expect(page.url).to eq('http://google.com/')
1327
1444
  expect(page.body).to be_empty
1328
- expect(page.dom.url).to eq(subject.watir.url)
1445
+ expect(page.dom.url).to eq('http://google.com/')
1329
1446
  end
1330
1447
  end
1331
1448
  end
@@ -1337,22 +1454,22 @@ describe Arachni::Browser do
1337
1454
  end
1338
1455
 
1339
1456
  it 'fires the given event' do
1340
- @browser.fire_event @browser.watir.div( id: 'my-div' ), :click
1457
+ @browser.fire_event @browser.selenium.find_element( id: 'my-div' ), :click
1341
1458
  pages_should_have_form_with_input [@browser.to_page], 'by-ajax'
1342
1459
  end
1343
1460
 
1344
1461
  it 'accepts events without the "on" prefix' do
1345
1462
  pages_should_not_have_form_with_input [@browser.to_page], 'by-ajax'
1346
1463
 
1347
- @browser.fire_event @browser.watir.div( id: 'my-div' ), :onclick
1464
+ @browser.fire_event @browser.selenium.find_element( id: 'my-div' ), :onclick
1348
1465
  pages_should_have_form_with_input [@browser.to_page], 'by-ajax'
1349
1466
 
1350
- @browser.fire_event @browser.watir.div( id: 'my-div' ), :click
1467
+ @browser.fire_event @browser.selenium.find_element( id: 'my-div' ), :click
1351
1468
  pages_should_have_form_with_input [@browser.to_page], 'by-ajax'
1352
1469
  end
1353
1470
 
1354
1471
  it 'returns a playable transition' do
1355
- transition = @browser.fire_event @browser.watir.div( id: 'my-div' ), :click
1472
+ transition = @browser.fire_event @browser.selenium.find_element( id: 'my-div' ), :click
1356
1473
  pages_should_have_form_with_input [@browser.to_page], 'by-ajax'
1357
1474
 
1358
1475
  @browser.load( url ).start_capture
@@ -1362,12 +1479,51 @@ describe Arachni::Browser do
1362
1479
  pages_should_have_form_with_input [@browser.to_page], 'by-ajax'
1363
1480
  end
1364
1481
 
1365
- context 'when the element is not visible' do
1366
- it 'returns nil' do
1367
- element = @browser.watir.div( id: 'my-div' )
1482
+ context 'when new timers are introduced' do
1483
+ let(:url) { "#{@url}/trigger_events/with_new_timers/3000" }
1484
+
1485
+ it 'waits for them' do
1486
+ @browser.fire_event @browser.selenium.find_element( id: 'my-div' ), :click
1487
+ pages_should_have_form_with_input [@browser.to_page], 'by-ajax'
1488
+ end
1489
+
1490
+ context 'when a new timer exceeds Options.http.request_timeout' do
1491
+ let(:url) { "#{@url}/trigger_events/with_new_timers/#{Arachni::Options.http.request_timeout + 5000}" }
1492
+
1493
+ it 'waits for Options.http.request_timeout' do
1494
+ t = Time.now
1495
+
1496
+ @browser.fire_event @browser.selenium.find_element( id: 'my-div' ), :click
1497
+ pages_should_not_have_form_with_input [@browser.to_page], 'by-ajax'
1498
+
1499
+ expect(Time.now - t).to be <= Arachni::Options.http.request_timeout
1500
+ end
1501
+ end
1502
+ end
1503
+
1504
+ context 'when cookies are set' do
1505
+ let(:url) { @url + '/each_element_with_events/set-cookie' }
1368
1506
 
1369
- allow(element).to receive(:visible?) { false }
1507
+ it 'sets them globally' do
1508
+ expect(Arachni::HTTP::Client.cookies).to be_empty
1370
1509
 
1510
+ @browser.fire_event described_class::ElementLocator.new(
1511
+ tag_name: :button,
1512
+ attributes: {
1513
+ onclick: 'setCookie()'
1514
+ }
1515
+ ), :click
1516
+
1517
+ cookie = Arachni::HTTP::Client.cookies.first
1518
+ expect(cookie.name).to eq 'cookie_name'
1519
+ expect(cookie.value).to eq 'cookie value'
1520
+ end
1521
+ end
1522
+
1523
+ context 'when the element is not visible' do
1524
+ it 'returns nil' do
1525
+ @browser.goto "#{url}/invisible-div"
1526
+ element = @browser.selenium.find_element( id: 'invisible-div' )
1371
1527
  expect(@browser.fire_event( element, :click )).to be_nil
1372
1528
  end
1373
1529
  end
@@ -1382,57 +1538,45 @@ describe Arachni::Browser do
1382
1538
 
1383
1539
  allow(element).to receive(:locate){ raise Selenium::WebDriver::Error::WebDriverError }
1384
1540
  expect(@browser.fire_event( element, :click )).to be_nil
1385
-
1386
- allow(element).to receive(:locate){ raise Watir::Exception::Error }
1387
- expect(@browser.fire_event( element, :click )).to be_nil
1388
1541
  end
1389
1542
  end
1390
1543
  end
1391
1544
 
1392
- context 'when the element never appears' do
1393
- it 'returns nil' do
1394
- element = @browser.watir.div( id: 'my-div' )
1395
-
1396
- allow(element).to receive(:exists?) { false }
1397
-
1398
- expect(@browser.fire_event( element, :click )).to be_nil
1399
- end
1400
- end
1401
-
1402
1545
  context 'when the trigger fails with' do
1403
- let(:element) { @browser.watir.div( id: 'my-div' ) }
1546
+ let(:element) { @browser.selenium.find_element( id: 'my-div' ) }
1404
1547
 
1405
- context Selenium::WebDriver::Error::WebDriverError do
1548
+ context 'Selenium::WebDriver::Error::WebDriverError' do
1406
1549
  it 'returns nil' do
1407
- allow(element).to receive(:fire_event){ raise Selenium::WebDriver::Error::WebDriverError }
1408
- expect(@browser.fire_event( element, :click )).to be_nil
1409
- end
1410
- end
1550
+ allow(@browser).to receive(:wait_for_pending_requests) do
1551
+ raise Selenium::WebDriver::Error::WebDriverError
1552
+ end
1411
1553
 
1412
- context Watir::Exception::Error do
1413
- it 'returns nil' do
1414
- allow(element).to receive(:fire_event){ raise Watir::Exception::Error }
1415
1554
  expect(@browser.fire_event( element, :click )).to be_nil
1416
1555
  end
1417
1556
  end
1418
1557
  end
1419
1558
 
1420
1559
  context 'form' do
1421
- context :submit do
1560
+ context ':submit' do
1422
1561
  let(:url) { "#{@url}/fire_event/form/onsubmit" }
1423
1562
 
1424
1563
  context 'when option' do
1425
- describe :inputs do
1564
+ describe ':inputs' do
1565
+
1566
+ def element
1567
+ @browser.selenium.find_element(:tag_name, :form)
1568
+ end
1569
+
1426
1570
  context 'is given' do
1427
1571
  let(:inputs) do
1428
1572
  {
1429
- name: "The Dude",
1573
+ name: 'The Dude',
1430
1574
  email: 'the.dude@abides.com'
1431
1575
  }
1432
1576
  end
1433
1577
 
1434
1578
  before(:each) do
1435
- @browser.fire_event @browser.watir.form, :submit, inputs: inputs
1579
+ @browser.fire_event element, :submit, inputs: inputs
1436
1580
  end
1437
1581
 
1438
1582
  it 'fills in its inputs with the given values' do
@@ -1447,7 +1591,7 @@ describe Arachni::Browser do
1447
1591
  it 'returns a playable transition' do
1448
1592
  @browser.load url
1449
1593
 
1450
- transition = @browser.fire_event @browser.watir.form, :submit, inputs: inputs
1594
+ transition = @browser.fire_event element, :submit, inputs: inputs
1451
1595
 
1452
1596
  @browser.load url
1453
1597
 
@@ -1513,7 +1657,7 @@ describe Arachni::Browser do
1513
1657
 
1514
1658
  it 'returns a playable transition' do
1515
1659
  @browser.load url
1516
- transition = @browser.fire_event @browser.watir.form, :submit, inputs: inputs
1660
+ transition = @browser.fire_event element, :submit, inputs: inputs
1517
1661
 
1518
1662
  @browser.load url
1519
1663
 
@@ -1541,7 +1685,7 @@ describe Arachni::Browser do
1541
1685
 
1542
1686
  it 'returns a playable transition' do
1543
1687
  @browser.load url
1544
- transition = @browser.fire_event @browser.watir.form, :submit, inputs: inputs
1688
+ transition = @browser.fire_event element, :submit, inputs: inputs
1545
1689
 
1546
1690
  @browser.load url
1547
1691
 
@@ -1570,7 +1714,7 @@ describe Arachni::Browser do
1570
1714
  context 'is not given' do
1571
1715
  it 'fills in its inputs with sample values' do
1572
1716
  @browser.load url
1573
- @browser.fire_event @browser.watir.form, :submit
1717
+ @browser.fire_event element, :submit
1574
1718
 
1575
1719
  expect(@browser.watir.div( id: 'container-name' ).text).to eq(
1576
1720
  Arachni::Options.input.value_for_name( 'name' )
@@ -1582,7 +1726,7 @@ describe Arachni::Browser do
1582
1726
 
1583
1727
  it 'returns a playable transition' do
1584
1728
  @browser.load url
1585
- transition = @browser.fire_event @browser.watir.form, :submit
1729
+ transition = @browser.fire_event element, :submit
1586
1730
 
1587
1731
  @browser.load url
1588
1732
 
@@ -1603,7 +1747,7 @@ describe Arachni::Browser do
1603
1747
  let(:url) { "#{@url}/fire_event/form/disabled_inputs" }
1604
1748
 
1605
1749
  it 'is skips those inputs' do
1606
- @browser.fire_event @browser.watir.form, :submit
1750
+ @browser.fire_event element, :submit
1607
1751
 
1608
1752
  expect(@browser.watir.div( id: 'container-name' ).text).to eq(
1609
1753
  Arachni::Options.input.value_for_name( 'name' )
@@ -1617,13 +1761,17 @@ describe Arachni::Browser do
1617
1761
  end
1618
1762
 
1619
1763
  context 'image button' do
1620
- context :click do
1764
+ context ':click' do
1621
1765
  before( :each ) { @browser.start_capture }
1622
1766
  let(:url) { "#{@url}fire_event/form/image-input" }
1623
1767
 
1768
+ def element
1769
+ @browser.selenium.find_element( :xpath, '//input[@type="image"]')
1770
+ end
1771
+
1624
1772
  it 'submits the form with x, y coordinates' do
1625
1773
  @browser.load( url )
1626
- @browser.fire_event @browser.watir.input( type: 'image'), :click
1774
+ @browser.fire_event element, :click
1627
1775
 
1628
1776
  pages_should_have_form_with_input @browser.captured_pages, 'myImageButton.x'
1629
1777
  pages_should_have_form_with_input @browser.captured_pages, 'myImageButton.y'
@@ -1631,7 +1779,7 @@ describe Arachni::Browser do
1631
1779
 
1632
1780
  it 'returns a playable transition' do
1633
1781
  @browser.load( url )
1634
- transition = @browser.fire_event @browser.watir.input( type: 'image'), :click
1782
+ transition = @browser.fire_event element, :click
1635
1783
 
1636
1784
  captured_pages = @browser.flush_pages
1637
1785
  pages_should_have_form_with_input captured_pages, 'myImageButton.x'
@@ -1658,18 +1806,22 @@ describe Arachni::Browser do
1658
1806
  string[0...-1] : string
1659
1807
  end
1660
1808
 
1661
- context event do
1809
+ context event.to_s do
1662
1810
  let( :url ) { "#{@url}/fire_event/input/#{event}" }
1663
1811
 
1664
1812
  context 'when option' do
1665
- describe :inputs do
1813
+ describe ':inputs' do
1814
+ def element
1815
+ @browser.selenium.find_element(:tag_name, :input)
1816
+ end
1817
+
1666
1818
  context 'is given' do
1667
1819
  let(:value) do
1668
1820
  'The Dude'
1669
1821
  end
1670
1822
 
1671
1823
  before(:each) do
1672
- @browser.fire_event @browser.watir.input, event, value: value
1824
+ @browser.fire_event element, event, value: value
1673
1825
  end
1674
1826
 
1675
1827
  it 'fills in its inputs with the given values' do
@@ -1680,7 +1832,7 @@ describe Arachni::Browser do
1680
1832
 
1681
1833
  it 'returns a playable transition' do
1682
1834
  @browser.load url
1683
- transition = @browser.fire_event @browser.watir.input, event, value: value
1835
+ transition = @browser.fire_event element, event, value: value
1684
1836
 
1685
1837
  @browser.load url
1686
1838
  expect(@browser.watir.div( id: 'container' ).text).to be_empty
@@ -1702,7 +1854,7 @@ describe Arachni::Browser do
1702
1854
 
1703
1855
  it 'returns a playable transition' do
1704
1856
  @browser.load url
1705
- transition = @browser.fire_event @browser.watir.input, event, value: value
1857
+ transition = @browser.fire_event element, event, value: value
1706
1858
 
1707
1859
  @browser.load url
1708
1860
  expect(@browser.watir.div( id: 'container' ).text).to be_empty
@@ -1715,7 +1867,7 @@ describe Arachni::Browser do
1715
1867
 
1716
1868
  context 'is not given' do
1717
1869
  it 'fills in a sample value' do
1718
- @browser.fire_event @browser.watir.input, event
1870
+ @browser.fire_event element, event
1719
1871
 
1720
1872
  expect(@browser.watir.div( id: 'container' ).text).to eq(
1721
1873
  calculate_expectation.call( Arachni::Options.input.value_for_name( 'name' ) )
@@ -1724,7 +1876,7 @@ describe Arachni::Browser do
1724
1876
 
1725
1877
  it 'returns a playable transition' do
1726
1878
  @browser.load url
1727
- transition = @browser.fire_event @browser.watir.input, event
1879
+ transition = @browser.fire_event element, event
1728
1880
 
1729
1881
  @browser.load url
1730
1882
  expect(@browser.watir.div( id: 'container' ).text).to be_empty
@@ -1742,6 +1894,44 @@ describe Arachni::Browser do
1742
1894
  end
1743
1895
  end
1744
1896
 
1897
+ describe '#elements_with_events' do
1898
+ before :each do
1899
+ @browser.load url
1900
+ end
1901
+
1902
+ let(:elements_with_events) do
1903
+ elements_with_events = {}
1904
+ @browser.each_element_with_events do |locator, events|
1905
+ elements_with_events[locator] = events
1906
+ end
1907
+ elements_with_events
1908
+ end
1909
+
1910
+ let(:url) { @url + '/trigger_events' }
1911
+
1912
+ it 'returns all elements with associated events' do
1913
+ expect(subject.elements_with_events.to_s).to eq elements_with_events.to_s
1914
+ end
1915
+
1916
+ it 'caches results' do
1917
+ expect(subject).to receive(:each_element_with_events)
1918
+ subject.elements_with_events
1919
+
1920
+ expect(subject).to_not receive(:each_element_with_events)
1921
+ subject.elements_with_events
1922
+ end
1923
+
1924
+ context 'when passed true' do
1925
+ it 'clears the cache' do
1926
+ expect(subject).to receive(:each_element_with_events)
1927
+ subject.elements_with_events
1928
+
1929
+ expect(subject).to receive(:each_element_with_events)
1930
+ subject.elements_with_events( true )
1931
+ end
1932
+ end
1933
+ end
1934
+
1745
1935
  describe '#each_element_with_events' do
1746
1936
  before :each do
1747
1937
  @browser.load url
@@ -1762,19 +1952,19 @@ describe Arachni::Browser do
1762
1952
  tag_name: 'body',
1763
1953
  attributes: { 'onmouseover' => 'makePOST();' }
1764
1954
  ),
1765
- [[:onmouseover, 'makePOST();']]
1955
+ { onmouseover: ['makePOST();'] }
1766
1956
  ],
1767
1957
  [
1768
1958
  described_class::ElementLocator.new(
1769
1959
  tag_name: 'div',
1770
1960
  attributes: { 'id' => 'my-div', 'onclick' => 'addForm();' }
1771
1961
  ),
1772
- [[:onclick, 'addForm();']]
1962
+ { onclick: ['addForm();']}
1773
1963
  ]
1774
1964
  ])
1775
1965
  end
1776
1966
 
1777
- context :a do
1967
+ context ':a' do
1778
1968
  context 'and the href is not empty' do
1779
1969
  context 'and it starts with javascript:' do
1780
1970
  let(:url) { @url + '/each_element_with_events/a/href/javascript' }
@@ -1786,7 +1976,7 @@ describe Arachni::Browser do
1786
1976
  tag_name: 'a',
1787
1977
  attributes: { 'href' => 'javascript:doStuff()' }
1788
1978
  ),
1789
- [[:click, 'javascript:doStuff()']]
1979
+ {click: [ 'javascript:doStuff()']}
1790
1980
  ]
1791
1981
  ])
1792
1982
  end
@@ -1810,8 +2000,8 @@ describe Arachni::Browser do
1810
2000
  end
1811
2001
  end
1812
2002
 
1813
- context :form do
1814
- context :input do
2003
+ context ':form' do
2004
+ context ':input' do
1815
2005
  context 'of type "image"' do
1816
2006
  let(:url) { @url + '/each_element_with_events/form/input/image' }
1817
2007
 
@@ -1826,7 +2016,7 @@ describe Arachni::Browser do
1826
2016
  'src' => '/__sinatra__/404.png'
1827
2017
  }
1828
2018
  ),
1829
- [[:click, 'image']]
2019
+ {click: ['image']}
1830
2020
  ]
1831
2021
  ])
1832
2022
  end
@@ -1846,7 +2036,7 @@ describe Arachni::Browser do
1846
2036
  'action' => 'javascript:doStuff()'
1847
2037
  }
1848
2038
  ),
1849
- [[:submit, 'javascript:doStuff()']]
2039
+ {submit: ['javascript:doStuff()']}
1850
2040
  ]
1851
2041
  ])
1852
2042
  end
@@ -1855,7 +2045,7 @@ describe Arachni::Browser do
1855
2045
  context 'and it does not start with javascript:' do
1856
2046
  let(:url) { @url + '/each_element_with_events/form/action/regular' }
1857
2047
 
1858
- it 'is ignored'do
2048
+ it 'is ignored' do
1859
2049
  expect(elements_with_events).to be_empty
1860
2050
  end
1861
2051
  end
@@ -1863,7 +2053,7 @@ describe Arachni::Browser do
1863
2053
  context 'and is out of scope' do
1864
2054
  let(:url) { @url + '/each_element_with_events/form/action/out-of-scope' }
1865
2055
 
1866
- it 'is ignored'do
2056
+ it 'is ignored' do
1867
2057
  expect(elements_with_events).to be_empty
1868
2058
  end
1869
2059
  end
@@ -1876,7 +2066,7 @@ describe Arachni::Browser do
1876
2066
  @browser.load( @url + '/trigger_events' ).start_capture
1877
2067
 
1878
2068
  locators = []
1879
- @browser.watir.elements.each do |element|
2069
+ @browser.selenium.find_elements(:css, '*').each do |element|
1880
2070
  begin
1881
2071
  locators << described_class::ElementLocator.from_html( element.opening_tag )
1882
2072
  rescue
@@ -1899,6 +2089,10 @@ describe Arachni::Browser do
1899
2089
  end
1900
2090
 
1901
2091
  describe '#trigger_events' do
2092
+ it 'returns self' do
2093
+ expect(@browser.load( @url + '/explore' ).trigger_events).to eq(@browser)
2094
+ end
2095
+
1902
2096
  it 'waits for AJAX requests to complete' do
1903
2097
  @browser.load( @url + '/trigger_events-wait-for-ajax' ).start_capture.trigger_events
1904
2098
 
@@ -1916,6 +2110,7 @@ describe Arachni::Browser do
1916
2110
 
1917
2111
  it 'assigns the proper page transitions' do
1918
2112
  pages = @browser.load( @url + '/explore' ).trigger_events.page_snapshots
2113
+
1919
2114
  expect(pages.map(&:dom).map(&:transitions)).to eq([
1920
2115
  [
1921
2116
  { :page => :load },
@@ -1933,7 +2128,8 @@ describe Arachni::Browser do
1933
2128
  }
1934
2129
  } => :click
1935
2130
  },
1936
- { "#{@url}get-ajax?ajax-token=my-token" => :request }
2131
+ { "#{@url}get-ajax?ajax-token=my-token" => :request },
2132
+ { "#{@url}post-ajax" => :request }
1937
2133
  ],
1938
2134
  [
1939
2135
  { :page => :load },
@@ -1947,6 +2143,8 @@ describe Arachni::Browser do
1947
2143
  } => :click
1948
2144
  },
1949
2145
  { "#{@url}href-ajax" => :request },
2146
+ { "#{@url}post-ajax" => :request },
2147
+ { "#{@url}href-ajax" => :request }
1950
2148
  ]
1951
2149
  ].map { |transitions| transitions_from_array( transitions ) })
1952
2150
  end
@@ -1975,10 +2173,6 @@ describe Arachni::Browser do
1975
2173
  pages_should_have_form_with_input @browser.captured_pages, 'myImageButton.y'
1976
2174
  end
1977
2175
  end
1978
-
1979
- it 'returns self' do
1980
- expect(@browser.load( @url + '/explore' ).trigger_events).to eq(@browser)
1981
- end
1982
2176
  end
1983
2177
 
1984
2178
  describe '#source' do
@@ -2190,7 +2384,7 @@ describe Arachni::Browser do
2190
2384
  end
2191
2385
 
2192
2386
  it "waits a maximum of #{Arachni::OptionGroups::BrowserCluster}#job_timeout" do
2193
- Arachni::Options.browser_cluster.job_timeout = 4
2387
+ Arachni::Options.browser_cluster.job_timeout = 2
2194
2388
 
2195
2389
  t = Time.now
2196
2390
  @browser.goto( @url + '/wait_for_elements#stuff/here' )
@@ -2216,7 +2410,7 @@ describe Arachni::Browser do
2216
2410
  end
2217
2411
 
2218
2412
  context "#{Arachni::OptionGroups::BrowserCluster}#ignore_images" do
2219
- context true do
2413
+ context 'true' do
2220
2414
  it 'does not load images' do
2221
2415
  Arachni::Options.browser_cluster.ignore_images = true
2222
2416
  @browser.shutdown
@@ -2228,7 +2422,7 @@ describe Arachni::Browser do
2228
2422
  end
2229
2423
  end
2230
2424
 
2231
- context false do
2425
+ context 'false' do
2232
2426
  it 'loads images' do
2233
2427
  Arachni::Options.browser_cluster.ignore_images = false
2234
2428
  @browser.shutdown
@@ -2266,16 +2460,19 @@ describe Arachni::Browser do
2266
2460
  context "with #{Arachni::OptionGroups::Scope}#auto_redundant_paths has bee configured" do
2267
2461
  it 'respects scope restrictions' do
2268
2462
  Arachni::Options.scope.auto_redundant_paths = 0
2269
- expect(@browser.load( @url + '/explore?test=1&test2=2' ).response.code).to eq(0)
2463
+ expect(@browser.load( @url + '/explore?test=1&test2=2' ).response).to be_nil
2270
2464
  end
2271
2465
  end
2272
2466
 
2273
- describe :cookies do
2467
+ describe ':cookies' do
2274
2468
  it 'loads the given cookies' do
2275
2469
  cookie = { 'myname' => 'myvalue' }
2276
2470
  @browser.goto @url, cookies: cookie
2277
2471
 
2278
- expect(@browser.cookies.find { |c| c.name == cookie.keys.first }.inputs).to eq(cookie)
2472
+ cookie_data = @browser.cookies.
2473
+ find { |c| c.name == cookie.keys.first }.inputs
2474
+
2475
+ expect(cookie_data).to eq(cookie)
2279
2476
  end
2280
2477
 
2281
2478
  it 'includes them in the transition' do
@@ -2284,23 +2481,10 @@ describe Arachni::Browser do
2284
2481
 
2285
2482
  expect(transition.options[:cookies]).to eq(cookie)
2286
2483
  end
2287
-
2288
- context 'when auditing existing cookies' do
2289
- it 'preserves the HttpOnly attribute' do
2290
- @browser.goto( @url )
2291
- expect(@browser.cookies.size).to eq(1)
2292
-
2293
- cookies = { @browser.cookies.first.name => 'updated' }
2294
- @browser.goto( @url, cookies: cookies )
2295
-
2296
- @browser.cookies.first.value == 'updated'
2297
- expect(@browser.cookies.first).to be_http_only
2298
- end
2299
- end
2300
2484
  end
2301
2485
 
2302
- describe :take_snapshot do
2303
- describe true do
2486
+ describe ':take_snapshot' do
2487
+ describe 'true' do
2304
2488
  it 'captures a snapshot of the loaded page' do
2305
2489
  @browser.goto @url, take_snapshot: true
2306
2490
  pages = @browser.page_snapshots
@@ -2313,7 +2497,7 @@ describe Arachni::Browser do
2313
2497
  end
2314
2498
  end
2315
2499
 
2316
- describe false do
2500
+ describe 'false' do
2317
2501
  it 'does not capture a snapshot of the loaded page' do
2318
2502
  @browser.goto @url, take_snapshot: false
2319
2503
  expect(@browser.page_snapshots).to be_empty
@@ -2334,15 +2518,15 @@ describe Arachni::Browser do
2334
2518
  end
2335
2519
  end
2336
2520
 
2337
- describe :update_transitions do
2338
- describe true do
2521
+ describe ':update_transitions' do
2522
+ describe 'true' do
2339
2523
  it 'pushes the page load to the transitions' do
2340
2524
  t = @browser.goto( @url, update_transitions: true )
2341
2525
  expect(@browser.to_page.dom.transitions).to include t
2342
2526
  end
2343
2527
  end
2344
2528
 
2345
- describe false do
2529
+ describe 'false' do
2346
2530
  it 'does not push the page load to the transitions' do
2347
2531
  t = @browser.goto( @url, update_transitions: false )
2348
2532
  expect(@browser.to_page.dom.transitions).to be_empty
@@ -2363,7 +2547,16 @@ describe Arachni::Browser do
2363
2547
  expect(@browser.load( @url )).to eq(@browser)
2364
2548
  end
2365
2549
 
2366
- describe :cookies do
2550
+ it 'updates the global cookie-jar' do
2551
+ @browser.load @url
2552
+
2553
+ cookie = Arachni::HTTP::Client.cookies.find(&:http_only?)
2554
+
2555
+ expect(cookie.name).to eq('This name should be updated; and properly escaped')
2556
+ expect(cookie.value).to eq('This value should be updated; and properly escaped')
2557
+ end
2558
+
2559
+ describe ':cookies' do
2367
2560
  it 'loads the given cookies' do
2368
2561
  cookie = { 'myname' => 'myvalue' }
2369
2562
  @browser.load @url, cookies: cookie
@@ -2372,8 +2565,8 @@ describe Arachni::Browser do
2372
2565
  end
2373
2566
  end
2374
2567
 
2375
- describe :take_snapshot do
2376
- describe true do
2568
+ describe ':take_snapshot' do
2569
+ describe 'true' do
2377
2570
  it 'captures a snapshot of the loaded page' do
2378
2571
  @browser.load @url, take_snapshot: true
2379
2572
  pages = @browser.page_snapshots
@@ -2386,7 +2579,7 @@ describe Arachni::Browser do
2386
2579
  end
2387
2580
  end
2388
2581
 
2389
- describe false do
2582
+ describe 'false' do
2390
2583
  it 'does not capture a snapshot of the loaded page' do
2391
2584
  @browser.load @url, take_snapshot: false
2392
2585
  expect(@browser.page_snapshots).to be_empty
@@ -2408,7 +2601,7 @@ describe Arachni::Browser do
2408
2601
  end
2409
2602
 
2410
2603
  context 'when given a' do
2411
- describe String do
2604
+ describe 'String' do
2412
2605
  it 'treats it as a URL' do
2413
2606
  expect(hit_count).to eq(0)
2414
2607
 
@@ -2420,7 +2613,7 @@ describe Arachni::Browser do
2420
2613
  end
2421
2614
  end
2422
2615
 
2423
- describe Arachni::HTTP::Response do
2616
+ describe 'Arachni::HTTP::Response' do
2424
2617
  it 'loads it' do
2425
2618
  expect(hit_count).to eq(0)
2426
2619
 
@@ -2432,34 +2625,89 @@ describe Arachni::Browser do
2432
2625
  end
2433
2626
  end
2434
2627
 
2435
- describe Arachni::Page do
2628
+ describe 'Arachni::Page::DOM' do
2436
2629
  it 'loads it' do
2437
2630
  expect(hit_count).to eq(0)
2438
2631
 
2439
- @browser.load Arachni::HTTP::Client.get( @url, mode: :sync ).to_page
2632
+ page = Arachni::HTTP::Client.get( @url, mode: :sync ).to_page
2633
+
2634
+ expect(hit_count).to eq(1)
2635
+
2636
+ @browser.load page.dom
2637
+
2440
2638
  expect(@browser.source).to include( ua )
2441
2639
  expect(@browser.preloads).not_to include( @url )
2442
2640
 
2641
+ expect(hit_count).to eq(2)
2642
+ end
2643
+
2644
+ it 'replays its #transitions' do
2645
+ @browser.load "#{@url}play-transitions"
2646
+ page = @browser.explore_and_flush.last
2647
+ expect(page.body).to include ua
2648
+
2649
+ @browser.load page.dom
2650
+ expect(@browser.source).to include ua
2651
+
2652
+ page.dom.transitions.clear
2653
+ @browser.load page.dom
2654
+ expect(@browser.source).not_to include ua
2655
+ end
2656
+
2657
+ it 'loads its #skip_states' do
2658
+ @browser.load( @url )
2659
+ pages = @browser.load( @url + '/explore' ).trigger_events.
2660
+ page_snapshots
2661
+
2662
+ page = pages.last
2663
+ expect(page.dom.skip_states).to be_subset @browser.skip_states
2664
+
2665
+ token = @browser.generate_token
2666
+
2667
+ dpage = page.dup
2668
+ dpage.dom.skip_states << token
2669
+
2670
+ @browser.load dpage.dom
2671
+ expect(@browser.skip_states).to include token
2672
+ end
2673
+ end
2674
+
2675
+ describe 'Arachni::Page' do
2676
+ it 'loads it' do
2677
+ expect(hit_count).to eq(0)
2678
+
2679
+ page = Arachni::HTTP::Client.get( @url, mode: :sync ).to_page
2680
+
2443
2681
  expect(hit_count).to eq(1)
2682
+
2683
+ @browser.load page
2684
+
2685
+ expect(@browser.source).to include( ua )
2686
+ expect(@browser.preloads).not_to include( @url )
2687
+
2688
+ expect(hit_count).to eq(2)
2444
2689
  end
2445
2690
 
2446
2691
  it 'uses its #cookie_jar' do
2447
2692
  expect(@browser.cookies).to be_empty
2448
2693
 
2694
+ cookie = Arachni::Cookie.new(
2695
+ url: @url,
2696
+ inputs: {
2697
+ 'my-name' => 'my-value'
2698
+ }
2699
+ )
2700
+
2449
2701
  page = Arachni::Page.from_data(
2450
2702
  url: @url,
2451
- cookie_jar: [
2452
- Arachni::Cookie.new(
2453
- url: @url,
2454
- inputs: {
2455
- 'my-name' => 'my-value'
2456
- }
2457
- )
2458
- ]
2703
+ cookie_jar: [ cookie ]
2459
2704
  )
2460
2705
 
2706
+ expect(@browser.cookies).to_not include cookie
2707
+
2461
2708
  @browser.load( page )
2462
- expect(@browser.cookies).to eq(page.cookie_jar)
2709
+
2710
+ expect(@browser.cookies).to include cookie
2463
2711
  end
2464
2712
 
2465
2713
  it 'replays its DOM#transitions' do
@@ -2491,7 +2739,6 @@ describe Arachni::Browser do
2491
2739
  @browser.load dpage
2492
2740
  expect(@browser.skip_states).to include token
2493
2741
  end
2494
-
2495
2742
  end
2496
2743
 
2497
2744
  describe 'other' do
@@ -2534,7 +2781,7 @@ describe Arachni::Browser do
2534
2781
  end
2535
2782
 
2536
2783
  context 'when given a' do
2537
- describe Arachni::HTTP::Response do
2784
+ describe 'Arachni::HTTP::Response' do
2538
2785
  it 'preloads it' do
2539
2786
  @browser.preload Arachni::HTTP::Client.get( @url, mode: :sync )
2540
2787
  clear_hit_count
@@ -2549,7 +2796,7 @@ describe Arachni::Browser do
2549
2796
  end
2550
2797
  end
2551
2798
 
2552
- describe Arachni::Page do
2799
+ describe 'Arachni::Page' do
2553
2800
  it 'preloads it' do
2554
2801
  @browser.preload Arachni::Page.from_url( @url )
2555
2802
  clear_hit_count
@@ -2605,7 +2852,7 @@ describe Arachni::Browser do
2605
2852
  end
2606
2853
 
2607
2854
  context 'when given a' do
2608
- describe Arachni::HTTP::Response do
2855
+ describe 'Arachni::HTTP::Response' do
2609
2856
  it 'caches it' do
2610
2857
  @browser.cache Arachni::HTTP::Client.get( @url, mode: :sync )
2611
2858
  clear_hit_count
@@ -2620,7 +2867,7 @@ describe Arachni::Browser do
2620
2867
  end
2621
2868
  end
2622
2869
 
2623
- describe Arachni::Page do
2870
+ describe 'Arachni::Page' do
2624
2871
  it 'caches it' do
2625
2872
  @browser.cache Arachni::Page.from_url( @url )
2626
2873
  clear_hit_count
@@ -2795,19 +3042,72 @@ describe Arachni::Browser do
2795
3042
  end
2796
3043
 
2797
3044
  describe '#cookies' do
2798
- it 'returns the browser cookies' do
3045
+ it 'returns cookies visible via JavaScript' do
2799
3046
  @browser.load @url
2800
- expect(@browser.cookies.size).to eq(1)
3047
+
2801
3048
  cookie = @browser.cookies.first
3049
+ expect(cookie.name).to eq 'cookie_name'
3050
+ expect(cookie.value).to eq 'cookie value'
3051
+ expect(cookie.raw_name).to eq 'cookie_name'
3052
+ expect(cookie.raw_value).to eq '"cookie value"'
3053
+ end
2802
3054
 
2803
- expect(cookie).to be_kind_of Arachni::Cookie
2804
- expect(cookie.name).to eq('This name should be updated; and properly escaped')
2805
- expect(cookie.value).to eq('This value should be updated; and properly escaped')
3055
+ it 'preserves expiration value' do
3056
+ @browser.load "#{@url}/cookies/expires"
3057
+
3058
+ cookie = @browser.cookies.first
3059
+ expect(cookie.name).to eq 'without_expiration'
3060
+ expect(cookie.value).to eq 'stuff'
3061
+ expect(cookie.expires).to be_nil
3062
+
3063
+ cookie = @browser.cookies.last
3064
+ expect(cookie.name).to eq 'with_expiration'
3065
+ expect(cookie.value).to eq 'bar'
3066
+ expect(cookie.expires.to_s).to eq Time.parse( '2047-08-01 09:30:11 +0000' ).to_s
2806
3067
  end
2807
3068
 
2808
- it 'preserves the HttpOnly attribute' do
2809
- @browser.load @url
2810
- expect(@browser.cookies.first).to be_http_only
3069
+ it 'preserves the domain' do
3070
+ @browser.load "#{@url}/cookies/domains"
3071
+
3072
+ cookies = @browser.cookies
3073
+
3074
+ cookie = cookies.find { |c| c.name == 'include_subdomains' }
3075
+ expect(cookie.name).to eq 'include_subdomains'
3076
+ expect(cookie.value).to eq 'bar1'
3077
+ expect(cookie.domain).to eq '.127.0.0.2'
3078
+ end
3079
+
3080
+ it 'ignores cookies for other domains' do
3081
+ @browser.load "#{@url}/cookies/domains"
3082
+
3083
+ cookies = @browser.cookies
3084
+ expect(cookies.find { |c| c.name == 'other_domain' }).to be_nil
3085
+ end
3086
+
3087
+ it 'preserves the path' do
3088
+ @browser.load "#{@url}/cookies/under/path"
3089
+
3090
+ cookie = @browser.cookies.first
3091
+ expect(cookie.name).to eq 'cookie_under_path'
3092
+ expect(cookie.value).to eq 'value'
3093
+ expect(cookie.path).to eq '/cookies/under/'
3094
+ end
3095
+
3096
+ it 'preserves httpOnly' do
3097
+ @browser.load "#{@url}/cookies/under/path"
3098
+
3099
+ cookie = @browser.cookies.first
3100
+ expect(cookie.name).to eq 'cookie_under_path'
3101
+ expect(cookie.value).to eq 'value'
3102
+ expect(cookie.path).to eq '/cookies/under/'
3103
+ expect(cookie).to_not be_http_only
3104
+
3105
+ @browser.load "#{@url}/cookies/httpOnly"
3106
+
3107
+ cookie = @browser.cookies.first
3108
+ expect(cookie.name).to eq 'http_only'
3109
+ expect(cookie.value).to eq 'stuff'
3110
+ expect(cookie).to be_http_only
2811
3111
  end
2812
3112
 
2813
3113
  context 'when parsing v1 cookies' do
@@ -2817,7 +3117,9 @@ describe Arachni::Browser do
2817
3117
  @browser.load @url
2818
3118
  @browser.javascript.run( "document.cookie = '#{cookie}';" )
2819
3119
 
2820
- expect(@browser.cookies.first.value).to eq('06142010_0:e275d357943e9a2de0')
3120
+ cookie = @browser.cookies.find { |c| c.name == 'rsession' }
3121
+ expect(cookie.value).to eq('06142010_0:e275d357943e9a2de0')
3122
+ expect(cookie.raw_value).to eq('"06142010_0%3Ae275d357943e9a2de0"')
2821
3123
  end
2822
3124
  end
2823
3125
 
@@ -2829,14 +3131,20 @@ describe Arachni::Browser do
2829
3131
  end
2830
3132
 
2831
3133
  describe '#snapshot_id' do
2832
- before(:each) { Arachni::Options.url = @url }
3134
+ before(:each) do
3135
+ Arachni::Options.url = @url
3136
+
3137
+ @empty_snapshot_id ||= @browser.load( empty_snapshot_id_url ).snapshot_id
3138
+
3139
+ @snapshot_id = @browser.load( url ).snapshot_id
3140
+ end
2833
3141
 
2834
3142
  let(:empty_snapshot_id_url) { @url + '/snapshot_id/default' }
2835
3143
  let(:empty_snapshot_id) do
2836
- @browser.load( empty_snapshot_id_url ).snapshot_id
3144
+ @empty_snapshot_id
2837
3145
  end
2838
3146
  let(:snapshot_id) do
2839
- @browser.load( url ).snapshot_id
3147
+ @snapshot_id
2840
3148
  end
2841
3149
 
2842
3150
  let(:url) { @url + '/trigger_events' }
@@ -2845,7 +3153,22 @@ describe Arachni::Browser do
2845
3153
  expect(snapshot_id).to eq(@browser.load( url ).snapshot_id)
2846
3154
  end
2847
3155
 
2848
- context :a do
3156
+ context 'when there are new cookies' do
3157
+ let(:url) { @url + '/each_element_with_events/set-cookie' }
3158
+
3159
+ it 'takes them into account' do
3160
+ @browser.fire_event described_class::ElementLocator.new(
3161
+ tag_name: :button,
3162
+ attributes: {
3163
+ onclick: 'setCookie()'
3164
+ }
3165
+ ), :click
3166
+
3167
+ expect(@browser.snapshot_id).not_to eq(snapshot_id)
3168
+ end
3169
+ end
3170
+
3171
+ context ':a' do
2849
3172
  context 'and the href is not empty' do
2850
3173
  context 'and it starts with javascript:' do
2851
3174
  let(:url) { @url + '/each_element_with_events/a/href/javascript' }
@@ -2881,10 +3204,10 @@ describe Arachni::Browser do
2881
3204
  end
2882
3205
  end
2883
3206
 
2884
- context :form do
3207
+ context ':form' do
2885
3208
  let(:empty_snapshot_id_url) { @url + '/snapshot_id/form/default' }
2886
3209
 
2887
- context :input do
3210
+ context ':input' do
2888
3211
  context 'of type "image"' do
2889
3212
  let(:url) { @url + '/each_element_with_events/form/input/image' }
2890
3213