nvd-json_feeds 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 (67) hide show
  1. checksums.yaml +7 -0
  2. data/.document +3 -0
  3. data/.github/workflows/ruby.yml +29 -0
  4. data/.gitignore +9 -0
  5. data/.rspec +1 -0
  6. data/.yardopts +1 -0
  7. data/ChangeLog.md +25 -0
  8. data/Gemfile +13 -0
  9. data/LICENSE.txt +20 -0
  10. data/README.md +136 -0
  11. data/Rakefile +31 -0
  12. data/gemspec.yml +22 -0
  13. data/lib/nvd/json_feeds.rb +25 -0
  14. data/lib/nvd/json_feeds/exceptions.rb +15 -0
  15. data/lib/nvd/json_feeds/feed.rb +50 -0
  16. data/lib/nvd/json_feeds/feed_file.rb +95 -0
  17. data/lib/nvd/json_feeds/feed_uri.rb +131 -0
  18. data/lib/nvd/json_feeds/gz_feed_file.rb +60 -0
  19. data/lib/nvd/json_feeds/gz_feed_uri.rb +25 -0
  20. data/lib/nvd/json_feeds/json_feed_file.rb +21 -0
  21. data/lib/nvd/json_feeds/meta.rb +122 -0
  22. data/lib/nvd/json_feeds/meta_feed_uri.rb +22 -0
  23. data/lib/nvd/json_feeds/schema/configurations.rb +61 -0
  24. data/lib/nvd/json_feeds/schema/configurations/node.rb +98 -0
  25. data/lib/nvd/json_feeds/schema/cpe/has_uri.rb +66 -0
  26. data/lib/nvd/json_feeds/schema/cpe/match.rb +117 -0
  27. data/lib/nvd/json_feeds/schema/cpe/name.rb +67 -0
  28. data/lib/nvd/json_feeds/schema/cve_feed.rb +142 -0
  29. data/lib/nvd/json_feeds/schema/cve_item.rb +94 -0
  30. data/lib/nvd/json_feeds/schema/cvss_v2.rb +298 -0
  31. data/lib/nvd/json_feeds/schema/cvss_v3.rb +332 -0
  32. data/lib/nvd/json_feeds/schema/has_data_version.rb +54 -0
  33. data/lib/nvd/json_feeds/schema/impact.rb +73 -0
  34. data/lib/nvd/json_feeds/schema/impact/base_metric_v2.rb +132 -0
  35. data/lib/nvd/json_feeds/schema/impact/base_metric_v3.rb +79 -0
  36. data/lib/nvd/json_feeds/schema/timestamp.rb +9 -0
  37. data/lib/nvd/json_feeds/version.rb +6 -0
  38. data/lib/nvd/json_feeds/zip_feed_file.rb +64 -0
  39. data/lib/nvd/json_feeds/zip_feed_uri.rb +25 -0
  40. data/nvd-json_feeds.gemspec +61 -0
  41. data/spec/feed_file_examples.rb +27 -0
  42. data/spec/feed_file_spec.rb +42 -0
  43. data/spec/feed_spec.rb +56 -0
  44. data/spec/feed_uri_spec.rb +81 -0
  45. data/spec/fixtures/gz_feed_file/nvdcve-1.1-recent.json.gz +0 -0
  46. data/spec/fixtures/nvdcve-1.1-recent.json +180 -0
  47. data/spec/fixtures/zip_feed_file/nvdcve-1.1-recent.json.zip +0 -0
  48. data/spec/gz_feed_file_spec.rb +66 -0
  49. data/spec/gz_feed_uri_spec.rb +35 -0
  50. data/spec/json_feed_file_spec.rb +18 -0
  51. data/spec/json_feeds_spec.rb +8 -0
  52. data/spec/meta_spec.rb +141 -0
  53. data/spec/schema/configurations/node_spec.rb +87 -0
  54. data/spec/schema/configurations_spec.rb +57 -0
  55. data/spec/schema/cpe/match_spec.rb +188 -0
  56. data/spec/schema/cpe/name_spec.rb +54 -0
  57. data/spec/schema/cve_feed_spec.rb +162 -0
  58. data/spec/schema/cve_item_spec.rb +116 -0
  59. data/spec/schema/impact/base_metric_v2_spec.rb +183 -0
  60. data/spec/schema/impact/base_metric_v3_spec.rb +80 -0
  61. data/spec/schema/impact_spec.rb +53 -0
  62. data/spec/schema/shared_examples.rb +136 -0
  63. data/spec/schema/timestamp_spec.rb +8 -0
  64. data/spec/spec_helper.rb +8 -0
  65. data/spec/zip_feed_file_spec.rb +66 -0
  66. data/spec/zip_feed_uri_spec.rb +35 -0
  67. metadata +156 -0
@@ -0,0 +1,94 @@
1
+ require 'nvd/json_feeds/schema/timestamp'
2
+ require 'nvd/json_feeds/schema/configurations'
3
+ require 'nvd/json_feeds/schema/impact'
4
+ require 'cve_schema/cve'
5
+
6
+ module NVD
7
+ module JSONFeeds
8
+ module Schema
9
+ #
10
+ # Represents the `"CVE_Item"` JSON object.
11
+ #
12
+ class CVEItem
13
+
14
+ # The CVE object.
15
+ #
16
+ # @return [CVESchema::CVE]
17
+ attr_reader :cve
18
+
19
+ # @return [Configurations, nil]
20
+ attr_reader :configurations
21
+
22
+ # @return [Impact, nil]
23
+ attr_reader :impact
24
+
25
+ # @return [DateTime, nil]
26
+ attr_reader :published_date
27
+
28
+ # @return [DateTime, nil]
29
+ attr_reader :last_modified_date
30
+
31
+ #
32
+ # Initializes the CVE Item object.
33
+ #
34
+ # @param [CVESchema::CVE] cve
35
+ # The CVE object.
36
+ #
37
+ def initialize(cve: , configurations: nil,
38
+ impact: nil,
39
+ published_date: nil,
40
+ last_modified_date: nil)
41
+ @cve = cve
42
+
43
+ @configurations = configurations
44
+ @impact = impact
45
+ @published_date = published_date
46
+ @last_modified_date = last_modified_date
47
+ end
48
+
49
+ #
50
+ # Maps the parsed JSON to a Symbol Hash for {#initialize}.
51
+ #
52
+ # @param [Hash{String => Object}] json
53
+ # The parsed JSON.
54
+ #
55
+ # @return [Hash{Symbol => Object}]
56
+ # The mapped Symbol Hash.
57
+ #
58
+ def self.from_json(json)
59
+ {
60
+ cve: CVESchema::CVE.load(json.fetch('cve')),
61
+ configurations: if (configurations = json['configurations'])
62
+ Configurations.load(configurations)
63
+ end,
64
+ impact: if (impact = json['impact'])
65
+ Impact.load(impact)
66
+ end,
67
+
68
+ published_date: if (published_date = json['publishedDate'])
69
+ Timestamp.parse(published_date)
70
+ end,
71
+
72
+ last_modified_date: if (last_modified_date = json['lastModifiedDate'])
73
+ Timestamp.parse(last_modified_date)
74
+ end
75
+ }
76
+ end
77
+
78
+ #
79
+ # Loads the CVE Item object from the parsed JSON.
80
+ #
81
+ # @param [Hash{String => Object}] json
82
+ # The parsed JSON.
83
+ #
84
+ # @return [CVEItem]
85
+ # The loaded CVE Item object.
86
+ #
87
+ def self.load(json)
88
+ new(**from_json(json))
89
+ end
90
+
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,298 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NVD
4
+ module JSONFeeds
5
+ module Schema
6
+ #
7
+ # Represents the `"cvssV2"` value.
8
+ #
9
+ class CVSSv2
10
+
11
+ # @see https://csrc.nist.gov/schema/nvd/feed/1.1-Beta/cvss-v2.0_beta.json
12
+ VERSIONS = {
13
+ '2.0' => :"2.0"
14
+ }
15
+
16
+ # @see https://csrc.nist.gov/schema/nvd/feed/1.1-Beta/cvss-v2.0_beta.json
17
+ ACCESS_VECTORS = {
18
+ 'NETWORK' => :NETWORK,
19
+ 'ADJACENT_NETWORK' => :ADJACENT_NETWORK,
20
+ 'LOCAL' => :LOCAL
21
+ }
22
+
23
+ # @see https://csrc.nist.gov/schema/nvd/feed/1.1-Beta/cvss-v2.0_beta.json
24
+ ACCESS_COMPLEXITIES = {
25
+ 'HIGH' => :HIGH,
26
+ 'MEDIUM' => :MEDIUM,
27
+ 'LOW' => :LOW
28
+ }
29
+
30
+ # @see https://csrc.nist.gov/schema/nvd/feed/1.1-Beta/cvss-v2.0_beta.json
31
+ AUTHENTICATIONS = {
32
+ 'MULTIPLE' => :MULTIPLE,
33
+ 'SINGLE' => :SINGLE,
34
+ 'NONE' => :NONE
35
+ }
36
+
37
+ # @see https://csrc.nist.gov/schema/nvd/feed/1.1-Beta/cvss-v2.0_beta.json
38
+ CIAS = {
39
+ 'NONE' => :NONE,
40
+ 'PARTIAL' => :PARTIAL,
41
+ 'COMPLETE' => :COMPLETE
42
+ }
43
+
44
+ # @see https://csrc.nist.gov/schema/nvd/feed/1.1-Beta/cvss-v2.0_beta.json
45
+ EXPLOITABILITIES = {
46
+ 'UNPROVEN' => :UNPROVEN,
47
+ 'PROOF_OF_CONCEPT' => :PROOF_OF_CONCEPT,
48
+ 'FUNCTIONAL' => :FUNCTIONAL,
49
+ 'HIGH' => :HIGH,
50
+ 'NOT_DEFINED' => :NOT_DEFINED
51
+ }
52
+
53
+ # @see https://csrc.nist.gov/schema/nvd/feed/1.1-Beta/cvss-v2.0_beta.json
54
+ REMEDIATION_LEVELS = {
55
+ 'OFFICIAL_FIX' => :OFFICIAL_FIX,
56
+ 'TEMPORARY_FIX' => :TEMPORARY_FIX,
57
+ 'WORKAROUND' => :WORKAROUND,
58
+ 'UNAVAILABLE' => :UNAVAILABLE,
59
+ 'NOT_DEFINED' => :NOT_DEFINED
60
+ }
61
+
62
+ # @see https://csrc.nist.gov/schema/nvd/feed/1.1-Beta/cvss-v2.0_beta.json
63
+ REPORT_CONFIDENCES = {
64
+ 'UNCONFIRMED' => :UNCONFIRMED,
65
+ 'UNCORROBORATED' => :UNCORROBORATED,
66
+ 'CONFIRMED' => :CONFIRMED,
67
+ 'NOT_DEFINED' => :NOT_DEFINED
68
+ }
69
+
70
+ # @see https://csrc.nist.gov/schema/nvd/feed/1.1-Beta/cvss-v2.0_beta.json
71
+ COLLATERAL_DAMAGE_POTENTIALS = {
72
+ 'NONE' => :NONE,
73
+ 'LOW' => :LOW,
74
+ 'LOW_MEDIUM' => :LOW_MEDIUM,
75
+ 'MEDIUM_HIGH' => :MEDIUM_HIGH,
76
+ 'HIGH' => :HIGH,
77
+ 'NOT_DEFINED' => :NOT_DEFINED
78
+ }
79
+
80
+ # @see https://csrc.nist.gov/schema/nvd/feed/1.1-Beta/cvss-v2.0_beta.json
81
+ TARGET_DISTRIBUTIONS = {
82
+ "NONE" => :NONE,
83
+ "LOW" => :LOW,
84
+ "MEDIUM" => :MEDIUM,
85
+ "HIGH" => :HIGH,
86
+ "NOT_DEFINED" => :NOT_DEFINED
87
+ }
88
+
89
+ # @see https://csrc.nist.gov/schema/nvd/feed/1.1-Beta/cvss-v2.0_beta.json
90
+ CIA_REQUIREMENTS = {
91
+ 'LOW' => :LOW,
92
+ 'MEDIUM' => :MEDIUM,
93
+ 'HIGH' => :HIGH,
94
+ 'NOT_DEFINED' => :NOT_DEFINED
95
+ }
96
+
97
+ # @return [:"2.0"]
98
+ attr_reader :version
99
+
100
+ # @return [String]
101
+ attr_reader :vector_string
102
+
103
+ # @return [Float]
104
+ attr_reader :base_score
105
+
106
+ # @return [:NETWORK, :ADJACENT_NETWORK, :LOCAL]]
107
+ attr_reader :access_vector
108
+
109
+ # @return [:HIGH, :MEDIUM, :LOW]
110
+ attr_reader :access_complexity
111
+
112
+ # @return [:MULTIPLE, :SINGLE, :NONE]
113
+ attr_reader :authentication
114
+
115
+ # @return [:NONE, :PARTIAL, :COMPLETE]
116
+ attr_reader :confidentiality_impact
117
+
118
+ # @return [:NONE, :PARTIAL, :COMPLETE]
119
+ attr_reader :integrity_impact
120
+
121
+ # @return [:NONE, :PARTIAL, :COMPLETE]
122
+ attr_reader :availability_impact
123
+
124
+ # @return [Float]
125
+ attr_reader :base_score
126
+
127
+ # @return [:UNPROVEN, :PROOF_OF_CONCEPT, :FUNCTIONAL, :HIGH, :NOT_DEFINED]
128
+ attr_reader :exploitability
129
+
130
+ # @return [:OFFICIAL_FIX, :TEMPORARY_FIX, :WORKAROUND, :UNAVAILABLE, :NOT_DEFINED]
131
+ attr_reader :remediation_level
132
+
133
+ # @return [:UNCONFIRMED, :UNCORROBORATED, :CONFIRMED, :NOT_DEFINED]
134
+ attr_reader :report_confidence
135
+
136
+ # @return [Float, nil]
137
+ attr_reader :temporal_score
138
+
139
+ # @return [:NONE, :LOW, :LOW_MEDIUM, :MEDIUM_HIGH, :HIGH, :NOT_DEFINED]
140
+ attr_reader :collateral_damage_potential
141
+
142
+ # @return [:NONE, :LOW, :MEDIUM, :HIGH, :NOT_DEFINED]
143
+ attr_reader :target_distribution
144
+
145
+ # @return [:NONE, :PARTIAL, :COMPLETE]
146
+ attr_reader :confidentiality_requirement
147
+
148
+ # @return [:NONE, :PARTIAL, :COMPLETE]
149
+ attr_reader :integrity_requirement
150
+
151
+ # @return [:NONE, :PARTIAL, :COMPLETE]
152
+ attr_reader :availability_requirement
153
+
154
+ # @return [Float, nil]
155
+ attr_reader :environmental_score
156
+
157
+ #
158
+ # Initializes the CVSS v2 object.
159
+ #
160
+ def initialize(version: ,
161
+ vector_string: ,
162
+ base_score: ,
163
+ access_vector: nil,
164
+ access_Complexity: nil,
165
+ authentication: nil,
166
+ confidentiality_impact: nil,
167
+ integrity_impact: nil,
168
+ availability_impact: nil,
169
+ exploitability: nil,
170
+ remediation_level: nil,
171
+ report_confidence: nil,
172
+ temporal_score: nil,
173
+ collateral_damage_potential: nil,
174
+ target_distribution: nil,
175
+ confidentiality_requirement: nil,
176
+ integrity_requirement: nil,
177
+ availability_requirement: nil,
178
+ environmental_score: nil)
179
+ @version = version
180
+ @vector_string = vector_string
181
+ @base_score = base_score
182
+
183
+ @access_vector = access_vector
184
+ @access_Complexity = access_Complexity
185
+ @authentication = authentication
186
+ @confidentiality_impact = confidentiality_impact
187
+ @integrity_impact = integrity_impact
188
+ @availability_impact = availability_impact
189
+ @base_score = base_score
190
+ @exploitability = exploitability
191
+ @remediation_level = remediation_level
192
+ @report_confidence = report_confidence
193
+ @temporal_score = temporal_score
194
+ @collateral_damage_potential = collateral_damage_potential
195
+ @target_distribution = target_distribution
196
+ @confidentiality_requirement = confidentiality_requirement
197
+ @integrity_requirement = integrity_requirement
198
+ @availability_requirement = availability_requirement
199
+ @environmental_score = environmental_score
200
+ end
201
+
202
+ #
203
+ # Maps the parsed JSON to a Symbol Hash for {#initialize}.
204
+ #
205
+ # @param [Hash{String => Object}] json
206
+ # The parsed JSON.
207
+ #
208
+ # @return [Hash{Symbol => Object}]
209
+ # The Symbol Hash.
210
+ #
211
+ # @see https://csrc.nist.gov/schema/nvd/feed/1.1-Beta/cvss-v2.0_beta.json
212
+ #
213
+ def self.from_json(json)
214
+ {
215
+ version: VERSIONS.fetch(json.fetch('version')),
216
+
217
+ vector_string: json.fetch('vectorString'),
218
+
219
+ access_vector: if (value = json['accessVector'])
220
+ ACCESS_VECTORS.fetch(value)
221
+ end,
222
+
223
+ access_Complexity: if (value = json['accessComplexity'])
224
+ ACCESS_COMPLEXITIES.fetch(value)
225
+ end,
226
+
227
+ authentication: if (value = json['authentication'])
228
+ AUTHENTICATIONS.fetch(value)
229
+ end,
230
+
231
+ confidentiality_impact: if (value = json['confidentialityImpact'])
232
+ CIAS.fetch(value)
233
+ end,
234
+
235
+ integrity_impact: if (value = json['integrityImpact'])
236
+ CIAS.fetch(value)
237
+ end,
238
+
239
+ availability_impact: if (value = json['availabilityImpact'])
240
+ CIAS.fetch(value)
241
+ end,
242
+
243
+ base_score: json.fetch('baseScore'),
244
+
245
+ exploitability: if (value = json['exploitability'])
246
+ EXPLOITABILITIES.fetch(value)
247
+ end,
248
+
249
+ remediation_level: if (value = json['remediationLevel'])
250
+ REMEDIATION_LEVELS.fetch(value)
251
+ end,
252
+
253
+ report_confidence: if (value = json['reportConfidence'])
254
+ REPORT_CONFIDENCES.fetch(value)
255
+ end,
256
+
257
+ temporal_score: json['temporalScore'],
258
+
259
+ collateral_damage_potential: if (value = json['collateralDamagePotential'])
260
+ COLLATERAL_DAMAGE_POTENTIALS.fetch(value)
261
+ end,
262
+
263
+ target_distribution: if (value = json['targetDistribution'])
264
+ TARGET_DISTRIBUTIONS.fetch(value)
265
+ end,
266
+
267
+ confidentiality_requirement: if (value = json['confidentialityRequirement'])
268
+ CIA_REQUIREMENTS.fetch(value)
269
+ end,
270
+
271
+ integrity_requirement: if (value = json['integrityRequirement'])
272
+ CIA_REQUIREMENTS.fetch(value)
273
+ end,
274
+
275
+ availability_requirement: if (value = json['availabilityRequirement'])
276
+ CIA_REQUIREMENTS.fetch(value)
277
+ end,
278
+
279
+ environmental_score: json['environmentalScore']
280
+ }
281
+ end
282
+
283
+ #
284
+ # Loads the CVSS v2 object from the parsed JSON.
285
+ #
286
+ # @param [Hash{String => Object}] json
287
+ # The parsed JSON.
288
+ #
289
+ # @return [CVSSv2]
290
+ # The CVSSv3 V2 object.
291
+ #
292
+ def self.load(json)
293
+ new(**from_json(json))
294
+ end
295
+ end
296
+ end
297
+ end
298
+ end
@@ -0,0 +1,332 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NVD
4
+ module JSONFeeds
5
+ module Schema
6
+ #
7
+ # Represents the `"cvssV3"` value.
8
+ #
9
+ class CVSSv3
10
+
11
+ # @see https://csrc.nist.gov/schema/nvd/feed/1.1-Beta/cvss-v3.x_beta.json
12
+ VERSIONS = {
13
+ '3.0' => :"3.0",
14
+ '3.1' => :"3.1"
15
+ }
16
+
17
+ # @see https://csrc.nist.gov/schema/nvd/feed/1.1-Beta/cvss-v3.x_beta.json
18
+ ATTACK_VECTORS = {
19
+ 'NETWORK' => :NETWORK,
20
+ 'ADJACENT_NETWORK' => :ADJACENT_NETWORK,
21
+ 'LOCAL' => :LOCAL,
22
+ 'PHYSICAL' => :PHYSICAL
23
+ }
24
+
25
+ # @see https://csrc.nist.gov/schema/nvd/feed/1.1-Beta/cvss-v3.x_beta.json
26
+ MODIFIED_ATTACK_VECTORS = ATTACK_VECTORS.merge(
27
+ 'NOT_DEFINED' => :NOT_DEFINED
28
+ )
29
+
30
+ # @see https://csrc.nist.gov/schema/nvd/feed/1.1-Beta/cvss-v3.x_beta.json
31
+ ATTACK_COMPLEXITIES = {
32
+ 'HIGH' => :HIGH,
33
+ 'LOW' => :LOW
34
+ }
35
+
36
+ # @see https://csrc.nist.gov/schema/nvd/feed/1.1-Beta/cvss-v3.x_beta.json
37
+ MODIFIED_ATTACK_COMPLEXITIES = MODIFIED_ATTACK_VECTORS.merge(
38
+ 'NOT_DEFINED' => :NOT_DEFINED
39
+ )
40
+
41
+ # @see https://csrc.nist.gov/schema/nvd/feed/1.1-Beta/cvss-v3.x_beta.json
42
+ PRIVILEGES_REQUIRED = {
43
+ 'HIGH' => :HIGH,
44
+ 'LOW' => :LOW,
45
+ 'NONE' => :NONE
46
+ }
47
+
48
+ # @see https://csrc.nist.gov/schema/nvd/feed/1.1-Beta/cvss-v3.x_beta.json
49
+ MODIFIED_PRIVILEGES_REQUIRED = PRIVILEGES_REQUIRED.merge(
50
+ 'NOT_DEFINED' => :NOT_DEFINED
51
+ )
52
+
53
+ # @see https://csrc.nist.gov/schema/nvd/feed/1.1-Beta/cvss-v3.x_beta.json
54
+ USER_INTERACTIONS = {
55
+ 'NONE' => :NONE,
56
+ 'REQUIRED' => :REQUIRED
57
+ }
58
+
59
+ # @see https://csrc.nist.gov/schema/nvd/feed/1.1-Beta/cvss-v3.x_beta.json
60
+ MODIFIED_USER_INTERACTIONS = USER_INTERACTIONS.merge(
61
+ 'NOT_DEFINED' => :NOT_DEFINED
62
+ )
63
+
64
+ # @see https://csrc.nist.gov/schema/nvd/feed/1.1-Beta/cvss-v3.x_beta.json
65
+ SCOPES = {
66
+ 'UNCHANGED' => :UNCHANGED,
67
+ 'CHANGED' => :CHANGED
68
+ }
69
+
70
+ # @see https://csrc.nist.gov/schema/nvd/feed/1.1-Beta/cvss-v3.x_beta.json
71
+ MODIFIED_SCOPES = SCOPES.merge(
72
+ 'NOT_DEFINED' => :NOT_DEFINED
73
+ )
74
+
75
+ # @see https://csrc.nist.gov/schema/nvd/feed/1.1-Beta/cvss-v3.x_beta.json
76
+ CIAS = {
77
+ 'NONE' => :NONE,
78
+ 'LOW' => :LOW,
79
+ 'HIGH' => :HIGH
80
+ }
81
+
82
+ # @see https://csrc.nist.gov/schema/nvd/feed/1.1-Beta/cvss-v3.x_beta.json
83
+ MODIFIED_CIAS = CIAS.merge(
84
+ 'NOT_DEFINED' => :NOT_DEFINED
85
+ )
86
+
87
+ # @see https://csrc.nist.gov/schema/nvd/feed/1.1-Beta/cvss-v3.x_beta.json
88
+ EXPLOIT_CODE_MATURITIES = {
89
+ 'UNPROVEN' => :UNPROVEN,
90
+ 'PROOF_OF_CONCEPT' => :PROOF_OF_CONCEPT,
91
+ 'FUNCTIONAL' => :FUNCTIONAL,
92
+ 'HIGH' => :HIGH,
93
+ 'NOT_DEFINED' => :NOT_DEFINED
94
+ }
95
+
96
+ # @see https://csrc.nist.gov/schema/nvd/feed/1.1-Beta/cvss-v3.x_beta.json
97
+ REMEDIATION_LEVELS = {
98
+ 'OFFICIAL_FIX' => :OFFICIAL_FIX,
99
+ 'TEMPORARY_FIX' => :TEMPORARY_FIX,
100
+ 'WORKAROUND' => :WORKAROUND,
101
+ 'UNAVAILABLE' => :UNAVAILABLE,
102
+ 'NOT_DEFINED' => :NOT_DEFINED
103
+ }
104
+
105
+ # @see https://csrc.nist.gov/schema/nvd/feed/1.1-Beta/cvss-v3.x_beta.json
106
+ CONFIDENCES = {
107
+ 'UNKNOWN' => :UNKNOWN,
108
+ 'REASONABLE' => :REASONABLE,
109
+ 'CONFIRMED' => :CONFIRMED,
110
+ 'NOT_DEFINED' => :NOT_DEFINED
111
+ }
112
+
113
+ # @see https://csrc.nist.gov/schema/nvd/feed/1.1-Beta/cvss-v3.x_beta.json
114
+ CIA_REQUIREMENTS = {
115
+ 'LOW' => :LOW,
116
+ 'MEDIUM' => :MEDIUM,
117
+ 'HIGH' => :HIGH,
118
+ 'NOT_DEFINED' => :NOT_DEFINED
119
+ }
120
+
121
+ # @see https://csrc.nist.gov/schema/nvd/feed/1.1-Beta/cvss-v3.x_beta.json
122
+ SEVERITIES = {
123
+ 'NONE' => :NONE,
124
+ 'LOW' => :LOW,
125
+ 'MEDIUM' => :MEDIUM,
126
+ 'HIGH' => :HIGH,
127
+ 'CRITICAL' => :CRITICAL
128
+ }
129
+
130
+ #
131
+ # Initializes the CVSS v3 object.
132
+ #
133
+ def initialize(version: ,
134
+ vector_string: ,
135
+ base_score: ,
136
+ base_severity: ,
137
+ attack_vector: nil,
138
+ attack_complexity: nil,
139
+ privileges_required: nil,
140
+ user_interaction: nil,
141
+ scope: nil,
142
+ confidentiality_impact: nil,
143
+ integrity_impact: nil,
144
+ availability_impact: nil,
145
+ exploit_code_maturity: nil,
146
+ remediation_level: nil,
147
+ report_confidence: nil,
148
+ temporal_score: nil,
149
+ temporal_severity: nil,
150
+ confidentiality_requirement: nil,
151
+ integrity_requirement: nil,
152
+ availability_requirement: nil,
153
+ modified_attack_vector: nil,
154
+ modified_attack_complexity: nil,
155
+ modified_privileges_required: nil,
156
+ modified_user_interaction: nil,
157
+ modified_scope: nil,
158
+ modified_confidentiality_impact: nil,
159
+ modified_integrity_impact: nil,
160
+ modified_availability_impact: nil,
161
+ environmental_score: nil,
162
+ environmental_severity: nil)
163
+ @version = version
164
+ @vector_string = vector_string
165
+ @base_score = base_score
166
+ @base_severity = base_severity
167
+
168
+ @attack_vector = attack_vector
169
+ @attack_complexity = attack_complexity
170
+ @privileges_required = privileges_required
171
+ @user_interaction = user_interaction
172
+ @scope = scope
173
+ @confidentiality_impact = confidentiality_impact
174
+ @integrity_impact = integrity_impact
175
+ @availability_impact = availability_impact
176
+ @exploit_code_maturity = exploit_code_maturity
177
+ @remediation_level = remediation_level
178
+ @report_confidence = report_confidence
179
+ @temporal_score = temporal_score
180
+ @temporal_severity = temporal_severity
181
+ @confidentiality_requirement = confidentiality_requirement
182
+ @integrity_requirement = integrity_requirement
183
+ @availability_requirement = availability_requirement
184
+ @modified_attack_vector = modified_attack_vector
185
+ @modified_attack_complexity = modified_attack_complexity
186
+ @modified_privileges_required = modified_privileges_required
187
+ @modified_user_interaction = modified_user_interaction
188
+ @modified_scope = modified_scope
189
+ @modified_confidentiality_impact = modified_confidentiality_impact
190
+ @modified_integrity_impact = modified_integrity_impact
191
+ @modified_availability_impact = modified_availability_impact
192
+ @environmental_score = environmental_score
193
+ @environmental_severity = environmental_severity
194
+ end
195
+
196
+ #
197
+ # Maps the parsed JSON to a Symbol Hash for {#initialize}.
198
+ #
199
+ # @param [Hash{String => Object}] json
200
+ # The parsed JSON.
201
+ #
202
+ # @return [Hash{Symbol => Object}]
203
+ # The Symbol Hash.
204
+ #
205
+ # @see https://csrc.nist.gov/schema/nvd/feed/1.1-Beta/cvss-v3.x_beta.json
206
+ #
207
+ def self.from_json(json)
208
+ {
209
+ version: VERSIONS.fetch(json.fetch('version')),
210
+ vector_string: json.fetch('vectorString'),
211
+
212
+ attack_vector: if (value = json['attackVector'])
213
+ ATTACK_VECTORS.fetch(value)
214
+ end,
215
+
216
+ attack_complexity: if (value = json['attackComplexity'])
217
+ ATTACK_COMPLEXITIES.fetch(value)
218
+ end,
219
+
220
+ privileges_required: if (value = json['privilegesRequired'])
221
+ PRIVILEGES_REQUIRED.fetch(value)
222
+ end,
223
+
224
+ user_interaction: if (value = json['userInteraction'])
225
+ USER_INTERACTIONS.fetch(value)
226
+ end,
227
+
228
+ scope: if (value = json['scope'])
229
+ SCOPES.fetch(value)
230
+ end,
231
+
232
+ confidentiality_impact: if (value = json['confidentialityImpact'])
233
+ CIAS.fetch(value)
234
+ end,
235
+
236
+ integrity_impact: if (value = json['integrityImpact'])
237
+ CIAS.fetch(value)
238
+ end,
239
+
240
+ availability_impact: if (value = json['availabilityImpact'])
241
+ CIAS.fetch(value)
242
+ end,
243
+
244
+ base_score: json['baseScore'],
245
+ base_severity: if (value = json['baseSeverity'])
246
+ SEVERITIES.fetch(value)
247
+ end,
248
+
249
+ exploit_code_maturity: if (value = json['exploitCodeMaturity'])
250
+ EXPLOIT_CODE_MATURITIES.fetch(value)
251
+ end,
252
+
253
+ remediation_level: if (value = json['remediationLevel'])
254
+ REMEDIATION_LEVELS.fetch(value)
255
+ end,
256
+
257
+ report_confidence: if (value = json['reportConfidence'])
258
+ CONFIDENCES.fetch(value)
259
+ end,
260
+
261
+ temporal_score: json['temporalScore'],
262
+
263
+ temporal_severity: if (value = json['temporalSeverity'])
264
+ SEVERITIES.fetch(value)
265
+ end,
266
+
267
+ confidentiality_requirement: if (value = json['confidentialityRequirement'])
268
+ CIA_REQUIREMENTS.fetch(value)
269
+ end,
270
+
271
+ integrity_requirement: if (value = json['integrityRequirement'])
272
+ CIA_REQUIREMENTS.fetch(value)
273
+ end,
274
+
275
+ availability_requirement: if (value = json['availabilityRequirement'])
276
+ CIA_REQUIREMENTS.fetch(value)
277
+ end,
278
+
279
+ modified_attack_vector: if (value = json['modifiedAttackVector'])
280
+ MODIFIED_ATTACK_VECTORS.fetch(value)
281
+ end,
282
+
283
+ modified_attack_complexity: if (value = json['modifiedAttackComplexity'])
284
+ MODIFIED_ATTACK_COMPLEXITIES.fetch(value)
285
+ end,
286
+
287
+ modified_privileges_required: if (value = json['modifiedPrivilegesRequired'])
288
+ MODIFIED_PRIVILEGES_REQUIRED.fetch(value)
289
+ end,
290
+
291
+ modified_user_interaction: if (value = json['modifiedUserInteraction'])
292
+ MODIFIED_USER_INTERACTIONS.fetch(value)
293
+ end,
294
+
295
+ modified_scope: if (value = json['modifiedScope'])
296
+ SCOPES.fetch(value)
297
+ end,
298
+
299
+ modified_confidentiality_impact: if (value = json['modifiedConfidentialityImpact'])
300
+ MODIFIED_CIA.fetch(value)
301
+ end,
302
+
303
+ modified_integrity_impact: if (value = json['modifiedIntegrityImpact'])
304
+ MODIFIED_CIA.fetch(value)
305
+ end,
306
+
307
+ modified_availability_impact: if (value = json['modifiedAvailabilityImpact'])
308
+ MODIFIED_CIA.fetch(value)
309
+ end,
310
+
311
+ environmental_score: json['environmentalScore'],
312
+ environmental_severity: json['environmentalSeverity']
313
+ }
314
+ end
315
+
316
+ #
317
+ # Loads the CVSS v3 object from the parsed JSON.
318
+ #
319
+ # @param [Hash{String => Object}] json
320
+ # The parsed JSON.
321
+ #
322
+ # @return [CVSSv3]
323
+ # The CVSSv3 V3 object.
324
+ #
325
+ def self.load(json)
326
+ new(**from_json(json))
327
+ end
328
+
329
+ end
330
+ end
331
+ end
332
+ end