cvss-suite 2.0.0 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5917987479ecee6f2a020076b59751dda816e259d984a540bd1b6c0fb40b6422
4
- data.tar.gz: 5225e8afd1e553709590bc2bb1a60955c76462d62bbfe825bf2a2081d4647163
3
+ metadata.gz: d4f32e67e6919d58fbd35bc9af64a0af838e484ecfc28d17f83ebc623df9cff5
4
+ data.tar.gz: fc758c191bfbbd12e24e15d8b2d4fe1e012e4597ea0fcc28972bbe4bb9d8f66d
5
5
  SHA512:
6
- metadata.gz: 6824cf5f7f04f2f8eb5ef5613e61fd86b275b36fd316c7f4d4d60af8f9422176b1485eefe24de482e9dc98c328291ed2a7bccafdec3f03d353fae505c43d988c
7
- data.tar.gz: 2014e6368dea9deecd623d88a7f7b4d4c5367d1cb3a832ebdac3f6b47d5308b03e1129d157a11dad7e6ac93645ca971ad8dc4b8d85efdd83145f0f58883af6a4
6
+ metadata.gz: e6af1a297fb42858352914040f4d7d75923e3d6e88ed0ae14b85243252d58d169a8eddc900fd0ad1f5506a86bfc24f576e8d321fd7f2b4a01afa040ac9861ebc
7
+ data.tar.gz: fcb7590bd3fbe1eef4c8d5ea4f72e1cf04db96005034f74f9e764cb3853f1e0d39d73a6ba3c77416be69853f01a3c248d880997ae474534f5c8f2e7724a86ff6
@@ -15,7 +15,7 @@ jobs:
15
15
  uses: actions/setup-ruby@v1
16
16
  with:
17
17
  ruby-version: ${{ matrix.ruby }}
18
- - name: Build
18
+ - name: Install gems
19
19
  run: |
20
20
  gem install bundler -v ">= 1.10"
21
21
  bundle install --jobs 4 --retry 3
@@ -13,9 +13,9 @@ jobs:
13
13
  uses: actions/setup-ruby@v1
14
14
  with:
15
15
  ruby-version: 2.7
16
- - name: Build
16
+ - name: Install gems
17
17
  run: |
18
- gem install bundler -v "=> 1.10"
18
+ gem install bundler -v ">= 1.10"
19
19
  gem install rubocop
20
- - name: Run tests
20
+ - name: Run checks
21
21
  run: rubocop -F --fail-level C -f s
@@ -5,6 +5,39 @@ AllCops:
5
5
 
6
6
  Metrics/LineLength:
7
7
  Max: 120
8
+ Exclude:
9
+ - 'lib/cvss_suite/cvss3/cvss3_environmental.rb'
10
+ - 'lib/cvss_suite/cvss31/cvss31_environmental.rb'
11
+
12
+ Metrics/ClassLength:
13
+ Exclude:
14
+ - 'lib/cvss_suite/cvss3/cvss3_environmental.rb'
15
+ - 'lib/cvss_suite/cvss31/cvss31_environmental.rb'
16
+
17
+ Metrics/MethodLength:
18
+ Exclude:
19
+ - 'lib/cvss_suite/cvss3/cvss3_environmental.rb'
20
+ - 'lib/cvss_suite/cvss31/cvss31_environmental.rb'
21
+
22
+ Metrics/BlockLength:
23
+ Exclude:
24
+ - 'spec/cvss3/cvss3_spec.rb'
25
+ - 'spec/cvss31/cvss31_spec.rb'
26
+
27
+ Style/IfUnlessModifier:
28
+ Exclude:
29
+ - 'lib/cvss_suite/cvss3/cvss3_environmental.rb'
30
+ - 'lib/cvss_suite/cvss31/cvss31_environmental.rb'
31
+
32
+ Style/GuardClause:
33
+ Exclude:
34
+ - 'lib/cvss_suite/cvss3/cvss3_environmental.rb'
35
+ - 'lib/cvss_suite/cvss31/cvss31_environmental.rb'
36
+
37
+ Style/ConditionalAssignment:
38
+ Exclude:
39
+ - 'lib/cvss_suite/cvss3/cvss3_environmental.rb'
40
+ - 'lib/cvss_suite/cvss31/cvss31_environmental.rb'
8
41
 
9
42
  Style/FrozenStringLiteralComment:
10
43
  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
+ ## [2.0.1] - 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
  ## [2.0.0] - 2020-05-10
6
11
 
7
12
  ### Breaking Changes
data/README.md CHANGED
@@ -104,8 +104,6 @@ Properties (Access Vector, Remediation Level, etc) do have a position attribute,
104
104
 
105
105
  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.
106
106
 
107
- 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).
108
-
109
107
  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.
110
108
 
111
109
  ## Changelog
@@ -36,5 +36,5 @@ Besides calculating the Base, Temporal and Environmental Score, you are able to
36
36
  spec.add_development_dependency 'bundler', '>= 1.10'
37
37
  spec.add_development_dependency 'rspec', '~> 3.4'
38
38
  spec.add_development_dependency 'rspec-its', '~> 1.2'
39
- spec.add_development_dependency 'simplecov', '~> 0.11'
39
+ spec.add_development_dependency 'simplecov', '~> 0.18'
40
40
  end
