cvss-suite 1.2.1 → 1.2.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 792fd7bf771ac83da4c5a4ee81cfce2e5ce42edf32d3a8d84ecdccdb8df1f555
4
- data.tar.gz: 6bc9148983a577d0e26ed5b19407ba6a366070e46166aae1a0b440c2328a59e4
3
+ metadata.gz: eba339bafe4db99aa85aadd132b2e10faeddc2cc5abc37b9554e5e14caaf9dd4
4
+ data.tar.gz: fbe718029edb8a08b0da04944bfac0b29b8e813dbb621b51b914bb3d644d832a
5
5
  SHA512:
6
- metadata.gz: ce3abc3c7f0c6eeaa02b3739da79e61445936bc8ee2e0c066252c06477022ec1aaf752ca18400727aac8f81f3627f96cb89fd932df261168d156f000da860db6
7
- data.tar.gz: c0ef0261fec46ae6340bf52f04e1739ffd92915b76039027fb98cf06db9ecd5e99472d31b54068c49618607ebdef6fd98e1b8a70bd2a7a097799d2321c17fe21
6
+ metadata.gz: 7576066639774a2e6ab36d716c657ff4e794f93d9eeda6565287772a5c097478877ba56a9fcf891b5c247fb15698bace28e92f4c2ea86e802f5c4a08e1046da2
7
+ data.tar.gz: 4c6f90f5431563ef303f9804f12375eb64f2b423e1e078dec2b62184b4f609fbcc0140e6bbcd483945014e1d681c820863efcc824f6b56816acc63ba16f32c51
@@ -2,6 +2,39 @@ inherit_from: .rubocop_todo.yml
2
2
 
3
3
  Metrics/LineLength:
4
4
  Max: 120
5
+ Exclude:
6
+ - 'lib/cvss_suite/cvss3/cvss3_environmental.rb'
7
+ - 'lib/cvss_suite/cvss31/cvss31_environmental.rb'
8
+
9
+ Metrics/ClassLength:
10
+ Exclude:
11
+ - 'lib/cvss_suite/cvss3/cvss3_environmental.rb'
12
+ - 'lib/cvss_suite/cvss31/cvss31_environmental.rb'
13
+
14
+ Metrics/MethodLength:
15
+ Exclude:
16
+ - 'lib/cvss_suite/cvss3/cvss3_environmental.rb'
17
+ - 'lib/cvss_suite/cvss31/cvss31_environmental.rb'
18
+
19
+ Metrics/BlockLength:
20
+ Exclude:
21
+ - 'spec/cvss3/cvss3_spec.rb'
22
+ - 'spec/cvss31/cvss31_spec.rb'
23
+
24
+ Style/IfUnlessModifier:
25
+ Exclude:
26
+ - 'lib/cvss_suite/cvss3/cvss3_environmental.rb'
27
+ - 'lib/cvss_suite/cvss31/cvss31_environmental.rb'
28
+
29
+ Style/GuardClause:
30
+ Exclude:
31
+ - 'lib/cvss_suite/cvss3/cvss3_environmental.rb'
32
+ - 'lib/cvss_suite/cvss31/cvss31_environmental.rb'
33
+
34
+ Style/ConditionalAssignment:
35
+ Exclude:
36
+ - 'lib/cvss_suite/cvss3/cvss3_environmental.rb'
37
+ - 'lib/cvss_suite/cvss31/cvss31_environmental.rb'
5
38
 
6
39
  Style/FrozenStringLiteralComment:
7
40
  Enabled: false
data/CHANGES.md CHANGED
@@ -2,6 +2,11 @@
2
2
  All notable changes to this project will be documented in this file.
