nvd_feed_api 0.2.0 → 0.4.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.
- checksums.yaml +5 -5
- data/.github/FUNDING.yml +3 -0
- data/.gitignore +1 -1
- data/.gitlab-ci.yml +17 -10
- data/.rubocop.yml +15 -5
- data/.tool-versions +1 -0
- data/.yardopts +2 -0
- data/Gemfile +24 -1
- data/Gemfile.lock +64 -0
- data/README.md +2 -1
- data/lib/nvd_feed_api/feed.rb +27 -17
- data/lib/nvd_feed_api/meta.rb +6 -6
- data/lib/nvd_feed_api/version.rb +1 -1
- data/lib/nvd_feed_api.rb +47 -20
- data/nvd_feed_api.gemspec +13 -24
- data/pages/CHANGELOG.md +40 -0
- data/pages/INSTALL.md +2 -9
- data/renovate.json +15 -0
- data/test/test_nvd_feed_api.rb +10 -10
- metadata +29 -128
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: d03fa81fd296a62aba7a9356b3c41135851febb254af4db13758c5b76475739f
|
|
4
|
+
data.tar.gz: c0d716121dccaeaee6944ccd3e0d85cf59854084ae68d0f7347fb678dc4760bf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b5bef50a5709e8bd53a138110e80f6a5ee34d02f5849e1a3d9add0c9573e963926adbdf6eeb610b75d04d25d285b4450b8e99aa724582d382ed072ef46c89a8a
|
|
7
|
+
data.tar.gz: 7be0a9191d6efb0e7a80e7a868d8d019186268008473e3e731fe9e4e3e1d21b85b7cc6189c912d5315495dbb12dbaaa688ca077823ba844a01d91b11696ae954
|
data/.github/FUNDING.yml
ADDED
data/.gitignore
CHANGED
data/.gitlab-ci.yml
CHANGED
|
@@ -1,36 +1,43 @@
|
|
|
1
1
|
# Official language image. Look for the different tagged releases at:
|
|
2
2
|
# https://hub.docker.com/r/library/ruby/tags/
|
|
3
|
-
image: ruby:2.4-alpine
|
|
4
3
|
|
|
4
|
+
# Caching: https://docs.gitlab.com/ee/ci/caching/#caching-ruby-dependencies
|
|
5
5
|
cache:
|
|
6
|
+
key: ${CI_COMMIT_REF_SLUG}
|
|
6
7
|
paths:
|
|
7
8
|
- vendor/ruby # cache gems in between builds
|
|
8
9
|
|
|
9
10
|
before_script:
|
|
10
11
|
- ruby -v # Print out ruby version for debugging
|
|
11
|
-
- gem install bundler
|
|
12
|
+
- gem install bundler --no-document # Bundler is not installed with the image
|
|
12
13
|
# install nproc (coreutils) for bundle -j
|
|
13
14
|
# install git for building the gemspec
|
|
14
15
|
# install make, gcc for building gem native extension (commonmarker)
|
|
15
16
|
# libc-dev for musl-dev dependency (stdlib.h) needed by gcc
|
|
16
17
|
- apk --no-cache add coreutils git make gcc libc-dev
|
|
17
18
|
- bundle install -j $(nproc) --path vendor # Install dependencies into ./vendor/ruby
|
|
18
|
-
- rake install # install the gem
|
|
19
|
+
- bundle exec rake install # install the gem
|
|
19
20
|
|
|
20
|
-
|
|
21
|
+
# Anchors: https://docs.gitlab.com/ee/ci/yaml/README.html#anchors
|
|
22
|
+
.test_template: &job_definition
|
|
21
23
|
stage: test
|
|
22
24
|
script:
|
|
23
|
-
|
|
25
|
+
- bundle exec rubocop
|
|
26
|
+
- bundle exec rake test
|
|
24
27
|
|
|
25
|
-
test:
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
#test:2.4:
|
|
29
|
+
# <<: *job_definition
|
|
30
|
+
# image: ruby:2.4-alpine
|
|
31
|
+
|
|
32
|
+
test:3.1:
|
|
33
|
+
<<: *job_definition
|
|
34
|
+
image: ruby:3.1-alpine
|
|
29
35
|
|
|
30
36
|
pages:
|
|
31
37
|
stage: deploy
|
|
38
|
+
image: ruby:3.1-alpine
|
|
32
39
|
script:
|
|
33
|
-
- yard doc
|
|
40
|
+
- bundle exec yard doc
|
|
34
41
|
- mkdir public
|
|
35
42
|
- mv doc/* public/
|
|
36
43
|
artifacts:
|
data/.rubocop.yml
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
AllCops:
|
|
2
|
-
TargetRubyVersion: 2.
|
|
2
|
+
TargetRubyVersion: 2.7
|
|
3
|
+
NewCops: enable
|
|
4
|
+
|
|
5
|
+
Layout/HashAlignment:
|
|
6
|
+
EnforcedHashRocketStyle: table
|
|
7
|
+
|
|
8
|
+
Layout/LineLength:
|
|
9
|
+
Enabled: false
|
|
3
10
|
|
|
4
11
|
# Rubocop is too stupid too see that the variable is used
|
|
5
12
|
Lint/UselessAssignment:
|
|
@@ -18,10 +25,7 @@ Metrics/ClassLength:
|
|
|
18
25
|
Enabled: false
|
|
19
26
|
|
|
20
27
|
Metrics/CyclomaticComplexity:
|
|
21
|
-
Max:
|
|
22
|
-
|
|
23
|
-
Metrics/LineLength:
|
|
24
|
-
Enabled: false
|
|
28
|
+
Max: 25
|
|
25
29
|
|
|
26
30
|
Metrics/MethodLength:
|
|
27
31
|
Max: 100
|
|
@@ -35,6 +39,9 @@ Naming/VariableName:
|
|
|
35
39
|
Security/JSONLoad:
|
|
36
40
|
Enabled: false
|
|
37
41
|
|
|
42
|
+
Style/CaseLikeIf:
|
|
43
|
+
Enabled: true
|
|
44
|
+
|
|
38
45
|
Style/FrozenStringLiteralComment:
|
|
39
46
|
EnforcedStyle: never
|
|
40
47
|
|
|
@@ -44,3 +51,6 @@ Style/PerlBackrefs:
|
|
|
44
51
|
# Allow explicit return
|
|
45
52
|
Style/RedundantReturn:
|
|
46
53
|
Enabled: false
|
|
54
|
+
|
|
55
|
+
Style/WordArray:
|
|
56
|
+
EnforcedStyle: brackets
|
data/.tool-versions
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ruby 3.1.0
|
data/.yardopts
CHANGED
data/Gemfile
CHANGED
|
@@ -1,4 +1,27 @@
|
|
|
1
1
|
source 'https://rubygems.org'
|
|
2
2
|
|
|
3
|
-
# Specify your gem's dependencies in .gemspec
|
|
4
3
|
gemspec
|
|
4
|
+
|
|
5
|
+
group :runtime, :cli do
|
|
6
|
+
gem 'archive-zip', '~> 0.11'
|
|
7
|
+
gem 'nokogiri', '~> 1.11'
|
|
8
|
+
gem 'oj', '>= 3.7.8', '<4'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
group :development, :install do
|
|
12
|
+
gem 'bundler', '~> 2.1'
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
group :development, :test do
|
|
16
|
+
gem 'minitest', '~> 5.12'
|
|
17
|
+
gem 'rake', '~> 13.0'
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
group :development, :lint do
|
|
21
|
+
gem 'rubocop', '~> 1.23'
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
group :development, :docs do
|
|
25
|
+
gem 'commonmarker', '~> 0.21' # for markdown support in YARD
|
|
26
|
+
gem 'yard', ['>= 0.9.27', '< 0.10']
|
|
27
|
+
end
|
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
nvd_feed_api (0.4.0)
|
|
5
|
+
archive-zip (~> 0.11)
|
|
6
|
+
nokogiri (~> 1.11)
|
|
7
|
+
oj (>= 3.7.8, < 4)
|
|
8
|
+
|
|
9
|
+
GEM
|
|
10
|
+
remote: https://rubygems.org/
|
|
11
|
+
specs:
|
|
12
|
+
archive-zip (0.12.0)
|
|
13
|
+
io-like (~> 0.3.0)
|
|
14
|
+
ast (2.4.2)
|
|
15
|
+
commonmarker (0.23.2)
|
|
16
|
+
io-like (0.3.1)
|
|
17
|
+
mini_portile2 (2.7.1)
|
|
18
|
+
minitest (5.15.0)
|
|
19
|
+
nokogiri (1.13.1)
|
|
20
|
+
mini_portile2 (~> 2.7.0)
|
|
21
|
+
racc (~> 1.4)
|
|
22
|
+
oj (3.13.10)
|
|
23
|
+
parallel (1.21.0)
|
|
24
|
+
parser (3.0.3.2)
|
|
25
|
+
ast (~> 2.4.1)
|
|
26
|
+
racc (1.6.0)
|
|
27
|
+
rainbow (3.0.0)
|
|
28
|
+
rake (13.0.6)
|
|
29
|
+
regexp_parser (2.2.0)
|
|
30
|
+
rexml (3.2.5)
|
|
31
|
+
rubocop (1.24.1)
|
|
32
|
+
parallel (~> 1.10)
|
|
33
|
+
parser (>= 3.0.0.0)
|
|
34
|
+
rainbow (>= 2.2.2, < 4.0)
|
|
35
|
+
regexp_parser (>= 1.8, < 3.0)
|
|
36
|
+
rexml
|
|
37
|
+
rubocop-ast (>= 1.15.1, < 2.0)
|
|
38
|
+
ruby-progressbar (~> 1.7)
|
|
39
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
|
40
|
+
rubocop-ast (1.15.1)
|
|
41
|
+
parser (>= 3.0.1.1)
|
|
42
|
+
ruby-progressbar (1.11.0)
|
|
43
|
+
unicode-display_width (2.1.0)
|
|
44
|
+
webrick (1.7.0)
|
|
45
|
+
yard (0.9.27)
|
|
46
|
+
webrick (~> 1.7.0)
|
|
47
|
+
|
|
48
|
+
PLATFORMS
|
|
49
|
+
ruby
|
|
50
|
+
|
|
51
|
+
DEPENDENCIES
|
|
52
|
+
archive-zip (~> 0.11)
|
|
53
|
+
bundler (~> 2.1)
|
|
54
|
+
commonmarker (~> 0.21)
|
|
55
|
+
minitest (~> 5.12)
|
|
56
|
+
nokogiri (~> 1.11)
|
|
57
|
+
nvd_feed_api!
|
|
58
|
+
oj (>= 3.7.8, < 4)
|
|
59
|
+
rake (~> 13.0)
|
|
60
|
+
rubocop (~> 1.23)
|
|
61
|
+
yard (>= 0.9.27, < 0.10)
|
|
62
|
+
|
|
63
|
+
BUNDLED WITH
|
|
64
|
+
2.3.6
|
data/README.md
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
[][rubygems]
|
|
6
6
|
[][rubygems]
|
|
7
7
|
[][rubygems]
|
|
8
|
+
[](https://inventory.rawsec.ml/tools.html#nvd_feed_api)
|
|
8
9
|
|
|
9
10
|
[rubygems]:https://rubygems.org/gems/nvd_feed_api/
|
|
10
11
|
|
|
@@ -12,7 +13,7 @@
|
|
|
12
13
|
|
|
13
14
|
**nvd_feed_api** is a simple ruby API for NVD CVE feeds.
|
|
14
15
|
|
|
15
|
-
The API will help you to download and manage NVD Data Feeds, search for CVEs, build your
|
|
16
|
+
The API will help you to download and manage NVD Data Feeds, search for CVEs, build your vulnerability assessment platform or vulnerability database.
|
|
16
17
|
|
|
17
18
|
Name | Link
|
|
18
19
|
--- | ---
|
data/lib/nvd_feed_api/feed.rb
CHANGED
|
@@ -13,7 +13,7 @@ class NVDFeedScraper
|
|
|
13
13
|
class Feed
|
|
14
14
|
class << self
|
|
15
15
|
# Get / set default feed storage location, where will be stored JSON feeds and archives by default.
|
|
16
|
-
# @return [String] default feed storage location. Default to
|
|
16
|
+
# @return [String] default feed storage location. Default to `/tmp/`.
|
|
17
17
|
# @example
|
|
18
18
|
# NVDFeedScraper::Feed.default_storage_location = '/srv/downloads/'
|
|
19
19
|
attr_accessor :default_storage_location
|
|
@@ -69,11 +69,11 @@ class NVDFeedScraper
|
|
|
69
69
|
# f.json_file # => "/tmp/nvdcve-1.0-2014.json"
|
|
70
70
|
attr_reader :json_file
|
|
71
71
|
|
|
72
|
-
# @return [String] the type of the feed, should always be
|
|
72
|
+
# @return [String] the type of the feed, should always be `CVE`.
|
|
73
73
|
# @note Return nil if not previously loaded by {#json_pull}.
|
|
74
74
|
attr_reader :data_type
|
|
75
75
|
|
|
76
|
-
# @return [String] the format of the feed, should always be
|
|
76
|
+
# @return [String] the format of the feed, should always be `MITRE`.
|
|
77
77
|
# @note Return nil if not previously loaded by {#json_pull}.
|
|
78
78
|
attr_reader :data_format
|
|
79
79
|
|
|
@@ -96,7 +96,7 @@ class NVDFeedScraper
|
|
|
96
96
|
# @param gz_url [String] see {#gz_url}.
|
|
97
97
|
# @param zip_url [String] see {#zip_url}.
|
|
98
98
|
def initialize(name, updated, meta_url, gz_url, zip_url)
|
|
99
|
-
#
|
|
99
|
+
# From meta file
|
|
100
100
|
@name = name
|
|
101
101
|
@updated = updated
|
|
102
102
|
@meta_url = meta_url
|
|
@@ -146,7 +146,7 @@ class NVDFeedScraper
|
|
|
146
146
|
# Download the JSON feed and fill the attribute.
|
|
147
147
|
# @param opts [Hash] see {#download_file}.
|
|
148
148
|
# @return [String] the path of the saved JSON file. Default use {Feed#default_storage_location}.
|
|
149
|
-
# @note Will
|
|
149
|
+
# @note Will download and save the zip of the JSON file, unzip and save it. This massively consume time.
|
|
150
150
|
# @see #json_file
|
|
151
151
|
def json_pull(opts = {})
|
|
152
152
|
opts[:destination_path] ||= Feed.default_storage_location
|
|
@@ -184,6 +184,7 @@ class NVDFeedScraper
|
|
|
184
184
|
# Verify hash integrity
|
|
185
185
|
computed_h = Digest::SHA256.file(@json_file)
|
|
186
186
|
raise "File corruption: #{@json_file}" unless meta.sha256.casecmp(computed_h.hexdigest).zero?
|
|
187
|
+
|
|
187
188
|
# update data
|
|
188
189
|
doc = Oj::Doc.open(File.read(@json_file))
|
|
189
190
|
@data_type = doc.fetch('/CVE_data_type')
|
|
@@ -223,11 +224,15 @@ class NVDFeedScraper
|
|
|
223
224
|
def cve(*arg_cve)
|
|
224
225
|
raise 'json_file is nil, it needs to be populated with json_pull' if @json_file.nil?
|
|
225
226
|
raise "json_file (#{@json_file}) doesn't exist" unless File.file?(@json_file)
|
|
227
|
+
|
|
226
228
|
return_value = nil
|
|
227
229
|
raise 'no argument provided, 1 or more expected' if arg_cve.empty?
|
|
230
|
+
|
|
228
231
|
if arg_cve.length == 1
|
|
229
|
-
|
|
232
|
+
case arg_cve[0]
|
|
233
|
+
when String
|
|
230
234
|
raise "bad CVE name (#{arg_cve[0]})" unless /^CVE-[0-9]{4}-[0-9]{4,}$/i.match?(arg_cve[0])
|
|
235
|
+
|
|
231
236
|
doc = Oj::Doc.open(File.read(@json_file))
|
|
232
237
|
# Quicker than doc.fetch('/CVE_Items').size
|
|
233
238
|
(1..@data_number_of_cves).each do |i|
|
|
@@ -237,13 +242,14 @@ class NVDFeedScraper
|
|
|
237
242
|
end
|
|
238
243
|
end
|
|
239
244
|
doc.close
|
|
240
|
-
|
|
245
|
+
when Array
|
|
241
246
|
return_value = []
|
|
242
247
|
# Sorting CVE can allow us to parse quicker
|
|
243
248
|
# Upcase to be sure include? works
|
|
244
249
|
cves_to_find = arg_cve[0].map(&:upcase).sort
|
|
245
250
|
raise 'one of the provided arguments is not a String' unless cves_to_find.all? { |x| x.is_a?(String) }
|
|
246
251
|
raise 'bad CVE name' unless cves_to_find.all? { |x| /^CVE-[0-9]{4}-[0-9]{4,}$/i.match?(x) }
|
|
252
|
+
|
|
247
253
|
doc = Oj::Doc.open(File.read(@json_file))
|
|
248
254
|
# Quicker than doc.fetch('/CVE_Items').size
|
|
249
255
|
(1..@data_number_of_cves).each do |i|
|
|
@@ -273,6 +279,7 @@ class NVDFeedScraper
|
|
|
273
279
|
def available_cves
|
|
274
280
|
raise 'json_file is nil, it needs to be populated with json_pull' if @json_file.nil?
|
|
275
281
|
raise "json_file (#{@json_file}) doesn't exist" unless File.file?(@json_file)
|
|
282
|
+
|
|
276
283
|
doc = Oj::Doc.open(File.read(@json_file))
|
|
277
284
|
# Quicker than doc.fetch('/CVE_Items').size
|
|
278
285
|
cve_names = []
|
|
@@ -290,6 +297,7 @@ class NVDFeedScraper
|
|
|
290
297
|
# 'CVE-2007'
|
|
291
298
|
def name=(arg_name)
|
|
292
299
|
raise "name (#{arg_name}) is not a string" unless arg_name.is_a?(String)
|
|
300
|
+
|
|
293
301
|
@name = arg_name
|
|
294
302
|
end
|
|
295
303
|
|
|
@@ -299,6 +307,7 @@ class NVDFeedScraper
|
|
|
299
307
|
# '10/19/2017 3:27:02 AM -04:00'
|
|
300
308
|
def updated=(arg_updated)
|
|
301
309
|
raise "updated date (#{arg_updated}) is not a string" unless arg_updated.is_a?(String)
|
|
310
|
+
|
|
302
311
|
@updated = arg_updated
|
|
303
312
|
end
|
|
304
313
|
|
|
@@ -308,6 +317,7 @@ class NVDFeedScraper
|
|
|
308
317
|
# 'https://static.nvd.nist.gov/feeds/json/cve/1.0/nvdcve-1.0-2007.meta'
|
|
309
318
|
def meta_url=(arg_meta_url)
|
|
310
319
|
raise "meta_url (#{arg_meta_url}) is not a string" unless arg_meta_url.is_a?(String)
|
|
320
|
+
|
|
311
321
|
@meta_url = arg_meta_url
|
|
312
322
|
end
|
|
313
323
|
|
|
@@ -317,6 +327,7 @@ class NVDFeedScraper
|
|
|
317
327
|
# 'https://static.nvd.nist.gov/feeds/json/cve/1.0/nvdcve-1.0-2007.json.gz'
|
|
318
328
|
def gz_url=(arg_gz_url)
|
|
319
329
|
raise "gz_url (#{arg_gz_url}) is not a string" unless arg_gz_url.is_a?(String)
|
|
330
|
+
|
|
320
331
|
@gz_url = arg_gz_url
|
|
321
332
|
end
|
|
322
333
|
|
|
@@ -326,6 +337,7 @@ class NVDFeedScraper
|
|
|
326
337
|
# 'https://static.nvd.nist.gov/feeds/json/cve/1.0/nvdcve-1.0-2007.json.zip'
|
|
327
338
|
def zip_url=(arg_zip_url)
|
|
328
339
|
raise "zip_url (#{arg_zip_url}) is not a string" unless arg_zip_url.is_a?(String)
|
|
340
|
+
|
|
329
341
|
@zip_url = arg_zip_url
|
|
330
342
|
end
|
|
331
343
|
|
|
@@ -352,30 +364,28 @@ class NVDFeedScraper
|
|
|
352
364
|
uri = URI(file_url)
|
|
353
365
|
filename = uri.path.split('/').last
|
|
354
366
|
destination_file = destination_path + filename
|
|
355
|
-
|
|
356
|
-
if
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
skip_download = true if opts[:sha256].casecmp(computed_h.hexdigest).zero?
|
|
360
|
-
end
|
|
367
|
+
if !opts[:sha256].nil? && File.file?(destination_file)
|
|
368
|
+
# Verify hash to see if it is the latest
|
|
369
|
+
computed_h = Digest::SHA256.file(destination_file)
|
|
370
|
+
skip_download = true if opts[:sha256].casecmp(computed_h.hexdigest).zero?
|
|
361
371
|
end
|
|
362
372
|
unless skip_download
|
|
363
373
|
res = Net::HTTP.get_response(uri)
|
|
364
374
|
raise "#{file_url} ended with #{res.code} #{res.message}" unless res.is_a?(Net::HTTPSuccess)
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
end
|
|
375
|
+
|
|
376
|
+
File.binwrite(destination_file, res.body)
|
|
368
377
|
end
|
|
369
378
|
return destination_file
|
|
370
379
|
end
|
|
371
380
|
|
|
372
381
|
# Update the feed
|
|
373
382
|
# @param fresh_feed [Feed] the fresh feed from which the feed will be updated.
|
|
374
|
-
# @return [Boolean]
|
|
383
|
+
# @return [Boolean] `true` if the feed was updated, `false` if it wasn't.
|
|
375
384
|
# @note Is not intended to be used directly, use {NVDFeedScraper#update_feeds} instead.
|
|
376
385
|
def update!(fresh_feed)
|
|
377
386
|
return_value = false
|
|
378
387
|
raise "#{fresh_feed} is not a Feed" unless fresh_feed.is_a?(Feed)
|
|
388
|
+
|
|
379
389
|
# update attributes
|
|
380
390
|
if updated != fresh_feed.updated
|
|
381
391
|
self.name = fresh_feed.name
|
data/lib/nvd_feed_api/meta.rb
CHANGED
|
@@ -76,26 +76,26 @@ class NVDFeedScraper
|
|
|
76
76
|
# Parse the meta file from the URL and set the attributes.
|
|
77
77
|
# @overload parse
|
|
78
78
|
# Parse the meta file from the URL and set the attributes.
|
|
79
|
-
# @return [Integer] Returns
|
|
79
|
+
# @return [Integer] Returns `0` when there is no error.
|
|
80
80
|
# @overload parse(url)
|
|
81
81
|
# Set the URL of the meta file of the feed and
|
|
82
82
|
# parse the meta file from the URL and set the attributes.
|
|
83
83
|
# @param url [String] see {Feed.meta_url}
|
|
84
|
-
# @return [Integer] Returns
|
|
84
|
+
# @return [Integer] Returns `0` when there is no error.
|
|
85
85
|
def parse(*arg)
|
|
86
|
-
if arg.
|
|
87
|
-
elsif arg.length == 1 # arg = url
|
|
86
|
+
if arg.length == 1 # arg = url
|
|
88
87
|
self.url = arg[0]
|
|
89
|
-
|
|
88
|
+
elsif arg.length > 1
|
|
90
89
|
raise 'Too much arguments'
|
|
91
90
|
end
|
|
92
91
|
|
|
93
92
|
raise "Can't parse if the URL is empty" if @url.nil?
|
|
93
|
+
|
|
94
94
|
uri = URI(@url)
|
|
95
95
|
|
|
96
96
|
meta = Net::HTTP.get(uri)
|
|
97
97
|
|
|
98
|
-
meta =
|
|
98
|
+
meta = meta.split.to_h { |x| x.split(':', 2) }
|
|
99
99
|
|
|
100
100
|
raise 'no lastModifiedDate attribute found' unless meta['lastModifiedDate']
|
|
101
101
|
raise 'no valid size attribute found' unless /[0-9]+/.match?(meta['size'])
|
data/lib/nvd_feed_api/version.rb
CHANGED
data/lib/nvd_feed_api.rb
CHANGED
|
@@ -18,8 +18,9 @@ require 'nvd_feed_api/feed'
|
|
|
18
18
|
# scraper.feeds("CVE-2007")
|
|
19
19
|
# cve2007, cve2015 = scraper.feeds("CVE-2007", "CVE-2015")
|
|
20
20
|
class NVDFeedScraper
|
|
21
|
+
BASE = 'https://nvd.nist.gov'.freeze
|
|
21
22
|
# The NVD url where is located the data feeds.
|
|
22
|
-
URL =
|
|
23
|
+
URL = "#{BASE}/vuln/data-feeds".freeze
|
|
23
24
|
# Load constants
|
|
24
25
|
include NvdFeedApi
|
|
25
26
|
|
|
@@ -31,21 +32,34 @@ class NVDFeedScraper
|
|
|
31
32
|
|
|
32
33
|
# Scrap / parse the website to get the feeds and fill the {#feeds} attribute.
|
|
33
34
|
# @note {#scrap} need to be called only once but can be called again to update if the NVD feed page changed.
|
|
34
|
-
# @return [Integer]
|
|
35
|
+
# @return [Integer] Number of scrapped feeds.
|
|
35
36
|
def scrap
|
|
36
37
|
uri = URI(@url)
|
|
37
38
|
html = Net::HTTP.get(uri)
|
|
38
39
|
|
|
39
40
|
doc = Nokogiri::HTML(html)
|
|
40
41
|
@feeds = []
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
42
|
+
tmp_feeds = {}
|
|
43
|
+
doc.css('#vuln-feed-table table.xml-feed-table tr[data-testid]').each do |tr|
|
|
44
|
+
num, type = tr.attr('data-testid')[13..].split('-')
|
|
45
|
+
case type
|
|
46
|
+
when 'meta'
|
|
47
|
+
tmp_feeds[num] = {}
|
|
48
|
+
tmp_feeds[num][:name] = tr.css('td')[0].text
|
|
49
|
+
tmp_feeds[num][:updated] = tr.css('td')[1].text
|
|
50
|
+
tmp_feeds[num][:meta] = BASE + tr.css('td')[2].css('> a').attr('href').value
|
|
51
|
+
when 'gz'
|
|
52
|
+
tmp_feeds[num][:gz] = BASE + tr.css('td > a').attr('href').value
|
|
53
|
+
when 'zip'
|
|
54
|
+
tmp_feeds[num][:zip] = BASE + tr.css('td > a').attr('href').value
|
|
55
|
+
@feeds.push(Feed.new(tmp_feeds[num][:name],
|
|
56
|
+
tmp_feeds[num][:updated],
|
|
57
|
+
tmp_feeds[num][:meta],
|
|
58
|
+
tmp_feeds[num][:gz],
|
|
59
|
+
tmp_feeds[num][:zip]))
|
|
60
|
+
end
|
|
48
61
|
end
|
|
62
|
+
return @feeds.size
|
|
49
63
|
end
|
|
50
64
|
|
|
51
65
|
# Return feeds. Can only be called after {#scrap}.
|
|
@@ -72,17 +86,20 @@ class NVDFeedScraper
|
|
|
72
86
|
# @see https://nvd.nist.gov/vuln/data-feeds
|
|
73
87
|
def feeds(*arg_feeds)
|
|
74
88
|
raise 'call scrap method before using feeds method' if @feeds.nil?
|
|
89
|
+
|
|
75
90
|
return_value = nil
|
|
76
91
|
if arg_feeds.empty?
|
|
77
92
|
return_value = @feeds
|
|
78
93
|
elsif arg_feeds.length == 1
|
|
79
|
-
|
|
94
|
+
case arg_feeds[0]
|
|
95
|
+
when String
|
|
80
96
|
@feeds.each do |feed| # feed is an object
|
|
81
97
|
return_value = feed if arg_feeds.include?(feed.name)
|
|
82
98
|
end
|
|
83
99
|
# if nothing found return nil
|
|
84
|
-
|
|
100
|
+
when Array
|
|
85
101
|
raise 'one of the provided arguments is not a String' unless arg_feeds[0].all? { |x| x.is_a?(String) }
|
|
102
|
+
|
|
86
103
|
# Sorting CVE can allow us to parse quicker
|
|
87
104
|
# Upcase to be sure include? works
|
|
88
105
|
# Does not use map(&:upcase) to preserve CVE-Recent and CVE-Modified
|
|
@@ -114,6 +131,7 @@ class NVDFeedScraper
|
|
|
114
131
|
# scraper.available_feeds => ["CVE-Modified", "CVE-Recent", "CVE-2017", "CVE-2016", "CVE-2015", "CVE-2014", "CVE-2013", "CVE-2012", "CVE-2011", "CVE-2010", "CVE-2009", "CVE-2008", "CVE-2007", "CVE-2006", "CVE-2005", "CVE-2004", "CVE-2003", "CVE-2002"]
|
|
115
132
|
def available_feeds
|
|
116
133
|
raise 'call scrap method before using available_feeds method' if @feeds.nil?
|
|
134
|
+
|
|
117
135
|
feed_names = []
|
|
118
136
|
@feeds.each do |feed| # feed is an objet
|
|
119
137
|
feed_names.push(feed.name)
|
|
@@ -146,9 +164,12 @@ class NVDFeedScraper
|
|
|
146
164
|
def cve(*arg_cve)
|
|
147
165
|
return_value = nil
|
|
148
166
|
raise 'no argument provided, 1 or more expected' if arg_cve.empty?
|
|
167
|
+
|
|
149
168
|
if arg_cve.length == 1
|
|
150
|
-
|
|
169
|
+
case arg_cve[0]
|
|
170
|
+
when String
|
|
151
171
|
raise 'bad CVE name' unless /^CVE-[0-9]{4}-[0-9]{4,}$/i.match?(arg_cve[0])
|
|
172
|
+
|
|
152
173
|
year = /^CVE-([0-9]{4})-[0-9]{4,}$/i.match(arg_cve[0]).captures[0]
|
|
153
174
|
matched_feed = nil
|
|
154
175
|
feed_names = available_feeds
|
|
@@ -163,12 +184,14 @@ class NVDFeedScraper
|
|
|
163
184
|
# CVE-2002 feed (the 1st one) contains CVE from 1999 to 2002
|
|
164
185
|
matched_feed = 'CVE-2002' if matched_feed.nil? && ('1999'..'2001').to_a.include?(year)
|
|
165
186
|
raise "bad CVE year in #{arg_cve}" if matched_feed.nil?
|
|
187
|
+
|
|
166
188
|
f = feeds(matched_feed)
|
|
167
189
|
f.json_pull
|
|
168
190
|
return_value = f.cve(arg_cve[0])
|
|
169
|
-
|
|
191
|
+
when Array
|
|
170
192
|
raise 'one of the provided arguments is not a String' unless arg_cve[0].all? { |x| x.is_a?(String) }
|
|
171
193
|
raise 'bad CVE name' unless arg_cve[0].all? { |x| /^CVE-[0-9]{4}-[0-9]{4,}$/i.match?(x) }
|
|
194
|
+
|
|
172
195
|
return_value = []
|
|
173
196
|
# Sorting CVE can allow us to parse quicker
|
|
174
197
|
# Upcase to be sure include? works
|
|
@@ -185,6 +208,7 @@ class NVDFeedScraper
|
|
|
185
208
|
# So virtually add those feed...
|
|
186
209
|
feed_names.merge(virtual_feeds)
|
|
187
210
|
raise 'unexisting CVE year was provided in some CVE' unless feeds_to_match.subset?(feed_names)
|
|
211
|
+
|
|
188
212
|
matched_feeds = feeds_to_match.intersection(feed_names)
|
|
189
213
|
# and now that the intersection is done remove those virtual feeds and add CVE-2002 instead if needed
|
|
190
214
|
unless matched_feeds.intersection(virtual_feeds.to_set).empty?
|
|
@@ -195,9 +219,10 @@ class NVDFeedScraper
|
|
|
195
219
|
feeds_arr.each do |feed|
|
|
196
220
|
feed.json_pull
|
|
197
221
|
cves_obj = feed.cve(cves_to_find.select { |cve| cve.include?(feed.name) })
|
|
198
|
-
|
|
222
|
+
case cves_obj
|
|
223
|
+
when Hash
|
|
199
224
|
return_value.push(cves_obj)
|
|
200
|
-
|
|
225
|
+
when Array
|
|
201
226
|
return_value.push(*cves_obj)
|
|
202
227
|
else
|
|
203
228
|
raise 'cve() method of the feed instance returns wrong value'
|
|
@@ -217,16 +242,16 @@ class NVDFeedScraper
|
|
|
217
242
|
# @overload update_feeds(feed)
|
|
218
243
|
# One feed.
|
|
219
244
|
# @param feed [Feed] feed object to update.
|
|
220
|
-
# @return [Boolean]
|
|
245
|
+
# @return [Boolean] `true` if the feed was updated, `false` if it wasn't.
|
|
221
246
|
# @overload update_feeds(feed_arr)
|
|
222
247
|
# An array of feed.
|
|
223
248
|
# @param feed_arr [Array<Feed>] array of feed objects to update.
|
|
224
|
-
# @return [Array<Boolean>]
|
|
249
|
+
# @return [Array<Boolean>] `true` if the feed was updated, `false` if it wasn't.
|
|
225
250
|
# @overload update_feeds(feed, *)
|
|
226
251
|
# Multiple feeds.
|
|
227
252
|
# @param feed [Feed] feed object to update.
|
|
228
253
|
# @param * [Feed] As many feed objects as you want.
|
|
229
|
-
# @return [Array<Boolean>]
|
|
254
|
+
# @return [Array<Boolean>] `true` if the feed was updated, `false` if it wasn't.
|
|
230
255
|
# @example
|
|
231
256
|
# s = NVDFeedScraper.new
|
|
232
257
|
# s.scrap
|
|
@@ -235,13 +260,15 @@ class NVDFeedScraper
|
|
|
235
260
|
def update_feeds(*arg_feed)
|
|
236
261
|
return_value = false
|
|
237
262
|
raise 'no argument provided, 1 or more expected' if arg_feed.empty?
|
|
263
|
+
|
|
238
264
|
scrap
|
|
239
265
|
if arg_feed.length == 1
|
|
240
|
-
|
|
266
|
+
case arg_feed[0]
|
|
267
|
+
when Feed
|
|
241
268
|
new_feed = feeds(arg_feed[0].name)
|
|
242
269
|
# update attributes
|
|
243
270
|
return_value = arg_feed[0].update!(new_feed)
|
|
244
|
-
|
|
271
|
+
when Array
|
|
245
272
|
return_value = []
|
|
246
273
|
arg_feed[0].each do |f|
|
|
247
274
|
res = update_feeds(f)
|
data/nvd_feed_api.gemspec
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
3
|
-
require 'nvd_feed_api/version'
|
|
1
|
+
require_relative 'lib/nvd_feed_api/version'
|
|
4
2
|
|
|
5
3
|
Gem::Specification.new do |s|
|
|
6
4
|
s.name = 'nvd_feed_api'
|
|
7
5
|
s.version = NvdFeedApi::VERSION
|
|
8
6
|
s.platform = Gem::Platform::RUBY
|
|
9
|
-
s.date = '2018-01-06'
|
|
10
7
|
s.summary = 'API for NVD CVE feeds'
|
|
11
8
|
s.description = 'A simple API for NVD CVE feeds'
|
|
12
9
|
s.authors = ['Alexandre ZANNI']
|
|
@@ -20,27 +17,19 @@ Gem::Specification.new do |s|
|
|
|
20
17
|
s.require_paths = ['lib']
|
|
21
18
|
|
|
22
19
|
s.metadata = {
|
|
23
|
-
'yard.run'
|
|
24
|
-
'bug_tracker_uri'
|
|
25
|
-
'changelog_uri'
|
|
26
|
-
'documentation_uri'
|
|
27
|
-
'homepage_uri'
|
|
28
|
-
'source_code_uri'
|
|
29
|
-
'wiki_uri'
|
|
20
|
+
'yard.run' => 'yard',
|
|
21
|
+
'bug_tracker_uri' => 'https://gitlab.com/noraj/nvd_api/issues',
|
|
22
|
+
'changelog_uri' => 'https://noraj.gitlab.io/nvd_api/file.CHANGELOG.html',
|
|
23
|
+
'documentation_uri' => 'https://noraj.gitlab.io/nvd_api/',
|
|
24
|
+
'homepage_uri' => 'https://noraj.gitlab.io/nvd_api/',
|
|
25
|
+
'source_code_uri' => 'https://gitlab.com/noraj/nvd_api/tree/master',
|
|
26
|
+
'wiki_uri' => 'https://gitlab.com/noraj/nvd_api/wikis/home',
|
|
27
|
+
'rubygems_mfa_required' => 'true'
|
|
30
28
|
}
|
|
31
29
|
|
|
32
|
-
s.required_ruby_version = '
|
|
30
|
+
s.required_ruby_version = ['>= 2.7.0', '< 3.2']
|
|
33
31
|
|
|
34
|
-
s.add_dependency('archive-zip', '~> 0.
|
|
35
|
-
s.add_dependency('nokogiri', '~> 1.
|
|
36
|
-
s.add_dependency('oj', '
|
|
37
|
-
|
|
38
|
-
s.add_development_dependency('bundler', '~> 1.15')
|
|
39
|
-
s.add_development_dependency('commonmarker', '~> 0.17') # for GMF support in YARD
|
|
40
|
-
s.add_development_dependency('github-markup', '~> 1.6') # for GMF support in YARD
|
|
41
|
-
s.add_development_dependency('minitest', '~> 5.10')
|
|
42
|
-
s.add_development_dependency('rake', '~> 12.3')
|
|
43
|
-
s.add_development_dependency('redcarpet', '~> 3.4') # for GMF support in YARD
|
|
44
|
-
s.add_development_dependency('rubocop', '~> 0.51')
|
|
45
|
-
s.add_development_dependency('yard', '~> 0.9')
|
|
32
|
+
s.add_dependency('archive-zip', '~> 0.11')
|
|
33
|
+
s.add_dependency('nokogiri', '~> 1.11')
|
|
34
|
+
s.add_dependency('oj', '>= 3.7.8', '<4')
|
|
46
35
|
end
|
data/pages/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,43 @@
|
|
|
1
|
+
# [unreleased]
|
|
2
|
+
|
|
3
|
+
# [0.4.0] - 31 January 2021
|
|
4
|
+
|
|
5
|
+
- Dependencies:
|
|
6
|
+
- Update to yard [v0.9.27](https://github.com/lsegal/yard/releases/tag/v0.9.27)
|
|
7
|
+
- Move from Redcarpet to CommonMarker markdown provider
|
|
8
|
+
- Move doc syntax from Rdoc to markdown
|
|
9
|
+
- Move dev dependencies from gemspec to gemfile
|
|
10
|
+
- Chore:
|
|
11
|
+
- Add support for Ruby 3.1
|
|
12
|
+
- Update rubocop rules
|
|
13
|
+
|
|
14
|
+
# [0.3.1] - 13 October 2020
|
|
15
|
+
|
|
16
|
+
[0.3.1]: https://gitlab.com/noraj/nvd_api/tags/v0.3.1
|
|
17
|
+
|
|
18
|
+
- fix scrap method to reflect NVD feeds page changes
|
|
19
|
+
- update dependencies
|
|
20
|
+
- update rubocop rules
|
|
21
|
+
|
|
22
|
+
# [0.3.0] - 22 January 2019
|
|
23
|
+
|
|
24
|
+
[0.3.0]: https://gitlab.com/noraj/nvd_api/tags/v0.3.0
|
|
25
|
+
|
|
26
|
+
- update dependencies: updated gemspec, ruby 2.6 support, fix gem doc flag, fix oj crash (seg fault)
|
|
27
|
+
- Gemfile.lock: now Gemfile.lock is not ignored anymore
|
|
28
|
+
- gitlab-ci: add ruby 2.6 test, add caching key, and anchors for better reuse, always use bundle
|
|
29
|
+
- NVDFeedScraper `scrap` method: change return value
|
|
30
|
+
- rubocop: fix lint
|
|
31
|
+
|
|
32
|
+
# [0.2.1] - 2 May 2018
|
|
33
|
+
|
|
34
|
+
[0.2.1]: https://gitlab.com/noraj/nvd_api/tags/v0.2.1
|
|
35
|
+
|
|
36
|
+
- Gitlab-CI: test with ruby 2.4.x and 2.5.x
|
|
37
|
+
- style: fix Style/ExpandPathArguments cop
|
|
38
|
+
- security: fix Security/Open cop, protect from pipe command injection
|
|
39
|
+
- test: fix NVD URL after NVD changed it
|
|
40
|
+
|
|
1
41
|
# [0.2.0] - 20 January 2018
|
|
2
42
|
|
|
3
43
|
[0.2.0]: https://gitlab.com/noraj/nvd_api/tags/v0.2.0
|
data/pages/INSTALL.md
CHANGED
|
@@ -10,14 +10,7 @@ $ gem install nvd_feed_api
|
|
|
10
10
|
|
|
11
11
|
## Development
|
|
12
12
|
|
|
13
|
-
It's better to use [
|
|
14
|
-
|
|
15
|
-
To keep clean gem dependencies create a gemset with rvm:
|
|
16
|
-
|
|
17
|
-
```
|
|
18
|
-
$ rvm gemset create nvd_feed_api
|
|
19
|
-
$ rvm gemset use nvd_feed_api
|
|
20
|
-
```
|
|
13
|
+
It's better to use [rbenv](https://github.com/rbenv/rbenv) to have latests version of ruby and to avoid trashing your system ruby.
|
|
21
14
|
|
|
22
15
|
### Install from rubygems.org
|
|
23
16
|
|
|
@@ -53,7 +46,7 @@ Note: if an automatic install is needed you can get the version with `$ gem buil
|
|
|
53
46
|
|
|
54
47
|
### Run the API in irb without installing the gem
|
|
55
48
|
|
|
56
|
-
|
|
49
|
+
Useful when you want to try your changes without building the gem and re-installing it each time.
|
|
57
50
|
|
|
58
51
|
```
|
|
59
52
|
$ git clone https://gitlab.com/noraj/nvd_api.git nvd_feed_api
|
data/renovate.json
ADDED
data/test/test_nvd_feed_api.rb
CHANGED
|
@@ -9,7 +9,7 @@ class NVDAPITest < Minitest::Test
|
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
def test_scraper_scrap
|
|
12
|
-
|
|
12
|
+
assert_operator(0, :<, @s.scrap, 'scrap method returns nothing')
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def test_scraper_feeds_noarg
|
|
@@ -78,7 +78,7 @@ class NVDAPITest < Minitest::Test
|
|
|
78
78
|
f2017, f2016, f_modified = @s.feeds('CVE-2017', 'CVE-2016', 'CVE-Modified')
|
|
79
79
|
# one arg
|
|
80
80
|
# can't use assert_instance_of because there is no boolean class
|
|
81
|
-
assert(
|
|
81
|
+
assert(['TrueClass', 'FalseClass'].include?(@s.update_feeds(f2017).class.to_s), "update_feeds doesn't return a boolean")
|
|
82
82
|
# two args
|
|
83
83
|
assert_instance_of(Array, @s.update_feeds(f2017, f2016), "update_feeds doesn't return an array")
|
|
84
84
|
refute_empty(@s.update_feeds(f2017, f2016), 'update_feeds returns an empty array')
|
|
@@ -109,9 +109,9 @@ class NVDAPITest < Minitest::Test
|
|
|
109
109
|
|
|
110
110
|
def test_feed_attributes
|
|
111
111
|
name = 'CVE-2010'
|
|
112
|
-
meta_url = 'https://
|
|
113
|
-
gz_url = 'https://
|
|
114
|
-
zip_url = 'https://
|
|
112
|
+
meta_url = 'https://nvd.nist.gov/feeds/json/cve/1.1/nvdcve-1.1-2010.meta'
|
|
113
|
+
gz_url = 'https://nvd.nist.gov/feeds/json/cve/1.1/nvdcve-1.1-2010.json.gz'
|
|
114
|
+
zip_url = 'https://nvd.nist.gov/feeds/json/cve/1.1/nvdcve-1.1-2010.json.zip'
|
|
115
115
|
f = @s.feeds('CVE-2010')
|
|
116
116
|
# Test name
|
|
117
117
|
assert_instance_of(String, f.name, "name doesn't return a string")
|
|
@@ -231,7 +231,7 @@ class NVDAPITest < Minitest::Test
|
|
|
231
231
|
f_new = @s.feeds('CVE-2006')
|
|
232
232
|
# Right arg
|
|
233
233
|
# can't use assert_instance_of because there is no boolean class
|
|
234
|
-
assert(
|
|
234
|
+
assert(['TrueClass', 'FalseClass'].include?(f.update!(f_new).class.to_s), "update! doesn't return a boolean")
|
|
235
235
|
# Bad arg
|
|
236
236
|
err = assert_raises(RuntimeError) do
|
|
237
237
|
f.update!('bad_arg')
|
|
@@ -240,25 +240,25 @@ class NVDAPITest < Minitest::Test
|
|
|
240
240
|
end
|
|
241
241
|
|
|
242
242
|
def test_meta_parse_noarg
|
|
243
|
-
m = NVDFeedScraper::Meta.new('https://
|
|
243
|
+
m = NVDFeedScraper::Meta.new('https://nvd.nist.gov/feeds/json/cve/1.1/nvdcve-1.1-2015.meta')
|
|
244
244
|
assert_equal(0, m.parse, 'parse method return nothing')
|
|
245
245
|
end
|
|
246
246
|
|
|
247
247
|
def test_meta_parse_witharg
|
|
248
248
|
m = NVDFeedScraper::Meta.new
|
|
249
|
-
meta_url = 'https://
|
|
249
|
+
meta_url = 'https://nvd.nist.gov/feeds/json/cve/1.1/nvdcve-1.1-2015.meta'
|
|
250
250
|
assert_equal(0, m.parse(meta_url), 'parse method return nothing')
|
|
251
251
|
end
|
|
252
252
|
|
|
253
253
|
def test_meta_url_setter
|
|
254
254
|
m = NVDFeedScraper::Meta.new
|
|
255
|
-
meta_url = 'https://
|
|
255
|
+
meta_url = 'https://nvd.nist.gov/feeds/json/cve/1.1/nvdcve-1.1-2015.meta'
|
|
256
256
|
assert_equal(meta_url, m.url = meta_url, 'the meta URL is not set correctly')
|
|
257
257
|
end
|
|
258
258
|
|
|
259
259
|
def test_meta_attributes
|
|
260
260
|
m = NVDFeedScraper::Meta.new
|
|
261
|
-
meta_url = 'https://
|
|
261
|
+
meta_url = 'https://nvd.nist.gov/feeds/json/cve/1.1/nvdcve-1.1-2015.meta'
|
|
262
262
|
m.url = meta_url
|
|
263
263
|
m.parse
|
|
264
264
|
# Test gz_size
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: nvd_feed_api
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Alexandre ZANNI
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2022-01-31 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: archive-zip
|
|
@@ -16,154 +16,48 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '0.
|
|
19
|
+
version: '0.11'
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '0.
|
|
26
|
+
version: '0.11'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: nokogiri
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
31
|
- - "~>"
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: '1.
|
|
33
|
+
version: '1.11'
|
|
34
34
|
type: :runtime
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
38
|
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: '1.
|
|
40
|
+
version: '1.11'
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: oj
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
44
44
|
requirements:
|
|
45
|
-
- - "
|
|
46
|
-
- !ruby/object:Gem::Version
|
|
47
|
-
version: '3.3'
|
|
48
|
-
type: :runtime
|
|
49
|
-
prerelease: false
|
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
-
requirements:
|
|
52
|
-
- - "~>"
|
|
53
|
-
- !ruby/object:Gem::Version
|
|
54
|
-
version: '3.3'
|
|
55
|
-
- !ruby/object:Gem::Dependency
|
|
56
|
-
name: bundler
|
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
|
58
|
-
requirements:
|
|
59
|
-
- - "~>"
|
|
60
|
-
- !ruby/object:Gem::Version
|
|
61
|
-
version: '1.15'
|
|
62
|
-
type: :development
|
|
63
|
-
prerelease: false
|
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
-
requirements:
|
|
66
|
-
- - "~>"
|
|
67
|
-
- !ruby/object:Gem::Version
|
|
68
|
-
version: '1.15'
|
|
69
|
-
- !ruby/object:Gem::Dependency
|
|
70
|
-
name: commonmarker
|
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
|
72
|
-
requirements:
|
|
73
|
-
- - "~>"
|
|
74
|
-
- !ruby/object:Gem::Version
|
|
75
|
-
version: '0.17'
|
|
76
|
-
type: :development
|
|
77
|
-
prerelease: false
|
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
-
requirements:
|
|
80
|
-
- - "~>"
|
|
81
|
-
- !ruby/object:Gem::Version
|
|
82
|
-
version: '0.17'
|
|
83
|
-
- !ruby/object:Gem::Dependency
|
|
84
|
-
name: github-markup
|
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
|
86
|
-
requirements:
|
|
87
|
-
- - "~>"
|
|
88
|
-
- !ruby/object:Gem::Version
|
|
89
|
-
version: '1.6'
|
|
90
|
-
type: :development
|
|
91
|
-
prerelease: false
|
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
-
requirements:
|
|
94
|
-
- - "~>"
|
|
95
|
-
- !ruby/object:Gem::Version
|
|
96
|
-
version: '1.6'
|
|
97
|
-
- !ruby/object:Gem::Dependency
|
|
98
|
-
name: minitest
|
|
99
|
-
requirement: !ruby/object:Gem::Requirement
|
|
100
|
-
requirements:
|
|
101
|
-
- - "~>"
|
|
45
|
+
- - ">="
|
|
102
46
|
- !ruby/object:Gem::Version
|
|
103
|
-
version:
|
|
104
|
-
|
|
105
|
-
prerelease: false
|
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
-
requirements:
|
|
108
|
-
- - "~>"
|
|
109
|
-
- !ruby/object:Gem::Version
|
|
110
|
-
version: '5.10'
|
|
111
|
-
- !ruby/object:Gem::Dependency
|
|
112
|
-
name: rake
|
|
113
|
-
requirement: !ruby/object:Gem::Requirement
|
|
114
|
-
requirements:
|
|
115
|
-
- - "~>"
|
|
116
|
-
- !ruby/object:Gem::Version
|
|
117
|
-
version: '12.3'
|
|
118
|
-
type: :development
|
|
119
|
-
prerelease: false
|
|
120
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
-
requirements:
|
|
122
|
-
- - "~>"
|
|
123
|
-
- !ruby/object:Gem::Version
|
|
124
|
-
version: '12.3'
|
|
125
|
-
- !ruby/object:Gem::Dependency
|
|
126
|
-
name: redcarpet
|
|
127
|
-
requirement: !ruby/object:Gem::Requirement
|
|
128
|
-
requirements:
|
|
129
|
-
- - "~>"
|
|
130
|
-
- !ruby/object:Gem::Version
|
|
131
|
-
version: '3.4'
|
|
132
|
-
type: :development
|
|
133
|
-
prerelease: false
|
|
134
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
135
|
-
requirements:
|
|
136
|
-
- - "~>"
|
|
47
|
+
version: 3.7.8
|
|
48
|
+
- - "<"
|
|
137
49
|
- !ruby/object:Gem::Version
|
|
138
|
-
version: '
|
|
139
|
-
|
|
140
|
-
name: rubocop
|
|
141
|
-
requirement: !ruby/object:Gem::Requirement
|
|
142
|
-
requirements:
|
|
143
|
-
- - "~>"
|
|
144
|
-
- !ruby/object:Gem::Version
|
|
145
|
-
version: '0.51'
|
|
146
|
-
type: :development
|
|
50
|
+
version: '4'
|
|
51
|
+
type: :runtime
|
|
147
52
|
prerelease: false
|
|
148
53
|
version_requirements: !ruby/object:Gem::Requirement
|
|
149
54
|
requirements:
|
|
150
|
-
- - "
|
|
55
|
+
- - ">="
|
|
151
56
|
- !ruby/object:Gem::Version
|
|
152
|
-
version:
|
|
153
|
-
-
|
|
154
|
-
name: yard
|
|
155
|
-
requirement: !ruby/object:Gem::Requirement
|
|
156
|
-
requirements:
|
|
157
|
-
- - "~>"
|
|
158
|
-
- !ruby/object:Gem::Version
|
|
159
|
-
version: '0.9'
|
|
160
|
-
type: :development
|
|
161
|
-
prerelease: false
|
|
162
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
163
|
-
requirements:
|
|
164
|
-
- - "~>"
|
|
57
|
+
version: 3.7.8
|
|
58
|
+
- - "<"
|
|
165
59
|
- !ruby/object:Gem::Version
|
|
166
|
-
version: '
|
|
60
|
+
version: '4'
|
|
167
61
|
description: A simple API for NVD CVE feeds
|
|
168
62
|
email: alexandre.zanni@europe.com
|
|
169
63
|
executables:
|
|
@@ -173,6 +67,7 @@ executables:
|
|
|
173
67
|
extensions: []
|
|
174
68
|
extra_rdoc_files: []
|
|
175
69
|
files:
|
|
70
|
+
- ".github/FUNDING.yml"
|
|
176
71
|
- ".gitignore"
|
|
177
72
|
- ".gitlab-ci.yml"
|
|
178
73
|
- ".gitlab/CONTRIBUTING.md"
|
|
@@ -180,8 +75,10 @@ files:
|
|
|
180
75
|
- ".gitlab/issue_templates/Feature_proposal.md"
|
|
181
76
|
- ".gitlab/merge_request_templates/MR.md"
|
|
182
77
|
- ".rubocop.yml"
|
|
78
|
+
- ".tool-versions"
|
|
183
79
|
- ".yardopts"
|
|
184
80
|
- Gemfile
|
|
81
|
+
- Gemfile.lock
|
|
185
82
|
- LICENSE.txt
|
|
186
83
|
- README.md
|
|
187
84
|
- Rakefile
|
|
@@ -197,6 +94,7 @@ files:
|
|
|
197
94
|
- pages/EXAMPLES.md
|
|
198
95
|
- pages/FEATURES.md
|
|
199
96
|
- pages/INSTALL.md
|
|
97
|
+
- renovate.json
|
|
200
98
|
- test/test_nvd_feed_api.rb
|
|
201
99
|
homepage: https://noraj.gitlab.io/nvd_api/
|
|
202
100
|
licenses:
|
|
@@ -209,24 +107,27 @@ metadata:
|
|
|
209
107
|
homepage_uri: https://noraj.gitlab.io/nvd_api/
|
|
210
108
|
source_code_uri: https://gitlab.com/noraj/nvd_api/tree/master
|
|
211
109
|
wiki_uri: https://gitlab.com/noraj/nvd_api/wikis/home
|
|
212
|
-
|
|
110
|
+
rubygems_mfa_required: 'true'
|
|
111
|
+
post_install_message:
|
|
213
112
|
rdoc_options: []
|
|
214
113
|
require_paths:
|
|
215
114
|
- lib
|
|
216
115
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
217
116
|
requirements:
|
|
218
|
-
- - "
|
|
117
|
+
- - ">="
|
|
118
|
+
- !ruby/object:Gem::Version
|
|
119
|
+
version: 2.7.0
|
|
120
|
+
- - "<"
|
|
219
121
|
- !ruby/object:Gem::Version
|
|
220
|
-
version: '2
|
|
122
|
+
version: '3.2'
|
|
221
123
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
222
124
|
requirements:
|
|
223
125
|
- - ">="
|
|
224
126
|
- !ruby/object:Gem::Version
|
|
225
127
|
version: '0'
|
|
226
128
|
requirements: []
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
signing_key:
|
|
129
|
+
rubygems_version: 3.3.3
|
|
130
|
+
signing_key:
|
|
230
131
|
specification_version: 4
|
|
231
132
|
summary: API for NVD CVE feeds
|
|
232
133
|
test_files:
|