@@ -41,33 +41,33 @@ module CvssSuite
41
41
  @properties.push(@access_vector =
42
42
  CvssProperty.new(name: 'Access Vector', abbreviation: 'AV', position: [0],
43
43
  values: [{ name: 'Network', abbreviation: 'N', weight: 1.0 },
44
- { name: 'Adjacent Network', abbreviation: 'A', weight: 0.646 },
45
- { name: 'Local', abbreviation: 'L', weight: 0.395 }]))
44
+ { name: 'Adjacent Network', abbreviation: 'A', weight: 0.646 },
45
+ { name: 'Local', abbreviation: 'L', weight: 0.395 }]))
46
46
  @properties.push(@access_complexity =
47
47
  CvssProperty.new(name: 'Access Complexity', abbreviation: 'AC', position: [1],
48
48
  values: [{ name: 'Low', abbreviation: 'L', weight: 0.71 },
49
- { name: 'Medium', abbreviation: 'M', weight: 0.61 },
50
- { name: 'High', abbreviation: 'H', weight: 0.35 }]))
49
+ { name: 'Medium', abbreviation: 'M', weight: 0.61 },
50
+ { name: 'High', abbreviation: 'H', weight: 0.35 }]))
51
51
  @properties.push(@authentication =
52
52
  CvssProperty.new(name: 'Authentication', abbreviation: 'Au', position: [2],
53
53
  values: [{ name: 'None', abbreviation: 'N', weight: 0.704 },
54
- { name: 'Single', abbreviation: 'S', weight: 0.56 },
55
- { name: 'Multiple', abbreviation: 'M', weight: 0.45 }]))
54
+ { name: 'Single', abbreviation: 'S', weight: 0.56 },
55
+ { name: 'Multiple', abbreviation: 'M', weight: 0.45 }]))
56
56
  @properties.push(@confidentiality_impact =
57
57
  CvssProperty.new(name: 'Confidentiality Impact', abbreviation: 'C', position: [3],
58
58
  values: [{ name: 'None', abbreviation: 'N', weight: 0.0 },
59
- { name: 'Partial', abbreviation: 'P', weight: 0.275 },
60
- { name: 'Complete', abbreviation: 'C', weight: 0.66 }]))
59
+ { name: 'Partial', abbreviation: 'P', weight: 0.275 },
60
+ { name: 'Complete', abbreviation: 'C', weight: 0.66 }]))
61
61
  @properties.push(@integrity_impact =
62
62
  CvssProperty.new(name: 'Integrity Impact', abbreviation: 'I', position: [4],
63
63
  values: [{ name: 'None', abbreviation: 'N', weight: 0.0 },
64
- { name: 'Partial', abbreviation: 'P', weight: 0.275 },
65
- { name: 'Complete', abbreviation: 'C', weight: 0.66 }]))
64
+ { name: 'Partial', abbreviation: 'P', weight: 0.275 },
65
+ { name: 'Complete', abbreviation: 'C', weight: 0.66 }]))
66
66
  @properties.push(@availability_impact =
67
67
  CvssProperty.new(name: 'Availability Impact', abbreviation: 'A', position: [5],
68
68
  values: [{ name: 'None', abbreviation: 'N', weight: 0.0 },
69
- { name: 'Partial', abbreviation: 'P', weight: 0.275 },
70
- { name: 'Complete', abbreviation: 'C', weight: 0.66 }]))
69
+ { name: 'Partial', abbreviation: 'P', weight: 0.275 },
70
+ { name: 'Complete', abbreviation: 'C', weight: 0.66 }]))
71
71
  end
72
72
 
73
73
  def calc_impact(sr_cr_score, sr_ir_score, sr_ar_score)
@@ -37,36 +37,36 @@ module CvssSuite
37
37
  @properties.push(@collateral_damage_potential =
38
38
  CvssProperty.new(name: 'Collateral Damage Potential', abbreviation: 'CDP', position: [6, 9],
39
39
  values: [{ name: 'None', abbreviation: 'N', weight: 0.0 },
40
- { name: 'Low', abbreviation: 'L', weight: 0.1 },
41
- { name: 'Low-Medium', abbreviation: 'LM', weight: 0.3 },
42
- { name: 'Medium-High', abbreviation: 'MH', weight: 0.4 },
43
- { name: 'High', abbreviation: 'H', weight: 0.5 },
44
- { name: 'Not Defined', abbreviation: 'ND', weight: 0.0 }]))
40
+ { name: 'Low', abbreviation: 'L', weight: 0.1 },
41
+ { name: 'Low-Medium', abbreviation: 'LM', weight: 0.3 },
42
+ { name: 'Medium-High', abbreviation: 'MH', weight: 0.4 },
43
+ { name: 'High', abbreviation: 'H', weight: 0.5 },
44
+ { name: 'Not Defined', abbreviation: 'ND', weight: 0.0 }]))
45
45
  @properties.push(@target_distribution =
46
46
  CvssProperty.new(name: 'Target Distribution', abbreviation: 'TD', position: [7, 10],
47
47
  values: [{ name: 'None', abbreviation: 'N', weight: 0.0 },
48
- { name: 'Low', abbreviation: 'L', weight: 0.25 },
49
- { name: 'Medium', abbreviation: 'M', weight: 0.75 },
50
- { name: 'High', abbreviation: 'H', weight: 1.0 },
51
- { name: 'Not Defined', abbreviation: 'ND', weight: 1.0 }]))
48
+ { name: 'Low', abbreviation: 'L', weight: 0.25 },
49
+ { name: 'Medium', abbreviation: 'M', weight: 0.75 },
50
+ { name: 'High', abbreviation: 'H', weight: 1.0 },
51
+ { name: 'Not Defined', abbreviation: 'ND', weight: 1.0 }]))
52
52
  @properties.push(@security_requirements_cr =
53
53
  CvssProperty.new(name: 'Confidentiality Requirement', abbreviation: 'CR', position: [8, 11],
54
54
  values: [{ name: 'Low', abbreviation: 'L', weight: 0.5 },
55
- { name: 'Medium', abbreviation: 'M', weight: 1.0 },
56
- { name: 'High', abbreviation: 'H', weight: 1.51 },
57
- { name: 'Not Defined', abbreviation: 'ND', weight: 1.0 }]))
55
+ { name: 'Medium', abbreviation: 'M', weight: 1.0 },
56
+ { name: 'High', abbreviation: 'H', weight: 1.51 },
57
+ { name: 'Not Defined', abbreviation: 'ND', weight: 1.0 }]))
58
58
  @properties.push(@security_requirements_ir =
59
59
  CvssProperty.new(name: 'Integrity Requirement', abbreviation: 'IR', position: [9, 12],
60
60
  values: [{ name: 'Low', abbreviation: 'L', weight: 0.5 },
61
- { name: 'Medium', abbreviation: 'M', weight: 1.0 },
62
- { name: 'High', abbreviation: 'H', weight: 1.51 },
63
- { name: 'Not Defined', abbreviation: 'ND', weight: 1.0 }]))
61
+ { name: 'Medium', abbreviation: 'M', weight: 1.0 },
62
+ { name: 'High', abbreviation: 'H', weight: 1.51 },
63
+ { name: 'Not Defined', abbreviation: 'ND', weight: 1.0 }]))
64
64
  @properties.push(@security_requirements_ar =
65
65
  CvssProperty.new(name: 'Availability Requirement', abbreviation: 'AR', position: [10, 13],
66
66
  values: [{ name: 'Low', abbreviation: 'L', weight: 0.5 },
67
- { name: 'Medium', abbreviation: 'M', weight: 1.0 },
68
- { name: 'High', abbreviation: 'H', weight: 1.51 },
69
- { name: 'Not Defined', abbreviation: 'ND', weight: 1.0 }]))
67
+ { name: 'Medium', abbreviation: 'M', weight: 1.0 },
68
+ { name: 'High', abbreviation: 'H', weight: 1.51 },
69
+ { name: 'Not Defined', abbreviation: 'ND', weight: 1.0 }]))
70
70
  end
71
71
  end
72
72
  end
@@ -33,24 +33,24 @@ module CvssSuite
33
33
  @properties.push(@exploitability =
34
34
  CvssProperty.new(name: 'Exploitability', abbreviation: 'E', position: [6],
35
35
  values: [{ name: 'Not Defined', abbreviation: 'ND', weight: 1 },
36
- { name: 'Unproven', abbreviation: 'U', weight: 0.85 },
37
- { name: 'Proof-of-Concept', abbreviation: 'POC', weight: 0.9 },
38
- { name: 'Functional', abbreviation: 'F', weight: 0.95 },
39
- { name: 'High', abbreviation: 'H', weight: 1 }]))
36
+ { name: 'Unproven', abbreviation: 'U', weight: 0.85 },
37
+ { name: 'Proof-of-Concept', abbreviation: 'POC', weight: 0.9 },
38
+ { name: 'Functional', abbreviation: 'F', weight: 0.95 },
39
+ { name: 'High', abbreviation: 'H', weight: 1 }]))
40
40
  @properties.push(@remediation_level =
41
41
  CvssProperty.new(name: 'Remediation Level', abbreviation: 'RL', position: [7],
42
42
  values: [{ name: 'Not Defined', abbreviation: 'ND', weight: 1 },
43
- { name: 'Official Fix', abbreviation: 'OF', weight: 0.87 },
44
- { name: 'Temporary Fix', abbreviation: 'TF', weight: 0.9 },
45
- { name: 'Workaround', abbreviation: 'W', weight: 0.95 },
46
- { name: 'Unavailable', abbreviation: 'U', weight: 1 }]))
43
+ { name: 'Official Fix', abbreviation: 'OF', weight: 0.87 },
44
+ { name: 'Temporary Fix', abbreviation: 'TF', weight: 0.9 },
45
+ { name: 'Workaround', abbreviation: 'W', weight: 0.95 },
46
+ { name: 'Unavailable', abbreviation: 'U', weight: 1 }]))
47
47
 
