cvss-suite 1.1.1 → 2.0.1

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 (38) hide show
  1. checksums.yaml +5 -5
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +21 -0
  3. data/.github/ISSUE_TEMPLATE/custom.md +7 -0
  4. data/.github/ISSUE_TEMPLATE/feature_request.md +17 -0
  5. data/.github/workflows/rspec.yml +23 -0
  6. data/.github/workflows/rubocop.yml +21 -0
  7. data/.gitignore +1 -0
  8. data/.rubocop.yml +45 -1
  9. data/.rubocop_todo.yml +59 -0
  10. data/CHANGES.md +61 -1
  11. data/PULL_REQUEST_TEMPLATE.md +24 -0
  12. data/README.md +43 -16
  13. data/_config.yml +1 -0
  14. data/bin/console +3 -3
  15. data/cvss_suite.gemspec +14 -13
  16. data/lib/cvss_suite.rb +13 -11
  17. data/lib/cvss_suite/cvss.rb +85 -73
  18. data/lib/cvss_suite/cvss2/cvss2.rb +39 -36
  19. data/lib/cvss_suite/cvss2/cvss2_base.rb +69 -75
  20. data/lib/cvss_suite/cvss2/cvss2_environmental.rb +52 -54
  21. data/lib/cvss_suite/cvss2/cvss2_temporal.rb +40 -41
  22. data/lib/cvss_suite/cvss3/cvss3.rb +39 -36
  23. data/lib/cvss_suite/cvss3/cvss3_base.rb +72 -75
  24. data/lib/cvss_suite/cvss3/cvss3_environmental.rb +159 -109
  25. data/lib/cvss_suite/cvss3/cvss3_temporal.rb +41 -42
  26. data/lib/cvss_suite/cvss31/cvss31.rb +60 -0
  27. data/lib/cvss_suite/cvss31/cvss31_base.rb +93 -0
  28. data/lib/cvss_suite/cvss31/cvss31_environmental.rb +194 -0
  29. data/lib/cvss_suite/cvss31/cvss31_temporal.rb +56 -0
  30. data/lib/cvss_suite/cvss_metric.rb +31 -35
  31. data/lib/cvss_suite/cvss_property.rb +57 -56
  32. data/lib/cvss_suite/helpers/cvss31_helper.rb +27 -0
  33. data/lib/cvss_suite/helpers/cvss3_helper.rb +21 -15
  34. data/lib/cvss_suite/invalid_cvss.rb +37 -45
  35. data/lib/cvss_suite/version.rb +2 -2
  36. metadata +21 -25
  37. data/.travis.yml +0 -4
  38. data/lib/cvss_suite/helpers/extensions.rb +0 -32
@@ -11,47 +11,46 @@
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.
16
-
17
- class Cvss3Temporal < CvssMetric
18
-
19
- ##
20
- # Property of this metric
21
-
22
- attr_reader :exploit_code_maturity, :remediation_level, :report_confidence
23
-
14
+ module CvssSuite
24
15
  ##
