virustotal_api 0.4.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +26 -0
  3. data/.gitignore +1 -0
  4. data/.rubocop.yml +12 -5
  5. data/CHANGELOG.md +7 -2
  6. data/README.md +48 -56
  7. data/lib/virustotal_api.rb +5 -7
  8. data/lib/virustotal_api/analysis.rb +24 -0
  9. data/lib/virustotal_api/base.rb +35 -10
  10. data/lib/virustotal_api/domain.rb +24 -0
  11. data/lib/virustotal_api/exceptions.rb +3 -0
  12. data/lib/virustotal_api/file.rb +56 -0
  13. data/lib/virustotal_api/ip.rb +24 -0
  14. data/lib/virustotal_api/uri.rb +2 -1
  15. data/lib/virustotal_api/url.rb +46 -0
  16. data/lib/virustotal_api/version.rb +2 -1
  17. data/test/analysis_test.rb +23 -0
  18. data/test/base_test.rb +8 -28
  19. data/test/domain_test.rb +32 -0
  20. data/test/exceptions_test.rb +14 -0
  21. data/test/file_test.rb +68 -0
  22. data/test/fixtures/analysis.yml +544 -0
  23. data/test/fixtures/domain.yml +830 -0
  24. data/test/fixtures/file_analyse.yml +52 -0
  25. data/test/fixtures/file_find.yml +1236 -0
  26. data/test/fixtures/file_unauthorized.yml +51 -0
  27. data/test/fixtures/file_upload.yml +54 -0
  28. data/test/fixtures/ip.yml +716 -0
  29. data/test/fixtures/unscanned_url_find.yml +44 -0
  30. data/test/fixtures/url_analyse.yml +52 -0
  31. data/test/fixtures/url_find.yml +599 -0
  32. data/test/{ip_report_test.rb → ip_test.rb} +4 -4
  33. data/test/uri_test.rb +1 -1
  34. data/test/url_test.rb +65 -0
  35. data/test/version_test.rb +1 -1
  36. data/virustotal_api.gemspec +10 -8
  37. metadata +86 -70
  38. data/.github/workflows/gem_publish.yml +0 -38
  39. data/lib/virustotal_api/domain_report.rb +0 -36
  40. data/lib/virustotal_api/file_report.rb +0 -37
  41. data/lib/virustotal_api/file_rescan.rb +0 -36
  42. data/lib/virustotal_api/file_scan.rb +0 -38
  43. data/lib/virustotal_api/ip_report.rb +0 -36
  44. data/lib/virustotal_api/url_report.rb +0 -41
  45. data/lib/virustotal_api/url_scan.rb +0 -36
  46. data/test/domain_report_test.rb +0 -32
  47. data/test/file_report_test.rb +0 -36
  48. data/test/file_rescan_test.rb +0 -32
  49. data/test/file_scan_test.rb +0 -30
  50. data/test/fixtures/domain_report.yml +0 -311
  51. data/test/fixtures/ip_report.yml +0 -1323
  52. data/test/fixtures/queue_unscanned_url_report.yml +0 -46
  53. data/test/fixtures/report.yml +0 -110
  54. data/test/fixtures/report_not_found.yml +0 -42
  55. data/test/fixtures/request_forbidden.yml +0 -38
  56. data/test/fixtures/rescan.yml +0 -47
  57. data/test/fixtures/scan.yml +0 -49
  58. data/test/fixtures/unscanned_url_report.yml +0 -43
  59. data/test/fixtures/url_report.yml +0 -95
  60. data/test/fixtures/url_scan.yml +0 -48
  61. data/test/url_report_test.rb +0 -57
  62. data/test/url_scan_test.rb +0 -30
@@ -3,4 +3,7 @@
3
3
  module VirustotalAPI
4
4
  class RateLimitError < RuntimeError
5
5
  end
6
+
7
+ class Unauthorized < RuntimeError
8
+ end
6
9
  end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module VirustotalAPI
