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,75 @@
1
+ require 'cve_schema/cve/impact/cvss_v2'
2
+ require 'cve_schema/cve/impact/cvss_v3'
3
+
4
+ module CVESchema
5
+ class CVE
6
+ class Impact
7
+
8
+ # @return [CVSSv2, nil]
9
+ attr_reader :cvssv2
10
+
11
+ alias cvss_v2 cvssv2
12
+
13
+ # @return [CVSSv3, nil]
14
+ attr_reader :cvssv3
15
+
16
+ alias cvss_v3 cvssv3
17
+
18
+ #
19
+ # Initializes the impact object.
20
+ #
21
+ # @param [CVSSv2, nil] cvssv2
22
+ # The CVSSv2 object.
23
+ #
24
+ # @param [CVSSv3, nil] cvssv3
25
+ # The CVSSv3 object.
26
+ #
27
+ def initialize(cvssv2: nil, cvssv3: nil)
28
+ @cvssv2 = cvssv2
29
+ @cvssv3 = cvssv3
30
+ end
31
+
32
+ #
33
+ # Maps the parsed JSON to a Symbol Hash for {#initialize}.
34
+ #
35
+ # @param [Hash{String => Object}] json
36
+ # The parsed JSON.
37
+ #
38
+ # @return [Hash{Symbol => Object}]
39
+ # The mapped Symbol Hash.
40
+ #
41
+ # @api semipublic
42
+ #
43
+ def self.from_json(json)
44
+ # HACK: the "impact" value is often an Array containing a single Hash
45
+ hash = case json
46
+ when Hash then json
47
+ when Array then json[0]
48
+ else
49
+ raise(InvalidJSON,'"impact" is neither a Hash or Array')
50
+ end
51
+
52
+ {
53
+ cvssv2: hash['cvssv2'] && CVSSv2.load(hash['cvssv2']),
54
+ cvssv3: hash['cvssv3'] && CVSSv3.load(hash['cvssv3'])
55
+ }
56
+ end
57
+
58
+ #
59
+ # Loads the impact object from the parsed JSON.
60
+ #
61
+ # @param [Hash{String => Object}] json
62
+ # The parsed JSON.
63
+ #
64
+ # @return [Impact]
65
+ # The loaded impact object.
66
+ #
67
+ # @api semipublic
68
+ #
69
+ def self.load(json)
70
+ new(**from_json(json))
71
+ end
72
+
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,318 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CVESchema
4
+ class CVE
5
+ class Impact
6
+ class CVSSv2
7
+
8
+ class BM
9
+
10
+ AV = {'L' => :L, 'A' => :A, 'N' => :N}
11
+
12
+ # The Access Vector.
13
+ #
14
+ # @return [:L, :A, :N]
15
+ attr_reader :av
16
+
17
+ AC = {'H' => :H, 'M' => :M, 'L' => :L}
18
+
19
+ # The Access Complexity.
20
+ #
21
+ # @return [:H, :M, :L]
22
+ attr_reader :ac
23
+
24
+ AU = {'M' => :M, 'S' => :S, 'N' => :N}
25
+
26
+ # The Authentication
27
+ #
28
+ # @return [:M, :S, :N]
29
+ attr_reader :au
30
+
31
+ C = {'N' => :N, 'P' => :P, 'C' => :C}
32
+
33
+ # The Confidentiality impact.
34
+ #
35
+ # @return [:N, :P, :C]
36
+ attr_reader :c
37
+
38
+ I = {'N' => :N, 'P' => :P, 'C' => :C}
39
+
40
+ # The Integrity impact.
41
+ #
42
+ # @return [:N, :P, :C]
43
+ attr_reader :i
44
+
45
+ A = {'N' => :N, 'P' => :P, 'C' => :C}
46
+
47
+ # The Availability impact.
48
+ #
49
+ # @return [:N, :P, :C]
50
+ attr_reader :a
51
+
52
+ # The CVSSv2 Base Metrics Group score assuming all elements are present.
53
+ #
54
+ # @return [String]
55
+ attr_reader :score
56
+
57
+ def initialize(av: nil, ac: nil, au: nil, c: nil, i: nil, a: nil,
58
+ score: nil)
59
+ @av = av
60
+ @ac = ac
61
+ @c = c
62
+ @i = i
63
+ @a = a
64
+ @score = score
65
+ end
66
+
67
+ #
68
+ # Maps the parsed JSON to a Symbol Hash for {#initialize}.
69
+ #
70
+ # @param [Hash{String => Object}] json
71
+ # The parsed JSON.
72
+ #
73
+ # @return [Hash{Symbol => Object}]
74
+ # The mapped Symbol Hash.
75
+ #
76
+ def self.from_json(json)
77
+ {
78
+ av: AV[json['AV']],
79
+ ac: AC[json['AC']],
80
+ au: AU[json['AU']],
81
+ c: C[json['C']],
82
+ i: I[json['I']],
83
+ a: A[json['A']],
84
+
85
+ score: json['SCORE']
86
+ }
87
+ end
88
+
89
+ #
90
+ # Loads the BM object from the parsed JSON.
91
+ #
92
+ # @param [Hash{String => Object}] json
93
+ # The parsed JSON.
94
+ #
95
+ # @return [self]
96
+ # The loaded BM object.
97
+ #
98
+ def self.load(json)
99
+ new(**from_json(json))
100
+ end
101
+
102
+ end
103
+
104
+ # @return [BM, nil]
105
+ attr_reader :bm
106
+
107
+ class TM
108
+
109
+ E = {'U' => :U, 'POC' => :POC, 'F' => :F, 'H' => :H, 'ND' => :ND}
110
+
111
+ # Exploitability
112
+ #
113
+ # @return [:U, :POC, :F, :H, :ND]
114
+ attr_reader :e
115
+
116
+ RL = {'OF' => :OF, 'TF' => :TF, 'W' => :W, 'U' => :U, 'ND' => :ND}
117
+
118
+ # Remediation Level.
119
+ #
120
+ # @return [:OF, :TF, :W, :U, :ND]
121
+ attr_reader :rl
122
+
123
+ RC = {'UC' => :UC, 'UR' => :UR, 'C' => :C, 'ND' => :ND}
124
+
125
+ # Report Confidence.
126
+ #
127
+ # @return [:UC, :UR, :C, :ND]
128
+ attr_reader :rc
129
+
130
+ # The CVSSv2 Temporal Metrics Group score assuming all elements are present.
131
+ #
132
+ # @return [String, nil]
133
+ attr_reader :score
134
+
135
+ def initialize(e: nil, rl: nil, rc: nil, score: nil)
136
+ @e = e
137
+ @rl = rl
138
+ @rc = rc
139
+ @score = score
140
+ end
141
+
142
+ #
143
+ # Maps the parsed JSON to a Symbol Hash for {#initialize}.
144
+ #
145
+ # @param [Hash{String => Object}] json
146
+ # The parsed JSON.
147
+ #
148
+ # @return [Hash{Symbol => Object}]
149
+ # The mapped Symbol Hash.
150
+ #
151
+ def self.from_json(json)
152
+ {
153
+ e: E[json['E']],
154
+ rl: RL[json['RL']],
155
+ rc: RC[json['RC']],
156
+
157
+ score: json['SCORE']
158
+ }
159
+ end
160
+
161
+ #
162
+ # Loads the TM object from the parsed JSON.
163
+ #
164
+ # @param [Hash{String => Object}] json
165
+ # The parsed JSON.
166
+ #
167
+ # @return [self]
168
+ # The loaded TM object.
169
+ #
170
+ def self.load(json)
171
+ new(**from_json(json))
172
+ end
173
+
174
+ end
175
+
176
+ # The Temporal Metrics Group.
177
+ #
178
+ # @return [TM, nil]
179
+ attr_reader :tm
180
+
181
+ class EM
182
+
183
+ CDP = {
184
+ 'N' => :N,
185
+ 'L' => :L,
186
+ 'LM' => :LM,
187
+ 'MH' => :MH,
188
+ 'H' => :H,
189
+ 'ND' => :ND
190
+ }
191
+
192
+ # The Collateral Damage Potential.
193
+ #
194
+ # @return [:N, :L, :LM, :MH, :H, :ND]
195
+ attr_reader :cdp
196
+
197
+ TD = {'N' => :N, 'L' => :L, 'M' => :M, 'H' => :H, 'ND' => :ND}
198
+
199
+ # The Target Distribution.
200
+ #
201
+ # @return [:N, :L, :M, :H, :ND]
202
+ attr_reader :td
203
+
204
+ CR = {'L' => :L, 'M' => :M, 'H' => :H, 'ND' => :ND}
205
+
206
+ # Security Requirements Confidentiality.
207
+ #
208
+ # @return [:L, :M, :H, :ND]
209
+ attr_reader :cr
210
+
211
+ IR = {'L' => :L, 'M' => :M, 'H' => :H, 'ND' => :ND}
212
+
213
+ # Security Requirements Integrity.
214
+ #
215
+ # @return [:L, :M, :H, :ND]
216
+ attr_reader :ir
217
+
218
+ AR = {'L' => :L, 'M' => :M, 'H' => :H, 'ND' => :ND}
219
+
220
+ # Security Requirements Availability.
221
+ #
222
+ # @return [:L, :M, :H, :ND]
223
+ attr_reader :ar
224
+
225
+ def initialize(cdp: nil, td: nil, cr: nil, ir: nil, ar: nil)
226
+ @cdp = cdp
227
+ @td = td
228
+ @cr = cr
229
+ @ir = ir
230
+ @ar = ar
231
+ end
232
+
233
+ #
234
+ # Maps the parsed JSON to a Symbol Hash for {#initialize}.
235
+ #
236
+ # @param [Hash{String => Object}] json
237
+ # The parsed JSON.
238
+ #
239
+ # @return [Hash{Symbol => Object}]
240
+ # The mapped Symbol Hash.
241
+ #
242
+ def self.from_json(json)
243
+ {
244
+ cdp: CDP[json['CDP']],
245
+ td: TD[json['TD']],
246
+ cr: CR[json['CR']],
247
+ ir: IR[json['IR']],
248
+ ar: AR[json['AR']]
249
+ }
250
+ end
251
+
252
+ #
253
+ # Loads the EM object from the parsed JSON.
254
+ #
255
+ # @param [Hash{String => Object}] json
256
+ # The parsed JSON.
257
+ #
258
+ # @return [self]
259
+ # The loaded EM object.
260
+ #
261
+ def self.load(json)
262
+ new(**from_json(json))
263
+ end
264
+
265
+ end
266
+
267
+ # @return [EM, nil]
268
+ attr_reader :em
269
+
270
+ #
271
+ # Initializes the CVSSv2.
272
+ #
273
+ # @param [BM, nil] bm
274
+ #
275
+ # @param [TM, nil] tm
276
+ #
277
+ # @param [EM, nil] em
278
+ #
279
+ def initialize(bm: nil, tm: nil, em: nil)
280
+ @bm = bm
281
+ @tm = tm
282
+ @em = em
283
+ end
284
+
285
+ #
286
+ # Maps the parsed JSON to a Symbol Hash for {#initialize}.
287
+ #
288
+ # @param [Hash{String => Object}] json
289
+ # The parsed JSON.
290
+ #
291
+ # @return [Hash{Symbol => Object}]
292
+ # the mapped Symbol Hash.
293
+ #
294
+ def self.from_json(json)
295
+ {
296
+ bm: json['BM'] && BM.load(json['BM']),
297
+ tm: json['TM'] && TM.load(json['TM']),
298
+ em: json['EM'] && EM.load(json['EM']),
299
+ }
300
+ end
301
+
302
+ #
303
+ # Loads the CVSSv2 object from the parsed JSON.
304
+ #
305
+ # @param [Hash{String => Object}] json
306
+ # The parsed JSON.
307
+ #
308
+ # @return [self]
309
+ # The loaded CVSSv2 object.
310
+ #
311
+ def self.load(json)
312
+ new(**from_json(json))
313
+ end
314
+
315
+ end
316
+ end
317
+ end
318
+ end
@@ -0,0 +1,388 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CVESchema
4
+ class CVE
5
+ class Impact
6
+ class CVSSv3
7
+
8
+ #
9
+ # The Base Metric Group scoring information.
10
+ #
11
+ class BM
12
+
13
+ AV = {'N' => :N, 'A' => :A, 'L' => :L, 'P' => :P}
14
+
15
+ # The Attack Vector.
16
+ #
17
+ # @return [:N, :A, :L, :P]
18
+ attr_reader :av
19
+
20
+ AC = {'L' => :L, 'H' => :H}
21
+
22
+ # The Attack Complexity.
23
+ #
24
+ # @return [:L, :H]
25
+ attr_reader :ac
26
+
27
+ PR = {'N' => :N, 'L' => :L, 'H' => :H}
28
+
29
+ # The Privileges Required.
30
+ #
31
+ # @return [:N, :L, :H]
32
+ attr_reader :pr
33
+
34
+ UI = {'N' => :N, 'R' => :R}
35
+
36
+ # The User Interaction.
37
+ #
38
+ # @return [:N, :R]
39
+ attr_reader :ui
40
+
41
+ S = {'U' => :U, 'C' => :C}
42
+
43
+ # The Scope
44
+ #
45
+ # @return [:U, :C]
46
+ attr_reader :s
47
+
48
+ C = {'H' => :H, 'L' => :L, 'N' => :N}
49
+
50
+ # The Confidentiality Impact.
51
+ #
52
+ # @return [:H, :L, :N]
53
+ attr_reader :c
54
+
55
+ I = {'H' => :H, 'L' => :L, 'N' => :N}
56
+
57
+ # The Integrity Impact
58
+ #
59
+ # @return [:H, :L, :N]
60
+ attr_reader :i
61
+
62
+ A = {'H' => :H, 'L' => :L, 'N' => :N}
63
+
64
+ # The Availability Impact
65
+ #
66
+ # @return [:H, :L, :N]
67
+ attr_reader :a
68
+
69
+ # The CVSSv3 score.
70
+ #
71
+ # @return [String]
72
+ attr_reader :score
73
+
74
+ #
75
+ # Initializes the BM object.
76
+ #
77
+ def initialize(av: nil, ac: nil, pr: nil, ui: nil, s: nil, c: nil,
78
+ i: nil, a: nil, score: nil)
79
+ @av = av
80
+ @ac = ac
81
+ @pr = pr
82
+ @ui = ui
83
+ @s = s
84
+ @c = c
85
+ @i = i
86
+ @a = a
87
+
88
+ @score = score
89
+ end
90
+
91
+ #
92
+ # Maps the parsed JSON to a Symbol Hash for {#initialize}.
93
+ #
94
+ # @param [Hash{String => Object}] json
95
+ # The parsed JSON.
96
+ #
97
+ # @return [Hash{Symbol => Object}]
98
+ # The mapped Symbol Hash.
99
+ #
100
+ def self.from_json(json)
101
+ {
102
+ av: AV[json['AV']],
103
+ ac: AC[json['AC']],
104
+ pr: PR[json['PR']],
105
+ ui: UI[json['UI']],
106
+ s: S[json['S']],
107
+ c: C[json['C']],
108
+ i: I[json['I']],
109
+ a: A[json['A']],
110
+
111
+ score: json['SCORE']
112
+ }
113
+ end
114
+
115
+ #
116
+ # Loads the BM object from the parsed JSON.
117
+ #
118
+ # @param [Hash{String => Object}] json
119
+ # The parsed JSON.
120
+ #
121
+ # @return [BM]
122
+ # The loaded BM object.
123
+ #
124
+ def self.load(json)
125
+ new(**from_json(json))
126
+ end
127
+
128
+ end
129
+
130
+ # @return [BM, nil]
131
+ attr_reader :bm
132
+
133
+ class TM
134
+
135
+ E = {'X' => :X, 'H' => :H, 'F' => :F, 'P' => :P, 'U' => :U}
136
+
137
+ # Exploit Code Maturity.
138
+ #
139
+ # @return [:X, :H, :F, :P, :U]
140
+ attr_reader :e
141
+
142
+ RL = {'X' => :X, 'U' => :U, 'W' => :W, 'T' => :T, 'O' => :O}
143
+
144
+ # Remediation Level.
145
+ #
146
+ # @return [:X, :U, :W, :T, :O]
147
+ attr_reader :rl
148
+
149
+ RC = {'X' => :X, 'C' => :C, 'R' => :R, 'U' => :U}
150
+
151
+ # Report Confidence.
152
+ #
153
+ # @return [:X, :C, :R, :U]
154
+ attr_reader :rc
155
+
156
+ #
157
+ # Initializes the TM object.
158
+ #
159
+ def initialize(e: nil, rl: nil, rc: nil)
160
+ @e = e
161
+ @rl = rl
162
+ @rc = rc
163
+ end
164
+
165
+ #
166
+ # Maps the parsed JSON to the Symbol Hash for {#initialize}.
167
+ #
168
+ # @param [Hash{String => Object}] json
169
+ # The parsed JSON.
170
+ #
171
+ # @return [Hash{Symbol => Object}]
172
+ # The mapped Symbol Hash.
173
+ #
174
+ def self.from_json(json)
175
+ {
176
+ e: E[json['E']],
177
+ rl: RL[json['RL']],
178
+ rc: RC[json['RC']]
179
+ }
180
+ end
181
+
182
+ #
183
+ # Loads the TM object from the parsed JSON.
184
+ #
185
+ # @param [Hash{String => Object}] json
186
+ # The parsed JSON.
187
+ #
188
+ # @return [TM]
189
+ # The loaded TM object.
190
+ #
191
+ def self.load(json)
192
+ new(**from_json(json))
193
+ end
194
+
195
+ end
196
+
197
+ # @return [TM, nil]
198
+ attr_reader :tm
199
+
200
+ class EM
201
+
202
+ CR = {'X' => :X, 'H' => :H, 'M' => :M, 'L' => :L}
203
+
204
+ # Security Requirements Confidentiality.
205
+ #
206
+ # @return [:X, :H, :M, :L]
207
+ attr_reader :cr
208
+
209
+ IR = {'X' => :X, 'H' => :H, 'M' => :M, 'L' => :L}
210
+
211
+ # Security Requirements Integrity.
212
+ #
213
+ # @return [:X, :H, :M, :L]
214
+ attr_reader :ir
215
+
216
+ AR = {'X' => :X, 'H' => :H, 'M' => :M, 'L' => :L}
217
+
218
+ # Security Requirements Availability.
219
+ #
220
+ # @return [:X, :H, :M, :L]
221
+ attr_reader :ar
222
+
223
+ MAV = {'N' => :N, 'A' => :A, 'L' => :L, 'P' => :P}
224
+
225
+ # The Modified Attack Vector.
226
+ #
227
+ # @return [:N, :A, :L, :P]
228
+ attr_reader :mav
229
+
230
+ MAC = {'L' => :L, 'H' => :H}
231
+
232
+ # The Modified Attack Complexity.
233
+ #
234
+ # @return [:L, :H]
235
+ attr_reader :mac
236
+
237
+ MPR = {'N' => :N, 'L' => :L, 'H' => :H}
238
+
239
+ # The Modified Privileges Required.
240
+ #
241
+ # @return [:N, :L, :H]
242
+ attr_reader :mpr
243
+
244
+ MUI = {'N' => :N, 'R' => :R}
245
+
246
+ # The Modified User Interaction.
247
+ #
248
+ # @return [:N, :R]
249
+ attr_reader :mui
250
+
251
+ MS = {'U' => :S, 'C' => :C}
252
+
253
+ # The Modified Scope.
254
+ #
255
+ # @return [:U, :C]
256
+ attr_reader :ms
257
+
258
+ MC = {'H' => :H, 'L' => :L, 'N' => :N}
259
+
260
+ # The Modified Confidentiality Impact.
261
+ #
262
+ # @return [:H, :L, :N]
263
+ attr_reader :mc
264
+
265
+ MI = {'H' => :H, 'L' => :L, 'N' => :N}
266
+
267
+ # The Modified Integrity Impact.
268
+ #
269
+ # @return [:H, :L, :N]
270
+ attr_reader :mi
271
+
272
+ MA = {'H' => :H, 'L' => :L, 'N' => :N}
273
+
274
+ # The Modified Availability Impact.
275
+ #
276
+ # @return [:H, :L, :N]
277
+ attr_reader :ma
278
+
279
+ #
280
+ # Initializes the EM object.
281
+ #
282
+ def initialize(cr: nil, ir: nil, ar: nil, mav: nil, mac: nil,
283
+ mpr: nil, mui: nil, ms: nil, mc: nil, mi: nil, ma: nil)
284
+ @cr = cr
285
+ @ir = ir
286
+ @ar = ar
287
+ @mav = mav
288
+ @mac = mac
289
+ @mpr = mpr
290
+ @mui = mui
291
+ @ms = ms
292
+ @mc = mc
293
+ @mi = mi
294
+ @ma = ma
295
+ end
296
+
297
+ #
298
+ # Maps the parsed JSON to a Symbol Hash for {#initialize}.
299
+ #
300
+ # @param [Hash{String => Object}] json
301
+ # The parsed JSON.
302
+ #
303
+ # @return [Hash{Symbol => Object}]
304
+ # The mapped Symbol Hash.
305
+ #
306
+ def self.from_json(json)
307
+ {
308
+ cr: CR[json['CR']],
309
+ ir: IR[json['IR']],
310
+ ar: AR[json['AR']],
311
+ mav: MAV[json['MAV']],
312
+ mac: MAC[json['MAC']],
313
+ mpr: MPR[json['MPR']],
314
+ mui: MUI[json['MUI']],
315
+ ms: MS[json['MS']],
316
+ mc: MC[json['MC']],
317
+ mi: MI[json['MI']],
318
+ ma: MA[json['MA']]
319
+ }
320
+ end
321
+
322
+ #
323
+ # Loads the EM object from the parsed JSON.
324
+ #
325
+ # @param [Hash{String => Object}] json
326
+ # The parsed JSON.
327
+ #
328
+ # @return [EM]
329
+ # The loaded EM object.
330
+ #
331
+ def self.load(json)
332
+ new(**from_json(json))
333
+ end
334
+
335
+ end
336
+
337
+ # @return [EM, nil]
338
+ attr_reader :em
339
+
340
+ #
341
+ # Initializes the CVSSv2.
342
+ #
343
+ # @param [BM, nil] bm
344
+ #
345
+ # @param [TM, nil] tm
346
+ #
347
+ # @param [EM, nil] em
348
+ #
349
+ def initialize(bm: nil, tm: nil, em: nil)
350
+ @bm = bm
351
+ @tm = tm
352
+ @em = em
353
+ end
354
+
355
+ #
356
+ # Maps the parsed JSON to a Symbol Hash for {#initialize}.
357
+ #
358
+ # @param [Hash{String => Object}] json
359
+ # The parsed JSON.
360
+ #
361
+ # @return [Hash{Symbol => Object}]
362
+ # The mapped Symbol Hash.
363
+ #
364
+ def self.from_json(json)
365
+ {
366
+ bm: json['BM'] && BM.load(json['BM']),
367
+ tm: json['TM'] && TM.load(json['TM']),
368
+ em: json['EM'] && EM.load(json['EM'])
369
+ }
370
+ end
371
+
372
+ #
373
+ # Loads the CVSSv3 object from the parsed JSON.
374
+ #
375
+ # @param [Hash{String => Object}] json
376
+ # The parsed JSON.
377
+ #
378
+ # @return [CVSSv3]
379
+ # the loaded CVSSv3 object.
380
+ #
381
+ def self.load(json)
382
+ new(**from_json(json))
383
+ end
384
+
385
+ end
386
+ end
387
+ end
388
+ end