25
- # Returns score of this metric
26
-
27
- def score
28
- return 1.0 unless valid?
29
- @exploit_code_maturity.score * @remediation_level.score * @report_confidence.score
30
- end
31
-
32
- private
33
-
34
- def init_properties
35
- @properties.push(@exploit_code_maturity =
36
- CvssProperty.new(name: 'Exploit Code Maturity', abbreviation: 'E', position: [8],
37
- choices: [{ name: 'Not Defined', abbreviation: 'X', weight: 1.0 },
38
- { name: 'Unproven', abbreviation: 'U', weight: 0.91 },
39
- { name: 'Proof-of-Concept', abbreviation: 'P', weight: 0.94 },
40
- { name: 'Functional', abbreviation: 'F', weight: 0.97 },
41
- { name: 'High', abbreviation: 'H', weight: 1.0 }]))
42
- @properties.push(@remediation_level =
43
- CvssProperty.new(name: 'Remediation Level', abbreviation: 'RL', position: [9],
44
- choices: [{ name: 'Not Defined', abbreviation: 'X', weight: 1.0 },
45
- { name: 'Official Fix', abbreviation: 'O', weight: 0.95 },
46
- { name: 'Temporary Fix', abbreviation: 'T', weight: 0.96 },
47
- { name: 'Workaround', abbreviation: 'W', weight: 0.97 },
48
- { name: 'Unavailable', abbreviation: 'U', weight: 1.0 }]))
49
-
50
- @properties.push(@report_confidence =
51
- CvssProperty.new(name: 'Report Confidence', abbreviation: 'RC', position: [10],
52
- choices: [{ name: 'Not Defined', abbreviation: 'X', weight: 1.0 },
53
- { name: 'Unknown', abbreviation: 'U', weight: 0.92 },
54
- { name: 'Reasonable', abbreviation: 'R', weight: 0.96 },
55
- { name: 'Confirmed', abbreviation: 'C', weight: 1.0 }]))
16
+ # This class represents a CVSS Temporal metric in version 3.
17
+ class Cvss3Temporal < CvssMetric
18
+ ##
19
+ # Property of this metric
20
+ attr_reader :exploit_code_maturity, :remediation_level, :report_confidence
21
+
22
+ ##
23
+ # Returns score of this metric
24
+ def score
25
+ return 1.0 unless valid?
26
+
27
+ @exploit_code_maturity.score * @remediation_level.score * @report_confidence.score
28
+ end
29
+
30
+ private
31
+
32
+ def init_properties
33
+ @properties.push(@exploit_code_maturity =
34
+ CvssProperty.new(name: 'Exploit Code Maturity', abbreviation: 'E', position: [8],
35
+ values: [{ name: 'Not Defined', abbreviation: 'X', weight: 1.0 },
36
+ { name: 'Unproven', abbreviation: 'U', weight: 0.91 },
37
+ { name: 'Proof-of-Concept', abbreviation: 'P', weight: 0.94 },
38
+ { name: 'Functional', abbreviation: 'F', weight: 0.97 },
39
+ { name: 'High', abbreviation: 'H', weight: 1.0 }]))
40
+ @properties.push(@remediation_level =
41
+ CvssProperty.new(name: 'Remediation Level', abbreviation: 'RL', position: [9],
42
+ values: [{ name: 'Not Defined', abbreviation: 'X', weight: 1.0 },
43
+ { name: 'Official Fix', abbreviation: 'O', weight: 0.95 },
44
+ { name: 'Temporary Fix', abbreviation: 'T', weight: 0.96 },
45
+ { name: 'Workaround', abbreviation: 'W', weight: 0.97 },
46
+ { name: 'Unavailable', abbreviation: 'U', weight: 1.0 }]))
47
+
48
+ @properties.push(@report_confidence =
49
+ CvssProperty.new(name: 'Report Confidence', abbreviation: 'RC', position: [10],
50
+ values: [{ name: 'Not Defined', abbreviation: 'X', weight: 1.0 },
51
+ { name: 'Unknown', abbreviation: 'U', weight: 0.92 },
52
+ { name: 'Reasonable', abbreviation: 'R', weight: 0.96 },
53
+ { name: 'Confirmed', abbreviation: 'C', weight: 1.0 }]))
54
+ end
56
55
  end
