cve_schema 0.1.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 (70) hide show
  1. checksums.yaml +7 -0
  2. data/.document +3 -0
  3. data/.github/workflows/ruby.yml +28 -0
  4. data/.gitignore +6 -0
  5. data/.rspec +1 -0
  6. data/.yardopts +1 -0
  7. data/ChangeLog.md +26 -0
  8. data/Gemfile +14 -0
  9. data/LICENSE.txt +20 -0
  10. data/README.md +50 -0
  11. data/Rakefile +23 -0
  12. data/benchmark.rb +47 -0
  13. data/cve_schema.gemspec +61 -0
  14. data/gemspec.yml +19 -0
  15. data/lib/cve_schema.rb +2 -0
  16. data/lib/cve_schema/cve.rb +257 -0
  17. data/lib/cve_schema/cve/affects.rb +55 -0
  18. data/lib/cve_schema/cve/configuration.rb +14 -0
  19. data/lib/cve_schema/cve/credit.rb +14 -0
  20. data/lib/cve_schema/cve/data_meta.rb +185 -0
  21. data/lib/cve_schema/cve/description.rb +24 -0
  22. data/lib/cve_schema/cve/exploit.rb +14 -0
  23. data/lib/cve_schema/cve/has_lang_value.rb +93 -0
  24. data/lib/cve_schema/cve/id.rb +79 -0
  25. data/lib/cve_schema/cve/impact.rb +75 -0
  26. data/lib/cve_schema/cve/impact/cvss_v2.rb +318 -0
  27. data/lib/cve_schema/cve/impact/cvss_v3.rb +388 -0
  28. data/lib/cve_schema/cve/na.rb +8 -0
  29. data/lib/cve_schema/cve/problem_type.rb +56 -0
  30. data/lib/cve_schema/cve/product.rb +79 -0
  31. data/lib/cve_schema/cve/reference.rb +82 -0
  32. data/lib/cve_schema/cve/solution.rb +14 -0
  33. data/lib/cve_schema/cve/source.rb +75 -0
  34. data/lib/cve_schema/cve/timeline.rb +65 -0
  35. data/lib/cve_schema/cve/timestamp.rb +25 -0
  36. data/lib/cve_schema/cve/vendor.rb +83 -0
  37. data/lib/cve_schema/cve/version.rb +126 -0
  38. data/lib/cve_schema/cve/work_around.rb +14 -0
  39. data/lib/cve_schema/exceptions.rb +20 -0
  40. data/lib/cve_schema/version.rb +6 -0
  41. data/spec/affects_spec.rb +28 -0
  42. data/spec/configuration_spec.rb +6 -0
  43. data/spec/credit_spec.rb +6 -0
  44. data/spec/cve_schema_spec.rb +8 -0
  45. data/spec/cve_spec.rb +414 -0
  46. data/spec/data_meta_spec.rb +167 -0
  47. data/spec/description.rb +24 -0
  48. data/spec/exploit_spec.rb +6 -0
  49. data/spec/fixtures/CVE-2020-1994.json +140 -0
  50. data/spec/fixtures/CVE-2020-2005.json +152 -0
  51. data/spec/fixtures/CVE-2020-2050.json +233 -0
  52. data/spec/fixtures/CVE-2020-4700.json +99 -0
  53. data/spec/has_lang_value_spec.rb +56 -0
  54. data/spec/id_spec.rb +91 -0
  55. data/spec/impact/cvss_v3_spec.rb +118 -0
  56. data/spec/impact_spec.rb +45 -0
  57. data/spec/na_spec.rb +14 -0
  58. data/spec/problem_type_spec.rb +26 -0
  59. data/spec/product_spec.rb +73 -0
  60. data/spec/reference_spec.rb +70 -0
  61. data/spec/shared_examples.rb +19 -0
  62. data/spec/solution_spec.rb +6 -0
  63. data/spec/source_spec.rb +84 -0
  64. data/spec/spec_helper.rb +4 -0
  65. data/spec/timeline_spec.rb +86 -0
  66. data/spec/timestamp_spec.rb +24 -0
  67. data/spec/vendor_spec.rb +73 -0
  68. data/spec/version_spec.rb +104 -0
  69. data/spec/work_around_spec.rb +6 -0
  70. metadata +133 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 9b2fd7358b100af7647547bef7243cc4ad90e7808a569250e60823aec3ab5ac8