48
48
  @properties.push(@report_confidence =
49
49
  CvssProperty.new(name: 'Report Confidence', abbreviation: 'RC', position: [8],
50
50
  values: [{ name: 'Not Defined', abbreviation: 'ND', weight: 1 },
51
- { name: 'Unconfirmed', abbreviation: 'UC', weight: 0.9 },
52
- { name: 'Uncorroborated', abbreviation: 'UR', weight: 0.95 },
53
- { name: 'Confirmed', abbreviation: 'C', weight: 1 }]))
51
+ { name: 'Unconfirmed', abbreviation: 'UC', weight: 0.9 },
52
+ { name: 'Uncorroborated', abbreviation: 'UR', weight: 0.95 },
53
+ { name: 'Confirmed', abbreviation: 'C', weight: 1 }]))
54
54
  end
55
55
  end
56
56
  end
@@ -41,7 +41,7 @@ module CvssSuite
41
41
  def environmental_score
42
42
  return temporal_score unless @environmental.valid?
43
43
 
44
- Cvss3Helper.round_up(@environmental.score(@temporal.score))
44
+ Cvss3Helper.round_up(@environmental.score(@base, @temporal))
45
45
  end
46
46
 
47
47
  private
@@ -52,41 +52,41 @@ module CvssSuite
52
52
  @properties.push(@attack_vector =
53
53
  CvssProperty.new(name: 'Attack Vector', abbreviation: 'AV', position: [0],
54
54
  values: [{ name: 'Network', abbreviation: 'N', weight: 0.85 },
55
- { name: 'Adjacent', abbreviation: 'A', weight: 0.62 },
56
- { name: 'Local', abbreviation: 'L', weight: 0.55 },
57
- { name: 'Physical', abbreviation: 'P', weight: 0.2 }]))
55
+ { name: 'Adjacent', abbreviation: 'A', weight: 0.62 },
56
+ { name: 'Local', abbreviation: 'L', weight: 0.55 },
57
+ { name: 'Physical', abbreviation: 'P', weight: 0.2 }]))
58
58
  @properties.push(@attack_complexity =
59
59
  CvssProperty.new(name: 'Attack Complexity', abbreviation: 'AC', position: [1],
60
60
  values: [{ name: 'Low', abbreviation: 'L', weight: 0.77 },
61
- { name: 'High', abbreviation: 'H', weight: 0.44 }]))
61
+ { name: 'High', abbreviation: 'H', weight: 0.44 }]))
62
62
  @properties.push(@privileges_required =
63
63
  CvssProperty.new(name: 'Privileges Required', abbreviation: 'PR', position: [2],
64
64
  values: [{ name: 'None', abbreviation: 'N', weight: 0.85 },
65
- { name: 'Low', abbreviation: 'L', weight: 0.62 },
66
- { name: 'High', abbreviation: 'H', weight: 0.27 }]))
65
+ { name: 'Low', abbreviation: 'L', weight: 0.62 },
66
+ { name: 'High', abbreviation: 'H', weight: 0.27 }]))
67
67
  @properties.push(@user_interaction =
68
68
  CvssProperty.new(name: 'User Interaction', abbreviation: 'UI', position: [3],
69
69
  values: [{ name: 'None', abbreviation: 'N', weight: 0.85 },
70
- { name: 'Required', abbreviation: 'R', weight: 0.62 }]))
70
+ { name: 'Required', abbreviation: 'R', weight: 0.62 }]))
71
71
  @properties.push(@scope =
72
72
  CvssProperty.new(name: 'Scope', abbreviation: 'S', position: [4],
73
73
  values: [{ name: 'Unchanged', abbreviation: 'U' },
74
- { name: 'Changed', abbreviation: 'C' }]))
74
+ { name: 'Changed', abbreviation: 'C' }]))
75
75
  @properties.push(@confidentiality =
76
76
  CvssProperty.new(name: 'Confidentiality', abbreviation: 'C', position: [5],
77
77
  values: [{ name: 'None', abbreviation: 'N', weight: 0.0 },
78
- { name: 'Low', abbreviation: 'L', weight: 0.22 },
79
- { name: 'High', abbreviation: 'H', weight: 0.56 }]))
78
+ { name: 'Low', abbreviation: 'L', weight: 0.22 },
79
+ { name: 'High', abbreviation: 'H', weight: 0.56 }]))
80
80
  @properties.push(@integrity =
81
81
  CvssProperty.new(name: 'Integrity', abbreviation: 'I', position: [6],
82
82
  values: [{ name: 'None', abbreviation: 'N', weight: 0.0 },
83
- { name: 'Low', abbreviation: 'L', weight: 0.22 },
84
- { name: 'High', abbreviation: 'H', weight: 0.56 }]))
83
+ { name: 'Low', abbreviation: 'L', weight: 0.22 },
84
+ { name: 'High', abbreviation: 'H', weight: 0.56 }]))
85
85
  @properties.push(@availability =
86
86
  CvssProperty.new(name: 'Availability', abbreviation: 'A', position: [7],
87
87
  values: [{ name: 'None', abbreviation: 'N', weight: 0.0 },
88
- { name: 'Low', abbreviation: 'L', weight: 0.22 },
89
- { name: 'High', abbreviation: 'H', weight: 0.56 }]))
88
+ { name: 'Low', abbreviation: 'L', weight: 0.22 },
89
+ { name: 'High', abbreviation: 'H', weight: 0.56 }]))
90
90
  end
91
91
  end
92
92
  end
@@ -26,8 +26,20 @@ module CvssSuite
26
26
  ##
27
27
  # Returns score of this metric
28
28
 
29
- def score(temporal_score)
30
- privilege_score = Cvss3Helper.privileges_required_score(@modified_privileges_required, @modified_scope)
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)
31
43
 
32
44
  modified_exploitability_sub_score = modified_exploitability_sub(privilege_score)
33
45
 
@@ -35,7 +47,7 @@ module CvssSuite
35
47
 
36
48
  return 0 if modified_impact_sub_score <= 0
37
49
 
38
- calculate_score(modified_impact_sub_score, modified_exploitability_sub_score, temporal_score)
50
+ calculate_score modified_impact_sub_score, modified_exploitability_sub_score, temporal.score
39
51
  end
40
52
 
41
53
  private
@@ -44,70 +56,79 @@ module CvssSuite
44
56
  @properties.push(@confidentiality_requirement =
45
57
  CvssProperty.new(name: 'Confidentiality Requirement', abbreviation: 'CR', position: [8, 11],
46
58
  values: [{ name: 'Low', abbreviation: 'L', weight: 0.5 },
47
- { name: 'Medium', abbreviation: 'M', weight: 1.0 },
48
- { name: 'High', abbreviation: 'H', weight: 1.5 },
49
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
59
+ { name: 'Medium', abbreviation: 'M', weight: 1.0 },
60
+ { name: 'High', abbreviation: 'H', weight: 1.5 },
61
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
50
62
  @properties.push(@integrity_requirement =
51
63
  CvssProperty.new(name: 'Integrity Requirement', abbreviation: 'IR', position: [9, 12],
52
64
  values: [{ name: 'Low', abbreviation: 'L', weight: 0.5 },
53
- { name: 'Medium', abbreviation: 'M', weight: 1.0 },
54
- { name: 'High', abbreviation: 'H', weight: 1.5 },
55
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
65
+ { name: 'Medium', abbreviation: 'M', weight: 1.0 },
66
+ { name: 'High', abbreviation: 'H', weight: 1.5 },
67
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
56
68
 
57
69
  @properties.push(@availability_requirement =
58
70
  CvssProperty.new(name: 'Availability Requirement', abbreviation: 'AR', position: [10, 13],
59
71
  values: [{ name: 'Low', abbreviation: 'L', weight: 0.5 },
60
- { name: 'Medium', abbreviation: 'M', weight: 1.0 },
61
- { name: 'High', abbreviation: 'H', weight: 1.5 },
62
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
72
+ { name: 'Medium', abbreviation: 'M', weight: 1.0 },
73
+ { name: 'High', abbreviation: 'H', weight: 1.5 },
74
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
63
75
  @properties.push(@modified_attack_vector =
64
76
  CvssProperty.new(name: 'Modified Attack Vector', abbreviation: 'MAV', position: [11, 14],
65
77
  values: [{ name: 'Network', abbreviation: 'N', weight: 0.85 },
66
- { name: 'Adjacent Network', abbreviation: 'A', weight: 0.62 },
67
- { name: 'Local', abbreviation: 'L', weight: 0.55 },
68
- { name: 'Physical', abbreviation: 'P', weight: 0.2 },
69
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
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 }]))
70
82
  @properties.push(@modified_attack_complexity =
71
83
  CvssProperty.new(name: 'Modified Attack Complexity', abbreviation: 'MAC', position: [12, 15],
72
84
  values: [{ name: 'Low', abbreviation: 'L', weight: 0.77 },
73
- { name: 'High', abbreviation: 'H', weight: 0.44 },
74
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
85
+ { name: 'High', abbreviation: 'H', weight: 0.44 },
86
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
75
87
  @properties.push(@modified_privileges_required =
76
88
  CvssProperty.new(name: 'Modified Privileges Required', abbreviation: 'MPR', position: [13, 16],
77
89
  values: [{ name: 'None', abbreviation: 'N', weight: 0.85 },
78
- { name: 'Low', abbreviation: 'L', weight: 0.62 },
79
- { name: 'High', abbreviation: 'H', weight: 0.27 },
80
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
90
+ { name: 'Low', abbreviation: 'L', weight: 0.62 },
91
+ { name: 'High', abbreviation: 'H', weight: 0.27 },
92
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
81
93
  @properties.push(@modified_user_interaction =
82
94
  CvssProperty.new(name: 'Modified User Interaction', abbreviation: 'MUI', position: [14, 17],
83
95
  values: [{ name: 'None', abbreviation: 'N', weight: 0.85 },
84
- { name: 'Required', abbreviation: 'R', weight: 0.62 },
85
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
96
+ { name: 'Required', abbreviation: 'R', weight: 0.62 },
97
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
86
98
  @properties.push(@modified_scope =
87
99
  CvssProperty.new(name: 'Modified Scope', abbreviation: 'MS', position: [15, 18],
88
100
  values: [{ name: 'Changed', abbreviation: 'C' },
89
- { name: 'Unchanged', abbreviation: 'U' }]))
101
+ { name: 'Unchanged', abbreviation: 'U' },
102
+ { name: 'Not Defined', abbreviation: 'X' }]))
90
103
  @properties.push(@modified_confidentiality =
91
104
  CvssProperty.new(name: 'Modified Confidentiality', abbreviation: 'MC', position: [16, 19],
92
105
  values: [{ name: 'None', abbreviation: 'N', weight: 0 },
93
- { name: 'Low', abbreviation: 'L', weight: 0.22 },
94
- { name: 'High', abbreviation: 'H', weight: 0.56 },
95
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
106
+ { name: 'Low', abbreviation: 'L', weight: 0.22 },
107
+ { name: 'High', abbreviation: 'H', weight: 0.56 },
108
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
96
109
  @properties.push(@modified_integrity =
97
110
  CvssProperty.new(name: 'Modified Integrity', abbreviation: 'MI', position: [17, 20],
98
111
  values: [{ name: 'None', abbreviation: 'N', weight: 0 },
99
- { name: 'Low', abbreviation: 'L', weight: 0.22 },
100
- { name: 'High', abbreviation: 'H', weight: 0.56 },
101
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
112
+ { name: 'Low', abbreviation: 'L', weight: 0.22 },
113
+ { name: 'High', abbreviation: 'H', weight: 0.56 },
114
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
102
115
  @properties.push(@modified_availability =
103
116
  CvssProperty.new(name: 'Modified Availability', abbreviation: 'MA', position: [18, 21],
104
117
  values: [{ name: 'None', abbreviation: 'N', weight: 0 },
105
- { name: 'Low', abbreviation: 'L', weight: 0.22 },
106
- { name: 'High', abbreviation: 'H', weight: 0.56 },
107
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
118
+ { name: 'Low', abbreviation: 'L', weight: 0.22 },
119
+ { name: 'High', abbreviation: 'H', weight: 0.56 },
120
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
108
121
  end
109
122
 
110
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.02)**15
127
+ else
128
+ return 6.42 * isc_modified
129
+ end
130
+ end
131
+
111
132
  if @modified_scope.selected_value[:name] == 'Changed'
112
133
  7.52 * (isc_modified - 0.029) - 3.25 * (isc_modified - 0.02)**15
113
134
  else
@@ -116,20 +137,54 @@ module CvssSuite
116
137
  end
117
138
 
118
139
  def isc_modified
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
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
122
158
 
123
159
  [0.915, (1 - confidentiality_score * integrity_score * availability_score)].min
124
160
  end
125
161
 
126
162
  def modified_exploitability_sub(privilege_score)
127
- 8.22 * @modified_attack_vector.score * @modified_attack_complexity.score *
128
- privilege_score * @modified_user_interaction.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
129
180
  end
130
181
 
131
182
  def calculate_score(modified_impact_sub_score, modified_exploitability_sub_score, temporal_score)
132
- factor = @modified_scope.selected_value[:name] == 'Changed' ? 1.08 : 1.0
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
133
188
 
134
189
  Cvss3Helper.round_up(
135
190
  [factor * (modified_impact_sub_score + modified_exploitability_sub_score), 10].min
@@ -33,24 +33,24 @@ module CvssSuite
33
33
  @properties.push(@exploit_code_maturity =
34
34
  CvssProperty.new(name: 'Exploit Code Maturity', abbreviation: 'E', position: [8],
35
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 }]))
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
40
  @properties.push(@remediation_level =
41
41
  CvssProperty.new(name: 'Remediation Level', abbreviation: 'RL', position: [9],
42
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 }]))
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
47
 
48
48
  @properties.push(@report_confidence =
49
49
  CvssProperty.new(name: 'Report Confidence', abbreviation: 'RC', position: [10],
50
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 }]))
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
54
  end
55
55
  end
56
56
  end
@@ -46,7 +46,7 @@ module CvssSuite
46
46
  def environmental_score
47
47
  return temporal_score unless @environmental.valid?
48
48
 
49
- Cvss31Helper.round_up(@environmental.score(@temporal.score))
49
+ Cvss31Helper.round_up(@environmental.score(@base, @temporal))
50
50
  end
51
51
 
52
52
  private
@@ -53,41 +53,41 @@ module CvssSuite
53
53
  @properties.push(@attack_vector =
54
54
  CvssProperty.new(name: 'Attack Vector', abbreviation: 'AV', position: [0],
55
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 }]))
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
59
  @properties.push(@attack_complexity =
60
60
  CvssProperty.new(name: 'Attack Complexity', abbreviation: 'AC', position: [1],
61
61
  values: [{ name: 'Low', abbreviation: 'L', weight: 0.77 },
62
- { name: 'High', abbreviation: 'H', weight: 0.44 }]))
62
+ { name: 'High', abbreviation: 'H', weight: 0.44 }]))
63
63
  @properties.push(@privileges_required =
64
64
  CvssProperty.new(name: 'Privileges Required', abbreviation: 'PR', position: [2],
65
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 }]))
66
+ { name: 'Low', abbreviation: 'L', weight: 0.62 },
67
+ { name: 'High', abbreviation: 'H', weight: 0.27 }]))
68
68
  @properties.push(@user_interaction =
69
69
  CvssProperty.new(name: 'User Interaction', abbreviation: 'UI', position: [3],
70
70
  values: [{ name: 'None', abbreviation: 'N', weight: 0.85 },
71
- { name: 'Required', abbreviation: 'R', weight: 0.62 }]))
71
+ { name: 'Required', abbreviation: 'R', weight: 0.62 }]))
72
72
  @properties.push(@scope =
73
73
  CvssProperty.new(name: 'Scope', abbreviation: 'S', position: [4],
74
74
  values: [{ name: 'Unchanged', abbreviation: 'U' },
75
- { name: 'Changed', abbreviation: 'C' }]))
75
+ { name: 'Changed', abbreviation: 'C' }]))
76
76
  @properties.push(@confidentiality =
77
77
  CvssProperty.new(name: 'Confidentiality', abbreviation: 'C', position: [5],
78
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 }]))
79
+ { name: 'Low', abbreviation: 'L', weight: 0.22 },
80
+ { name: 'High', abbreviation: 'H', weight: 0.56 }]))
81
81
  @properties.push(@integrity =
82
82
  CvssProperty.new(name: 'Integrity', abbreviation: 'I', position: [6],
83
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 }]))
84
+ { name: 'Low', abbreviation: 'L', weight: 0.22 },
85
+ { name: 'High', abbreviation: 'H', weight: 0.56 }]))
86
86
  @properties.push(@availability =
87
87
  CvssProperty.new(name: 'Availability', abbreviation: 'A', position: [7],
88
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 }]))
89
+ { name: 'Low', abbreviation: 'L', weight: 0.22 },
90
+ { name: 'High', abbreviation: 'H', weight: 0.56 }]))
91
91
  end
