cvss-suite 1.2.3 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -13,14 +13,12 @@ require_relative '../cvss_metric'
13
13
  require_relative '../helpers/cvss3_helper'
14
14
  require_relative '../helpers/cvss31_helper'
15
15
 
16
- ##
17
- # This class represents a CVSS Environmental metric in version 3.1.
18
-
19
16
  module CvssSuite
17
+ ##
18
+ # This class represents a CVSS Environmental metric in version 3.1.
20
19
  class Cvss31Environmental < CvssMetric
21
20
  ##
22
21
  # Property of this metric
23
-
24
22
  attr_reader :confidentiality_requirement, :integrity_requirement, :availability_requirement,
25
23
  :modified_attack_vector, :modified_attack_complexity, :modified_privileges_required,
26
24
  :modified_user_interaction, :modified_scope, :modified_confidentiality,
@@ -28,20 +26,8 @@ module CvssSuite
28
26
 
29
27
  ##
30
28
  # Returns score of this metric
31
- def score(base, temporal)
32
- @base = base
33
-
34
- merged_modified_privileges_required = @modified_privileges_required
35
- if @modified_privileges_required.selected_choice[:name] == 'Not Defined'
36
- merged_modified_privileges_required = @base.privileges_required
37
- end
38
-
39
- merged_modified_scope = @modified_scope
40
- if @modified_scope.selected_choice[:name] == 'Not Defined'
41
- merged_modified_scope = @base.scope
42
- end
43
-
44
- privilege_score = Cvss3Helper.privileges_required_score(merged_modified_privileges_required, merged_modified_scope)
29
+ def score(temporal_score)
30
+ privilege_score = Cvss3Helper.privileges_required_score(@modified_privileges_required, @modified_scope)
45
31
 
46
32
  modified_exploitability_sub_score = modified_exploitability_sub(privilege_score)
47
33
 
@@ -49,7 +35,7 @@ module CvssSuite
49
35
 
50
36
  return 0 if modified_impact_sub_score <= 0
51
37
 
52
- calculate_score modified_impact_sub_score, modified_exploitability_sub_score, temporal.score
38
+ calculate_score modified_impact_sub_score, modified_exploitability_sub_score, temporal_score
53
39
  end
54
40
 
55
41
  private
@@ -57,81 +43,72 @@ module CvssSuite
57
43
  def init_properties
