cvss-suite 3.0.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 35f019f9f2db03e3365a83f1740fa2491817d6057744cbfe460fb2f0e9954437
4
- data.tar.gz: 8e25a80d218017ca820305b01877f272574cab8fcc35d33a4adfa85e75396c6d
3
+ metadata.gz: 8d6c9f7e41ba7184e8140cf17c6fc0a1b2dced70a3a0e80a603700c2517f413c
4
+ data.tar.gz: 8277aaf7c847feb0d83adcf96f33e85dbbaa4916bb84fb3b1fad5fc1eb99ef57
5
5
  SHA512:
6
- metadata.gz: 41c7f6b1f517a891d6d4b59cbd6d32b5f139d4738776f28596609278f6bd21e4ea7bb532a545d04960ae9447ffc9e4ee03b690b42bb0d0aa05a031a7a85d407a
7
- data.tar.gz: ff3e271e463292488315a27db826e18f6b55f16142eb7e486bbb3a4cb7c684fa82c7f94e725409c898b06b681c5df8e794afb8289df812064c53d6f27ac753b2
6
+ metadata.gz: 3640b87d41a2b7533b756b416e115e8cde0bb4459a8aefe325d0db82816b48dc0b3f32bd2d6c9dde4ab48ec0bec94efc8572e0c94412618070a45ab04012dd04
7
+ data.tar.gz: fe15648aa4362009d44ef9159e38f40494b09911582845b29732cb6c6512694c6bdf4d3b57ec412a6e9e76c783c197746dd76a2cce79ce298facad8f4a8ac334
data/CHANGES.md CHANGED
@@ -2,6 +2,19 @@
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
+ ## [3.1.0] - 2022-09-27
6
+
7
+ ### Fixes
8
+ * Metrics are no longer order-dependent. Fixes [#30](https://github.com/0llirocks/cvss-suite/issues/30)
9
+
10
+ ### Improvements
11
+ * Temporal and Environmental metrics can now be partly omitted instead of setting them to X.
12
+
13
+ ## [3.0.1] - 2022-03-13
14
+
15
+ ### Notes
16
+ * Updated specification reference due to [Removing the edit linkset form](https://blog.rubygems.org/2019/03/08/and-then-there-was-one-metadata-links.html) and [Unable to edit gem online](https://github.com/rubygems/rubygems.org/issues/1899)
17
+
5
18
  ## [3.0.0] - 2022-03-13
6
19
 
7
20
  ### Breaking Changes
data/README.md CHANGED
@@ -100,14 +100,8 @@ valid = cvss.valid? # false
100
100
  cvss.base_score # will throw CvssSuite::Errors::InvalidVector: Vector is not valid!
101
101
  ```
102
102
 
103
- ## Notable Features
104
-
105
- Properties (Access Vector, Remediation Level, etc) do have a position attribute, with this they can be ordered the same way they appear in the vector.
106
-
107
103
  ## Known Issues
108
104
 
109
- 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.
110
-
111
105
  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.
112
106
 
113
107
  ## Changelog
data/cvss_suite.gemspec CHANGED
@@ -24,7 +24,14 @@ Gem::Specification.new do |spec|
24
24
  spec.summary = 'Ruby gem for processing cvss vectors.'
25
25
  spec.description = 'This Ruby gem helps you to process the vector of the Common Vulnerability Scoring System (https://www.first.org/cvss/specification-document).
26
26
  Besides calculating the Base, Temporal and Environmental Score, you are able to extract the selected option.'
27
- spec.homepage = 'https://cvss-suite.0lli.rocks'
27
+
28
+ spec.metadata = {
29
+ 'bug_tracker_uri' => 'https://github.com/0llirocks/cvss-suite/issues',
30
+ 'changelog_uri' => 'https://github.com/0llirocks/cvss-suite/blob/master/CHANGES.md',
31
+ 'documentation_uri' => "https://www.rubydoc.info/gems/cvss-suite/#{CvssSuite::VERSION}",
32
+ 'homepage_uri' => 'https://cvss-suite.0lli.rocks',
33
+ 'source_code_uri' => 'https://github.com/0llirocks/cvss-suite'
34
+ }
28
35
 
29
36
  spec.required_ruby_version = '>= 2.6.0'
30
37
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
@@ -37,7 +37,7 @@ module CvssSuite
37
37
  ##
38
38
  # Returns if CVSS vector is valid.
39
39
  def valid?
40
- if @amount_of_properties == required_amount_of_properties
40
+ if @amount_of_properties >= required_amount_of_properties
41
41
  base = @base.valid?
42
42
  temporal = @base.valid? && @temporal.valid?
43
43
  environmental = @base.valid? && @environmental.valid?
@@ -83,41 +83,21 @@ module CvssSuite
83
83
  private
84
84
 
85
85
  def extract_metrics
86
- properties = prepared_vector.split('/')
86
+ properties = @vector.split('/')
87
87
  @amount_of_properties = properties.size
88
88
  properties.each_with_index do |property, index|
89
89
  property = property.split(':')
90
90
  @properties.push({ name: property[0], selected: property[1], position: index })
91
91
  end
92
+ @properties = [] if @properties.group_by { |p| p[:name] }.select { |_k, v| v.size > 1 }.length.positive?
92
93
  end
93
94
 
94
95
  def check_validity
95
96
  raise CvssSuite::Errors::InvalidVector, 'Vector is not valid!' unless valid?
96
97
  end
97
98
 
98
- def prepared_vector
99
- start_of_vector = @vector.index('AV')
100
-
101
- if start_of_vector.nil?
102
- ''
103
- elsif start_of_vector == 1
104
- match_array = @vector.scan(/\((?>[^)(]+|\g<0>)*\)/)
105
- if match_array.length == 1 && match_array[0] == @vector
106
- @vector.slice!(0)
107
- @vector.slice!(@vector.length - 1)
108
- @vector
109
- else
110
- ''
111
- end
112
- else
113
- @vector[start_of_vector..]
114
- end
115
- end
116
-
117
99
  def required_amount_of_properties
118
- total = @base.count if @base.valid?
119
- total += @temporal.count if @temporal.valid?
120
- total += @environmental.count if @environmental.valid?
100
+ total = @base.count
121
101
  total || 0
122
102
  end
123
103
  end
@@ -51,40 +51,40 @@ module CvssSuite
51
51
 
52
52
  def init_properties
53
53
  @properties.push(@attack_vector =
54
- CvssProperty.new(name: 'Attack Vector', abbreviation: 'AV', position: [0],
54
+ CvssProperty.new(name: 'Attack Vector', abbreviation: 'AV',
55
55
  values: [{ name: 'Network', abbreviation: 'N', weight: 0.85 },
56
56
  { name: 'Adjacent', abbreviation: 'A', weight: 0.62 },
57
57
  { name: 'Local', abbreviation: 'L', weight: 0.55 },
58
58
  { name: 'Physical', abbreviation: 'P', weight: 0.2 }]))
59
59
  @properties.push(@attack_complexity =
60
- CvssProperty.new(name: 'Attack Complexity', abbreviation: 'AC', position: [1],
60
+ CvssProperty.new(name: 'Attack Complexity', abbreviation: 'AC',
61
61
  values: [{ name: 'Low', abbreviation: 'L', weight: 0.77 },
62
62
  { name: 'High', abbreviation: 'H', weight: 0.44 }]))
63
63
  @properties.push(@privileges_required =
64
- CvssProperty.new(name: 'Privileges Required', abbreviation: 'PR', position: [2],
64
+ CvssProperty.new(name: 'Privileges Required', abbreviation: 'PR',
65
65
  values: [{ name: 'None', abbreviation: 'N', weight: 0.85 },
66
66
  { name: 'Low', abbreviation: 'L', weight: 0.62 },
67
67
  { name: 'High', abbreviation: 'H', weight: 0.27 }]))
68
68
  @properties.push(@user_interaction =
69
- CvssProperty.new(name: 'User Interaction', abbreviation: 'UI', position: [3],
69
+ CvssProperty.new(name: 'User Interaction', abbreviation: 'UI',
70
70
  values: [{ name: 'None', abbreviation: 'N', weight: 0.85 },
71
71
  { name: 'Required', abbreviation: 'R', weight: 0.62 }]))
72
72
  @properties.push(@scope =
73
- CvssProperty.new(name: 'Scope', abbreviation: 'S', position: [4],
73
+ CvssProperty.new(name: 'Scope', abbreviation: 'S',
74
74
  values: [{ name: 'Unchanged', abbreviation: 'U' },
75
75
  { name: 'Changed', abbreviation: 'C' }]))
76
76
  @properties.push(@confidentiality =
77
- CvssProperty.new(name: 'Confidentiality', abbreviation: 'C', position: [5],
77
+ CvssProperty.new(name: 'Confidentiality', abbreviation: 'C',
78
78
  values: [{ name: 'None', abbreviation: 'N', weight: 0.0 },
79
79
  { name: 'Low', abbreviation: 'L', weight: 0.22 },
80
80
  { name: 'High', abbreviation: 'H', weight: 0.56 }]))
81
81
  @properties.push(@integrity =
82
- CvssProperty.new(name: 'Integrity', abbreviation: 'I', position: [6],
82
+ CvssProperty.new(name: 'Integrity', abbreviation: 'I',
83
83
  values: [{ name: 'None', abbreviation: 'N', weight: 0.0 },
84
84
  { name: 'Low', abbreviation: 'L', weight: 0.22 },
85
85
  { name: 'High', abbreviation: 'H', weight: 0.56 }]))
86
86
  @properties.push(@availability =
87
- CvssProperty.new(name: 'Availability', abbreviation: 'A', position: [7],
87
+ CvssProperty.new(name: 'Availability', abbreviation: 'A',
88
88
  values: [{ name: 'None', abbreviation: 'N', weight: 0.0 },
89
89
  { name: 'Low', abbreviation: 'L', weight: 0.22 },
90
90
  { name: 'High', abbreviation: 'H', weight: 0.56 }]))
@@ -55,66 +55,66 @@ module CvssSuite
55
55
 
56
56
  def init_properties
57
57
  @properties.push(@confidentiality_requirement =
58
- CvssProperty.new(name: 'Confidentiality Requirement', abbreviation: 'CR', position: [8, 11],
58
+ CvssProperty.new(name: 'Confidentiality Requirement', abbreviation: 'CR',
59
59
  values: [{ name: 'Low', abbreviation: 'L', weight: 0.5 },
60
60
  { name: 'Medium', abbreviation: 'M', weight: 1.0 },
61
61
  { name: 'High', abbreviation: 'H', weight: 1.5 },
62
62
  { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
63
63
  @properties.push(@integrity_requirement =
64
- CvssProperty.new(name: 'Integrity Requirement', abbreviation: 'IR', position: [9, 12],
64
+ CvssProperty.new(name: 'Integrity Requirement', abbreviation: 'IR',
65
65
  values: [{ name: 'Low', abbreviation: 'L', weight: 0.5 },
66
66
  { name: 'Medium', abbreviation: 'M', weight: 1.0 },
67
67
  { name: 'High', abbreviation: 'H', weight: 1.5 },
68
68
  { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
69
69
 
70
70
  @properties.push(@availability_requirement =
71
- CvssProperty.new(name: 'Availability Requirement', abbreviation: 'AR', position: [10, 13],
71
+ CvssProperty.new(name: 'Availability Requirement', abbreviation: 'AR',
72
72
  values: [{ name: 'Low', abbreviation: 'L', weight: 0.5 },
73
73
  { name: 'Medium', abbreviation: 'M', weight: 1.0 },
74
74
  { name: 'High', abbreviation: 'H', weight: 1.5 },
75
75
  { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
76
76
  @properties.push(@modified_attack_vector =
77
- CvssProperty.new(name: 'Modified Attack Vector', abbreviation: 'MAV', position: [11, 14],
77
+ CvssProperty.new(name: 'Modified Attack Vector', abbreviation: 'MAV',
78
78
  values: [{ name: 'Network', abbreviation: 'N', weight: 0.85 },
79
79
  { name: 'Adjacent Network', abbreviation: 'A', weight: 0.62 },
80
80
  { name: 'Local', abbreviation: 'L', weight: 0.55 },
81
81
  { name: 'Physical', abbreviation: 'P', weight: 0.2 },
82
82
  { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
83
83
  @properties.push(@modified_attack_complexity =
84
- CvssProperty.new(name: 'Modified Attack Complexity', abbreviation: 'MAC', position: [12, 15],
84
+ CvssProperty.new(name: 'Modified Attack Complexity', abbreviation: 'MAC',
85
85
  values: [{ name: 'Low', abbreviation: 'L', weight: 0.77 },
86
86
  { name: 'High', abbreviation: 'H', weight: 0.44 },
87
87
  { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
88
88
  @properties.push(@modified_privileges_required =
89
- CvssProperty.new(name: 'Modified Privileges Required', abbreviation: 'MPR', position: [13, 16],
89
+ CvssProperty.new(name: 'Modified Privileges Required', abbreviation: 'MPR',
90
90
  values: [{ name: 'None', abbreviation: 'N', weight: 0.85 },
91
91
  { name: 'Low', abbreviation: 'L', weight: 0.62 },
92
92
  { name: 'High', abbreviation: 'H', weight: 0.27 },
93
93
  { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
94
94
  @properties.push(@modified_user_interaction =
95
- CvssProperty.new(name: 'Modified User Interaction', abbreviation: 'MUI', position: [14, 17],
95
+ CvssProperty.new(name: 'Modified User Interaction', abbreviation: 'MUI',
96
96
  values: [{ name: 'None', abbreviation: 'N', weight: 0.85 },
97
97
  { name: 'Required', abbreviation: 'R', weight: 0.62 },
98
98
  { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
99
99
  @properties.push(@modified_scope =
100
- CvssProperty.new(name: 'Modified Scope', abbreviation: 'MS', position: [15, 18],
100
+ CvssProperty.new(name: 'Modified Scope', abbreviation: 'MS',
101
101
  values: [{ name: 'Changed', abbreviation: 'C' },
102
102
  { name: 'Unchanged', abbreviation: 'U' },
103
103
  { name: 'Not Defined', abbreviation: 'X' }]))
104
104
  @properties.push(@modified_confidentiality =
105
- CvssProperty.new(name: 'Modified Confidentiality', abbreviation: 'MC', position: [16, 19],
105
+ CvssProperty.new(name: 'Modified Confidentiality', abbreviation: 'MC',
106
106
  values: [{ name: 'None', abbreviation: 'N', weight: 0 },
107
107
  { name: 'Low', abbreviation: 'L', weight: 0.22 },
108
108
  { name: 'High', abbreviation: 'H', weight: 0.56 },
109
109
  { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
110
110
  @properties.push(@modified_integrity =
111
- CvssProperty.new(name: 'Modified Integrity', abbreviation: 'MI', position: [17, 20],
111
+ CvssProperty.new(name: 'Modified Integrity', abbreviation: 'MI',
112
112
  values: [{ name: 'None', abbreviation: 'N', weight: 0 },
113
113
  { name: 'Low', abbreviation: 'L', weight: 0.22 },
114
114
  { name: 'High', abbreviation: 'H', weight: 0.56 },
115
115
  { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
116
116
  @properties.push(@modified_availability =
117
- CvssProperty.new(name: 'Modified Availability', abbreviation: 'MA', position: [18, 21],
117
+ CvssProperty.new(name: 'Modified Availability', abbreviation: 'MA',
118
118
  values: [{ name: 'None', abbreviation: 'N', weight: 0 },
119
119
  { name: 'Low', abbreviation: 'L', weight: 0.22 },
120
120
  { name: 'High', abbreviation: 'H', weight: 0.56 },
@@ -32,14 +32,14 @@ module CvssSuite
32
32
 
33
33
  def init_properties
34
34
  @properties.push(@exploit_code_maturity =
35
- CvssProperty.new(name: 'Exploit Code Maturity', abbreviation: 'E', position: [8],
35
+ CvssProperty.new(name: 'Exploit Code Maturity', abbreviation: 'E',
36
36
  values: [{ name: 'Not Defined', abbreviation: 'X', weight: 1.0 },
37
37
  { name: 'Unproven', abbreviation: 'U', weight: 0.91 },
38
38
  { name: 'Proof-of-Concept', abbreviation: 'P', weight: 0.94 },
39
39
  { name: 'Functional', abbreviation: 'F', weight: 0.97 },
40
40
  { name: 'High', abbreviation: 'H', weight: 1.0 }]))
41
41
  @properties.push(@remediation_level =
42
- CvssProperty.new(name: 'Remediation Level', abbreviation: 'RL', position: [9],
42
+ CvssProperty.new(name: 'Remediation Level', abbreviation: 'RL',
43
43
  values: [{ name: 'Not Defined', abbreviation: 'X', weight: 1.0 },
44
44
  { name: 'Official Fix', abbreviation: 'O', weight: 0.95 },
45
45
  { name: 'Temporary Fix', abbreviation: 'T', weight: 0.96 },
@@ -47,7 +47,7 @@ module CvssSuite
47
47
  { name: 'Unavailable', abbreviation: 'U', weight: 1.0 }]))
48
48
 
49
49
  @properties.push(@report_confidence =
50
- CvssProperty.new(name: 'Report Confidence', abbreviation: 'RC', position: [10],
50
+ CvssProperty.new(name: 'Report Confidence', abbreviation: 'RC',
51
51
  values: [{ name: 'Not Defined', abbreviation: 'X', weight: 1.0 },
52
52
  { name: 'Unknown', abbreviation: 'U', weight: 0.92 },
53
53
  { name: 'Reasonable', abbreviation: 'R', weight: 0.96 },
@@ -52,40 +52,40 @@ module CvssSuite
52
52
 
53
53
  def init_properties
54
54
  @properties.push(@attack_vector =
55
- CvssProperty.new(name: 'Attack Vector', abbreviation: 'AV', position: [0],
55
+ CvssProperty.new(name: 'Attack Vector', abbreviation: 'AV',
56
56
  values: [{ name: 'Network', abbreviation: 'N', weight: 0.85 },
57
57
  { name: 'Adjacent', abbreviation: 'A', weight: 0.62 },
58
58
  { name: 'Local', abbreviation: 'L', weight: 0.55 },
59
59
  { name: 'Physical', abbreviation: 'P', weight: 0.2 }]))
60
60
  @properties.push(@attack_complexity =
61
- CvssProperty.new(name: 'Attack Complexity', abbreviation: 'AC', position: [1],
61
+ CvssProperty.new(name: 'Attack Complexity', abbreviation: 'AC',
62
62
  values: [{ name: 'Low', abbreviation: 'L', weight: 0.77 },
63
63
  { name: 'High', abbreviation: 'H', weight: 0.44 }]))
64
64
  @properties.push(@privileges_required =
65
- CvssProperty.new(name: 'Privileges Required', abbreviation: 'PR', position: [2],
65
+ CvssProperty.new(name: 'Privileges Required', abbreviation: 'PR',
66
66
  values: [{ name: 'None', abbreviation: 'N', weight: 0.85 },
67
67
  { name: 'Low', abbreviation: 'L', weight: 0.62 },
68
68
  { name: 'High', abbreviation: 'H', weight: 0.27 }]))
69
69
  @properties.push(@user_interaction =
70
- CvssProperty.new(name: 'User Interaction', abbreviation: 'UI', position: [3],
70
+ CvssProperty.new(name: 'User Interaction', abbreviation: 'UI',
71
71
  values: [{ name: 'None', abbreviation: 'N', weight: 0.85 },
72
72
  { name: 'Required', abbreviation: 'R', weight: 0.62 }]))
73
73
  @properties.push(@scope =
74
- CvssProperty.new(name: 'Scope', abbreviation: 'S', position: [4],
74
+ CvssProperty.new(name: 'Scope', abbreviation: 'S',
75
75
  values: [{ name: 'Unchanged', abbreviation: 'U' },
76
76
  { name: 'Changed', abbreviation: 'C' }]))
77
77
  @properties.push(@confidentiality =
78
- CvssProperty.new(name: 'Confidentiality', abbreviation: 'C', position: [5],
78
+ CvssProperty.new(name: 'Confidentiality', abbreviation: 'C',
79
79
  values: [{ name: 'None', abbreviation: 'N', weight: 0.0 },
80
80
  { name: 'Low', abbreviation: 'L', weight: 0.22 },
81
81
  { name: 'High', abbreviation: 'H', weight: 0.56 }]))
82
82
  @properties.push(@integrity =
83
- CvssProperty.new(name: 'Integrity', abbreviation: 'I', position: [6],
83
+ CvssProperty.new(name: 'Integrity', abbreviation: 'I',
84
84
  values: [{ name: 'None', abbreviation: 'N', weight: 0.0 },
85
85
  { name: 'Low', abbreviation: 'L', weight: 0.22 },
86
86
  { name: 'High', abbreviation: 'H', weight: 0.56 }]))
87
87
  @properties.push(@availability =
88
- CvssProperty.new(name: 'Availability', abbreviation: 'A', position: [7],
88
+ CvssProperty.new(name: 'Availability', abbreviation: 'A',
89
89
  values: [{ name: 'None', abbreviation: 'N', weight: 0.0 },
90
90
  { name: 'Low', abbreviation: 'L', weight: 0.22 },
91
91
  { name: 'High', abbreviation: 'H', weight: 0.56 }]))
@@ -55,66 +55,66 @@ module CvssSuite
55
55
 
56
56
  def init_properties
57
57
  @properties.push(@confidentiality_requirement =
58
- CvssProperty.new(name: 'Confidentiality Requirement', abbreviation: 'CR', position: [8, 11],
58
+ CvssProperty.new(name: 'Confidentiality Requirement', abbreviation: 'CR',
59
59
  values: [{ name: 'Low', abbreviation: 'L', weight: 0.5 },
60
60
  { name: 'Medium', abbreviation: 'M', weight: 1.0 },
61
61
  { name: 'High', abbreviation: 'H', weight: 1.5 },
62
62
  { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
63
63
  @properties.push(@integrity_requirement =
64
- CvssProperty.new(name: 'Integrity Requirement', abbreviation: 'IR', position: [9, 12],
64
+ CvssProperty.new(name: 'Integrity Requirement', abbreviation: 'IR',
65
65
  values: [{ name: 'Low', abbreviation: 'L', weight: 0.5 },
66
66
  { name: 'Medium', abbreviation: 'M', weight: 1.0 },
67
67
  { name: 'High', abbreviation: 'H', weight: 1.5 },
68
68
  { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
69
69
 
70
70
  @properties.push(@availability_requirement =
71
- CvssProperty.new(name: 'Availability Requirement', abbreviation: 'AR', position: [10, 13],
71
+ CvssProperty.new(name: 'Availability Requirement', abbreviation: 'AR',
72
72
  values: [{ name: 'Low', abbreviation: 'L', weight: 0.5 },
73
73
  { name: 'Medium', abbreviation: 'M', weight: 1.0 },
74
74
  { name: 'High', abbreviation: 'H', weight: 1.5 },
75
75
  { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
76
76
  @properties.push(@modified_attack_vector =
77
- CvssProperty.new(name: 'Modified Attack Vector', abbreviation: 'MAV', position: [11, 14],
77
+ CvssProperty.new(name: 'Modified Attack Vector', abbreviation: 'MAV',
78
78
  values: [{ name: 'Network', abbreviation: 'N', weight: 0.85 },
79
79
  { name: 'Adjacent Network', abbreviation: 'A', weight: 0.62 },
80
80
  { name: 'Local', abbreviation: 'L', weight: 0.55 },
81
81
  { name: 'Physical', abbreviation: 'P', weight: 0.2 },
82
82
  { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
83
83
  @properties.push(@modified_attack_complexity =
84
- CvssProperty.new(name: 'Modified Attack Complexity', abbreviation: 'MAC', position: [12, 15],
84
+ CvssProperty.new(name: 'Modified Attack Complexity', abbreviation: 'MAC',
85
85
  values: [{ name: 'Low', abbreviation: 'L', weight: 0.77 },
86
86
  { name: 'High', abbreviation: 'H', weight: 0.44 },
87
87
  { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
88
88
  @properties.push(@modified_privileges_required =
89
- CvssProperty.new(name: 'Modified Privileges Required', abbreviation: 'MPR', position: [13, 16],
89
+ CvssProperty.new(name: 'Modified Privileges Required', abbreviation: 'MPR',
90
90
  values: [{ name: 'None', abbreviation: 'N', weight: 0.85 },
91
91
  { name: 'Low', abbreviation: 'L', weight: 0.62 },
92
92
  { name: 'High', abbreviation: 'H', weight: 0.27 },
93
93
  { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
94
94
  @properties.push(@modified_user_interaction =
95
- CvssProperty.new(name: 'Modified User Interaction', abbreviation: 'MUI', position: [14, 17],
95
+ CvssProperty.new(name: 'Modified User Interaction', abbreviation: 'MUI',
96
96
  values: [{ name: 'None', abbreviation: 'N', weight: 0.85 },
97
97
  { name: 'Required', abbreviation: 'R', weight: 0.62 },
98
98
  { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
99
99
  @properties.push(@modified_scope =
100
- CvssProperty.new(name: 'Modified Scope', abbreviation: 'MS', position: [15, 18],
100
+ CvssProperty.new(name: 'Modified Scope', abbreviation: 'MS',
101
101
  values: [{ name: 'Changed', abbreviation: 'C' },
102
102
  { name: 'Unchanged', abbreviation: 'U' },
103
103
  { name: 'Not Defined', abbreviation: 'X' }]))
104
104
  @properties.push(@modified_confidentiality =
105
- CvssProperty.new(name: 'Modified Confidentiality', abbreviation: 'MC', position: [16, 19],
105
+ CvssProperty.new(name: 'Modified Confidentiality', abbreviation: 'MC',
106
106
  values: [{ name: 'None', abbreviation: 'N', weight: 0 },
107
107
  { name: 'Low', abbreviation: 'L', weight: 0.22 },
108
108
  { name: 'High', abbreviation: 'H', weight: 0.56 },
109
109
  { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
110
110
  @properties.push(@modified_integrity =
111
- CvssProperty.new(name: 'Modified Integrity', abbreviation: 'MI', position: [17, 20],
111
+ CvssProperty.new(name: 'Modified Integrity', abbreviation: 'MI',
112
112
  values: [{ name: 'None', abbreviation: 'N', weight: 0 },
113
113
  { name: 'Low', abbreviation: 'L', weight: 0.22 },
114
114
  { name: 'High', abbreviation: 'H', weight: 0.56 },
115
115
  { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
116
116
  @properties.push(@modified_availability =
117
- CvssProperty.new(name: 'Modified Availability', abbreviation: 'MA', position: [18, 21],
117
+ CvssProperty.new(name: 'Modified Availability', abbreviation: 'MA',
118
118
  values: [{ name: 'None', abbreviation: 'N', weight: 0 },
119
119
  { name: 'Low', abbreviation: 'L', weight: 0.22 },
120
120
  { name: 'High', abbreviation: 'H', weight: 0.56 },
@@ -32,14 +32,14 @@ module CvssSuite
32
32
 
33
33
  def init_properties
34
34
  @properties.push(@exploit_code_maturity =
35
- CvssProperty.new(name: 'Exploit Code Maturity', abbreviation: 'E', position: [8],
35
+ CvssProperty.new(name: 'Exploit Code Maturity', abbreviation: 'E',
36
36
  values: [{ name: 'Not Defined', abbreviation: 'X', weight: 1.0 },
37
37
  { name: 'Unproven', abbreviation: 'U', weight: 0.91 },
38
38
  { name: 'Proof-of-Concept', abbreviation: 'P', weight: 0.94 },
39
39
  { name: 'Functional', abbreviation: 'F', weight: 0.97 },
40
40
  { name: 'High', abbreviation: 'H', weight: 1.0 }]))
41
41
  @properties.push(@remediation_level =
42
- CvssProperty.new(name: 'Remediation Level', abbreviation: 'RL', position: [9],
42
+ CvssProperty.new(name: 'Remediation Level', abbreviation: 'RL',
43
43
  values: [{ name: 'Not Defined', abbreviation: 'X', weight: 1.0 },
44
44
  { name: 'Official Fix', abbreviation: 'O', weight: 0.95 },
45
45
  { name: 'Temporary Fix', abbreviation: 'T', weight: 0.96 },
@@ -47,7 +47,7 @@ module CvssSuite
47
47
  { name: 'Unavailable', abbreviation: 'U', weight: 1.0 }]))
48
48
 
49
49
  @properties.push(@report_confidence =
50
- CvssProperty.new(name: 'Report Confidence', abbreviation: 'RC', position: [10],
50
+ CvssProperty.new(name: 'Report Confidence', abbreviation: 'RC',
51
51
  values: [{ name: 'Not Defined', abbreviation: 'X', weight: 1.0 },
52
52
  { name: 'Unknown', abbreviation: 'U', weight: 0.92 },
53
53
  { name: 'Reasonable', abbreviation: 'R', weight: 0.96 },
@@ -41,10 +41,12 @@ module CvssSuite
41
41
  def extract_selected_values_from(selected_properties)
42
42
  selected_properties.each do |selected_property|
43
43
  property = @properties.detect do |p|
44
- p.abbreviation == selected_property[:name] && p.position.include?(selected_property[:position])
44
+ p.abbreviation == selected_property[:name] &&
45
+ (p.position&.include?(selected_property[:position]) || p.position.nil?)
45
46
  end
46
47
  property&.set_selected_value selected_property[:selected]
47
48
  end
49
+ @properties.reject(&:valid?).each(&:set_default_value)
48
50
  end
49
51
  end
50
52
  end
@@ -22,7 +22,7 @@ module CvssSuite
22
22
 
23
23
  def initialize(property)
24
24
  @property = property
25
- @property[:default_value] ||= 'Not Available'
25
+ @property[:default_value] ||= 'Not Defined'
26
26
  end
27
27
 
28
28
  ##
@@ -83,5 +83,15 @@ module CvssSuite
83
83
  end
84
84
  @selected_value = values.detect { |value| value[:selected] }
85
85
  end
86
+
87
+ ##
88
+ # Sets the default value.
89
+
90
+ def set_default_value
91
+ values.each do |value|
92
+ value[:selected] = value[:abbreviation].eql?('X')
93
+ end
94
+ @selected_value = values.detect { |value| value[:selected] }
95
+ end
86
96
  end
87
97
  end
@@ -10,5 +10,5 @@
10
10
  # See the LICENSE.md file in the top-level directory.
11
11
 
12
12
  module CvssSuite
13
- VERSION = '3.0.0'.freeze
13
+ VERSION = '3.1.0'.freeze
14
14
  end
data/lib/cvss_suite.rb CHANGED
@@ -34,11 +34,11 @@ module CvssSuite
34
34
  @vector_string = vector
35
35
  case version
36
36
  when 2
37
- Cvss2.new(@vector_string)
37
+ Cvss2.new(prepare_vector(@vector_string))
38
38
  when 3.0
39
- Cvss3.new(@vector_string)
39
+ Cvss3.new(prepare_vector(@vector_string))
40
40
  when 3.1
41
- Cvss31.new(@vector_string)
41
+ Cvss31.new(prepare_vector(@vector_string))
42
42
  else
43
43
  InvalidCvss.new
44
44
  end
@@ -51,4 +51,38 @@ module CvssSuite
51
51
  return beginning[:version] if @vector_string.start_with? beginning[:string]
52
52
  end
53
53
  end
54
+
55
+ def self.prepare_vector(vector)
56
+ vector = vector.clone
57
+
58
+ return prepare_cvss2_vector(vector) if version == 2
59
+
60
+ version_string = CVSS_VECTOR_BEGINNINGS.detect { |v| v[:version] == version } [:string]
61
+ start_of_vector = vector.index(version_string)
62
+
63
+ if start_of_vector.nil?
64
+ ''
65
+ else
66
+ vector[version_string.length..]
67
+ end
68
+ end
69
+
70
+ def self.prepare_cvss2_vector(vector)
71
+ start_of_vector = vector.index('AV')
72
+
73
+ if start_of_vector.nil?
74
+ ''
75
+ elsif start_of_vector == 1
76
+ match_array = vector.scan(/\((?>[^)(]+|\g<0>)*\)/)
77
+ if match_array.length == 1 && match_array[0] == vector
78
+ vector.slice!(0)
79
+ vector.slice!(vector.length - 1)
80
+ vector
81
+ else
82
+ ''
83
+ end
84
+ else
85
+ vector[start_of_vector..]
86
+ end
87
+ end
54
88
  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: 3.0.0
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - 0llirocks
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-03-13 00:00:00.000000000 Z
11
+ date: 2022-09-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -115,10 +115,15 @@ files:
115
115
  - lib/cvss_suite/helpers/cvss3_helper.rb
116
116
  - lib/cvss_suite/invalid_cvss.rb
117
117
  - lib/cvss_suite/version.rb
118
- homepage: https://cvss-suite.0lli.rocks
118
+ homepage:
119
119
  licenses:
120
120
  - MIT
121
- metadata: {}
121
+ metadata:
122
+ bug_tracker_uri: https://github.com/0llirocks/cvss-suite/issues
123
+ changelog_uri: https://github.com/0llirocks/cvss-suite/blob/master/CHANGES.md
124
+ documentation_uri: https://www.rubydoc.info/gems/cvss-suite/3.1.0
125
+ homepage_uri: https://cvss-suite.0lli.rocks
126
+ source_code_uri: https://github.com/0llirocks/cvss-suite
122
127
  post_install_message:
123
128
  rdoc_options: []
124
129
  require_paths: