arachni 1.3.2 → 1.4

Sign up to get free protection for your applications and to get access to all the features.
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