58
44
  @properties.push(@confidentiality_requirement =
59
45
  CvssProperty.new(name: 'Confidentiality Requirement', abbreviation: 'CR', position: [8, 11],
60
- choices: [{ name: 'Low', abbreviation: 'L', weight: 0.5 },
46
+ values: [{ name: 'Low', abbreviation: 'L', weight: 0.5 },
61
47
  { name: 'Medium', abbreviation: 'M', weight: 1.0 },
62
48
  { name: 'High', abbreviation: 'H', weight: 1.5 },
63
49
  { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
64
50
  @properties.push(@integrity_requirement =
65
51
  CvssProperty.new(name: 'Integrity Requirement', abbreviation: 'IR', position: [9, 12],
66
- choices: [{ name: 'Low', abbreviation: 'L', weight: 0.5 },
52
+ values: [{ name: 'Low', abbreviation: 'L', weight: 0.5 },
67
53
  { name: 'Medium', abbreviation: 'M', weight: 1.0 },
68
54
  { name: 'High', abbreviation: 'H', weight: 1.5 },
69
55
  { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
70
56
 
71
57
  @properties.push(@availability_requirement =
72
58
  CvssProperty.new(name: 'Availability Requirement', abbreviation: 'AR', position: [10, 13],
73
- choices: [{ name: 'Low', abbreviation: 'L', weight: 0.5 },
59
+ values: [{ name: 'Low', abbreviation: 'L', weight: 0.5 },
74
60
  { name: 'Medium', abbreviation: 'M', weight: 1.0 },
75
61
  { name: 'High', abbreviation: 'H', weight: 1.5 },
76
62
  { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
77
63
  @properties.push(@modified_attack_vector =
78
64
  CvssProperty.new(name: 'Modified Attack Vector', abbreviation: 'MAV', position: [11, 14],
79
- choices: [{ name: 'Network', abbreviation: 'N', weight: 0.85 },
65
+ values: [{ name: 'Network', abbreviation: 'N', weight: 0.85 },
80
66
  { name: 'Adjacent Network', abbreviation: 'A', weight: 0.62 },
81
67
  { name: 'Local', abbreviation: 'L', weight: 0.55 },
82
68
  { name: 'Physical', abbreviation: 'P', weight: 0.2 },
83
69
  { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
84
70
  @properties.push(@modified_attack_complexity =
85
71
  CvssProperty.new(name: 'Modified Attack Complexity', abbreviation: 'MAC', position: [12, 15],
86
- choices: [{ name: 'Low', abbreviation: 'L', weight: 0.77 },
72
+ values: [{ name: 'Low', abbreviation: 'L', weight: 0.77 },
87
73
  { name: 'High', abbreviation: 'H', weight: 0.44 },
88
74
  { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
89
75
  @properties.push(@modified_privileges_required =
90
76
  CvssProperty.new(name: 'Modified Privileges Required', abbreviation: 'MPR', position: [13, 16],
91
- choices: [{ name: 'None', abbreviation: 'N', weight: 0.85 },
77
+ values: [{ name: 'None', abbreviation: 'N', weight: 0.85 },
92
78
  { name: 'Low', abbreviation: 'L', weight: 0.62 },
93
79
  { name: 'High', abbreviation: 'H', weight: 0.27 },
94
80
  { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
95
81
  @properties.push(@modified_user_interaction =
96
82
  CvssProperty.new(name: 'Modified User Interaction', abbreviation: 'MUI', position: [14, 17],
97
- choices: [{ name: 'None', abbreviation: 'N', weight: 0.85 },
83
+ values: [{ name: 'None', abbreviation: 'N', weight: 0.85 },
98
84
  { name: 'Required', abbreviation: 'R', weight: 0.62 },
99
85
  { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
100
86
  @properties.push(@modified_scope =
101
87
  CvssProperty.new(name: 'Modified Scope', abbreviation: 'MS', position: [15, 18],
102
- choices: [{ name: 'Changed', abbreviation: 'C' },
103
- { name: 'Unchanged', abbreviation: 'U' },
104
- { name: 'Not Defined', abbreviation: 'X' }]))
88
+ values: [{ name: 'Changed', abbreviation: 'C' },
89
+ { name: 'Unchanged', abbreviation: 'U' }]))
105
90
  @properties.push(@modified_confidentiality =
106
91
  CvssProperty.new(name: 'Modified Confidentiality', abbreviation: 'MC', position: [16, 19],
107
- choices: [{ name: 'None', abbreviation: 'N', weight: 0 },
92
+ values: [{ name: 'None', abbreviation: 'N', weight: 0 },
108
93
  { name: 'Low', abbreviation: 'L', weight: 0.22 },
109
94
  { name: 'High', abbreviation: 'H', weight: 0.56 },
110
95
  { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
111
96
  @properties.push(@modified_integrity =
112
97
  CvssProperty.new(name: 'Modified Integrity', abbreviation: 'MI', position: [17, 20],
113
- choices: [{ name: 'None', abbreviation: 'N', weight: 0 },
98
+ values: [{ name: 'None', abbreviation: 'N', weight: 0 },
114
99
  { name: 'Low', abbreviation: 'L', weight: 0.22 },
115
100
  { name: 'High', abbreviation: 'H', weight: 0.56 },
116
101
  { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
117
102
  @properties.push(@modified_availability =
118
103
  CvssProperty.new(name: 'Modified Availability', abbreviation: 'MA', position: [18, 21],
119
- choices: [{ name: 'None', abbreviation: 'N', weight: 0 },
104
+ values: [{ name: 'None', abbreviation: 'N', weight: 0 },
120
105
  { name: 'Low', abbreviation: 'L', weight: 0.22 },
121
106
  { name: 'High', abbreviation: 'H', weight: 0.56 },
122
107
  { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
123
108
  end
124
109
 
125
110
  def modified_impact_sub(isc_modified)
126
- if @modified_scope.selected_choice[:name] == 'Not Defined'
127
- if @base.scope.selected_choice[:name] == 'Changed'
128
- return 7.52 * (isc_modified - 0.029) - 3.25 * (isc_modified * 0.9731 - 0.02)**13
129
- else
130
- return 6.42 * isc_modified
131
- end
132
- end
133
-
134
- if @modified_scope.selected_choice[:name] == 'Changed'
111
+ if @modified_scope.selected_value[:name] == 'Changed'
135
112
  7.52 * (isc_modified - 0.029) - 3.25 * (isc_modified * 0.9731 - 0.02)**13
136
113
  else
137
114
  6.42 * isc_modified
@@ -139,54 +116,20 @@ module CvssSuite
139
116
  end
140
117
 
141
118
  def isc_modified
142
- merged_modified_confidentiality = @modified_confidentiality
143
- if @modified_confidentiality.selected_choice[:name] == 'Not Defined'
144
- merged_modified_confidentiality = @base.confidentiality
145
- end
146
-
147
- merged_modified_integrity = @modified_integrity
148
- if @modified_integrity.selected_choice[:name] == 'Not Defined'
149
- merged_modified_integrity = @base.integrity
150
- end
151
-
152
- merged_modified_availability = @modified_availability
153
- if @modified_availability.selected_choice[:name] == 'Not Defined'
154
- merged_modified_availability = @base.availability
155
- end
156
-
157
- confidentiality_score = 1 - merged_modified_confidentiality.score * @confidentiality_requirement.score
158
- integrity_score = 1 - merged_modified_integrity.score * @integrity_requirement.score
159
- availability_score = 1 - merged_modified_availability.score * @availability_requirement.score
119
+ confidentiality_score = 1 - @modified_confidentiality.score * @confidentiality_requirement.score
120
+ integrity_score = 1 - @modified_integrity.score * @integrity_requirement.score
121
+ availability_score = 1 - @modified_availability.score * @availability_requirement.score
160
122
 
161
123
  [0.915, (1 - confidentiality_score * integrity_score * availability_score)].min
162
124
  end
163
125
 
164
126
  def modified_exploitability_sub(privilege_score)
165
- merged_modified_attack_vector = @modified_attack_vector
166
- if @modified_attack_vector.selected_choice[:name] == 'Not Defined'
167
- merged_modified_attack_vector = @base.attack_vector
168
- end
169
-
170
- merged_modified_attack_complexity = @modified_attack_complexity
171
- if @modified_attack_complexity.selected_choice[:name] == 'Not Defined'
172
- merged_modified_attack_complexity = @base.attack_complexity
173
- end
174
-
175
- merged_modified_user_interaction = @modified_user_interaction
176
- if @modified_user_interaction.selected_choice[:name] == 'Not Defined'
177
- merged_modified_user_interaction = @base.user_interaction
178
- end
179
-
180
- 8.22 * merged_modified_attack_vector.score * merged_modified_attack_complexity.score *
181
- privilege_score * merged_modified_user_interaction.score
127
+ 8.22 * @modified_attack_vector.score * @modified_attack_complexity.score *
128
+ privilege_score * @modified_user_interaction.score
182
129
  end
183
130
 
184
131
  def calculate_score(modified_impact_sub_score, modified_exploitability_sub_score, temporal_score)
185
- if @modified_scope.selected_choice[:name] == 'Not Defined'
186
- factor = @base.scope.selected_choice[:name] == 'Changed' ? 1.08 : 1.0
187
- else
188
- factor = @modified_scope.selected_choice[:name] == 'Changed' ? 1.08 : 1.0
189
- end
132
+ factor = @modified_scope.selected_value[:name] == 'Changed' ? 1.08 : 1.0
190
133
 
191
134
  Cvss31Helper.round_up(
192
135
  [factor * (modified_impact_sub_score + modified_exploitability_sub_score), 10].min
@@ -11,19 +11,16 @@
11
11
  require_relative '../cvss_property'
12
12
  require_relative '../cvss_metric'
13
13
 
14
- ##
15
- # This class represents a CVSS Temporal metric in version 3.1.
16
-
17
14
  module CvssSuite
15
+ ##
16
+ # This class represents a CVSS Temporal metric in version 3.1.
18
17
  class Cvss31Temporal < CvssMetric
19
18
  ##
20
19
  # Property of this metric
21
-
22
20
  attr_reader :exploit_code_maturity, :remediation_level, :report_confidence
23
21
 
24
22
  ##
25
23
  # Returns score of this metric
26
-
27
24
  def score
28
25
  return 1.0 unless valid?
29
26
 
@@ -35,14 +32,14 @@ module CvssSuite
35
32
  def init_properties
36
33
  @properties.push(@exploit_code_maturity =
37
34
  CvssProperty.new(name: 'Exploit Code Maturity', abbreviation: 'E', position: [8],
38
- choices: [{ name: 'Not Defined', abbreviation: 'X', weight: 1.0 },
35
+ values: [{ name: 'Not Defined', abbreviation: 'X', weight: 1.0 },
39
36
  { name: 'Unproven', abbreviation: 'U', weight: 0.91 },
40
37
  { name: 'Proof-of-Concept', abbreviation: 'P', weight: 0.94 },
41
38
  { name: 'Functional', abbreviation: 'F', weight: 0.97 },
42
39
  { name: 'High', abbreviation: 'H', weight: 1.0 }]))
43
40
  @properties.push(@remediation_level =
44
41
  CvssProperty.new(name: 'Remediation Level', abbreviation: 'RL', position: [9],
45
- choices: [{ name: 'Not Defined', abbreviation: 'X', weight: 1.0 },
42
+ values: [{ name: 'Not Defined', abbreviation: 'X', weight: 1.0 },
46
43
  { name: 'Official Fix', abbreviation: 'O', weight: 0.95 },
47
44
  { name: 'Temporary Fix', abbreviation: 'T', weight: 0.96 },
48
45
  { name: 'Workaround', abbreviation: 'W', weight: 0.97 },
@@ -50,7 +47,7 @@ module CvssSuite
50
47
 
51
48
  @properties.push(@report_confidence =
52
49
  CvssProperty.new(name: 'Report Confidence', abbreviation: 'RC', position: [10],
53
- choices: [{ name: 'Not Defined', abbreviation: 'X', weight: 1.0 },
50
+ values: [{ name: 'Not Defined', abbreviation: 'X', weight: 1.0 },
54
51
  { name: 'Unknown', abbreviation: 'U', weight: 0.92 },
55
52
  { name: 'Reasonable', abbreviation: 'R', weight: 0.96 },
56
53
  { name: 'Confirmed', abbreviation: 'C', weight: 1.0 }]))
@@ -8,23 +8,20 @@
8
8
  # This work is licensed under the terms of the MIT license.
9
9
  # See the LICENSE.md file in the top-level directory.
10
10
 
11
- ##
12
- # This class represents any CVSS metric.
13
-
14
11
  module CvssSuite
12
+ ##
13
+ # This class represents any CVSS metric.
15
14
  class CvssMetric
16
15
  ##
17
16
  # Creates a new CVSS metric by +properties+
18
-
19
17
  def initialize(selected_properties)
20
18
  @properties = []
21
19
  init_properties
22
- extract_selected_choices_from selected_properties
20
+ extract_selected_values_from selected_properties
23
21
  end
24
22
 
25
23
  ##
26
24
  # Returns if the metric is valid.
27
-
28
25
  def valid?
29
26
  @properties.each do |property|
30
27
  return false unless property.valid?
@@ -34,19 +31,18 @@ module CvssSuite
34
31
 
35
32
  ##
36
33
  # Returns number of properties for this metric.
37
-
38
34
  def count
39
35
  @properties.count
40
36
  end
41
37
 
42
38
  private
43
39
 
44
- def extract_selected_choices_from(selected_properties)
40
+ def extract_selected_values_from(selected_properties)
45
41
  selected_properties.each do |selected_property|
46
42
  property = @properties.detect do |p|
47
43
  p.abbreviation == selected_property[:name] && p.position.include?(selected_property[:position])
48
44
  end
49
- property.set_selected_choice selected_property[:selected] unless property.nil?
45
+ property&.set_selected_value selected_property[:selected]
50
46
  end
51
47
  end
52
48
  end
@@ -8,21 +8,20 @@
8
8
  # This work is licensed under the terms of the MIT license.
9
9
  # See the LICENSE.md file in the top-level directory.
10
10
 
11
- ##
12
- # This class represents a CVSS property of a CVSS metric.
13
-
14
11
  module CvssSuite
12
+ ##
13
+ # This class represents a CVSS property of a CVSS metric.
15
14
  class CvssProperty
16
15
  ##
17
16
  # Creates a new CVSS property by a +property+.
18
17
  #
19
18
  # +Property+ needs to consist of a name, a abbreviation,
20
19
  # the possible positions in the CVSS vector, a weight, and the
21
- # available choices for the property.
20
+ # available values for the property.
22
21
 
23
22
  def initialize(property)
24
23
  @property = property
25
- @property[:default_choice] ||= 'Not Available'
24
+ @property[:default_value] ||= 'Not Available'
26
25
  end
27
26
 
28
27
  ##
@@ -40,10 +39,10 @@ module CvssSuite
40
39
  end
41
40
 
42
41
  ##
43
- # Returns all available choices of the property.
42
+ # Returns all available values of the property.
44
43
 
45
- def choices
46
- @property[:choices]
44
+ def values
45
+ @property[:values]
47
46
  end
48
47
 
49
48
  ##
@@ -54,34 +53,34 @@ module CvssSuite
54
53
  end
55
54
 
56
55
  ##
57
- # Returns the selected choice of the property.
56
+ # Returns the selected value of the property.
58
57
 
59
- def selected_choice
60
- @selected_choice || @property[:default_choice]
58
+ def selected_value
59
+ @selected_value || @property[:default_value]
61
60
  end
62
61
 
63
62
  ##
64
63
  # Returns true if the property is valid.
65
64
 
66
65
  def valid?
67
- !@selected_choice.nil?
66
+ !@selected_value.nil?
68
67
  end
69
68
 
70
69
  ##
71
- # Returns the score of the selected choice.
70
+ # Returns the score of the selected value.
72
71
 
73
72
  def score
74
- @selected_choice[:weight]
73
+ @selected_value[:weight]
75
74
  end
76
75
 
77
76
  ##
78
- # Sets the selected choice by a +choice+.
77
+ # Sets the selected value by a +value+.
79
78
 
80
- def set_selected_choice(selected_choice)
81
- choices.each do |choice|
82
- choice[:selected] = selected_choice.eql?(choice[:abbreviation])
79
+ def set_selected_value(selected_value)
80
+ values.each do |value|
81
+ value[:selected] = selected_value.eql?(value[:abbreviation])
83
82
  end
84
- @selected_choice = choices.detect { |choice| choice[:selected] }
83
+ @selected_value = values.detect { |value| value[:selected] }
85
84
  end
86
85
  end
87
86
  end
@@ -8,10 +8,9 @@
8
8
  # This work is licensed under the terms of the MIT license.
9
9
  # See the LICENSE.md file in the top-level directory.
10
10
 
11
- ##
12
- # This module includes methods which are used by the CVSS 3 classes.
13
-
14
11
  module CvssSuite
12
+ ##
13
+ # This module includes methods which are used by the CVSS 3 classes.
15
14
  module Cvss3Helper
16
15
  ##
17
16
  # Since CVSS 3 all float values are rounded up, therefore this method is used
@@ -21,14 +20,14 @@ module CvssSuite
21
20
  end
22
21
 
23
22
  ##
24
- # Since CVSS 3 the Privilege Required score depends on the selected choice of the Scope metric.
23
+ # Since CVSS 3 the Privilege Required score depends on the selected value of the Scope metric.
25
24
  # This method takes a +Privilege+ +Required+ and a +Scope+ metric and returns the newly calculated score.
26
25
  def self.privileges_required_score(privileges_required, scope)
27
- changed = scope.selected_choice[:name] == 'Changed'
26
+ changed = scope.selected_value[:name] == 'Changed'
28
27
  privilege_score = privileges_required.score
29
28
  if changed
30
- privilege_score = 0.68 if privileges_required.selected_choice[:name] == 'Low'
31
- privilege_score = 0.50 if privileges_required.selected_choice[:name] == 'High'
29
+ privilege_score = 0.68 if privileges_required.selected_value[:name] == 'Low'
30
+ privilege_score = 0.50 if privileges_required.selected_value[:name] == 'High'
32
31
  end
33
32
  privilege_score
34
33
  end
@@ -8,47 +8,40 @@
8
8
  # This work is licensed under the terms of the MIT license.
9
9
  # See the LICENSE.md file in the top-level directory.
10
10
 
11
- # ##
12
- # # This class represents a invalid CVSS vector.
13
-
14
11
  module CvssSuite
12
+ ##
13
+ # This class represents a invalid CVSS vector.
15
14
  class InvalidCvss < Cvss
16
15
  ##
17
16
  # Creates a new invalid CVSS vector.
18
-
19
17
  def initialize; end
20
18
 
21
19
  ##
22
20
  # Since this is an invalid CVSS vector, it always returns false.
23
-
24
21
  def valid?
25
22
  false
26
23
  end
27
24
 
28
25
  ##
29
26
  # Since this is an invalid CVSS vector, it always throws an exception.
30
-
31
27
  def version
32
28
  check_validity
33
29
  end
34
30
 
35
31
  ##
36
32
  # Since this is an invalid CVSS vector, it always throws an exception.
37
-
38
33
  def base_score
39
34
  check_validity
40
35
  end
41
36
 
42
37
  ##
43
38
  # Since this is an invalid CVSS vector, it always throws an exception.
44
-
45
39
  def temporal_score
46
40
  check_validity
47
41
  end
48
42
 
49
43
  ##
50
44
  # Since this is an invalid CVSS vector, it always throws an exception.
51
-
52
45
  def environmental_score
53
46
  check_validity
54
47
  end
@@ -9,5 +9,5 @@
9
9
  # See the LICENSE.md file in the top-level directory.
10
10
 
11
11
  module CvssSuite
12
- VERSION = '1.2.3'
12
+ VERSION = '2.0.0'.freeze
13
13
  end
data/lib/cvss_suite.rb CHANGED
@@ -17,18 +17,15 @@ require 'cvss_suite/invalid_cvss'
17
17
 
18
18
  ##
19
19
  # Module of this gem.
20
-
21
20
  module CvssSuite
22
21
  CVSS_VECTOR_BEGINNINGS = [
23
22
  { string: 'AV:', version: 2 },
24
- { string: '(AV:', version: 2 },
25
23
  { string: 'CVSS:3.0/', version: 3.0 },
26
24
  { string: 'CVSS:3.1/', version: 3.1 }
27
- ]
25
+ ].freeze
28
26
 
29
27
  ##
30
28
  # Returns a CVSS class by a +vector+.
31
-
32
29
  def self.new(vector)
33
30
  return InvalidCvss.new unless vector.is_a? String
34
31
 
@@ -49,9 +46,7 @@ module CvssSuite
49
46
 
50
47
  def self.version
51
48
  CVSS_VECTOR_BEGINNINGS.each do |beginning|
52
- if @vector_string.start_with? beginning[:string]
53
- return beginning[:version]
54
- end
49
+ return beginning[:version] if @vector_string.start_with? beginning[:string]
55
50
  end
56
51
  end
57
52
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cvss-suite
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.3
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oliver Hamboerger
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-12-05 00:00:00.000000000 Z
11
+ date: 2020-05-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -79,6 +79,7 @@ files:
79
79
  - ".github/ISSUE_TEMPLATE/custom.md"
80
80
  - ".github/ISSUE_TEMPLATE/feature_request.md"
81
81
  - ".github/workflows/rspec.yml"
82
+ - ".github/workflows/rubocop.yml"
82
83
  - ".gitignore"
83
84
  - ".rspec"
84
85
  - ".rubocop.yml"
@@ -118,8 +119,7 @@ homepage: https://siemens.github.io/cvss-suite/
118
119
  licenses:
119
120
  - MIT
120
121
  metadata: {}
121
- post_install_message: Version 1.x of this gem is no longer supported, please update
122
- to a supported version.
122
+ post_install_message:
123
123
  rdoc_options: []
124
124
  require_paths:
125
125
  - lib
@@ -127,7 +127,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
127
127
  requirements:
128
128
  - - ">="
129
129
  - !ruby/object:Gem::Version
130
- version: 2.0.0
130
+ version: 2.4.0
131
131
  required_rubygems_version: !ruby/object:Gem::Requirement
132
132
  requirements:
133
133
  - - ">="