6
+ # A class for '/files' API
7
+ class File < Base
8
+ attr_reader :id, :report_url
9
+
10
+ def initialize(report)
11
+ super(report)
12
+ @id = report&.dig('data', 'id')
13
+ @report_url = report&.dig('data', 'links', 'self')
14
+ end
15
+
16
+ # Find a hash.
17
+ #
18
+ # @param [String] resource file as a md5/sha1/sha256 hash
19
+ # @param [String] api_key The key for virustotal
20
+ # @return [VirustotalAPI::File] Report Search Result
21
+ def self.find(resource, api_key)
22
+ report = perform("/files/#{resource}", api_key)
23
+ new(report)
24
+ end
25
+
26
+ # Upload a new file.
27
+ #
28
+ # @param [String] file_path for file to be sent for scan
29
+ # @param [String] api_key The key for virustotal
30
+ # @param [Hash] opts hash for additional options
31
+ # @return [VirusotalAPI::File] Report
32
+ def self.upload(file_path, api_key, opts = {})
33
+ filename = opts.fetch('filename') { ::File.basename(file_path) }
34
+ report = perform('/files', api_key, :post, filename: filename, file: ::File.open(file_path, 'r'))
35
+ new(report)
36
+ end
37
+
38
+ # Analyse a hash again.
39
+ #
40
+ # @param [String] resource file as a md5/sha1/sha256 hash
41
+ # @param [String] api_key The key for virustotal
42
+ # @return [VirustotalAPI::File] Report
43
+ def self.analyse(resource, api_key)
44
+ report = perform("/files/#{resource}/analyse", api_key, :post)
45
+ new(report)
46
+ end
47
+
48
+ # Check if the submitted hash is detected by an AV engine.
49
+ #
50
+ # @param [String] engine The engine to check.
51
+ # @return [Boolean] true if detected
52
+ def detected_by(engine)
53
+ report['data']['attributes']['last_analysis_results'][engine]['category'] == 'harmless'
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module VirustotalAPI
6
+ # A class for '/ip_addresses' API
7
+ class IP < Base
8
+ # rubocop:disable Lint/UselessMethodDefinition
9
+ def initialize(report)
10
+ super(report)
11
+ end
12
+
13
+ # Find an IP.
14
+ #
15
+ # @param [String] ip address The IP to find.
16
+ # @param [String] api_key The key for virustotal
17
+ # @return [VirustotalAPI::IPReport] Report
18
+ def self.find(ip, api_key)
19
+ report = perform("/ip_addresses/#{ip}", api_key)
20
+ new(report)
21
+ end
22
+ end
23
+ end
24
+ # rubocop:enable Lint/UselessMethodDefinition
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module VirustotalAPI
4
- URI = 'https://www.virustotal.com/vtapi/v2'
4
+ # The API base URI
5
+ URI = 'https://www.virustotal.com/api/v3'
5
6
  end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module VirustotalAPI
6
+ # A class for '/urls' API
7
+ class URL < Base
8
+ attr_reader :report_url, :id
9
+
10
+ def initialize(report)
11
+ super(report)
12
+ @report_url = report&.dig('data', 'links', 'self')
13
+ @id = report&.dig('data', 'id')
14
+ end
15
+
16
+ # Find a URL.
17
+ #
18
+ # @param [String] resource as an ip/domain/url
19
+ # @param [String] api_key The key for virustotal
20
+ # @return [VirustotalAPI::URL] Report
21
+ def self.find(resource, api_key)
22
+ report = perform("/urls/#{url_identifier(resource)}", api_key)
23
+ new(report)
24
+ end
25
+
26
+ # Analyse a URL again.
27
+ #
28
+ # @param [String] resource as an ip/domain/url
29
+ # @param [String] api_key The key for virustotal
30
+ # @return [VirustotalAPI::URL] Report
31
+ def self.analyse(resource, api_key)
32
+ report = perform("/urls/#{url_identifier(resource)}/analyse", api_key, :post)
33
+ new(report)
34
+ end
35
+
36
+ # Upload a URL for detection.
37
+ #
38
+ # @param [String] resource as an ip/domain/url
39
+ # @param [String] api_key The key for virustotal
40
+ # @return [VirustotalAPI::URL] Report
41
+ def self.upload(resource, api_key)
42
+ report = perform('/urls', api_key, :post, url: resource)
43
+ new(report)
44
+ end
45
+ end
46
+ end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module VirustotalAPI
4
- VERSION = '0.4.1'
4
+ # The GEM version
5
+ VERSION = '0.5.0'
5
6
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require './test/test_helper'
4
+
5
+ class VirustotalAPIAnalysisTest < Minitest::Test
6
+ def setup
7
+ @url = 'http://www.google.com'
8
+ @api_key = 'theapikey'
9
+ end
10
+
11
+ def test_todo
12
+ VCR.use_cassette('url_find') do
13
+ vtreport = VirustotalAPI::URL.find(@url, @api_key)
14
+ @id = vtreport.id
15
+ assert @id
16
+ end
17
+
18
+ VCR.use_cassette('analysis') do
19
+ analysis = VirustotalAPI::Analysis.find(@id, @api_key)
20
+ assert analysis.exists?
21
+ end
22
+ end
23
+ end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # rubocop:disable LineLength
4
3
  require './test/test_helper'