4
+ data.tar.gz: 930861c8ee83113009e4fa30461d87a85cdb6cffef2830c5af787fe188017385
5
+ SHA512:
6
+ metadata.gz: ffd0c2410c39c7ce6709edfaf8967d43760f9d2b334b81d2f2743733857cc6776aa3301fe205ae96b03054f14801a80ee069126b57c89c6bcc15d73ad6311fd7
7
+ data.tar.gz: 34f0096b85d8e75bd72181e3a584f94f595c5ecd37d75c653ed5e0fd1c97905124d4b508feb4709eafac7c34812af006bd3d504696f6a17e34e2b11b5addcc7d
@@ -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.4
13
+ # - 2.5
14
+ # - 2.6
15
+ - 2.7
16
+ - 3.0
17
+ # - jruby
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
@@ -0,0 +1,6 @@
1
+ /.bundle
2
+ /.yardoc/
3
+ /Gemfile.lock
4
+ /doc/
5
+ /pkg/
6
+ /vendor/cache/*.gem
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour --format documentation
@@ -0,0 +1 @@
1
+ --markup markdown --title "cve_schema Documentation" --protected
@@ -0,0 +1,26 @@
1
+ ### 0.1.0 / 2021-01-14
2
+
3
+ * Initial release:
4
+ * Supports [CVE JSON Schema v4.0].
5
+ * [ruby] >= 2.7.0
6
+ * Added {CVESchema::CVE}.
7
+ * Added {CVESchema::CVE::Affects}.
8
+ * Added {CVESchema::CVE::Configuration}.
9
+ * Added {CVESchema::CVE::Credit}.
10
+ * Added {CVESchema::CVE::DataMeta}.
11
+ * Added {CVESchema::CVE::Description}.
12
+ * Added {CVESchema::CVE::Exploit}.
13
+ * Added {CVESchema::CVE::ID}.
14
+ * Added {CVESchema::CVE::Impact}.
15
+ * Added {CVESchema::CVE::ProblemType}.
16
+ * Added {CVESchema::CVE::Product}.
17
+ * Added {CVESchema::CVE::Reference}.
18
+ * Added {CVESchema::CVE::Solution}.
19
+ * Added {CVESchema::CVE::Source}.
20
+ * Added {CVESchema::CVE::Timeline}.
21
+ * Added {CVESchema::CVE::Vendor}.
22
+ * Added {CVESchema::CVE::Version}.
23
+ * Added {CVESchema::CVE::WorkAround}.
24
+
25
+ [CVE JSON Schema v4.0]: https://github.com/CVEProject/cve-schema/blob/master/schema/v4.0/DRAFT-JSON-file-format-v4.md
26
+ [ruby]: https://www.ruby-lang.org/
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem 'rake'
7
+ gem 'rubygems-tasks', '~> 0.2'
8
+
9
+ gem 'json'
10
+ gem 'rspec', '~> 3.0'
11
+
12
+ gem 'kramdown'
13
+ gem 'yard', '~> 0.9'
14
+ end
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2020-2021 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
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,50 @@
1
+ # cve_schema
2
+
3
+ * [Homepage](https://github.com/postmodern/cve_schema#readme)
4
+ * [Issues](https://github.com/postmodern/cve_schema/issues)
5
+ * [Documentation](http://rubydoc.info/gems/cve_schema/frames)
6
+ * [Email](mailto:postmodern.mod3 at gmail.com)
7
+
8
+ ## Description
9
+
10
+ {CVESchema} provides common classes for CVE data and loading it from JSON.
11
+
12
+ ## Features
13
+
14
+ * Supports [CVE JSON Schema v4.0]
15
+ * Uses Plain-Old-Ruby-Objects (PORO) for speed!
16
+ * No runtime dependencies.
17
+
18
+ ## Examples
19
+
20
+ require 'cve_schema'
21
+ include CVESchema
22
+
23
+ json = JSON.parse(File.read('path/to/CVE-YYYY-XXXX.json'))
24
+ cve = CVE.load(json)
25
+
26
+ ## Requirements
27
+
28
+ * [ruby] >= 2.7.0
29
+
30
+ ## Install
31
+
32
+ $ gem install cve_schema
33
+
34
+ ## Benchmark
35
+
36
+ Loading all 192879 JSON files into memory. This may take a while ...
37
+ Mapping all 192879 to CVESchema::CVE objects ...
38
+
39
+ Total: 12.310090 0.275629 12.585719 ( 12.664896)
40
+ Avg: 0.000064 0.000001 0.000065 ( 0.000066)
41
+
42
+ ## Copyright
43
+
44
+ Copyright (c) 2020-2021 Hal Brodigan
45
+
46
+ See {file:LICENSE.txt} for details.
47
+
48
+ [CVE JSON Schema v4.0]: https://github.com/CVEProject/cve-schema/blob/master/schema/v4.0/DRAFT-JSON-file-format-v4.md
49
+
50
+ [ruby]: https://www.ruby-lang.org/
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+
5
+ begin
6
+ require 'bundler/setup'
7
+ rescue LoadError => e
8
+ abort e.message
9
+ end
10
+
11
+ require 'rake'
12
+ require 'rubygems/tasks'
13
+ Gem::Tasks.new
14
+
15
+ require 'rspec/core/rake_task'
16
+ RSpec::Core::RakeTask.new
17
+
18
+ task :test => :spec
19
+ task :default => :spec
20
+
21
+ require 'yard'
22
+ YARD::Rake::YardocTask.new
23
+ task :doc => :yard
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'cve_schema/cve'
5
+ require 'json'
6
+ require 'benchmark'
7
+
8
+ CVELIST = ENV.fetch('CVELIST',File.join(Gem.user_home,'src','cvelist'))
9
+
10
+ unless File.directory?(CVELIST)
11
+ $stderr.puts "#{CVELIST} does not exist!"
12
+ $stderr.puts "Please run: git clone https://github.com/CVEProject/cvelist #{CVELIST}"
13
+ exit -1
14
+ end
15
+
16
+ begin
17
+ json_files = Dir.glob(File.join(CVELIST,'**','**','CVE-*.json'))
18
+ n = json_files.length
19
+
20
+ puts "Loading all #{n} JSON files into memory. This may take a while ..."
21
+
22
+ all_json = {}
23
+ json_files.each do |path|
24
+ all_json[path] = JSON.parse(File.read(path))
25
+ end
26
+
27
+ puts "Mapping all #{n} to #{CVESchema::CVE} objects ..."
28
+
29
+ results = Benchmark.measure do
30
+ all_json.each do |path,json|
31
+ begin
32
+ CVESchema::CVE.from_json(json)
33
+ rescue CVESchema::InvalidJSON
34
+ # ignore
35
+ rescue => error
36
+ $stderr.puts "error encountered while parsing #{path}"
37
+ raise(error)
38
+ end
39
+ end
40
+ end
41
+
42
+ puts
43
+ puts "Total:\t#{results}"
44
+ puts "Avg:\t#{results / n}"
45
+ rescue Interrupt
46
+ exit 130
47
+ 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 'cve_schema/version'
14
+ CVESchema::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,19 @@
1
+ name: cve_schema
2
+ summary: Common classes for CVE data
3
+ description: |
4
+ CVESchema provides common classes for CVE data and loading it from JSON.
5
+ license: MIT
6
+ authors: Postmodern
7
+ email: postmodern.mod3@gmail.com
8
+ homepage: https://github.com/postmodern/cve_schema.rb#readme
9
+
10
+ metadata:
11
+ documentation_uri: https://rubydoc.info/gems/cve_schema
12
+ source_code_uri: https://github.com/postmodern/cve_schema.rb
13
+ bug_tracker_uri: https://github.com/postmodern/cve_schema.rb/issues
14
+ changelog_uri: https://github.com/postmodern/cve_schema.rb/blob/main/ChangeLog.md
15
+
16
+ required_ruby_version: ">= 2.7.0"
17
+
18
+ development_dependencies:
19
+ bundler: ~> 2.0
@@ -0,0 +1,2 @@
1
+ require 'cve_schema/cve'
2
+ require 'cve_schema/version'
@@ -0,0 +1,257 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cve_schema/exceptions'
4
+ require 'cve_schema/cve/data_meta'
5
+ require 'cve_schema/cve/affects'
6
+ require 'cve_schema/cve/configuration'
7
+ require 'cve_schema/cve/problem_type'
8
+ require 'cve_schema/cve/reference'
9
+ require 'cve_schema/cve/description'
10
+ require 'cve_schema/cve/exploit'
11
+ require 'cve_schema/cve/credit'
12
+ require 'cve_schema/cve/impact'
13
+ require 'cve_schema/cve/solution'
14
+ require 'cve_schema/cve/source'
15
+ require 'cve_schema/cve/work_around'
16
+ require 'cve_schema/cve/timeline'
17
+
18
+ module CVESchema
19
+ #
20
+ # Represents a `"cve"` JSON object.
21
+ #
22
+ class CVE
23
+
24
+ DATA_TYPES = {
25
+ 'CVE' => :CVE,
26
+ 'CNA' => :CNA,
27
+ 'CVEMENTOR' => :CVEMENTOR
28
+ }
29
+
30
+ # @return [:CVE, :CNA, :CVEMENTOR]
31
+ attr_reader :data_type
32
+
33
+ DATA_FORMAT = {
34
+ 'MITRE' => :MITRE
35
+ }
36
+
37
+ # @return [:MITRE]
38
+ attr_reader :data_format
39
+
40
+ DATA_VERSIONS = {
41
+ '4.0' => :"4.0"
42
+ }
43
+
44
+ # @return [:"4.0"]
45
+ attr_reader :data_version
46
+
47
+ # @return [DataMeta]
48
+ attr_reader :data_meta
49
+
50
+ alias metadata data_meta
51
+
52
+ # @return [Affects, nil]
53
+ attr_reader :affects
54
+
55
+ # @return [Array<Configuration>]
56
+ attr_reader :configuration
57
+
58
+ alias configurations configuration
59
+
60
+ # @return [ProblemType]
61
+ attr_reader :problemtype
62
+
63
+ alias problem_type problemtype
64
+ alias problem_types problemtype
65
+
66
+ # @return [Array<Reference>]
67
+ attr_reader :references
68
+
69
+ # @return [Array<Description>]
70
+ attr_reader :description
71
+
72
+ alias descriptions description
73
+
74
+ # @return [Array<Exploit>]
75
+ attr_reader :exploit
76
+
77
+ alias exploits exploit
78
+
79
+ # @return [Array<Credit>]
80
+ attr_reader :credit
81
+
82
+ alias credits credit
83
+
84
+ # @return [Impact, nil]
85
+ attr_reader :impact
86
+
87
+ # @return [Array<Solution>]
88
+ attr_reader :solution
89
+
90
+ alias solutions solution
91
+
92
+ # @return [Source, nil]
93
+ attr_reader :source
94
+
95
+ # @return [Array<WorkAround>]
96
+ attr_reader :work_around
97
+
98
+ alias work_arounds work_around
99
+
100
+ # @return [Array<Timeline>]
101
+ attr_reader :timeline
102
+
103
+ #
104
+ # Initializes the CVE.
105
+ #
106
+ # @param [:CVE, :CNA, :CVEMENTOR] data_type
107
+ #
108
+ # @param [:MITRE] data_format
109
+ #
110
+ # @param [:"4.0"] data_version
111
+ #
112
+ # @param [DataMeta] data_meta
113
+ #
114
+ # @param [Affects, nil] affects
115
+ #
116
+ # @param [Array<Configuration>] configuration
117
+ #
118
+ # @param [ArrayProblemType>] problemtype
119
+ #
120
+ # @param [Array<Reference>] references
121
+ #
122
+ # @param [Array<Description>] description
123
+ #
124
+ # @param [Array<Exploit>] exploit
125
+ #
126
+ # @param [Array<Credit>] credit
127
+ #
128
+ # @param [Array<Impact>] impact
129
+ #
130
+ # @param [Array<Solution>] solution
131
+ #
132
+ # @param [Source, nil] source
133
+ #
134
+ # @param [Array<WorkAround>] work_around
135
+ #
136
+ # @param [Array<Timeline>] timeline
137
+ #
138
+ # @api semipublic
139
+ #
140
+ def initialize(data_type: , data_format: , data_version: , data_meta: ,
141
+ affects: nil,
142
+ configuration: [],
143
+ problemtype: [],
144
+ references: [],
145
+ description: [],
146
+ exploit: [],
147
+ credit: [],
148
+ impact: nil,
149
+ solution: [],
150
+ source: nil,
151
+ work_around: [],
152
+ timeline: []
153
+ )
154
+ @data_type = data_type
155
+ @data_format = data_format
156
+ @data_version = data_version
157
+
158
+ @data_meta = data_meta
159
+ @affects = affects
160
+ @configuration = configuration
161
+ @problemtype = problemtype
162
+ @references = references
163
+ @description = description
164
+ @exploit = exploit
165
+ @credit = credit
166
+ @impact = impact
167
+ @solution = solution
168
+ @source = source
169
+ @work_around = work_around
170
+ @timeline = timeline
171
+ end
172
+
173
+ #
174
+ # Maps the JSON Hash into a Symbols Hash for {#initialize}.
175
+ #
176
+ # @param [Hash{String => Object}] json
177
+ # The parsed JSON.
178
+ #
179
+ # @return [Hash{Symbol => Object}]
180
+ # The maped Symbol Hash.
181
+ #
182
+ # @raise [MissingJSONKey]
183
+ # The `"data_type"`, `"data_format"`, `"data_version"`, or
184
+ # `"CVE_data_key"` JSON keys were missing.
185
+ #
186
+ # @api semipublic
187
+ #
188
+ def self.from_json(json)
189
+ {
190
+ data_type: if (data_type = json['data_type'])
191
+ DATA_TYPES.fetch(data_type) do
192
+ raise UnknownJSONValue.new('data_type',data_type)
193
+ end
194
+ else
195
+ raise MissingJSONKey.new('data_type')
196
+ end,
197
+
198
+ data_format: if (data_format = json['data_format'])
199
+ DATA_FORMAT.fetch(data_format) do
200
+ raise UnknownJSONValue.new('data_format',data_format)
201
+ end
202
+ else
203
+ raise MissingJSONKey.new('data_format')
204
+ end,
205
+
206
+ data_version: if (data_version = json['data_version'])
207
+ DATA_VERSIONS.fetch(data_version) do
208
+ raise UnknownJSONValue.new('data_version',data_version)
209
+ end
210
+ else
211
+ raise MissingJSONKey.new('data_version')
212
+ end,
213
+
214
+ data_meta: if (cve_data_meta = json['CVE_data_meta'])
215
+ DataMeta.load(cve_data_meta)
216
+ else
217
+ raise MissingJSONKey.new('CVE_data_meta')
218
+ end,
219
+
220
+ affects: json['affects'] && Affects.load(json['affects']),
221
+ configuration: Array(json['configuration']).map(&Configuration.method(:load)),
222
+ problemtype: Array(json['problemtype'] && json['problemtype']['problemtype_data']).map(&ProblemType.method(:load)),
223
+
224
+ references: Array(json['references'] && json['references']['reference_data']).map(&Reference.method(:load)),
225
+
226
+ description: Array(json['description'] && json['description']['description_data']).map(&Description.method(:load)),
227
+
228
+ exploit: Array(json['exploit']).map(&Exploit.method(:load)),
229
+ credit: Array(json['credit']).map(&Credit.method(:load)),
230
+ impact: json['impact'] && Impact.load(json['impact']),
231
+ solution: Array(json['solution']).map(&Solution.method(:load)),
232
+ source: json['source'] && Source.load(json['source']),
233
+ work_around: Array(json['work_around']).map(&WorkAround.method(:load)),
234
+ timeline: Array(json['timeline']).map(&Timeline.method(:load))
235
+ }
236
+ end
237
+
238
+ #
239
+ # Loads the CVE data from parsed JSON.
240
+ #
241
+ # @param [Hash{String => Object}] json
242
+ # The parsed JSON.
243
+ #
244
+ # @return [self]
245
+ #
246
+ # @raise [MissingJSONKey]
247
+ # The `"data_type"`, `"data_format"`, `"data_version"`, or
248
+ # `"CVE_data_key"` JSON keys were missing.
249
+ #
250
+ # @api public
251
+ #
252
+ def self.load(json)
253
+ new(**from_json(json))
254
+ end
255
+
256
+ end
257
+ end