3
3
  This project adheres to [Semantic Versioning](http://semver.org/).
4
4
 
5
+ ## [1.2.2] - 2020-07-19
6
+
7
+ ### Fixes
8
+ Fixed an error that resulted in incorrect environmental score if modified attributes were not defined.
9
+
5
10
  ## [1.2.1] - 2020-05-10
6
11
 
7
12
  ### Improvements
data/README.md CHANGED
@@ -100,8 +100,6 @@ Properties (Access Vector, Remediation Level, etc) do have a position attribute,
100
100
 
101
101
  Currently it is not possible to leave an attribute blank instead of ND/X. If you don't have a value for an attribute, please use ND/X instead.
102
102
 
103
- Because the documentation isn't clear on how to calculate the score if Modified Scope (CVSS 3.0 Environmental) is not defined, Modified Scope has to have a valid value (S/U).
104
-
105
103
  There is a possibility of implementations generating different scores (+/- 0,1) due to small floating-point inaccuracies. This can happen due to differences in floating point arithmetic between different languages and hardware platforms.
106
104
 
107
105
  ## Changelog
@@ -46,7 +46,7 @@ module CvssSuite
46
46
  def environmental_score
47
47
  return temporal_score unless @environmental.valid?
48
48
 
49
- Cvss3Helper.round_up(@environmental.score(@temporal.score))
49
+ Cvss3Helper.round_up(@environmental.score(@base, @temporal))
50
50
  end
51
51
 
52
52
  private
@@ -28,8 +28,20 @@ module CvssSuite
28
28
  ##
29
29
  # Returns score of this metric
30
30
 
31
- def score(temporal_score)
32
- privilege_score = Cvss3Helper.privileges_required_score(@modified_privileges_required, @modified_scope)
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)
33
45
 
34
46
  modified_exploitability_sub_score = modified_exploitability_sub(privilege_score)
35
47
 
@@ -37,7 +49,7 @@ module CvssSuite
37
49
 
38
50
  return 0 if modified_impact_sub_score <= 0
39
51
 
40
- calculate_score(modified_impact_sub_score, modified_exploitability_sub_score, temporal_score)
52
+ calculate_score modified_impact_sub_score, modified_exploitability_sub_score, temporal.score
41
53
  end
42
54
 
43
55
  private