5
4
 
6
5
  class VirustotalAPIBaseTest < Minitest::Test
@@ -15,45 +14,26 @@ class VirustotalAPIBaseTest < Minitest::Test
15
14
 
16
15
  # Instance Method
17
16
  def test_api_uri_instance_method
18
- base_uri = 'https://www.virustotal.com/vtapi/v2'
19
- vt_base = VirustotalAPI::Base.new
17
+ base_uri = 'https://www.virustotal.com/api/v3'
18
+ vt_base = VirustotalAPI::Base.new(nil)
20
19
 
21
20
  assert vt_base.api_uri.is_a?(String)
22
- assert vt_base.api_uri, base_uri
21
+ assert_equal base_uri, vt_base.api_uri
23
22
  end
24
23
 
25
24
  # Class Method
26
25
  def test_api_uri_class_method
27
- base_uri = 'https://www.virustotal.com/vtapi/v2'
26
+ base_uri = 'https://www.virustotal.com/api/v3'
28
27
 
29
28
  assert VirustotalAPI::Base.api_uri.is_a?(String)
30
- assert VirustotalAPI::Base.api_uri, base_uri
29
+ assert_equal base_uri, VirustotalAPI::Base.api_uri
31
30
  end
32
31
 
33
- def test_parse_code_200
34
- mock_response200 = Minitest::Mock.new
35
- mock_response200.expect(:code, 200)
36
- mock_response200.expect(:body, '{}')
37
-
38
- assert VirustotalAPI::Base.parse(mock_response200), {}
39
- end
40
-
41
- def test_parse_code_204
42
- mock_response204 = Minitest::Mock.new
43
- mock_response204.expect(:code, 204)
44
- mock_response204.expect(:body, '{}')
45
-
46
- assert_raises VirustotalAPI::RateLimitError do
47
- VirustotalAPI::Base.parse(mock_response204)
48
- end
49
- end
50
-
51
- # Test using FileReport
52
32
  def test_exists?
53
- VCR.use_cassette('report') do
54
- virustotal_report = VirustotalAPI::FileReport.find(@sha256, @api_key)
33
+ VCR.use_cassette('file_find') do
34
+ virustotal_report = VirustotalAPI::File.find(@sha256, @api_key)
55
35
 
56
- assert virustotal_report.exists?, true
36
+ assert virustotal_report.exists?
57
37
  end
58
38
  end
59
39
  end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require './test/test_helper'
4
+
5
+ class VirustotalAPIDomainTest < Minitest::Test
6
+ def setup
7
+ @domain = 'virustotal.com'
8
+ @api_key = 'testapikey'
9
+ end
10
+
11
+ def test_class_exists
12
+ assert VirustotalAPI::Domain
13
+ end
14
+
15
+ def test_report_response
16
+ VCR.use_cassette('domain') do
17
+ vtdomain_report = VirustotalAPI::Domain.find(@domain, @api_key)
18
+
19
+ # Make sure that the JSON was parsed
20
+ assert vtdomain_report.is_a?(VirustotalAPI::Domain)
21
+ assert vtdomain_report.report.is_a?(Hash)
22
+ end
23
+ end
24
+
25
+ def test_exists?
26
+ VCR.use_cassette('domain') do
27
+ vtdomain_report = VirustotalAPI::Domain.find(@domain, @api_key)
28
+
29
+ assert vtdomain_report.exists?
30
+ end
31
+ end
32
+ end
@@ -3,7 +3,21 @@
3
3
  require './test/test_helper'
