cve_schema 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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