@@ -88,7 +100,8 @@ module CvssSuite
88
100
  @properties.push(@modified_scope =
89
101
  CvssProperty.new(name: 'Modified Scope', abbreviation: 'MS', position: [15, 18],
90
102
  choices: [{ name: 'Changed', abbreviation: 'C' },
91
- { name: 'Unchanged', abbreviation: 'U' }]))
103
+ { name: 'Unchanged', abbreviation: 'U' },
104
+ { name: 'Not Defined', abbreviation: 'X' }]))
92
105
  @properties.push(@modified_confidentiality =
93
106
  CvssProperty.new(name: 'Modified Confidentiality', abbreviation: 'MC', position: [16, 19],
94
107
  choices: [{ name: 'None', abbreviation: 'N', weight: 0 },
@@ -110,6 +123,14 @@ module CvssSuite
110
123
  end
111
124
 
112
125
  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.02)**15
129
+ else
130
+ return 6.42 * isc_modified
131
+ end
132
+ end
133
+
113
134
  if @modified_scope.selected_choice[:name] == 'Changed'
114
135
  7.52 * (isc_modified - 0.029) - 3.25 * (isc_modified - 0.02)**15
115
136
  else
@@ -118,20 +139,54 @@ module CvssSuite
118
139
  end
119
140
 
120
141
  def isc_modified
121
- confidentiality_score = 1 - @modified_confidentiality.score * @confidentiality_requirement.score
122
- integrity_score = 1 - @modified_integrity.score * @integrity_requirement.score
123
- availability_score = 1 - @modified_availability.score * @availability_requirement.score
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
124
160
 
125
161
  [0.915, (1 - confidentiality_score * integrity_score * availability_score)].min
126
162
  end
127
163
 
128
164
  def modified_exploitability_sub(privilege_score)
129
- 8.22 * @modified_attack_vector.score * @modified_attack_complexity.score *
130
- privilege_score * @modified_user_interaction.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
131
182
  end
132
183
 
133
184
  def calculate_score(modified_impact_sub_score, modified_exploitability_sub_score, temporal_score)
134
- factor = @modified_scope.selected_choice[:name] == 'Changed' ? 1.08 : 1.0
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
135
190
 
136
191
  Cvss3Helper.round_up(
137
192
  [factor * (modified_impact_sub_score + modified_exploitability_sub_score), 10].min
@@ -47,7 +47,7 @@ module CvssSuite
47
47
  def environmental_score
48
48
  return temporal_score unless @environmental.valid?
49
49
 
50
- Cvss31Helper.round_up(@environmental.score(@temporal.score))
50
+ Cvss31Helper.round_up(@environmental.score(@base, @temporal))
51
51
  end
52
52
 
53
53
  private
@@ -28,9 +28,20 @@ module CvssSuite
28
28
 
29
29
  ##
30
30
  # Returns score of this metric
31
+ def score(base, temporal)
32
+ @base = base
31
33
 
32
- def score(temporal_score)
33
- privilege_score = Cvss3Helper.privileges_required_score(@modified_privileges_required, @modified_scope)
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)
34
45
 
35
46
  modified_exploitability_sub_score = modified_exploitability_sub(privilege_score)
36
47
 
@@ -38,7 +49,7 @@ module CvssSuite
38
49
 
39
50
  return 0 if modified_impact_sub_score <= 0
40
51
 
41
- calculate_score modified_impact_sub_score, modified_exploitability_sub_score, temporal_score
52
+ calculate_score modified_impact_sub_score, modified_exploitability_sub_score, temporal.score
42
53
  end
43
54
 
44
55
  private
@@ -89,7 +100,8 @@ module CvssSuite
89
100
  @properties.push(@modified_scope =
90
101
  CvssProperty.new(name: 'Modified Scope', abbreviation: 'MS', position: [15, 18],
91
102
  choices: [{ name: 'Changed', abbreviation: 'C' },
92
- { name: 'Unchanged', abbreviation: 'U' }]))
103
+ { name: 'Unchanged', abbreviation: 'U' },
104
+ { name: 'Not Defined', abbreviation: 'X' }]))
93
105
  @properties.push(@modified_confidentiality =
94
106
  CvssProperty.new(name: 'Modified Confidentiality', abbreviation: 'MC', position: [16, 19],
95
107
  choices: [{ name: 'None', abbreviation: 'N', weight: 0 },
@@ -111,6 +123,14 @@ module CvssSuite
111
123
  end
112
124
 
113
125
  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
+
114
134
  if @modified_scope.selected_choice[:name] == 'Changed'
115
135
  7.52 * (isc_modified - 0.029) - 3.25 * (isc_modified * 0.9731 - 0.02)**13
116
136
  else
@@ -119,20 +139,54 @@ module CvssSuite
119
139
  end
120
140
 
121
141
  def isc_modified
122
- confidentiality_score = 1 - @modified_confidentiality.score * @confidentiality_requirement.score
123
- integrity_score = 1 - @modified_integrity.score * @integrity_requirement.score
124
- availability_score = 1 - @modified_availability.score * @availability_requirement.score
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
125
160
 
126
161
  [0.915, (1 - confidentiality_score * integrity_score * availability_score)].min
127
162
  end
128
163
 
129
164
  def modified_exploitability_sub(privilege_score)
130
- 8.22 * @modified_attack_vector.score * @modified_attack_complexity.score *
131
- privilege_score * @modified_user_interaction.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
132
182
  end
133
183
 
134
184
  def calculate_score(modified_impact_sub_score, modified_exploitability_sub_score, temporal_score)
135
- factor = @modified_scope.selected_choice[:name] == 'Changed' ? 1.08 : 1.0
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
136
190
 
137
191
  Cvss31Helper.round_up(
138
192
  [factor * (modified_impact_sub_score + modified_exploitability_sub_score), 10].min
@@ -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.1'
12
+ VERSION = '1.2.2'
13
13
  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.1
4
+ version: 1.2.2
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-05-10 00:00:00.000000000 Z
11
+ date: 2020-07-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler