arachni 1.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +47 -0
- data/README.md +2 -2
- data/arachni.gemspec +1 -1
- data/components/checks/active/code_injection_php_input_wrapper.rb +8 -3
- data/components/checks/active/file_inclusion.rb +7 -3
- data/components/checks/active/path_traversal.rb +7 -3
- data/components/checks/passive/grep/cookie_set_for_parent_domain.rb +5 -3
- data/components/plugins/cookie_collector.rb +1 -1
- data/components/plugins/proxy.rb +4 -3
- data/components/plugins/vector_feed.rb +1 -1
- data/components/reporters/html/default/issue.erb +5 -0
- data/components/reporters/stdout.rb +4 -0
- data/lib/arachni/browser.rb +25 -6
- data/lib/arachni/browser/element_locator.rb +1 -1
- data/lib/arachni/browser/javascript/taint_tracer.rb +3 -3
- data/lib/arachni/browser/javascript/taint_tracer/frame.rb +1 -1
- data/lib/arachni/browser/javascript/taint_tracer/frame/called_function.rb +1 -1
- data/lib/arachni/browser/javascript/taint_tracer/sink/base.rb +1 -1
- data/lib/arachni/check/auditor.rb +2 -0
- data/lib/arachni/component/manager.rb +2 -2
- data/lib/arachni/component/options/base.rb +2 -2
- data/lib/arachni/element/base.rb +2 -2
- data/lib/arachni/element/cookie.rb +4 -4
- data/lib/arachni/element/form.rb +1 -1
- data/lib/arachni/element/generic_dom.rb +1 -1
- data/lib/arachni/framework.rb +9 -1
- data/lib/arachni/http/client.rb +2 -0
- data/lib/arachni/http/request.rb +2 -2
- data/lib/arachni/http/response.rb +1 -1
- data/lib/arachni/issue.rb +2 -2
- data/lib/arachni/option_group.rb +1 -1
- data/lib/arachni/option_groups/input.rb +1 -1
- data/lib/arachni/option_groups/scope.rb +1 -1
- data/lib/arachni/page.rb +1 -1
- data/lib/arachni/page/dom/transition.rb +3 -3
- data/lib/arachni/parser.rb +3 -1
- data/lib/arachni/platform/list.rb +1 -1
- data/lib/arachni/report.rb +1 -1
- data/lib/arachni/rpc/client/instance/framework.rb +6 -6
- data/lib/arachni/rpc/client/instance/service.rb +7 -7
- data/lib/arachni/rpc/server/dispatcher.rb +18 -5
- data/lib/arachni/rpc/server/dispatcher/node.rb +13 -6
- data/lib/arachni/rpc/server/framework/distributor.rb +1 -1
- data/lib/arachni/rpc/server/framework/master.rb +1 -1
- data/lib/arachni/rpc/server/framework/multi_instance.rb +2 -2
- data/lib/arachni/rpc/server/instance.rb +11 -3
- data/lib/arachni/ruby/hash.rb +7 -6
- data/lib/arachni/state/framework.rb +1 -0
- data/lib/version +1 -1
- data/spec/arachni/browser_spec.rb +25 -0
- data/spec/arachni/component/manager_spec.rb +1 -1
- data/spec/arachni/element/cookie_spec.rb +3 -3
- data/spec/arachni/http/request_spec.rb +3 -3
- data/spec/arachni/option_groups/scope_spec.rb +2 -2
- data/spec/arachni/parser_spec.rb +7 -0
- data/spec/arachni/reporter/manager_spec.rb +1 -1
- data/spec/arachni/rpc/server/dispatcher/node_spec.rb +2 -0
- data/spec/arachni/rpc/server/framework_spec.rb +1 -1
- data/spec/arachni/ruby/hash_spec.rb +8 -8
- data/spec/support/servers/checks/passive/grep/cookie_set_for_parent_domain.rb +1 -1
- data/spec/support/shared/element/capabilities/inputtable.rb +2 -2
- data/ui/cli/utilities.rb +3 -0
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a4f1fba6f25f0dd437f9d31c82b3f036d4b87ec9
|
4
|
+
data.tar.gz: eaa9814da188578b10283e23101525828d42b17a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a98cde207400471e0ba80cffc9fce6ce46348d43e76c509cbd06f5c7e6b4867f62f9e5382bedaa7b500d731a82428cde04d23db0ea72a4cfceb9087c8fe8062a
|
7
|
+
data.tar.gz: a66344c76f782b7042f003c0e7b525b5ea173d2f72257d77f9a4673be35280624d4c73a5f874c157b4b66fd5b3eb46a0196480d9b91379639da6cf26e288c045
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,52 @@
|
|
1
1
|
# ChangeLog
|
2
2
|
|
3
|
+
## 1.0.1 _(September 7, 2014)_
|
4
|
+
|
5
|
+
- `RPC::Server::Dispatcher`
|
6
|
+
- Check for Instance status via the bind address, not the external one.
|
7
|
+
- Added more status and debugging messages
|
8
|
+
- Fixed RPC connection leak when in Grid configuration.
|
9
|
+
- `Node`
|
10
|
+
- Don't raise error if the initial neighbour is unreachable, just add
|
11
|
+
it to the dead list as usual.
|
12
|
+
- `Browser`
|
13
|
+
- Fixed issue causing the removal of cookie HttpOnly flags.
|
14
|
+
- `Parser`
|
15
|
+
- `#link_vars` -- Return empty `Hash` when dealing with unparsable URL.
|
16
|
+
- `HTTP::Client`
|
17
|
+
- Debugging messages now include the `HTTP::Request#performer`.
|
18
|
+
- `HTTP::Request`
|
19
|
+
- `#to_typhoeus` -- Converted proxy type to `Symbol` to prevent the option
|
20
|
+
from being ignored.
|
21
|
+
- `UI::CLI::Utilities`
|
22
|
+
- `#print_issues` -- Updated to include all inputs of the given vector in
|
23
|
+
the message, if the issue is passive.
|
24
|
+
- `Check::Auditor`
|
25
|
+
- `#log` -- Updated to include all inputs of the given vector in the success
|
26
|
+
message, if the issue is passive.
|
27
|
+
- `Element::Cookie`
|
28
|
+
- `.encode` -- Encode `'` and `"`.
|
29
|
+
- `Hash` -- Renamed added methods to avoid clashes with `ActiveSupport`.
|
30
|
+
- `stringify_keys` => `my_stringify_keys`
|
31
|
+
- `symbolize_keys` => `my_symbolize_keys`
|
32
|
+
- `stringify` => `my_stringify`
|
33
|
+
- Plugins
|
34
|
+
- `proxy` -- Show control panel URL in output.
|
35
|
+
- Reporters
|
36
|
+
- `stdout`
|
37
|
+
- Updated to print out information about all available vector inputs.
|
38
|
+
- `html`
|
39
|
+
- Updated to include information about all available vector inputs in
|
40
|
+
issue title for passive issues.
|
41
|
+
- Checks
|
42
|
+
- Active
|
43
|
+
- `code_injection_php_input_wrapper` -- Fixed `nil` error when
|
44
|
+
manipulating mutations.
|
45
|
+
- `file_inclusion` -- Fixed `nil` error when manipulating mutations.
|
46
|
+
- `path_traversal` -- Fixed `nil` error when manipulating mutations.
|
47
|
+
- Passive
|
48
|
+
- `cookie_set_for_parent_domain` -- Only check `HTTP::Response` cookies.
|
49
|
+
|
3
50
|
## 1.0 _(August 29, 2014)_
|
4
51
|
|
5
52
|
- Executables:
|
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
* Arachni's license has changed, please see the _LICENSE_ file before working
|
4
4
|
with the project.
|
5
|
-
* v1.0 is not backwards compatible.
|
5
|
+
* v1.0 is not backwards compatible with v0.4.
|
6
6
|
|
7
7
|
<hr/>
|
8
8
|
|
@@ -11,7 +11,7 @@
|
|
11
11
|
<table>
|
12
12
|
<tr>
|
13
13
|
<th>Version</th>
|
14
|
-
<td>1.0</td>
|
14
|
+
<td>1.0.1</td>
|
15
15
|
</tr>
|
16
16
|
<tr>
|
17
17
|
<th>Homepage</th>
|
data/arachni.gemspec
CHANGED
@@ -6,9 +6,9 @@
|
|
6
6
|
web site for more information on licensing and terms of use.
|
7
7
|
=end
|
8
8
|
|
9
|
-
# @see OWASP https://www.owasp.org/index.php/Top_10_2007-Malicious_File_Execution
|
10
9
|
# @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
|
11
|
-
# @version 0.1
|
10
|
+
# @version 0.1.1
|
11
|
+
# @see OWASP https://www.owasp.org/index.php/Top_10_2007-Malicious_File_Execution
|
12
12
|
class Arachni::Checks::CodeInjectionPhpInputWrapper < Arachni::Check::Base
|
13
13
|
|
14
14
|
def self.options
|
@@ -20,6 +20,11 @@ class Arachni::Checks::CodeInjectionPhpInputWrapper < Arachni::Check::Base
|
|
20
20
|
# Add one more mutation (on the fly) which will include the extension
|
21
21
|
# of the original value (if that value was a filename) after a null byte.
|
22
22
|
each_mutation: proc do |mutation|
|
23
|
+
next if !mutation.affected_input_value ||
|
24
|
+
(mutation.is_a?( Arachni::Form ) &&
|
25
|
+
(mutation.mutation_with_original_values? ||
|
26
|
+
mutation.mutation_with_sample_values?))
|
27
|
+
|
23
28
|
# Don't bother if the current element type can't carry nulls.
|
24
29
|
next if !mutation.valid_input_value_data?( "\0" )
|
25
30
|
|
@@ -51,7 +56,7 @@ to try and load it.
|
|
51
56
|
},
|
52
57
|
elements: [ Element::Form, Element::Link, Element::Cookie, Element::Header ],
|
53
58
|
author: 'Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com> ',
|
54
|
-
version: '0.1',
|
59
|
+
version: '0.1.1',
|
55
60
|
platforms: [:php],
|
56
61
|
|
57
62
|
issue: {
|
@@ -9,8 +9,7 @@
|
|
9
9
|
# File inclusion check.
|
10
10
|
#
|
11
11
|
# @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
|
12
|
-
#
|
13
|
-
# @version 0.1.1
|
12
|
+
# @version 0.1.2
|
14
13
|
#
|
15
14
|
# @see http://cwe.mitre.org/data/definitions/98.html
|
16
15
|
# @see https://www.owasp.org/index.php/PHP_File_Inclusion
|
@@ -51,6 +50,11 @@ class Arachni::Checks::FileInclusion < Arachni::Check::Base
|
|
51
50
|
# Add one more mutation (on the fly) which will include the extension
|
52
51
|
# of the original value (if that value was a filename) after a null byte.
|
53
52
|
each_mutation: proc do |mutation|
|
53
|
+
next if !mutation.affected_input_value ||
|
54
|
+
(mutation.is_a?( Arachni::Form ) &&
|
55
|
+
(mutation.mutation_with_original_values? ||
|
56
|
+
mutation.mutation_with_sample_values?))
|
57
|
+
|
54
58
|
# Don't bother if the current element type can't carry nulls.
|
55
59
|
next if !mutation.valid_input_value_data?( "\0" )
|
56
60
|
|
@@ -101,7 +105,7 @@ content or errors in the HTTP response body.
|
|
101
105
|
elements: [ Element::Form, Element::Link, Element::Cookie,
|
102
106
|
Element::Header, Element::LinkTemplate ],
|
103
107
|
author: 'Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com> ',
|
104
|
-
version: '0.1.
|
108
|
+
version: '0.1.2',
|
105
109
|
platforms: options[:regexp].keys,
|
106
110
|
|
107
111
|
issue: {
|
@@ -9,8 +9,7 @@
|
|
9
9
|
# Path Traversal check.
|
10
10
|
#
|
11
11
|
# @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
|
12
|
-
#
|
13
|
-
# @version 0.4.1
|
12
|
+
# @version 0.4.2
|
14
13
|
#
|
15
14
|
# @see http://cwe.mitre.org/data/definitions/22.html
|
16
15
|
# @see http://www.owasp.org/index.php/Path_Traversal
|
@@ -40,6 +39,11 @@ class Arachni::Checks::PathTraversal < Arachni::Check::Base
|
|
40
39
|
# Add one more mutation (on the fly) which will include the extension
|
41
40
|
# of the original value (if that value was a filename) after a null byte.
|
42
41
|
each_mutation: proc do |mutation|
|
42
|
+
next if !mutation.affected_input_value ||
|
43
|
+
(mutation.is_a?( Arachni::Form ) &&
|
44
|
+
(mutation.mutation_with_original_values? ||
|
45
|
+
mutation.mutation_with_sample_values?))
|
46
|
+
|
43
47
|
# Don't bother if the current element type can't carry nulls.
|
44
48
|
next if !mutation.valid_input_value_data?( "\0" )
|
45
49
|
|
@@ -111,7 +115,7 @@ of relevant content in the HTML responses.
|
|
111
115
|
elements: [ Element::Form, Element::Link, Element::Cookie,
|
112
116
|
Element::Header, Element::LinkTemplate ],
|
113
117
|
author: 'Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com> ',
|
114
|
-
version: '0.4.
|
118
|
+
version: '0.4.2',
|
115
119
|
platforms: payloads.keys,
|
116
120
|
|
117
121
|
issue: {
|
@@ -7,11 +7,13 @@
|
|
7
7
|
=end
|
8
8
|
|
9
9
|
# @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
|
10
|
-
# @version 0.1
|
10
|
+
# @version 0.1.1
|
11
11
|
class Arachni::Checks::CookieSetForParentDomain < Arachni::Check::Base
|
12
12
|
|
13
13
|
def run
|
14
|
-
page.
|
14
|
+
return if !page.parser
|
15
|
+
|
16
|
+
page.parser.cookies.each do |cookie|
|
15
17
|
next if !cookie.domain.start_with?( '.' ) || audited?( cookie.name )
|
16
18
|
|
17
19
|
log( vector: cookie )
|
@@ -25,7 +27,7 @@ class Arachni::Checks::CookieSetForParentDomain < Arachni::Check::Base
|
|
25
27
|
description: %q{Logs cookies that are accessible by all subdomains.},
|
26
28
|
elements: [ Element::Cookie ],
|
27
29
|
author: 'Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>',
|
28
|
-
version: '0.1',
|
30
|
+
version: '0.1.1',
|
29
31
|
|
30
32
|
issue: {
|
31
33
|
name: %q{Cookie set for parent domain},
|
data/components/plugins/proxy.rb
CHANGED
@@ -16,7 +16,7 @@ require 'ostruct'
|
|
16
16
|
#
|
17
17
|
# @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
|
18
18
|
#
|
19
|
-
# @version 0.3
|
19
|
+
# @version 0.3.1
|
20
20
|
class Arachni::Plugins::Proxy < Arachni::Plugin::Base
|
21
21
|
|
22
22
|
BASEDIR = "#{File.dirname( __FILE__ )}/proxy/"
|
@@ -58,7 +58,8 @@ class Arachni::Plugins::Proxy < Arachni::Plugin::Base
|
|
58
58
|
def run
|
59
59
|
print_status "Listening on: http://#{@server[:BindAddress]}:#{@server[:Port]}"
|
60
60
|
|
61
|
-
|
61
|
+
print_info "Control panel URL: #{url_for( :panel )}"
|
62
|
+
print_info "Shutdown URL: #{url_for( :shutdown )}"
|
62
63
|
print_info 'The scan will resume once you visit the shutdown URL.'
|
63
64
|
|
64
65
|
print_info
|
@@ -463,7 +464,7 @@ a way to restrict usage enough to avoid users unwittingly interfering with each
|
|
463
464
|
others' sessions.
|
464
465
|
},
|
465
466
|
author: 'Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>',
|
466
|
-
version: '0.3',
|
467
|
+
version: '0.3.1',
|
467
468
|
options: [
|
468
469
|
Options::Port.new( :port,
|
469
470
|
description: 'Port to bind to.',
|
@@ -58,7 +58,7 @@ class Arachni::Plugins::VectorFeed < Arachni::Plugin::Base
|
|
58
58
|
page_buffer = []
|
59
59
|
print_status "Imported #{feed.size} vectors."
|
60
60
|
feed.each do |obj|
|
61
|
-
vector = (obj.respond_to?( :value ) ? obj.value : obj).
|
61
|
+
vector = (obj.respond_to?( :value ) ? obj.value : obj).my_symbolize_keys( false )
|
62
62
|
|
63
63
|
exception_jail false do
|
64
64
|
if page?( vector )
|
@@ -10,6 +10,11 @@
|
|
10
10
|
<% if issue.active? %>
|
11
11
|
input
|
12
12
|
<code><%= issue.affected_input_name %></code>
|
13
|
+
<% elsif issue.vector.respond_to? :inputs %>
|
14
|
+
with inputs
|
15
|
+
<% issue.vector.inputs.keys.map do |iname| %>
|
16
|
+
<code><%= iname %></code>
|
17
|
+
<% end.join( ', ') %>
|
13
18
|
<% end %>
|
14
19
|
|
15
20
|
<% if issue.variations.first.request %>
|
@@ -109,6 +109,10 @@ class Arachni::Reporters::Stdout < Arachni::Reporter::Base
|
|
109
109
|
print_info "Input name: #{issue.affected_input_name}"
|
110
110
|
end
|
111
111
|
|
112
|
+
if issue.vector.respond_to? :inputs
|
113
|
+
print_info "All inputs: #{issue.vector.inputs.keys.join(', ')}"
|
114
|
+
end
|
115
|
+
|
112
116
|
print_line
|
113
117
|
print_info "Tags: #{issue.tags.join(', ')}" if issue.tags.is_a?( Array )
|
114
118
|
print_line
|
data/lib/arachni/browser.rb
CHANGED
@@ -308,6 +308,7 @@ class Browser
|
|
308
308
|
|
309
309
|
@javascript.wait_till_ready
|
310
310
|
wait_for_timers
|
311
|
+
|
311
312
|
wait_for_pending_requests
|
312
313
|
end
|
313
314
|
|
@@ -553,7 +554,7 @@ class Browser
|
|
553
554
|
event = event.to_s.downcase.sub( /^on/, '' ).to_sym
|
554
555
|
locator = nil
|
555
556
|
|
556
|
-
options[:inputs] = options[:inputs].
|
557
|
+
options[:inputs] = options[:inputs].my_stringify if options[:inputs]
|
557
558
|
|
558
559
|
if element.is_a? ElementLocator
|
559
560
|
locator = element
|
@@ -792,10 +793,22 @@ class Browser
|
|
792
793
|
# @return [Array<Cookie>]
|
793
794
|
# Browser cookies.
|
794
795
|
def cookies
|
796
|
+
js_cookies = begin
|
797
|
+
# Watir doesn't tell us if cookies are HttpOnly, so we need to figure
|
798
|
+
# this out ourselves, by checking for JS visibility.
|
799
|
+
javascript.run( 'return document.cookie' )
|
800
|
+
# We may not have a page.
|
801
|
+
rescue Selenium::WebDriver::Error::UnknownError
|
802
|
+
''
|
803
|
+
end
|
804
|
+
|
795
805
|
watir.cookies.to_a.map do |c|
|
796
|
-
|
797
|
-
|
798
|
-
c[:
|
806
|
+
original_name = c[:name].to_s
|
807
|
+
|
808
|
+
c[:path] = '/' if c[:path] == '//'
|
809
|
+
c[:name] = Cookie.decode( c[:name].to_s )
|
810
|
+
c[:value] = Cookie.decode( c[:value].to_s )
|
811
|
+
c[:httponly] = !js_cookies.include?( original_name )
|
799
812
|
|
800
813
|
Cookie.new c.merge( url: @last_url )
|
801
814
|
end
|
@@ -944,7 +957,8 @@ class Browser
|
|
944
957
|
self.class.executable,
|
945
958
|
"--webdriver=#{port}",
|
946
959
|
"--proxy=http://#{@proxy.address}/",
|
947
|
-
'--ignore-ssl-errors=true'
|
960
|
+
'--ignore-ssl-errors=true',
|
961
|
+
"--debug=#{!!debug?}"
|
948
962
|
)
|
949
963
|
@process.detach = true
|
950
964
|
|
@@ -1065,7 +1079,12 @@ class Browser
|
|
1065
1079
|
set_cookies[cookie.name] = cookie
|
1066
1080
|
end
|
1067
1081
|
cookies.each do |name, value|
|
1068
|
-
set_cookies[name]
|
1082
|
+
if set_cookies[name]
|
1083
|
+
set_cookies[name] = set_cookies[name].dup
|
1084
|
+
set_cookies[name].update( name => value )
|
1085
|
+
else
|
1086
|
+
set_cookies[name] = Cookie.new( url: url, inputs: { name => value } )
|
1087
|
+
end
|
1069
1088
|
end
|
1070
1089
|
|
1071
1090
|
url = "#{url}/set-cookies-#{request_token}"
|
@@ -74,9 +74,9 @@ class TaintTracer < Proxy
|
|
74
74
|
return [] if !data
|
75
75
|
|
76
76
|
data.map do |entry|
|
77
|
-
Sink::DataFlow.new( (entry['data'] || {}).
|
77
|
+
Sink::DataFlow.new( (entry['data'] || {}).my_symbolize_keys( false ).merge(
|
78
78
|
trace: [entry['trace']].flatten.compact.
|
79
|
-
map { |h| Frame.new h.
|
79
|
+
map { |h| Frame.new h.my_symbolize_keys( false ) }
|
80
80
|
)
|
81
81
|
)
|
82
82
|
end
|
@@ -88,7 +88,7 @@ class TaintTracer < Proxy
|
|
88
88
|
data.map do |entry|
|
89
89
|
Sink::ExecutionFlow.new( entry.merge(
|
90
90
|
trace: [entry['trace']].flatten.compact.
|
91
|
-
map { |h| Frame.new h.
|
91
|
+
map { |h| Frame.new h.my_symbolize_keys( false ) }
|
92
92
|
)
|
93
93
|
)
|
94
94
|
end
|
@@ -172,7 +172,7 @@ class Manager < Hash
|
|
172
172
|
return {} if !info.include?( :options ) || info[:options].empty?
|
173
173
|
|
174
174
|
user_opts ||= {}
|
175
|
-
user_opts = user_opts.
|
175
|
+
user_opts = user_opts.my_symbolize_keys(false)
|
176
176
|
|
177
177
|
options = {}
|
178
178
|
errors = {}
|
@@ -209,7 +209,7 @@ class Manager < Hash
|
|
209
209
|
format_error_string( component_name, errors )
|
210
210
|
end
|
211
211
|
|
212
|
-
options.
|
212
|
+
options.my_symbolize_keys( false )
|
213
213
|
end
|
214
214
|
|
215
215
|
# It parses the component array making sure that its structure is valid
|
@@ -117,7 +117,7 @@ class Arachni::Component::Options::Base
|
|
117
117
|
# @return [Hash]
|
118
118
|
# Data representing this instance that are suitable the RPC transmission.
|
119
119
|
def to_rpc_data
|
120
|
-
to_h.merge( class: self.class.to_s ).
|
120
|
+
to_h.merge( class: self.class.to_s ).my_stringify_keys
|
121
121
|
end
|
122
122
|
|
123
123
|
# @param [Hash] data {#to_rpc_data}
|
@@ -127,7 +127,7 @@ class Arachni::Component::Options::Base
|
|
127
127
|
data.delete('class')
|
128
128
|
name = data.delete('name')
|
129
129
|
|
130
|
-
new name, data.
|
130
|
+
new name, data.my_symbolize_keys(false)
|
131
131
|
end
|
132
132
|
|
133
133
|
def ==( option )
|