cvss-suite 3.0.1 → 3.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4b5de123089a1d8250c5fdccbf1d859a0da8be387ed88875fb88a5613a786cbb
4
- data.tar.gz: cd9150e3086e5f3304f9b4c3de53f587d25b41033218c398aa1e925385e22cee
3
+ metadata.gz: 9474da7f6ca4ff4f9016d55b23714c1a5ca7e1a6a1fce6e4fb74fddbda9ea757
4
+ data.tar.gz: a581c242701b79f72ef2b97208ab9a0524942dcba8ddca75a0df7b5ef0b36c71
5
5
  SHA512:
6
- metadata.gz: 32ef998978e20dfb978dacccfda21b587f31a63ea5426e3e0fc9a1b1c448696d27c641375cb8d35c917c19779098ce2aceca88aaa035efcda6da8d5a5c8c8860
7
- data.tar.gz: 5347e86397270b74cb5b78b5a1fc5eb7e9d9a6de13d56de62a4170c84c459406fd2cfe614434af7a83fdc434ed64ffe17de4738bb418fd4b771c01807140e1fc
6
+ metadata.gz: 2e3d15e35b59915b919faa4b99d3ff8a43d9b9ab231a9993e6b1876cd8b0c55ead7c73d0078a011245ebf40e6fa88f0abc9936eeb7af48c4972df8252d97e037
7
+ data.tar.gz: e061ce21c13ad6759b3b54f01d3330b339322213cf103fbe1350185da8dbf621d6a22ba211fd882fc174daec62ea42695a79ae37511adbe863b6b48fc75b4af2
@@ -8,9 +8,9 @@ jobs:
8
8
  runs-on: ubuntu-latest
9
9
  strategy:
10
10
  matrix:
11
- ruby: [ '2.6', '2.7', '3.0', '3.1' ]
11
+ ruby: [ '2.6', '2.7', '3.0', '3.1', '3.2' ]
12
12
  steps:
13
- - uses: actions/checkout@v2
13
+ - uses: actions/checkout@v3
14
14
  - name: Set up ${{ matrix.ruby }}
15
15
  uses: ruby/setup-ruby@v1