57
- end
56
+ end
@@ -0,0 +1,60 @@
1
+ # CVSS-Suite, a Ruby gem to manage the CVSS vector
2
+ #
3
+ # Copyright (c) Siemens AG, 2019
4
+ #
5
+ # Authors:
6
+ # Oliver Hambörger <oliver.hamboerger@siemens.com>
7
+ #
8
+ # This work is licensed under the terms of the MIT license.
9
+ # See the LICENSE.md file in the top-level directory.
10
+
11
+ require_relative '../cvss'
12
+ require_relative 'cvss31_base'
13
+ require_relative 'cvss31_temporal'
14
+ require_relative 'cvss31_environmental'
15
+ require_relative '../helpers/cvss31_helper'
16
+
17
+ module CvssSuite
18
+ ##
19
+ # This class represents a CVSS vector in version 3.1.
20
+ class Cvss31 < Cvss
21
+ ##
22
+ # Returns the Version of the CVSS vector.
23
+
24
+ def version
25
+ 3.1
26
+ end
27
+
28
+ ##
29
+ # Returns the Base Score of the CVSS vector.
30
+
31
+ def base_score
32
+ check_validity
33
+ Cvss31Helper.round_up(@base.score)
34
+ end
35
+
36
+ ##
37
+ # Returns the Temporal Score of the CVSS vector.
38
+
39
+ def temporal_score
40
+ Cvss31Helper.round_up(Cvss31Helper.round_up(@base.score) * @temporal.score)
41
+ end
42
+
43
+ ##
44
+ # Returns the Environmental Score of the CVSS vector.
45
+
46
+ def environmental_score
47
+ return temporal_score unless @environmental.valid?
48
+
49
+ Cvss31Helper.round_up(@environmental.score(@base, @temporal))
50
+ end
51
+
52
+ private
53
+
54
+ def init_metrics
55
+ @base = Cvss31Base.new(@properties)
56
+ @temporal = Cvss31Temporal.new(@properties)
57
+ @environmental = Cvss31Environmental.new(@properties)
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,93 @@
1
+ # CVSS-Suite, a Ruby gem to manage the CVSS vector
2
+ #
3
+ # Copyright (c) Siemens AG, 2019
4
+ #
5
+ # Authors:
6
+ # Oliver Hambörger <oliver.hamboerger@siemens.com>
7
+ #
8
+ # This work is licensed under the terms of the MIT license.
9
+ # See the LICENSE.md file in the top-level directory.
10
+
11
+ require_relative '../cvss_property'
12
+ require_relative '../cvss_metric'
13
+ require_relative '../helpers/cvss3_helper'
14
+
15
+ module CvssSuite
16
+ ##
17
+ # This class represents a CVSS Base metric in version 3.1.
18
+ class Cvss31Base < CvssMetric
19
+ ##
20
+ # Property of this metric
21
+
22
+ attr_reader :attack_vector, :attack_complexity, :privileges_required, :user_interaction,
23
+ :scope, :confidentiality, :integrity, :availability
24
+
25
+ ##
26
+ # Returns score of this metric
27
+ def score
28
+ privilege_score = Cvss3Helper.privileges_required_score(@privileges_required, @scope)
29
+
30
+ exploitability = 8.22 * @attack_vector.score * @attack_complexity.score *
31
+ privilege_score * @user_interaction.score
32
+
33
+ isc_base = 1 - ((1 - @confidentiality.score) * (1 - @integrity.score) * (1 - @availability.score))
34
+
35
+ impact_sub_score = if @scope.selected_value[:name] == 'Changed'
36
+ 7.52 * (isc_base - 0.029) - 3.25 * (isc_base - 0.02)**15
37
+ else
38
+ 6.42 * isc_base
39
+ end
40
+
41
+ return 0 if impact_sub_score <= 0
42
+
43
+ if @scope.selected_value[:name] == 'Changed'
44
+ [10, 1.08 * (impact_sub_score + exploitability)].min
45
+ else
46
+ [10, impact_sub_score + exploitability].min
47
+ end
48
+ end
49
+
50
+ private
51
+
52
+ def init_properties
53
+ @properties.push(@attack_vector =
54
+ CvssProperty.new(name: 'Attack Vector', abbreviation: 'AV', position: [0],
55
+ values: [{ name: 'Network', abbreviation: 'N', weight: 0.85 },
56
+ { name: 'Adjacent', abbreviation: 'A', weight: 0.62 },
57
+ { name: 'Local', abbreviation: 'L', weight: 0.55 },
58
+ { name: 'Physical', abbreviation: 'P', weight: 0.2 }]))
59
+ @properties.push(@attack_complexity =
60
+ CvssProperty.new(name: 'Attack Complexity', abbreviation: 'AC', position: [1],
61
+ values: [{ name: 'Low', abbreviation: 'L', weight: 0.77 },
62
+ { name: 'High', abbreviation: 'H', weight: 0.44 }]))
63
+ @properties.push(@privileges_required =
64
+ CvssProperty.new(name: 'Privileges Required', abbreviation: 'PR', position: [2],
65
+ values: [{ name: 'None', abbreviation: 'N', weight: 0.85 },
66
+ { name: 'Low', abbreviation: 'L', weight: 0.62 },
67
+ { name: 'High', abbreviation: 'H', weight: 0.27 }]))
68
+ @properties.push(@user_interaction =
69
+ CvssProperty.new(name: 'User Interaction', abbreviation: 'UI', position: [3],
70
+ values: [{ name: 'None', abbreviation: 'N', weight: 0.85 },
71
+ { name: 'Required', abbreviation: 'R', weight: 0.62 }]))
72
+ @properties.push(@scope =
73
+ CvssProperty.new(name: 'Scope', abbreviation: 'S', position: [4],
74
+ values: [{ name: 'Unchanged', abbreviation: 'U' },
75
+ { name: 'Changed', abbreviation: 'C' }]))
76
+ @properties.push(@confidentiality =
77
+ CvssProperty.new(name: 'Confidentiality', abbreviation: 'C', position: [5],
78
+ values: [{ name: 'None', abbreviation: 'N', weight: 0.0 },
79
+ { name: 'Low', abbreviation: 'L', weight: 0.22 },
80
+ { name: 'High', abbreviation: 'H', weight: 0.56 }]))
81
+ @properties.push(@integrity =
82
+ CvssProperty.new(name: 'Integrity', abbreviation: 'I', position: [6],
83
+ values: [{ name: 'None', abbreviation: 'N', weight: 0.0 },
84
+ { name: 'Low', abbreviation: 'L', weight: 0.22 },
85
+ { name: 'High', abbreviation: 'H', weight: 0.56 }]))
86
+ @properties.push(@availability =
87
+ CvssProperty.new(name: 'Availability', abbreviation: 'A', position: [7],
88
+ values: [{ name: 'None', abbreviation: 'N', weight: 0.0 },
89
+ { name: 'Low', abbreviation: 'L', weight: 0.22 },
90
+ { name: 'High', abbreviation: 'H', weight: 0.56 }]))
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,194 @@
1
+ # CVSS-Suite, a Ruby gem to manage the CVSS vector
2
+ #
3
+ # Copyright (c) Siemens AG, 2019
4
+ #
5
+ # Authors:
6
+ # Oliver Hambörger <oliver.hamboerger@siemens.com>
7
+ #
8
+ # This work is licensed under the terms of the MIT license.
9
+ # See the LICENSE.md file in the top-level directory.
10
+
11
+ require_relative '../cvss_property'
12
+ require_relative '../cvss_metric'
13
+ require_relative '../helpers/cvss3_helper'
14
+ require_relative '../helpers/cvss31_helper'
15
+
16
+ module CvssSuite
17
+ ##
18
+ # This class represents a CVSS Environmental metric in version 3.1.
19
+ class Cvss31Environmental < CvssMetric
20
+ ##
21
+ # Property of this metric
22
+ attr_reader :confidentiality_requirement, :integrity_requirement, :availability_requirement,
23
+ :modified_attack_vector, :modified_attack_complexity, :modified_privileges_required,
24
+ :modified_user_interaction, :modified_scope, :modified_confidentiality,
25
+ :modified_integrity, :modified_availability
26
+
27
+ ##
28
+ # Returns score of this metric
29
+ def score(base, temporal)
30
+ @base = base
31
+
32
+ merged_modified_privileges_required = @modified_privileges_required
33
+ if @modified_privileges_required.selected_value[:name] == 'Not Defined'
34
+ merged_modified_privileges_required = @base.privileges_required
35
+ end
36
+
37
+ merged_modified_scope = @modified_scope
38
+ if @modified_scope.selected_value[:name] == 'Not Defined'
39
+ merged_modified_scope = @base.scope
40
+ end
41
+
42
+ privilege_score = Cvss3Helper.privileges_required_score(merged_modified_privileges_required, merged_modified_scope)
43
+
44
+ modified_exploitability_sub_score = modified_exploitability_sub(privilege_score)
45
+
46
+ modified_impact_sub_score = modified_impact_sub(isc_modified)
47
+
48
+ return 0 if modified_impact_sub_score <= 0
49
+
50
+ calculate_score modified_impact_sub_score, modified_exploitability_sub_score, temporal.score
51
+ end
52
+
53
+ private
54
+
55
+ def init_properties
56
+ @properties.push(@confidentiality_requirement =
57
+ CvssProperty.new(name: 'Confidentiality Requirement', abbreviation: 'CR', position: [8, 11],
58
+ values: [{ name: 'Low', abbreviation: 'L', weight: 0.5 },
59
+ { name: 'Medium', abbreviation: 'M', weight: 1.0 },
60
+ { name: 'High', abbreviation: 'H', weight: 1.5 },
61
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
62
+ @properties.push(@integrity_requirement =
63
+ CvssProperty.new(name: 'Integrity Requirement', abbreviation: 'IR', position: [9, 12],
64
+ values: [{ name: 'Low', abbreviation: 'L', weight: 0.5 },
65
+ { name: 'Medium', abbreviation: 'M', weight: 1.0 },
66
+ { name: 'High', abbreviation: 'H', weight: 1.5 },
67
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
68
+
69
+ @properties.push(@availability_requirement =
70
+ CvssProperty.new(name: 'Availability Requirement', abbreviation: 'AR', position: [10, 13],
71
+ values: [{ name: 'Low', abbreviation: 'L', weight: 0.5 },
72
+ { name: 'Medium', abbreviation: 'M', weight: 1.0 },
73
+ { name: 'High', abbreviation: 'H', weight: 1.5 },
74
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
75
+ @properties.push(@modified_attack_vector =
76
+ CvssProperty.new(name: 'Modified Attack Vector', abbreviation: 'MAV', position: [11, 14],
77
+ values: [{ name: 'Network', abbreviation: 'N', weight: 0.85 },
78
+ { name: 'Adjacent Network', abbreviation: 'A', weight: 0.62 },
79
+ { name: 'Local', abbreviation: 'L', weight: 0.55 },
80
+ { name: 'Physical', abbreviation: 'P', weight: 0.2 },
81
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
82
+ @properties.push(@modified_attack_complexity =
83
+ CvssProperty.new(name: 'Modified Attack Complexity', abbreviation: 'MAC', position: [12, 15],
84
+ values: [{ name: 'Low', abbreviation: 'L', weight: 0.77 },
85
+ { name: 'High', abbreviation: 'H', weight: 0.44 },
86
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
87
+ @properties.push(@modified_privileges_required =
88
+ CvssProperty.new(name: 'Modified Privileges Required', abbreviation: 'MPR', position: [13, 16],
89
+ values: [{ name: 'None', abbreviation: 'N', weight: 0.85 },
90
+ { name: 'Low', abbreviation: 'L', weight: 0.62 },
91
+ { name: 'High', abbreviation: 'H', weight: 0.27 },
92
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
93
+ @properties.push(@modified_user_interaction =
94
+ CvssProperty.new(name: 'Modified User Interaction', abbreviation: 'MUI', position: [14, 17],
95
+ values: [{ name: 'None', abbreviation: 'N', weight: 0.85 },
96
+ { name: 'Required', abbreviation: 'R', weight: 0.62 },
97
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
98
+ @properties.push(@modified_scope =
99
+ CvssProperty.new(name: 'Modified Scope', abbreviation: 'MS', position: [15, 18],
100
+ values: [{ name: 'Changed', abbreviation: 'C' },
101
+ { name: 'Unchanged', abbreviation: 'U' },
102
+ { name: 'Not Defined', abbreviation: 'X' }]))
103
+ @properties.push(@modified_confidentiality =
104
+ CvssProperty.new(name: 'Modified Confidentiality', abbreviation: 'MC', position: [16, 19],
105
+ values: [{ name: 'None', abbreviation: 'N', weight: 0 },
106
+ { name: 'Low', abbreviation: 'L', weight: 0.22 },
107
+ { name: 'High', abbreviation: 'H', weight: 0.56 },
108
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
109
+ @properties.push(@modified_integrity =
110
+ CvssProperty.new(name: 'Modified Integrity', abbreviation: 'MI', position: [17, 20],
111
+ values: [{ name: 'None', abbreviation: 'N', weight: 0 },
112
+ { name: 'Low', abbreviation: 'L', weight: 0.22 },
113
+ { name: 'High', abbreviation: 'H', weight: 0.56 },
114
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
115
+ @properties.push(@modified_availability =
116
+ CvssProperty.new(name: 'Modified Availability', abbreviation: 'MA', position: [18, 21],
117
+ values: [{ name: 'None', abbreviation: 'N', weight: 0 },
118
+ { name: 'Low', abbreviation: 'L', weight: 0.22 },
119
+ { name: 'High', abbreviation: 'H', weight: 0.56 },
120
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
121
+ end
122
+
123
+ def modified_impact_sub(isc_modified)
124
+ if @modified_scope.selected_value[:name] == 'Not Defined'
125
+ if @base.scope.selected_value[:name] == 'Changed'
126
+ return 7.52 * (isc_modified - 0.029) - 3.25 * (isc_modified * 0.9731 - 0.02)**13
127
+ else
128
+ return 6.42 * isc_modified
129
+ end
130
+ end
131
+
132
+ if @modified_scope.selected_value[:name] == 'Changed'
133
+ 7.52 * (isc_modified - 0.029) - 3.25 * (isc_modified * 0.9731 - 0.02)**13
134
+ else
135
+ 6.42 * isc_modified
136
+ end
137
+ end
138
+
139
+ def isc_modified
140
+ merged_modified_confidentiality = @modified_confidentiality
141
+ if @modified_confidentiality.selected_value[:name] == 'Not Defined'
142
+ merged_modified_confidentiality = @base.confidentiality
143
+ end
144
+
145
+ merged_modified_integrity = @modified_integrity
146
+ if @modified_integrity.selected_value[:name] == 'Not Defined'
147
+ merged_modified_integrity = @base.integrity
148
+ end
149
+
150
+ merged_modified_availability = @modified_availability
151
+ if @modified_availability.selected_value[:name] == 'Not Defined'
152
+ merged_modified_availability = @base.availability
153
+ end
154
+
155
+ confidentiality_score = 1 - merged_modified_confidentiality.score * @confidentiality_requirement.score
156
+ integrity_score = 1 - merged_modified_integrity.score * @integrity_requirement.score
157
+ availability_score = 1 - merged_modified_availability.score * @availability_requirement.score
158
+
159
+ [0.915, (1 - confidentiality_score * integrity_score * availability_score)].min
160
+ end
161
+
162
+ def modified_exploitability_sub(privilege_score)
163
+ merged_modified_attack_vector = @modified_attack_vector
164
+ if @modified_attack_vector.selected_value[:name] == 'Not Defined'
165
+ merged_modified_attack_vector = @base.attack_vector
166
+ end
167
+
168
+ merged_modified_attack_complexity = @modified_attack_complexity
169
+ if @modified_attack_complexity.selected_value[:name] == 'Not Defined'
170
+ merged_modified_attack_complexity = @base.attack_complexity
171
+ end
172
+
173
+ merged_modified_user_interaction = @modified_user_interaction
174
+ if @modified_user_interaction.selected_value[:name] == 'Not Defined'
175
+ merged_modified_user_interaction = @base.user_interaction
176
+ end
177
+
178
+ 8.22 * merged_modified_attack_vector.score * merged_modified_attack_complexity.score *
179
+ privilege_score * merged_modified_user_interaction.score
180
+ end
181
+
182
+ def calculate_score(modified_impact_sub_score, modified_exploitability_sub_score, temporal_score)
183
+ if @modified_scope.selected_value[:name] == 'Not Defined'
184
+ factor = @base.scope.selected_value[:name] == 'Changed' ? 1.08 : 1.0
185
+ else
186
+ factor = @modified_scope.selected_value[:name] == 'Changed' ? 1.08 : 1.0
187
+ end
188
+
189
+ Cvss31Helper.round_up(
190
+ [factor * (modified_impact_sub_score + modified_exploitability_sub_score), 10].min
191
+ ) * temporal_score
192
+ end
193
+ end
194
+ end
@@ -0,0 +1,56 @@
1
+ # CVSS-Suite, a Ruby gem to manage the CVSS vector
2
+ #
3
+ # Copyright (c) Siemens AG, 2019
4
+ #
5
+ # Authors:
6
+ # Oliver Hambörger <oliver.hamboerger@siemens.com>
7
+ #
8
+ # This work is licensed under the terms of the MIT license.
9
+ # See the LICENSE.md file in the top-level directory.
10
+
11
+ require_relative '../cvss_property'
12
+ require_relative '../cvss_metric'
13
+
14
+ module CvssSuite
15
+ ##
16
+ # This class represents a CVSS Temporal metric in version 3.1.
17
+ class Cvss31Temporal < CvssMetric
18
+ ##
19
+ # Property of this metric
20
+ attr_reader :exploit_code_maturity, :remediation_level, :report_confidence
21
+
22
+ ##
23
+ # Returns score of this metric
24
+ def score
25
+ return 1.0 unless valid?
26
+
27
+ @exploit_code_maturity.score * @remediation_level.score * @report_confidence.score
28
+ end
29
+
30
+ private
31
+
32
+ def init_properties
33
+ @properties.push(@exploit_code_maturity =
34
+ CvssProperty.new(name: 'Exploit Code Maturity', abbreviation: 'E', position: [8],
35
+ values: [{ name: 'Not Defined', abbreviation: 'X', weight: 1.0 },
36
+ { name: 'Unproven', abbreviation: 'U', weight: 0.91 },
37
+ { name: 'Proof-of-Concept', abbreviation: 'P', weight: 0.94 },
38
+ { name: 'Functional', abbreviation: 'F', weight: 0.97 },
39
+ { name: 'High', abbreviation: 'H', weight: 1.0 }]))
40
+ @properties.push(@remediation_level =
41
+ CvssProperty.new(name: 'Remediation Level', abbreviation: 'RL', position: [9],
42
+ values: [{ name: 'Not Defined', abbreviation: 'X', weight: 1.0 },
43
+ { name: 'Official Fix', abbreviation: 'O', weight: 0.95 },
44
+ { name: 'Temporary Fix', abbreviation: 'T', weight: 0.96 },
45
+ { name: 'Workaround', abbreviation: 'W', weight: 0.97 },
46
+ { name: 'Unavailable', abbreviation: 'U', weight: 1.0 }]))
47
+
48
+ @properties.push(@report_confidence =
49
+ CvssProperty.new(name: 'Report Confidence', abbreviation: 'RC', position: [10],
50
+ values: [{ name: 'Not Defined', abbreviation: 'X', weight: 1.0 },
51
+ { name: 'Unknown', abbreviation: 'U', weight: 0.92 },
52
+ { name: 'Reasonable', abbreviation: 'R', weight: 0.96 },
53
+ { name: 'Confirmed', abbreviation: 'C', weight: 1.0 }]))
54
+ end
55
+ end
56
+ end