4
4
 
5
5
  class RateLimitErrorTest < Minitest::Test
6
+ def setup
7
+ @sha256 = '01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b'
8
+ @api_key = 'testapikey'
9
+ end
10
+
6
11
  def test_class_exists
7
12
  assert VirustotalAPI::RateLimitError
13
+ assert VirustotalAPI::Unauthorized
14
+ end
15
+
16
+ def test_unauthorized
17
+ VCR.use_cassette('file_unauthorized') do
18
+ assert_raises VirustotalAPI::Unauthorized do
19
+ VirustotalAPI::File.find(@sha256, @api_key)
20
+ end
21
+ end
8
22
  end
9
23
  end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require './test/test_helper'
4
+
5
+ class VirustotalAPIFileTest < Minitest::Test
6
+ def setup
7
+ @sha256 = '01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b'
8
+ @file_path = File.expand_path('test/fixtures/null_file')
9
+ @api_key = 'testapikey'
10
+ end
11
+
12
+ def test_class_exists
13
+ assert VirustotalAPI::File
14
+ end
15
+
16
+ def test_report_response
17
+ VCR.use_cassette('file_find') do
18
+ virustotal_report = VirustotalAPI::File.find(@sha256, @api_key)
19
+
20
+ # Make sure that the JSON was parsed
21
+ assert virustotal_report.is_a?(VirustotalAPI::File)
22
+ assert virustotal_report.report.is_a?(Hash)
23
+ end
24
+ end
25
+
26
+ def test_find
27
+ permalink = 'https://www.virustotal.com/api/v3/files/' \
28
+ '01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b'
29
+ VCR.use_cassette('file_find') do
30
+ virustotal_report = VirustotalAPI::File.find(@sha256, @api_key)
31
+
32
+ assert virustotal_report.report_url.is_a?(String)
33
+ assert_equal permalink, virustotal_report.report_url
34
+ end
35
+ end
36
+
37
+ def test_upload
38
+ VCR.use_cassette('file_upload') do
39
+ virustotal_upload = VirustotalAPI::File.upload(@file_path, @api_key)
40
+
41
+ assert virustotal_upload.report.is_a?(Hash)
42
+ end
43
+ end
44
+
45
+ def test_upload_id
46
+ VCR.use_cassette('file_upload') do
47
+ virustotal_upload = VirustotalAPI::File.upload(@file_path, @api_key)
48
+
49
+ assert virustotal_upload.id.is_a?(String)
50
+ end
51
+ end
52
+
53
+ def test_analyse
54
+ VCR.use_cassette('file_analyse') do
55
+ virustotal_analyse = VirustotalAPI::File.analyse(@sha256, @api_key)
56
+
57
+ assert virustotal_analyse.report.is_a?(Hash)
58
+ end
59
+ end
60
+
61
+ def test_analyse_id
62
+ VCR.use_cassette('file_analyse') do
63
+ virustotal_analyse = VirustotalAPI::File.analyse(@sha256, @api_key)
64
+
65
+ assert virustotal_analyse.id.is_a?(String)
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,544 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://www.virustotal.com/api/v3/analyses/u-a354494a73382ea0b4bc47f4c9e8d6c578027cd4598196dc88f05a22b5817293-1599122231
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - "*/*"
12
+ User-Agent:
13
+ - rest-client/2.1.0 (linux-gnu x86_64) ruby/2.5.1p57
14
+ X-Apikey:
15
+ - theapikey
16
+ Content-Length:
17
+ - '0'
18
+ Content-Type:
19
+ - application/x-www-form-urlencoded
20
+ Accept-Encoding:
21
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
22
+ Host:
23
+ - www.virustotal.com
24
+ response:
25
+ status:
26
+ code: 200
27
+ message: OK
28
+ headers:
29
+ Cache-Control:
30
+ - no-cache
31
+ Content-Type:
32
+ - application/json; charset=utf-8
33
+ X-Cloud-Trace-Context:
34
+ - ee845ce2e3e28aee8c7f2c8e2de417cd
35
+ Date:
36
+ - Thu, 03 Sep 2020 08:43:03 GMT
37
+ Server:
38
+ - Google Frontend
39
+ Content-Length:
40
+ - '18600'
41
+ body:
42
+ encoding: UTF-8
43
+ string: |-
44
+ {
45
+ "data": {
46
+ "attributes": {
47
+ "date": 1599122231,
48
+ "results": {
49
+ "ADMINUSLabs": {
50
+ "category": "harmless",
51
+ "engine_name": "ADMINUSLabs",
52
+ "method": "blacklist",
53
+ "result": "clean"
54
+ },
55
+ "AegisLab WebGuard": {
56
+ "category": "harmless",
57
+ "engine_name": "AegisLab WebGuard",
58
+ "method": "blacklist",
59
+ "result": "clean"
60
+ },
61
+ "AlienVault": {
62
+ "category": "harmless",
63
+ "engine_name": "AlienVault",
64
+ "method": "blacklist",
65
+ "result": "clean"
66
+ },
67
+ "Antiy-AVL": {
68
+ "category": "harmless",
69
+ "engine_name": "Antiy-AVL",
70
+ "method": "blacklist",
71
+ "result": "clean"
72
+ },
73
+ "Artists Against 419": {
74
+ "category": "harmless",
75
+ "engine_name": "Artists Against 419",
76
+ "method": "blacklist",
77
+ "result": "clean"
78
+ },
79
+ "AutoShun": {
80
+ "category": "undetected",
81
+ "engine_name": "AutoShun",
82
+ "method": "blacklist",
83
+ "result": "unrated"
84
+ },
85
+ "Avira": {
86
+ "category": "harmless",
87
+ "engine_name": "Avira",
88
+ "method": "blacklist",
89
+ "result": "clean"
90
+ },
91
+ "BADWARE.INFO": {
92
+ "category": "harmless",
93
+ "engine_name": "BADWARE.INFO",
94
+ "method": "blacklist",
95
+ "result": "clean"
96
+ },
97
+ "Baidu-International": {
98
+ "category": "harmless",
99
+ "engine_name": "Baidu-International",
100
+ "method": "blacklist",
101
+ "result": "clean"
102
+ },
103
+ "BitDefender": {
104
+ "category": "harmless",
105
+ "engine_name": "BitDefender",
106
+ "method": "blacklist",
107
+ "result": "clean"
108
+ },
109
+ "BlockList": {
110
+ "category": "harmless",
111
+ "engine_name": "BlockList",
112
+ "method": "blacklist",
113
+ "result": "clean"
114
+ },
115
+ "Blueliv": {
116
+ "category": "harmless",
117
+ "engine_name": "Blueliv",
118
+ "method": "blacklist",
119
+ "result": "clean"
120
+ },
121
+ "CINS Army": {
122
+ "category": "harmless",
123
+ "engine_name": "CINS Army",
124
+ "method": "blacklist",
125
+ "result": "clean"
126
+ },
127
+ "CLEAN MX": {
128
+ "category": "harmless",
129
+ "engine_name": "CLEAN MX",
130
+ "method": "blacklist",
131
+ "result": "clean"
132
+ },
133
+ "CRDF": {
134
+ "category": "harmless",
135
+ "engine_name": "CRDF",
136
+ "method": "blacklist",
137
+ "result": "clean"
138
+ },
139
+ "Certego": {
140
+ "category": "harmless",
141
+ "engine_name": "Certego",
142
+ "method": "blacklist",
143
+ "result": "clean"
144
+ },
145
+ "Comodo Valkyrie Verdict": {
146
+ "category": "harmless",
147
+ "engine_name": "Comodo Valkyrie Verdict",
148
+ "method": "blacklist",
149
+ "result": "clean"
150
+ },
151
+ "CyRadar": {
152
+ "category": "harmless",
153
+ "engine_name": "CyRadar",
154
+ "method": "blacklist",
155
+ "result": "clean"
156
+ },
157
+ "Cyan": {
158
+ "category": "undetected",
159
+ "engine_name": "Cyan",
160
+ "method": "blacklist",
161
+ "result": "unrated"
162
+ },
163
+ "CyberCrime": {
164
+ "category": "harmless",
165
+ "engine_name": "CyberCrime",
166
+ "method": "blacklist",
167
+ "result": "clean"
168
+ },
169
+ "Cyren": {
170
+ "category": "harmless",
171
+ "engine_name": "Cyren",
172
+ "method": "blacklist",
173
+ "result": "clean"
174
+ },
175
+ "DNS8": {
176
+ "category": "harmless",
177
+ "engine_name": "DNS8",
178
+ "method": "blacklist",
179
+ "result": "clean"
180
+ },
181
+ "Dr.Web": {
182
+ "category": "harmless",
183
+ "engine_name": "Dr.Web",
184
+ "method": "blacklist",
185
+ "result": "clean"
186
+ },
187
+ "ESET": {
188
+ "category": "harmless",
189
+ "engine_name": "ESET",
190
+ "method": "blacklist",
191
+ "result": "clean"
192
+ },
193
+ "EmergingThreats": {
194
+ "category": "harmless",
195
+ "engine_name": "EmergingThreats",
196
+ "method": "blacklist",
197
+ "result": "clean"
198
+ },
199
+ "Emsisoft": {
200
+ "category": "harmless",
201
+ "engine_name": "Emsisoft",
202
+ "method": "blacklist",
203
+ "result": "clean"
204
+ },
205
+ "EonScope": {
206
+ "category": "harmless",
207
+ "engine_name": "EonScope",
208
+ "method": "blacklist",
209
+ "result": "clean"
210
+ },
211
+ "Feodo Tracker": {
212
+ "category": "harmless",
213
+ "engine_name": "Feodo Tracker",
214
+ "method": "blacklist",
215
+ "result": "clean"
216
+ },
217
+ "Forcepoint ThreatSeeker": {
218
+ "category": "harmless",
219
+ "engine_name": "Forcepoint ThreatSeeker",
220
+ "method": "blacklist",
221
+ "result": "clean"
222
+ },
223
+ "Fortinet": {
224
+ "category": "harmless",
225
+ "engine_name": "Fortinet",
226
+ "method": "blacklist",
227
+ "result": "clean"
228
+ },
229
+ "FraudScore": {
230
+ "category": "harmless",
231
+ "engine_name": "FraudScore",
232
+ "method": "blacklist",
233
+ "result": "clean"
234
+ },
235
+ "G-Data": {
236
+ "category": "harmless",
237
+ "engine_name": "G-Data",
238
+ "method": "blacklist",
239
+ "result": "clean"
240
+ },
241
+ "Google Safebrowsing": {
242
+ "category": "harmless",
243
+ "engine_name": "Google Safebrowsing",
244
+ "method": "blacklist",
245
+ "result": "clean"
246
+ },
247
+ "GreenSnow": {
248
+ "category": "harmless",
249
+ "engine_name": "GreenSnow",
250
+ "method": "blacklist",
251
+ "result": "clean"
252
+ },
253
+ "Hoplite Industries": {
254
+ "category": "harmless",
255
+ "engine_name": "Hoplite Industries",
256
+ "method": "blacklist",
257
+ "result": "clean"
258
+ },
259
+ "IPsum": {
260
+ "category": "harmless",
261
+ "engine_name": "IPsum",
262
+ "method": "blacklist",
263
+ "result": "clean"
264
+ },
265
+ "K7AntiVirus": {
266
+ "category": "harmless",
267
+ "engine_name": "K7AntiVirus",
268
+ "method": "blacklist",
269
+ "result": "clean"
270
+ },
271
+ "Kaspersky": {
272
+ "category": "harmless",
273
+ "engine_name": "Kaspersky",
274
+ "method": "blacklist",
275
+ "result": "clean"
276
+ },
277
+ "Lumu": {
278
+ "category": "undetected",
279
+ "engine_name": "Lumu",
280
+ "method": "blacklist",
281
+ "result": "unrated"
282
+ },
283
+ "MalSilo": {
284
+ "category": "harmless",
285
+ "engine_name": "MalSilo",
286
+ "method": "blacklist",
287
+ "result": "clean"
288
+ },
289
+ "Malware Domain Blocklist": {
290
+ "category": "harmless",
291
+ "engine_name": "Malware Domain Blocklist",
292
+ "method": "blacklist",
293
+ "result": "clean"
294
+ },
295
+ "MalwareDomainList": {
296
+ "category": "harmless",
297
+ "engine_name": "MalwareDomainList",
298
+ "method": "blacklist",
299
+ "result": "clean"
300
+ },
301
+ "MalwarePatrol": {
302
+ "category": "harmless",
303
+ "engine_name": "MalwarePatrol",
304
+ "method": "blacklist",
305
+ "result": "clean"
306
+ },
307
+ "Malwared": {
308
+ "category": "harmless",
309
+ "engine_name": "Malwared",
310
+ "method": "blacklist",
311
+ "result": "clean"
312
+ },
313
+ "Netcraft": {
314
+ "category": "undetected",
315
+ "engine_name": "Netcraft",
316
+ "method": "blacklist",
317
+ "result": "unrated"
318
+ },
319
+ "NotMining": {
320
+ "category": "undetected",
321
+ "engine_name": "NotMining",
322
+ "method": "blacklist",
323
+ "result": "unrated"
324
+ },
325
+ "Nucleon": {
326
+ "category": "harmless",
327
+ "engine_name": "Nucleon",
328
+ "method": "blacklist",
329
+ "result": "clean"
330
+ },
331
+ "OpenPhish": {
332
+ "category": "harmless",
333
+ "engine_name": "OpenPhish",
334
+ "method": "blacklist",
335
+ "result": "clean"
336
+ },
337
+ "PREBYTES": {
338
+ "category": "harmless",
339
+ "engine_name": "PREBYTES",
340
+ "method": "blacklist",
341
+ "result": "clean"
342
+ },
343
+ "PhishLabs": {
344
+ "category": "undetected",
345
+ "engine_name": "PhishLabs",
346
+ "method": "blacklist",
347
+ "result": "unrated"
348
+ },
349
+ "Phishing Database": {
350
+ "category": "harmless",
351
+ "engine_name": "Phishing Database",
352
+ "method": "blacklist",
353
+ "result": "clean"
354
+ },
355
+ "Phishtank": {
356
+ "category": "harmless",
357
+ "engine_name": "Phishtank",
358
+ "method": "blacklist",
359
+ "result": "clean"
360
+ },
361
+ "Quick Heal": {
362
+ "category": "harmless",
363
+ "engine_name": "Quick Heal",
364
+ "method": "blacklist",
365
+ "result": "clean"
366
+ },
367
+ "Quttera": {
368
+ "category": "harmless",
369
+ "engine_name": "Quttera",
370
+ "method": "blacklist",
371
+ "result": "clean"
372
+ },
373
+ "Rising": {
374
+ "category": "harmless",
375
+ "engine_name": "Rising",
376
+ "method": "blacklist",
377
+ "result": "clean"
378
+ },
379
+ "SCUMWARE.org": {
380
+ "category": "harmless",
381
+ "engine_name": "SCUMWARE.org",
382
+ "method": "blacklist",
383
+ "result": "clean"
384
+ },
385
+ "Sangfor": {
386
+ "category": "harmless",
387
+ "engine_name": "Sangfor",
388
+ "method": "blacklist",
389
+ "result": "clean"
390
+ },
391
+ "SecureBrain": {
392
+ "category": "harmless",
393
+ "engine_name": "SecureBrain",
394
+ "method": "blacklist",
395
+ "result": "clean"
396
+ },
397
+ "Snort IP sample list": {
398
+ "category": "harmless",
399
+ "engine_name": "Snort IP sample list",
400
+ "method": "blacklist",
401
+ "result": "clean"
402
+ },
403
+ "Sophos": {
404
+ "category": "harmless",
405
+ "engine_name": "Sophos",
406
+ "method": "blacklist",
407
+ "result": "clean"
408
+ },
409
+ "Spam404": {
410
+ "category": "harmless",
411
+ "engine_name": "Spam404",
412
+ "method": "blacklist",
413
+ "result": "clean"
414
+ },
415
+ "Spamhaus": {
416
+ "category": "harmless",
417
+ "engine_name": "Spamhaus",
418
+ "method": "blacklist",
419
+ "result": "clean"
420
+ },
421
+ "StopBadware": {
422
+ "category": "undetected",
423
+ "engine_name": "StopBadware",
424
+ "method": "blacklist",
425
+ "result": "unrated"
426
+ },
427
+ "StopForumSpam": {
428
+ "category": "harmless",
429
+ "engine_name": "StopForumSpam",
430
+ "method": "blacklist",
431
+ "result": "clean"
432
+ },
433
+ "Sucuri SiteCheck": {
434
+ "category": "harmless",
435
+ "engine_name": "Sucuri SiteCheck",
436
+ "method": "blacklist",
437
+ "result": "clean"
438
+ },
439
+ "Tencent": {
440
+ "category": "harmless",
441
+ "engine_name": "Tencent",
442
+ "method": "blacklist",
443
+ "result": "clean"
444
+ },
445
+ "ThreatHive": {
446
+ "category": "harmless",
447
+ "engine_name": "ThreatHive",
448
+ "method": "blacklist",
449
+ "result": "clean"
450
+ },
451
+ "Threatsourcing": {
452
+ "category": "harmless",
453
+ "engine_name": "Threatsourcing",
454
+ "method": "blacklist",
455
+ "result": "clean"
456
+ },
457
+ "Trustwave": {
458
+ "category": "harmless",
459
+ "engine_name": "Trustwave",
460
+ "method": "blacklist",
461
+ "result": "clean"
462
+ },
463
+ "URLhaus": {
464
+ "category": "harmless",
465
+ "engine_name": "URLhaus",
466
+ "method": "blacklist",
467
+ "result": "clean"
468
+ },
469
+ "VX Vault": {
470
+ "category": "harmless",
471
+ "engine_name": "VX Vault",
472
+ "method": "blacklist",
473
+ "result": "clean"
474
+ },
475
+ "Virusdie External Site Scan": {
476
+ "category": "harmless",
477
+ "engine_name": "Virusdie External Site Scan",
478
+ "method": "blacklist",
479
+ "result": "clean"
480
+ },
481
+ "Web Security Guard": {
482
+ "category": "harmless",
483
+ "engine_name": "Web Security Guard",
484
+ "method": "blacklist",
485
+ "result": "clean"
486
+ },
487
+ "Yandex Safebrowsing": {
488
+ "category": "harmless",
489
+ "engine_name": "Yandex Safebrowsing",
490
+ "method": "blacklist",
491
+ "result": "clean"
492
+ },
493
+ "ZeroCERT": {
494
+ "category": "harmless",
495
+ "engine_name": "ZeroCERT",
496
+ "method": "blacklist",
497
+ "result": "clean"
498
+ },
499
+ "desenmascara.me": {
500
+ "category": "harmless",
501
+ "engine_name": "desenmascara.me",
502
+ "method": "blacklist",
503
+ "result": "clean"
504
+ },
505
+ "malwares.com URL checker": {
506
+ "category": "harmless",
507
+ "engine_name": "malwares.com URL checker",
508
+ "method": "blacklist",
509
+ "result": "clean"
510
+ },
511
+ "securolytics": {
512
+ "category": "harmless",
513
+ "engine_name": "securolytics",
514
+ "method": "blacklist",
515
+ "result": "clean"
516
+ },
517
+ "zvelo": {
518
+ "category": "harmless",
519
+ "engine_name": "zvelo",
520
+ "method": "blacklist",
521
+ "result": "clean"
522
+ }
523
+ },
524
+ "stats": {
525
+ "harmless": 72,
526
+ "malicious": 0,
527
+ "suspicious": 0,
528
+ "timeout": 0,
529
+ "undetected": 7
530
+ },
531
+ "status": "completed"
532
+ },
533
+ "id": "u-a354494a73382ea0b4bc47f4c9e8d6c578027cd4598196dc88f05a22b5817293-1599122231",
534
+ "type": "analysis"
535
+ },
536
+ "meta": {
537
+ "url_info": {
538
+ "id": "a354494a73382ea0b4bc47f4c9e8d6c578027cd4598196dc88f05a22b5817293",
539
+ "url": "http://virustotal.com/"
540
+ }
541
+ }
542
+ }
543
+ recorded_at: Thu, 03 Sep 2020 08:43:03 GMT
544
+ recorded_with: VCR 6.0.0