ruby-rustscan 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ed273c201a779c2af67db77c918ceb5be91d5215115d0f24bf9eb4f787f54ec3
4
+ data.tar.gz: ecc1c363ba8068c177202cbe1e20f27e8740b2783637c1c7a815af9a25b5c84e
5
+ SHA512:
6
+ metadata.gz: 218a92ab0d1fc7ec48d5fbbac74d3a551344df13d933104255437c66b8ad5937f63f532ca895d8fa4b26ce42801851afe4cdc496388cbabe8a4bf7503ea232c0
7
+ data.tar.gz: 17b7fe2485ac511f0af7ed5530aa316181fade303287e59e38b5b5a7791c74aab1247671c5f227ab8bdea91c7c84c9c3bb55bc2273f5ab38edeaec6333d4b228
data/.document ADDED
@@ -0,0 +1,3 @@
1
+ -
2
+ ChangeLog.md
3
+ LICENSE.txt
@@ -0,0 +1,28 @@
1
+ name: CI
2
+
3
+ on: [ push, pull_request ]
4
+
5
+ jobs:
6
+ tests:
7
+ runs-on: ubuntu-latest
8
+ strategy:
9
+ fail-fast: false
10
+ matrix:
11
+ ruby:
12
+ - 2.6
13
+ - 2.7
14
+ - '3.0'
15
+ - 3.1
16
+ - jruby
17
+ - truffleruby
18
+ name: Ruby ${{ matrix.ruby }}
19
+ steps:
20
+ - uses: actions/checkout@v2
21
+ - name: Set up Ruby
22
+ uses: ruby/setup-ruby@v1
23
+ with:
24
+ ruby-version: ${{ matrix.ruby }}
25
+ - name: Install dependencies
26
+ run: bundle install --jobs 4 --retry 3
27
+ - name: Run tests
28
+ run: bundle exec rake test
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ /Gemfile.lock
2
+ /coverage
3
+ /doc
4
+ /pkg
5
+ /.yardoc
6
+ .DS_Store
7
+ *.db
8
+ *.log
9
+ *.swp
10
+ *~
11
+ *.gem
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour --format documentation
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --markup markdown --title 'Ruby Gobuster Documentation' --protected
data/ChangeLog.md ADDED
@@ -0,0 +1,5 @@
1
+ ### 0.1.0 / 2021-04-22
2
+
3
+ * Initial release:
4
+ * Added {Rustscan::Command}.
5
+
data/Gemfile ADDED
@@ -0,0 +1,17 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ # gem 'command_mapper', '~> 0.2', github: 'postmodern/command_mapper.rb'
6
+
7
+ group :development do
8
+ gem 'rake'
9
+ gem 'rubygems-tasks', '~> 0.2'
10
+ gem 'rspec', '~> 3.0'
11
+ gem 'simplecov', '~> 0.7'
12
+
13
+ gem 'kramdown'
14
+ gem 'redcarpet', platform: :mri
15
+ gem 'yard', '~> 0.9'
16
+ gem 'yard-spellcheck', require: false
17
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2022 Hal Brodigan
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ 'Software'), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,64 @@
1
+ # ruby-rustscan
2
+
3
+ [![CI](https://github.com/postmodern/ruby-rustscan/actions/workflows/ruby.yml/badge.svg)](https://github.com/postmodern/ruby-rustscan/actions/workflows/ruby.yml)
4
+ [![Gem Version](https://badge.fury.io/rb/ruby-rustscan.svg)](https://badge.fury.io/rb/ruby-rustscan)
5
+
6
+ * [Source](https://github.com/postmodern/ruby-rustscan/)
7
+ * [Issues](https://github.com/postmodern/ruby-rustscan/issues)
8
+ * [Documentation](http://rubydoc.info/gems/ruby-rustscan/frames)
9
+
10
+ ## Description
11
+
12
+ A Ruby interface to [rustscan], the Modern Port Scanner.
13
+
14
+ ## Features
15
+
16
+ * Provides a [Ruby interface][Rustscan::Command] for running the `rustscan`
17
+ command.
18
+
19
+ [Rustscan::Command]: https://rubydoc.info/gems/ruby-rustscan/Rustscan/Command
20
+
21
+ ## Examples
22
+
23
+ Run `rustscan --addresses 127.0.0.1 -p 80,443` from Ruby:
24
+
25
+ ```ruby
26
+ require 'rustscan/command'
27
+
28
+ Rustscan::Command.run(addresses: ['127.0.0.1'], ports: [80, 443])
29
+ ```
30
+
31
+ ## Requirements
32
+
33
+ * [ruby] >= 2.0.0
34
+ * [rustscan] >= 2.0.0
35
+ * [command_mapper] ~> 0.2, >= 0.2.1
36
+
37
+ [ruby]: https://www.ruby-lang.org/
38
+ [command_mapper]: https://github.com/postmodern/command_mapper.rb#readme
39
+
40
+ ## Install
41
+
42
+ ```shell
43
+ $ gem install ruby-rustscan
44
+ ```
45
+
46
+ ### gemspec
47
+
48
+ ```ruby
49
+ gemspec.add_dependency 'ruby-rustscan', '~> 0.1'
50
+ ```
51
+
52
+ ### Gemfile
53
+
54
+ ```ruby
55
+ gem 'ruby-rustscan', '~> 0.1'
56
+ ```
57
+
58
+ ## License
59
+
60
+ Copyright (c) 2022 Hal Brodigan
61
+
62
+ See {file:LICENSE.txt} for license information.
63
+
64
+ [rustscan]: https://github.com/OJ/rustscan#readme
data/Rakefile ADDED
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+
5
+ begin
6
+ require 'bundler/setup'
7
+ rescue LoadError => e
8
+ warn e.message
9
+ warn "Run `gem install bundler` to install Bundler"
10
+ exit -1
11
+ end
12
+
13
+ require 'rubygems/tasks'
14
+ Gem::Tasks.new
15
+
16
+ require 'rspec/core/rake_task'
17
+ RSpec::Core::RakeTask.new
18
+ task :test => :spec
19
+ task :default => :spec
20
+
21
+ require 'yard'
22
+ YARD::Rake::YardocTask.new
23
+ task :doc => :yard
data/gemspec.yml ADDED
@@ -0,0 +1,27 @@
1
+ name: ruby-rustscan
2
+ summary: A Ruby interface to rustscan.
3
+ description:
4
+ A Ruby interface to rustscan, the Modern Port Scanner.
5
+
6
+ license: MIT
7
+ authors: Postmodern
8
+ email: postmodern.mod3@gmail.com
9
+ homepage: https://github.com/postmodern/ruby-rustscan#readme
10
+ has_yard: true
11
+
12
+ metadata:
13
+ documentation_uri: https://rubydoc.info/gems/ruby-rustscan
14
+ source_code_uri: https://github.com/postmodern/ruby-rustscan
15
+ bug_tracker_uri: https://github.com/postmodern/ruby-rustscan/issues
16
+ changelog_uri: https://github.com/postmodern/ruby-rustscan/blob/master/ChangeLog.md
17
+ rubygems_mfa_required: 'true'
18
+
19
+ required_ruby_version: ">= 2.0.0"
20
+
21
+ requirements: rustscan >= 2.0.0
22
+
23
+ dependencies:
24
+ command_mapper: ~> 0.2, >= 0.2.1
25
+
26
+ development_dependencies:
27
+ bundler: ~> 2.0
@@ -0,0 +1,26 @@
1
+ require 'command_mapper/command'
2
+
3
+ module Rustscan
4
+ class Command < CommandMapper::Command
5
+
6
+ command 'rustscan' do
7
+ option '--accessible'
8
+ option '--greppable'
9
+ option '--help'
10
+ option '--no-config'
11
+ option '--top'
12
+ option '--version'
13
+ option '--addresses', value: {type: List.new}
14
+ option '--batch-size', value: {type: Num.new}
15
+ option '--ports', value: {type: List.new(type: Num.new)}
16
+ option '--scan-order', value: {type: Enum[:serial, :random]}
17
+ option '--scripts', value: {type: Enum[:none, :default, :custom]}
18
+ option '--timeout', value: {type: Num.new}
19
+ option '--tries', value: {type: Num.new}
20
+ option '--ulimit', value: {type: Num.new}
21
+
22
+ argument :command, repeats: true, required: false
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,4 @@
1
+ module Rustscan
2
+ # ruby-rustscan version
3
+ VERSION = '0.1.0'
4
+ end
@@ -0,0 +1,61 @@
1
+ # encoding: utf-8
2
+
3
+ require 'yaml'
4
+
5
+ Gem::Specification.new do |gem|
6
+ gemspec = YAML.load_file('gemspec.yml')
7
+
8
+ gem.name = gemspec.fetch('name')
9
+ gem.version = gemspec.fetch('version') do
10
+ lib_dir = File.join(File.dirname(__FILE__),'lib')
11
+ $LOAD_PATH << lib_dir unless $LOAD_PATH.include?(lib_dir)
12
+
13
+ require 'rustscan/version'
14
+ Rustscan::VERSION
15
+ end
16
+
17
+ gem.summary = gemspec['summary']
18
+ gem.description = gemspec['description']
19
+ gem.licenses = Array(gemspec['license'])
20
+ gem.authors = Array(gemspec['authors'])
21
+ gem.email = gemspec['email']
22
+ gem.homepage = gemspec['homepage']
23
+ gem.metadata = gemspec['metadata'] if gemspec['metadata']
24
+
25
+ glob = lambda { |patterns| gem.files & Dir[*patterns] }
26
+
27
+ gem.files = `git ls-files`.split($/)
28
+ gem.files = glob[gemspec['files']] if gemspec['files']
29
+
30
+ gem.executables = gemspec.fetch('executables') do
31
+ glob['bin/*'].map { |path| File.basename(path) }
32
+ end
33
+ gem.default_executable = gem.executables.first if Gem::VERSION < '1.7.'
34
+
35
+ gem.extensions = glob[gemspec['extensions'] || 'ext/**/extconf.rb']
36
+ gem.test_files = glob[gemspec['test_files'] || '{test/{**/}*_test.rb']
37
+ gem.extra_rdoc_files = glob[gemspec['extra_doc_files'] || '*.{txt,md}']
38
+
39
+ gem.require_paths = Array(gemspec.fetch('require_paths') {
40
+ %w[ext lib].select { |dir| File.directory?(dir) }
41
+ })
42
+
43
+ gem.requirements = Array(gemspec['requirements'])
44
+ gem.required_ruby_version = gemspec['required_ruby_version']
45
+ gem.required_rubygems_version = gemspec['required_rubygems_version']
46
+ gem.post_install_message = gemspec['post_install_message']
47
+
48
+ split = lambda { |string| string.split(/,\s*/) }
49
+
50
+ if gemspec['dependencies']
51
+ gemspec['dependencies'].each do |name,versions|
52
+ gem.add_dependency(name,split[versions])
53
+ end
54
+ end
55
+
56
+ if gemspec['development_dependencies']
57
+ gemspec['development_dependencies'].each do |name,versions|
58
+ gem.add_development_dependency(name,split[versions])
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,256 @@
1
+ require 'spec_helper'
2
+ require 'rustscan/command'
3
+
4
+ describe Rustscan::Command do
5
+ describe ".command_name" do
6
+ subject { described_class }
7
+
8
+ it "must be set to 'rustscan'" do
9
+ expect(subject.command_name).to eq('rustscan')
10
+ end
11
+ end
12
+
13
+ describe ":addresses" do
14
+ let(:ip1) { '127.0.0.1' }
15
+ let(:ip2) { '192.168.1.1' }
16
+
17
+ let(:addresses) { [ip1, ip2] }
18
+
19
+ subject { described_class.new(addresses: addresses) }
20
+
21
+ it "must map multiple addresses to --addresses and a comma separated list" do
22
+ expect(subject.command_argv).to eq(
23
+ [subject.command_name, '--addresses', "#{ip1},#{ip2}"]
24
+ )
25
+ end
26
+ end
27
+
28
+ describe ":batch_size" do
29
+ let(:batch_size) { 10 }
30
+
31
+ subject { described_class.new(batch_size: batch_size) }
32
+
33
+ it "must map to --batch-size" do
34
+ expect(subject.command_argv).to eq(
35
+ [subject.command_name, '--batch-size', "#{batch_size}"]
36
+ )
37
+ end
38
+
39
+ context "but when a non-number is given" do
40
+ let(:batch_size) { "foo" }
41
+
42
+ it "must only accept numeric values" do
43
+ expect {
44
+ subject.command_argv
45
+ }.to raise_error(CommandMapper::ValidationError,"option batch_size was given an invalid value (#{batch_size.inspect}): contains non-numeric characters (#{batch_size.inspect})")
46
+ end
47
+ end
48
+ end
49
+
50
+ describe ":ports" do
51
+ let(:port1) { 80 }
52
+ let(:port2) { 443 }
53
+ let(:port3) { 8080 }
54
+ let(:ports) { [port1, port2, port3] }
55
+
56
+ subject { described_class.new(ports: ports) }
57
+
58
+ it "must map to --ports and a comma-separated list" do
59
+ expect(subject.command_argv).to eq(
60
+ [subject.command_name, '--ports', "#{port1},#{port2},#{port3}"]
61
+ )
62
+ end
63
+
64
+ context "but when a non-number is given" do
65
+ let(:port2) { "foo" }
66
+
67
+ it "must only accept numeric values" do
68
+ expect {
69
+ subject.command_argv
70
+ }.to raise_error(CommandMapper::ValidationError,"option ports was given an invalid value (#{ports.inspect}): element contains non-numeric characters (#{port2.inspect})")
71
+ end
72
+ end
73
+ end
74
+
75
+ describe ":scan_order" do
76
+ context "when given :serial" do
77
+ let(:scan_order) { :serial }
78
+
79
+ subject { described_class.new(scan_order: scan_order) }
80
+
81
+ it "must map to --scan-order serial" do
82
+ expect(subject.command_argv).to eq(
83
+ [subject.command_name, '--scan-order', "#{scan_order}"]
84
+ )
85
+ end
86
+ end
87
+
88
+ context "when given :random" do
89
+ let(:scan_order) { :random }
90
+
91
+ subject { described_class.new(scan_order: scan_order) }
92
+
93
+ it "must map to --scan-order random" do
94
+ expect(subject.command_argv).to eq(
95
+ [subject.command_name, '--scan-order', "#{scan_order}"]
96
+ )
97
+ end
98
+ end
99
+
100
+ context "but when given an invalid scan order type" do
101
+ let(:scan_order) { :foo }
102
+
103
+ subject { described_class.new(scan_order: scan_order) }
104
+
105
+ it "must only accept :serial or :random" do
106
+ expect {
107
+ subject.command_argv
108
+ }.to raise_error(CommandMapper::ValidationError,"option scan_order was given an invalid value (#{scan_order.inspect}): unknown value (#{scan_order.inspect}) must be :serial, :random, or \"serial\", \"random\"")
109
+ end
110
+ end
111
+ end
112
+
113
+ describe ":scripts" do
114
+ context "when given :none" do
115
+ let(:scripts) { :none }
116
+
117
+ subject { described_class.new(scripts: scripts) }
118
+
119
+ it "must map to --scripts none" do
120
+ expect(subject.command_argv).to eq(
121
+ [subject.command_name, '--scripts', "#{scripts}"]
122
+ )
123
+ end
124
+ end
125
+
126
+ context "when given :default" do
127
+ let(:scripts) { :default }
128
+
129
+ subject { described_class.new(scripts: scripts) }
130
+
131
+ it "must map to --scripts default" do
132
+ expect(subject.command_argv).to eq(
133
+ [subject.command_name, '--scripts', "#{scripts}"]
134
+ )
135
+ end
136
+ end
137
+
138
+ context "when given :custom" do
139
+ let(:scripts) { :custom}
140
+
141
+ subject { described_class.new(scripts: scripts) }
142
+
143
+ it "must map to --scripts custom" do
144
+ expect(subject.command_argv).to eq(
145
+ [subject.command_name, '--scripts', "#{scripts}"]
146
+ )
147
+ end
148
+ end
149
+
150
+ context "but when given an invalid scan order type" do
151
+ let(:scripts) { :foo }
152
+
153
+ subject { described_class.new(scripts: scripts) }
154
+
155
+ it "must only accept :none, :default, or :random" do
156
+ expect {
157
+ subject.command_argv
158
+ }.to raise_error(CommandMapper::ValidationError,"option scripts was given an invalid value (#{scripts.inspect}): unknown value (#{scripts.inspect}) must be :none, :default, :custom, or \"none\", \"default\", \"custom\"")
159
+ end
160
+ end
161
+ end
162
+
163
+ describe ":timeout" do
164
+ let(:timeout) { 10 }
165
+
166
+ subject { described_class.new(timeout: timeout) }
167
+
168
+ it "must map to --timeout" do
169
+ expect(subject.command_argv).to eq(
170
+ [subject.command_name, '--timeout', "#{timeout}"]
171
+ )
172
+ end
173
+
174
+ context "but when a non-number is given" do
175
+ let(:timeout) { "foo" }
176
+
177
+ it "must only accept numeric values" do
178
+ expect {
179
+ subject.command_argv
180
+ }.to raise_error(CommandMapper::ValidationError,"option timeout was given an invalid value (#{timeout.inspect}): contains non-numeric characters (#{timeout.inspect})")
181
+ end
182
+ end
183
+ end
184
+
185
+ describe ":tries" do
186
+ let(:tries) { 10 }
187
+
188
+ subject { described_class.new(tries: tries) }
189
+
190
+ it "must map to --tries" do
191
+ expect(subject.command_argv).to eq(
192
+ [subject.command_name, '--tries', "#{tries}"]
193
+ )
194
+ end
195
+
196
+ context "but when a non-number is given" do
197
+ let(:tries) { "foo" }
198
+
199
+ it "must only accept numeric values" do
200
+ expect {
201
+ subject.command_argv
202
+ }.to raise_error(CommandMapper::ValidationError,"option tries was given an invalid value (#{tries.inspect}): contains non-numeric characters (#{tries.inspect})")
203
+ end
204
+ end
205
+ end
206
+
207
+ describe ":ulimit" do
208
+ let(:ulimit) { 10 }
209
+
210
+ subject { described_class.new(ulimit: ulimit) }
211
+
212
+ it "must map to --ulimit" do
213
+ expect(subject.command_argv).to eq(
214
+ [subject.command_name, '--ulimit', "#{ulimit}"]
215
+ )
216
+ end
217
+
218
+ context "but when a non-number is given" do
219
+ let(:ulimit) { "foo" }
220
+
221
+ it "must only accept numeric values" do
222
+ expect {
223
+ subject.command_argv
224
+ }.to raise_error(CommandMapper::ValidationError,"option ulimit was given an invalid value (#{ulimit.inspect}): contains non-numeric characters (#{ulimit.inspect})")
225
+ end
226
+ end
227
+ end
228
+
229
+ describe ":command" do
230
+ let(:addresses) { '127.0.0.1' }
231
+
232
+ context "when given one value" do
233
+ let(:command) { '-A' }
234
+
235
+ subject { described_class.new(addresses: addresses, command: command) }
236
+
237
+ it "must append the value to the end of the command" do
238
+ expect(subject.command_argv).to eq(
239
+ [subject.command_name, '--addresses', "#{addresses}", '--', command]
240
+ )
241
+ end
242
+ end
243
+
244
+ context "when given multiple values" do
245
+ let(:command) { %w[-A -sC] }
246
+
247
+ subject { described_class.new(addresses: addresses, command: command) }
248
+
249
+ it "must append each value to the end of the command" do
250
+ expect(subject.command_argv).to eq(
251
+ [subject.command_name, '--addresses', "#{addresses}", '--', *command]
252
+ )
253
+ end
254
+ end
255
+ end
256
+ end
@@ -0,0 +1,3 @@
1
+ require 'rspec'
2
+ require 'simplecov'
3
+ SimpleCov.start
metadata ADDED
@@ -0,0 +1,101 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby-rustscan
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Postmodern
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-04-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: command_mapper
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.2'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 0.2.1
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '0.2'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 0.2.1
33
+ - !ruby/object:Gem::Dependency
34
+ name: bundler
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '2.0'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '2.0'
47
+ description: A Ruby interface to rustscan, the Modern Port Scanner.
48
+ email: postmodern.mod3@gmail.com
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files:
52
+ - ChangeLog.md
53
+ - LICENSE.txt
54
+ - README.md
55
+ files:
56
+ - ".document"
57
+ - ".github/workflows/ruby.yml"
58
+ - ".gitignore"
59
+ - ".rspec"
60
+ - ".yardopts"
61
+ - ChangeLog.md
62
+ - Gemfile
63
+ - LICENSE.txt
64
+ - README.md
65
+ - Rakefile
66
+ - gemspec.yml
67
+ - lib/rustscan/command.rb
68
+ - lib/rustscan/version.rb
69
+ - ruby-rustscan.gemspec
70
+ - spec/command_spec.rb
71
+ - spec/spec_helper.rb
72
+ homepage: https://github.com/postmodern/ruby-rustscan#readme
73
+ licenses:
74
+ - MIT
75
+ metadata:
76
+ documentation_uri: https://rubydoc.info/gems/ruby-rustscan
77
+ source_code_uri: https://github.com/postmodern/ruby-rustscan
78
+ bug_tracker_uri: https://github.com/postmodern/ruby-rustscan/issues
79
+ changelog_uri: https://github.com/postmodern/ruby-rustscan/blob/master/ChangeLog.md
80
+ rubygems_mfa_required: 'true'
81
+ post_install_message:
82
+ rdoc_options: []
83
+ require_paths:
84
+ - lib
85
+ required_ruby_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: 2.0.0
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ requirements:
96
+ - rustscan >= 2.0.0
97
+ rubygems_version: 3.2.22
98
+ signing_key:
99
+ specification_version: 4
100
+ summary: A Ruby interface to rustscan.
101
+ test_files: []