92
92
  end
93
93
  end
@@ -26,8 +26,20 @@ module CvssSuite
26
26
 
27
27
  ##
28
28
  # Returns score of this metric
29
- def score(temporal_score)
30
- privilege_score = Cvss3Helper.privileges_required_score(@modified_privileges_required, @modified_scope)
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)
31
43
 
32
44
  modified_exploitability_sub_score = modified_exploitability_sub(privilege_score)
33
45
 
@@ -35,7 +47,7 @@ module CvssSuite
35
47
 
36
48
  return 0 if modified_impact_sub_score <= 0
37
49
 
38
- calculate_score modified_impact_sub_score, modified_exploitability_sub_score, temporal_score
50
+ calculate_score modified_impact_sub_score, modified_exploitability_sub_score, temporal.score
39
51
  end
40
52
 
41
53
  private
@@ -44,70 +56,79 @@ module CvssSuite
44
56
  @properties.push(@confidentiality_requirement =
45
57
  CvssProperty.new(name: 'Confidentiality Requirement', abbreviation: 'CR', position: [8, 11],
46
58
  values: [{ name: 'Low', abbreviation: 'L', weight: 0.5 },
47
- { name: 'Medium', abbreviation: 'M', weight: 1.0 },
48
- { name: 'High', abbreviation: 'H', weight: 1.5 },
49
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
59
+ { name: 'Medium', abbreviation: 'M', weight: 1.0 },
60
+ { name: 'High', abbreviation: 'H', weight: 1.5 },
61
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
50
62
  @properties.push(@integrity_requirement =
51
63
  CvssProperty.new(name: 'Integrity Requirement', abbreviation: 'IR', position: [9, 12],
52
64
  values: [{ name: 'Low', abbreviation: 'L', weight: 0.5 },
53
- { name: 'Medium', abbreviation: 'M', weight: 1.0 },
54
- { name: 'High', abbreviation: 'H', weight: 1.5 },
55
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
65
+ { name: 'Medium', abbreviation: 'M', weight: 1.0 },
66
+ { name: 'High', abbreviation: 'H', weight: 1.5 },
67
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
56
68
 
57
69
  @properties.push(@availability_requirement =
58
70
  CvssProperty.new(name: 'Availability Requirement', abbreviation: 'AR', position: [10, 13],
59
71
  values: [{ name: 'Low', abbreviation: 'L', weight: 0.5 },
60
- { name: 'Medium', abbreviation: 'M', weight: 1.0 },
61
- { name: 'High', abbreviation: 'H', weight: 1.5 },
62
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
72
+ { name: 'Medium', abbreviation: 'M', weight: 1.0 },
73
+ { name: 'High', abbreviation: 'H', weight: 1.5 },
74
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
63
75
  @properties.push(@modified_attack_vector =
64
76
  CvssProperty.new(name: 'Modified Attack Vector', abbreviation: 'MAV', position: [11, 14],
65
77
  values: [{ name: 'Network', abbreviation: 'N', weight: 0.85 },
66
- { name: 'Adjacent Network', abbreviation: 'A', weight: 0.62 },
67
- { name: 'Local', abbreviation: 'L', weight: 0.55 },
68
- { name: 'Physical', abbreviation: 'P', weight: 0.2 },
69
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
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 }]))
70
82
  @properties.push(@modified_attack_complexity =
71
83
  CvssProperty.new(name: 'Modified Attack Complexity', abbreviation: 'MAC', position: [12, 15],
72
84
  values: [{ name: 'Low', abbreviation: 'L', weight: 0.77 },
73
- { name: 'High', abbreviation: 'H', weight: 0.44 },
74
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
85
+ { name: 'High', abbreviation: 'H', weight: 0.44 },
86
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
75
87
  @properties.push(@modified_privileges_required =
76
88
  CvssProperty.new(name: 'Modified Privileges Required', abbreviation: 'MPR', position: [13, 16],
77
89
  values: [{ name: 'None', abbreviation: 'N', weight: 0.85 },
78
- { name: 'Low', abbreviation: 'L', weight: 0.62 },
79
- { name: 'High', abbreviation: 'H', weight: 0.27 },
80
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
90
+ { name: 'Low', abbreviation: 'L', weight: 0.62 },
91
+ { name: 'High', abbreviation: 'H', weight: 0.27 },
92
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
81
93
  @properties.push(@modified_user_interaction =
82
94
  CvssProperty.new(name: 'Modified User Interaction', abbreviation: 'MUI', position: [14, 17],
83
95
  values: [{ name: 'None', abbreviation: 'N', weight: 0.85 },
84
- { name: 'Required', abbreviation: 'R', weight: 0.62 },
85
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
96
+ { name: 'Required', abbreviation: 'R', weight: 0.62 },
97
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
86
98
  @properties.push(@modified_scope =
87
99
  CvssProperty.new(name: 'Modified Scope', abbreviation: 'MS', position: [15, 18],
88
100
  values: [{ name: 'Changed', abbreviation: 'C' },
89
- { name: 'Unchanged', abbreviation: 'U' }]))
101
+ { name: 'Unchanged', abbreviation: 'U' },
102
+ { name: 'Not Defined', abbreviation: 'X' }]))
90
103
  @properties.push(@modified_confidentiality =
91
104
  CvssProperty.new(name: 'Modified Confidentiality', abbreviation: 'MC', position: [16, 19],
92
105
  values: [{ name: 'None', abbreviation: 'N', weight: 0 },
93
- { name: 'Low', abbreviation: 'L', weight: 0.22 },
94
- { name: 'High', abbreviation: 'H', weight: 0.56 },
95
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
106
+ { name: 'Low', abbreviation: 'L', weight: 0.22 },
107
+ { name: 'High', abbreviation: 'H', weight: 0.56 },
108
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
96
109
  @properties.push(@modified_integrity =
97
110
  CvssProperty.new(name: 'Modified Integrity', abbreviation: 'MI', position: [17, 20],
98
111
  values: [{ name: 'None', abbreviation: 'N', weight: 0 },
99
- { name: 'Low', abbreviation: 'L', weight: 0.22 },
100
- { name: 'High', abbreviation: 'H', weight: 0.56 },
101
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
112
+ { name: 'Low', abbreviation: 'L', weight: 0.22 },
113
+ { name: 'High', abbreviation: 'H', weight: 0.56 },
114
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
102
115
  @properties.push(@modified_availability =
103
116
  CvssProperty.new(name: 'Modified Availability', abbreviation: 'MA', position: [18, 21],
104
117
  values: [{ name: 'None', abbreviation: 'N', weight: 0 },
105
- { name: 'Low', abbreviation: 'L', weight: 0.22 },
106
- { name: 'High', abbreviation: 'H', weight: 0.56 },
107
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
118
+ { name: 'Low', abbreviation: 'L', weight: 0.22 },
119
+ { name: 'High', abbreviation: 'H', weight: 0.56 },
120
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
108
121
  end
109
122
 
110
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
+
111
132
  if @modified_scope.selected_value[:name] == 'Changed'
112
133
  7.52 * (isc_modified - 0.029) - 3.25 * (isc_modified * 0.9731 - 0.02)**13
113
134
  else
@@ -116,20 +137,54 @@ module CvssSuite
116
137
  end
117
138
 
118
139
  def isc_modified
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
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
122
158
 
123
159
  [0.915, (1 - confidentiality_score * integrity_score * availability_score)].min
124
160
  end
125
161
 
126
162
  def modified_exploitability_sub(privilege_score)
127
- 8.22 * @modified_attack_vector.score * @modified_attack_complexity.score *
128
- privilege_score * @modified_user_interaction.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
129
180
  end
130
181
 
131
182
  def calculate_score(modified_impact_sub_score, modified_exploitability_sub_score, temporal_score)
132
- factor = @modified_scope.selected_value[:name] == 'Changed' ? 1.08 : 1.0
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
133
188
 
134
189
  Cvss31Helper.round_up(
135
190
  [factor * (modified_impact_sub_score + modified_exploitability_sub_score), 10].min
@@ -33,24 +33,24 @@ module CvssSuite
33
33
  @properties.push(@exploit_code_maturity =
34
34
  CvssProperty.new(name: 'Exploit Code Maturity', abbreviation: 'E', position: [8],
35
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 }]))
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
40
  @properties.push(@remediation_level =
41
41
  CvssProperty.new(name: 'Remediation Level', abbreviation: 'RL', position: [9],
42
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 }]))
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
47
 
48
48
  @properties.push(@report_confidence =
49
49
  CvssProperty.new(name: 'Report Confidence', abbreviation: 'RC', position: [10],
50
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 }]))
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
54
  end
55
55
  end
56
56
  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 = '2.0.0'.freeze
12
+ VERSION = '2.0.1'.freeze
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: 2.0.0
4
+ version: 2.0.1
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
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0.11'
61
+ version: '0.18'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '0.11'
68
+ version: '0.18'
69
69
  description: |-
70
70
  This Ruby gem helps you to process the vector of the Common Vulnerability Scoring System (https://www.first.org/cvss/specification-document).
71
71
  Besides calculating the Base, Temporal and Environmental Score, you are able to extract the selected option.