16
16
  with:
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.1] - 2023-10-15
6
+
7
+ ### Fixes
8
+ * CVSS prefix is missing in v3.1.0. Fixes [#33](https://github.com/0llirocks/cvss-suite/issues/33)
9
+
10
+ ## [3.1.0] - 2022-09-27
11
+
12
+ ### Fixes
13
+ * Metrics are no longer order-dependent. Fixes [#30](https://github.com/0llirocks/cvss-suite/issues/30)
14
+
15
+ ### Improvements
16
+ * Temporal and Environmental metrics can now be partly omitted instead of setting them to X.
17
+
5
18
  ## [3.0.1] - 2022-03-13
6
19
 
7
20
  ### Notes
data/README.md CHANGED
@@ -18,6 +18,12 @@ Add this line to your application's Gemfile:
18
18
  gem 'cvss-suite'
19
19
  ```
20
20
 
21
+ Since the naming of this gem is not following the naming convention you can also add the following line to automatically require the gem:
22
+
23
+ ```ruby
24
+ gem 'cvss-suite', require: 'cvss_suite'
25
+ ```
26
+
21
27
  And then execute:
22
28
 
23
29
  $ bundle
@@ -100,14 +106,8 @@ valid = cvss.valid? # false
100
106
  cvss.base_score # will throw CvssSuite::Errors::InvalidVector: Vector is not valid!
101
107
  ```
102
108
 
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
109
  ## Known Issues
108
110
 
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
111
  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
112
 
113
113
  ## Changelog
data/cvss_suite.gemspec CHANGED
@@ -26,11 +26,11 @@ Gem::Specification.new do |spec|
26
26
  Besides calculating the Base, Temporal and Environmental Score, you are able to extract the selected option.'
27
27
 
28
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'
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
34
  }
35
35
 
36
36
  spec.required_ruby_version = '>= 2.6.0'
@@ -1,7 +1,7 @@
1
1
  # CVSS-Suite, a Ruby gem to manage the CVSS vector
2
2
  #
3
3
  # Copyright (c) 2016-2022 Siemens AG
4
- # Copyright (c) 2022 0llirocks
4
+ # Copyright (c) 2022-2023 0llirocks
5
5
  #
6
6
  # Authors:
7
7
  # 0llirocks <http://0lli.rocks>
@@ -17,10 +17,6 @@ module CvssSuite
17
17
  # Metric of a CVSS vector.
18
18
  attr_reader :base, :temporal, :environmental
19
19
 
20
- ##
21
- # Returns the vector itself.
22
- attr_reader :vector
23
-
24
20
  ##
25
21
  # Creates a new CVSS vector by a +vector+.
26
22
  #
@@ -37,7 +33,7 @@ module CvssSuite
37
33
  ##
38
34
  # Returns if CVSS vector is valid.
39
35
  def valid?
40
- if @amount_of_properties == required_amount_of_properties
36
+ if @amount_of_properties >= required_amount_of_properties
41
37
  base = @base.valid?
42
38
  temporal = @base.valid? && @temporal.valid?
43
39
  environmental = @base.valid? && @environmental.valid?
@@ -80,44 +76,30 @@ module CvssSuite
80
76
  base_score
81
77
  end
82
78
 
79
+ ##
80
+ # Returns the vector itself.
81
+ def vector
82
+ @vector.to_s
83
+ end
84
+
83
85
  private
84
86
 
85
87
  def extract_metrics
86
- properties = prepared_vector.split('/')
88
+ properties = @vector.split('/')
87
89
  @amount_of_properties = properties.size
88
90
  properties.each_with_index do |property, index|
89
91
  property = property.split(':')
90
92
  @properties.push({ name: property[0], selected: property[1], position: index })
91
93
  end
94
+ @properties = [] if @properties.group_by { |p| p[:name] }.select { |_k, v| v.size > 1 }.length.positive?
92
95
  end
93
96
 
94
97
  def check_validity
95
98
  raise CvssSuite::Errors::InvalidVector, 'Vector is not valid!' unless valid?
96
99
  end
97
100
 
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
101
  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?
102
+ total = @base.count
121
103
  total || 0
122
104
  end
123
105
  end
@@ -1,7 +1,7 @@
1
1
  # CVSS-Suite, a Ruby gem to manage the CVSS vector
2
2
  #
3
3
  # Copyright (c) 2016-2022 Siemens AG
4
- # Copyright (c) 2022 0llirocks
4
+ # Copyright (c) 2022-2023 0llirocks
5
5
  #
6
6
  # Authors:
7
7
  # 0llirocks <http://0lli.rocks>
@@ -45,6 +45,12 @@ module CvssSuite
45
45
  Cvss3Helper.round_up(@environmental.score(@base, @temporal))
46
46
  end
47
47
 
48
+ ##
49
+ # Returns the vector itself.
50
+ def vector
51
+ "#{CvssSuite::CVSS_VECTOR_BEGINNINGS.find { |beginning| beginning[:version] == version }[:string]}#{@vector}"
52
+ end
53
+
48
54
  private
49
55
 
50
56
  def init_metrics
@@ -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 },
@@ -1,7 +1,7 @@
1
1
  # CVSS-Suite, a Ruby gem to manage the CVSS vector
2
2
  #
3
3
  # Copyright (c) 2019-2022 Siemens AG
4
- # Copyright (c) 2022 0llirocks
4
+ # Copyright (c) 2022-2023 0llirocks
5
5
  #
6
6
  # Authors:
7
7
  # 0llirocks <http://0lli.rocks>
@@ -50,6 +50,12 @@ module CvssSuite
50
50
  Cvss31Helper.round_up(@environmental.score(@base, @temporal))
51
51
  end
52
52
 
53
+ ##
54
+ # Returns the vector itself.
55
+ def vector
56
+ "#{CvssSuite::CVSS_VECTOR_BEGINNINGS.find { |beginning| beginning[:version] == version }[:string]}#{@vector}"
57
+ end
58
+
53
59
  private
54
60
 
55
61
  def init_metrics
@@ -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
@@ -1,7 +1,7 @@
1
1
  # CVSS-Suite, a Ruby gem to manage the CVSS vector
2
2
  #
3
3
  # Copyright (c) 2016-2022 Siemens AG
4
- # Copyright (c) 2022 0llirocks
4
+ # Copyright (c) 2022-2023 0llirocks
5
5
  #
6
6
  # Authors:
7
7
  # 0llirocks <http://0lli.rocks>
@@ -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.1'.freeze
13
+ VERSION = '3.1.1'.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.1
4
+ version: 3.1.1
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: 2023-10-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -121,7 +121,7 @@ licenses:
121
121
  metadata:
122
122
  bug_tracker_uri: https://github.com/0llirocks/cvss-suite/issues
123
123
  changelog_uri: https://github.com/0llirocks/cvss-suite/blob/master/CHANGES.md
124
- documentation_uri: https://www.rubydoc.info/gems/cvss-suite/3.0.1
124
+ documentation_uri: https://www.rubydoc.info/gems/cvss-suite/3.1.1
125
125
  homepage_uri: https://cvss-suite.0lli.rocks
126
126
  source_code_uri: https://github.com/0llirocks/cvss-suite
127
127
  post_install_message: