cvss_rating 0.2.2 → 0.5.3

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
  SHA1:
3
- metadata.gz: 18833ffe0a2110713321717882552cbd95baa964
4
- data.tar.gz: c9517ce89d7c9a16ec78f6e915b4c4ad24f57d2b
3
+ metadata.gz: ba239c3a20044c1f0bdec1bf20040f292fc58a0a
4
+ data.tar.gz: dd3f4a378df8d13d73240ba8ec36dcb4a20c0a63
5
5
  SHA512:
6
- metadata.gz: 67676bd99e61cb6d0946f490c358013a7956b71b44cb8033da4dfe8231364b74c9488d3e0d3da7d381e82dfd03858132507ed1951cccd9460f5eac444066fdb5
7
- data.tar.gz: 6ebbd458fdbd4a627ff5198e6909e537d87c410a3aaf1a64aea7e82e28617bf625c257f5324a27de35734f630d185c6a7ed10e8d37f042dbde327a3b36991283
6
+ metadata.gz: 7c09e29ab6844f87a3279fec34da5ec3bbdc7c68b9dd2f583745f214feeffab34e6d35c70c3ac99b2a67dd2b760ce3bed39da5c0689f37f0d21a36a50bf7325d
7
+ data.tar.gz: 80391b4cc42fa467640cacc70dd06af7ee5a413abefa1410d234a0ce81ab9093e6c9914ac33f26aa0bc733760c3a20c637aad19d79dce1e74da2bc2cfd9c8478
data/README.md CHANGED
@@ -2,7 +2,9 @@
2
2
 
3
3
  [![Build Status](https://travis-ci.org/mort666/cvss_rating.svg)](https://travis-ci.org/mort666/cvss_rating)
4
4
 
5
- Implements CVSS Risk Rating version 2.0
5
+ Implements vulnerability scoring system CVSS versions 2.0 and 3.0.
6
+
7
+ More information on the standard is available at [https://www.first.org/cvss](https://www.first.org/cvss)
6
8
 
7
9
  ## Installation
8
10
 
@@ -20,10 +22,37 @@ Or install it yourself as:
20
22
 
21
23
  ## Usage
22
24
 
23
- Check out the unit tests for examples of usage.
25
+ The following is basic usage to handle a CVSS 2.0 vector:
26
+
27
+ cvs = Cvss2::Rating.new
28
+ cvss.parse("AV:N/AC:M/Au:N/C:P/I:P/A:P")
29
+
30
+ # Calculate overallscore
31
+ cvss.overallscore
32
+
33
+ The following is basic usage to handle a CVSS 3.0 vector:
34
+
35
+ cvss = Cvss3::Rating.new
36
+ cvss.parse("AV:P/AC:H/PR:H/UI:R/S:C/C:H/I:L/A:N/E:U/RL:O/RC:U/CR:L/IR:L/AR:L")
37
+
38
+ # Calculate Base Score (returns array of score and risk level)
39
+ cvss.cvss_base_score
40
+
41
+ # Calculate Temporal Score (returns array of score and risk level)
42
+ cvss.cvss_temporal_score
43
+
44
+ # Calculate Environmental Score (returns array of score and risk level)
45
+ cvss.cvss_environmental_score
46
+
47
+ Check out the unit tests for more examples of usage.
24
48
 
25
49
  ## TODO
26
50
 
27
- * CVSS 3.0 Support
28
51
  * Code and API clean up
29
52
  * More Unit Tests
53
+
54
+ ## License
55
+
56
+ Copyright (c) Stephen Kapp 2015.
57
+
58
+ Released under the MIT License
data/cvss_rating.gemspec CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ["Stephen Kapp"]
10
10
  spec.email = ["mort666@virus.org"]
11
11
  spec.summary = %q{CVSS Risk Rating Calculation and Vector parsing}
12
- spec.description = %q{CVSS Risk Rating Calculation and Vector parsing, implements CVSS 2.0 rating}
12
+ spec.description = %q{CVSS Risk Rating Calculation and Vector parsing, implements CVSS 2.0 & 3.0 rating}
13
13
  spec.homepage = "https://github.com/mort666/cvss_rating"
14
14
  spec.license = "MIT"
15
15
 
@@ -0,0 +1,106 @@
1
+ # @author Stephen Kapp
2
+
3
+ require "cvss_rating/version"
4
+ require "cvss_rating/cvss3_formulas"
5
+ require "cvss_rating/cvss3_metrics"
6
+ require "cvss_rating/cvss3_vectors"
7
+
8
+ module Cvss3
9
+ class Rating
10
+ attr_accessor :exploitability, :base, :impact, :temporal, :environmental
11
+
12
+ include Cvss3Vectors
13
+
14
+ #
15
+ # Initialize the object, creates a clean initialized Cvss3::Rating object
16
+ #
17
+ # @param list [Hash] list of CVSS 3.0 attributes to be used during initialization
18
+ #
19
+
20
+ def initialize(attributes = {})
21
+ init
22
+
23
+ attributes.each do |name, value|
24
+ send("#{name}=", value)
25
+ end
26
+ end
27
+
28
+
29
+ #
30
+ # Takes score and determines risk level from None to Critical
31
+ #
32
+ # @param score [Float] risk score to be converted to risk level
33
+ # @return [String] risk level based on score
34
+
35
+ def risk_score(score)
36
+ risk_score = case score
37
+ when 0.0
38
+ "None"
39
+ when 0.1..3.9
40
+ "Low"
41
+ when 4.0..6.9
42
+ "Medium"
43
+ when 7.0..8.9
44
+ "High"
45
+ when 9.0..10.0
46
+ "Critical"
47
+ else
48
+ nil
49
+ end
50
+ end
51
+
52
+
53
+ #
54
+ # Calculate the CVSS 3.0 Base Score
55
+ #
56
+ # @return [Array] the CVSS 3.0 Base score with its risk level
57
+
58
+ def cvss_base_score
59
+ @exploitability = ::Cvss3::Formulas.new.exploitability_sub_score(@av, @ac, @pr, @ui)
60
+
61
+ @impact = ::Cvss3::Formulas.new.impact_sub_score_base(@ai, @ci, @ii)
62
+
63
+ @base = ::Cvss3::Formulas.new.cvss_base_formula(@impact, @sc, @exploitability)
64
+
65
+ @base_level = risk_score(@base)
66
+
67
+ return @base, @base_level
68
+ end
69
+
70
+ ##
71
+ #
72
+ # Calculate the CVSS 3.0 Temporal Score
73
+ #
74
+ # @return [Array] the CVSS 3.0 Temporal score with its risk level
75
+
76
+ def cvss_temporal_score
77
+ @temporal = ::Cvss3::Formulas.new.cvss_temporal_formula(@base, @ex, @rl, @rc)
78
+
79
+ @temporal_level = risk_score(@temporal)
80
+
81
+ return @temporal, @temporal_level
82
+ end
83
+
84
+ ##
85
+ #
86
+ # Calculate the CVSS 3.0 Temporal Score
87
+ #
88
+ # @return [Array] the CVSS 3.0 Temporal score with its risk level
89
+
90
+ def cvss_environmental_score
91
+ exploitability_sub_score_value_modified = ::Cvss3::Formulas.new.exploitability_sub_score_modified(self.mav(true),
92
+ self.mac(true), self.mpr(true), self.mui(true))
93
+
94
+ impact_sub_score_value_modified = ::Cvss3::Formulas.new.impact_sub_score_modified_base(self.ma(true), self.mc(true),
95
+ self.mi(true), @cr, @ir, @ar)
96
+
97
+ @environmental = ::Cvss3::Formulas.new.cvss_environmental_formula(impact_sub_score_value_modified,
98
+ exploitability_sub_score_value_modified,
99
+ @ex, @rl, @rc, self.ms(true))
100
+
101
+ @environmental_level = risk_score(@environmental)
102
+
103
+ return @environmental, @environmental_level
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,103 @@
1
+ module Cvss3
2
+ class Formulas
3
+ EXPLOITABILITY_COEFFICIENT = 8.22
4
+ IMPACT_COEFFICIENT = 6.42
5
+ IMPACT_MOD_COEFFICIENT = 7.52
6
+
7
+ def exploitability_sub_score(attack_vector_value, attack_complexity_value, privileges_required_value, user_interaction_value)
8
+
9
+ exploitability_sub_score_value = EXPLOITABILITY_COEFFICIENT * attack_vector_value * attack_complexity_value * privileges_required_value * user_interaction_value
10
+
11
+ return exploitability_sub_score_value
12
+ end
13
+
14
+ def exploitability_sub_score_modified(attack_vector_value_modified, attack_complexity_value_modified,
15
+ privileges_required_value_modified, user_interaction_value_modified)
16
+
17
+ exploitability_sub_score_value_modified = EXPLOITABILITY_COEFFICIENT * attack_vector_value_modified * attack_complexity_value_modified * privileges_required_value_modified * user_interaction_value_modified
18
+
19
+ return exploitability_sub_score_value_modified
20
+ end
21
+
22
+ def impact_sub_score_base(availability_value, confidentiality_value, integrity_value)
23
+
24
+ impact_sub_score_value = 1 - ((1 - confidentiality_value) * (1 - integrity_value) * (1 - availability_value))
25
+
26
+ return impact_sub_score_value
27
+ end
28
+
29
+ def impact_sub_score_modified_base(availability_value_modified, confidentiality_value_modified, integrity_value_modified,
30
+ confidentiality_requirement_value, integrity_requirement_value, availability_requirement_value)
31
+
32
+ impact_sub_score_value_modified = min(0.915, 1 - (1 - confidentiality_value_modified * confidentiality_requirement_value) * (1 - integrity_value_modified * integrity_requirement_value) * (1 - availability_value_modified * availability_requirement_value))
33
+
34
+ return impact_sub_score_value_modified
35
+ end
36
+
37
+ def cvss_base_formula(impact_sub_score_value, scope_value, exploitability_sub_score_value)
38
+
39
+ if scope_value == "unchanged"
40
+ impact_value = IMPACT_COEFFICIENT * impact_sub_score_value
41
+ cvss_base_value = min(10, impact_value + exploitability_sub_score_value)
42
+ elsif scope_value == "changed"
43
+ impact_value = IMPACT_MOD_COEFFICIENT * (impact_sub_score_value - 0.029) - 3.25 * ((impact_sub_score_value - 0.02) ** 15)
44
+ cvss_base_value = min(10, 1.08 * (impact_value + exploitability_sub_score_value))
45
+ end
46
+
47
+ if impact_sub_score_value <= 0
48
+ cvss_base_value = 0.0
49
+ else
50
+ cvss_base_value = cvss_base_value.ceil2(1)
51
+ end
52
+
53
+ return cvss_base_value
54
+ end
55
+
56
+ def cvss_temporal_formula(cvss_base_value, exploit_code_maturity_value, remediation_level_value, report_confidence_value)
57
+
58
+ cvss_temporal_value = cvss_base_value * exploit_code_maturity_value * remediation_level_value * \
59
+ report_confidence_value
60
+
61
+ cvss_temporal_value = cvss_temporal_value.ceil2(1)
62
+
63
+ return cvss_temporal_value
64
+ end
65
+
66
+ def cvss_environmental_formula(impact_sub_score_value_modified, exploitability_sub_score_value_modified,
67
+ exploit_code_maturity_value, remediation_level_value, report_confidence_value, scope_value_modified)
68
+
69
+ if scope_value_modified == "unchanged"
70
+ impact_value_modified = IMPACT_COEFFICIENT * impact_sub_score_value_modified
71
+ temp_score = min(10, impact_value_modified + exploitability_sub_score_value_modified)
72
+ temp_score2 = temp_score.ceil2(1)
73
+ temp_score3 = temp_score2 * exploit_code_maturity_value * remediation_level_value * report_confidence_value
74
+ elsif scope_value_modified == "changed"
75
+ impact_value_modified = IMPACT_MOD_COEFFICIENT * (impact_sub_score_value_modified - 0.029) - 3.25 * ((impact_sub_score_value_modified - 0.02) ** 15)
76
+ temp_score = min(10, 1.08 * (impact_value_modified + exploitability_sub_score_value_modified))
77
+ temp_score2 = temp_score.ceil2(1)
78
+ temp_score3 = temp_score2 * exploit_code_maturity_value * remediation_level_value * report_confidence_value
79
+ end
80
+
81
+ if impact_sub_score_value_modified <= 0
82
+ cvss_environmental_value = 0.0
83
+ else
84
+ cvss_environmental_value = temp_score3.ceil2(1)
85
+ end
86
+
87
+ return cvss_environmental_value
88
+ end
89
+
90
+
91
+ def min(*values)
92
+ values.min
93
+ end
94
+ end
95
+ end
96
+
97
+
98
+ class Float
99
+ def ceil2(exp = 0)
100
+ multiplier = 10 ** exp
101
+ ((self * multiplier).ceil).to_f/multiplier.to_f
102
+ end
103
+ end
@@ -0,0 +1,52 @@
1
+ module Cvss3
2
+ class Metrics
3
+ # Base Metrics
4
+ ATTACK_VECTOR = { :physical => 0.2, :local => 0.55, :adjacent_network => 0.62, :network => 0.85, :not_defined => 0.85 }
5
+ ATTACK_COMPLEXITY = { :high => 0.44, :low => 0.77, :not_defined => 0.77 }
6
+
7
+ PRIVILEGE_REQUIRED = { :not_defined => 0.85, :none => 0.85, :low => 0.62, :high => 0.27 }
8
+ PRIVILEGE_REQUIRED_CHANGED = { :not_defined => 0.85, :none => 0.85, :low => 0.68, :high => 0.50 }
9
+
10
+ USER_INTERACTION = {:not_defined => 0.85, :none => 0.85, :required => 0.62 }
11
+
12
+ CIA_IMPACT = { :none => 0.0, :low => 0.22, :high => 0.56, :not_defined => 0.56 }
13
+
14
+ # Environmental Metrics
15
+ CIA_REQUIREMENT = { :low => 0.5, :medium => 1.0, :high => 1.50, :not_defined => 1.0 }
16
+
17
+ # Temporal Metrics
18
+ EXPLOITABILITY = { :unproven => 0.91, :poc => 0.94, :functional => 0.97, :high => 1.0, :not_defined => 1.0 }
19
+
20
+ REMEDIATION_LEVEL = { :official => 0.95, :temporary => 0.96, :workaround => 0.97, :unavailable => 1.0, :not_defined => 1.0 }
21
+
22
+ REPORT_CONFIDENCE = { :unknown => 0.92, :reasonable => 0.96, :confirmed => 1.0, :not_defined => 1.0 }
23
+
24
+ # Key Lookup values
25
+
26
+ ATTACK_VECTOR_KEY = { :physical => 'P', :local => 'L', :adjacent_network => 'A', :network => 'N' }
27
+ ATTACK_COMPLEXITY_KEY = { :high => 'H', :low => 'L' }
28
+ PRIVILEGE_REQUIRED_KEY = { :none => 'N', :low => 'L', :high => 'H' }
29
+ PRIVILEGE_REQUIRED_CHANGED_KEY = { :none => 'N', :low => 'L', :high => 'H' }
30
+ USER_INTERACTION_KEY = { :none => 'N', :required => 'R' }
31
+
32
+ SCOPE_KEY = { :changed => 'C', :unchanged => 'U' }
33
+
34
+ CIA_IMPACT_KEY = { :none => 'N', :low => 'L', :high => 'H' }
35
+
36
+ CIA_REQUIREMENT_KEY = { :low => 'L', :medium => 'M', :high => 'H', :notdefined => 'ND' }
37
+
38
+ EXPLOITABILITY_KEY = { :unproven => 'U', :poc => 'P', :functional => 'F', :high => 'H', :not_defined => 'ND' }
39
+ REMEDIATION_LEVEL_KEY = { :official => 'O', :temporary => "T", :workaround => 'W', :unavailable => 'U', :not_defined => 'ND' }
40
+ REPORT_CONFIDENCE_KEY = { :unknown => 'U', :reasonable => 'R', :confirmed => 'C', :not_defined => 'ND' }
41
+
42
+ MODIFIED_ATTACK_VECTOR_KEY = { :physical => 'P', :local => 'L', :adjacent_network => 'A', :network => 'N' }
43
+ MODIFIED_ATTACK_COMPLEXITY_KEY = { :high => 'H', :low => 'L' }
44
+ MODIFIED_PRIVILEGE_REQUIRED_KEY = { :none => 'N', :low => 'L', :high => 'H' }
45
+ MODIFIED_PRIVILEGE_REQUIRED_CHANGED_KEY = { :none => 'N', :low => 'L', :high => 'H' }
46
+ MODIFIED_USER_INTERACTION_KEY = { :none => 'N', :required => 'R' }
47
+
48
+ MODIFIED_SCOPE_KEY = { :changed => 'C', :unchanged => 'U' }
49
+
50
+ MODIFIED_CIA_IMPACT_KEY = { :none => 'N', :low => 'L', :high => 'H' }
51
+ end
52
+ end
@@ -0,0 +1,551 @@
1
+ module Cvss3Vectors
2
+ attr_reader :av, :ac, :ui, :sc, :ci, :ai, :ii, :ex, :rl, :rc, :pr, :td, :cr, :ir
3
+
4
+ VECTORS = {
5
+ "cvss" => "cvss3=",
6
+ "av" => "av=",
7
+ "ac" => "ac=",
8
+ "ui" => "ui=",
9
+ "s" => "sc=",
10
+ "c" => "ci=",
11
+ "i" => "ii=",
12
+ "a" => "ai=",
13
+ "e" => "ex=",
14
+ "rl" => "rl=",
15
+ "rc" => "rc=",
16
+ "pr" => "pr=",
17
+ "cr" => "cr=",
18
+ "ir" => "ir=",
19
+ "ar" => "ar=",
20
+ "mav" => "mav=",
21
+ "mac" => "mac=",
22
+ "ms" => "ms=",
23
+ "mpr" => "mpr=",
24
+ "mui" => "mui=",
25
+ "mc" => "mc=",
26
+ "mi" => "mi=",
27
+ "ma" => "ma="
28
+ }
29
+
30
+ def parse(vector)
31
+ string = vector.split("/")
32
+ len = string.length
33
+
34
+ init
35
+
36
+ @originalkey = vector
37
+
38
+ string.each do |section|
39
+ tmp = section.split(":")
40
+ send(VECTORS[tmp[0].downcase].to_sym, tmp[1])
41
+ end
42
+ end
43
+
44
+ def set_key
45
+ @key = "AV:%s/AC:%s/PR:%s/UI:%s/C:%s/I:%s/A:%s" % [ self.av,
46
+ self.ac, self.pr, self.ui,
47
+ self.ci, self.ii, self.ai]
48
+
49
+ @key += "/E:%s" % self.ex if !@ex.nil?
50
+ @key += "/RL:%s" % self.rl if !@rl.nil?
51
+ @key += "/RC:%s" % self.rc if !@rc.nil?
52
+
53
+ @key += "/CR:%s" % self.cr if !@cr.nil?
54
+ @key += "/IR:%s" % self.ir if !@ir.nil?
55
+ @key += "/AR:%s" % self.ar if !@ar.nil?
56
+
57
+ @key += "/MAV:%s" % self.mav if !@mav.nil?
58
+ @key += "/MAC:%s" % self.mac if !@mac.nil?
59
+ @key += "/MPR:%s" % self.mpr if !@mpr.nil?
60
+ @key += "/MUI:%s" % self.mui if !@mui.nil?
61
+ @key += "/MS:%s" % self.ms if !@ms.nil?
62
+
63
+ @key += "/MC:%s" % self.mc if !@mc.nil?
64
+ @key += "/MI:%s" % self.mi if !@mi.nil?
65
+ @key += "/MA:%s" % self.ma if !@ma.nil?
66
+
67
+ end
68
+
69
+ def key
70
+ self.set_key
71
+ return @key
72
+ end
73
+
74
+ def get_key(vector, value)
75
+ get_key = eval("::Cvss3::Metrics::" + vector + "_KEY")[(eval("::Cvss3::Metrics::" + vector).select { |k,v| v == value }).keys[0]]
76
+ end
77
+
78
+ def cvss3=(cvss3)
79
+ if cvss3 != "3.0"
80
+ raise "Bad CVSS 3.0 Vector String"
81
+ end
82
+ end
83
+
84
+ def av=(av)
85
+ @av = case av
86
+ when "physical", "P"
87
+ ::Cvss3::Metrics::ATTACK_VECTOR[:physical]
88
+ when "local", "L"
89
+ ::Cvss3::Metrics::ATTACK_VECTOR[:local]
90
+ when "adjacent network", "A"
91
+ ::Cvss3::Metrics::ATTACK_VECTOR[:adjacent_network]
92
+ when "network", "N"
93
+ ::Cvss3::Metrics::ATTACK_VECTOR[:network]
94
+ else
95
+ raise "Bad Argument"
96
+ end
97
+ end
98
+
99
+ def av
100
+ av = get_key("ATTACK_VECTOR", @av) if !@av.nil?
101
+ end
102
+
103
+ def ac=(ac)
104
+ @ac = case ac
105
+ when "high", "H"
106
+ ::Cvss3::Metrics::ATTACK_COMPLEXITY[:high]
107
+ when "low", "L"
108
+ ::Cvss3::Metrics::ATTACK_COMPLEXITY[:low]
109
+ else
110
+ raise "Bad Argument"
111
+ end
112
+ end
113
+
114
+ def ac
115
+ ac = get_key("ATTACK_COMPLEXITY", @ac) if !@ac.nil?
116
+ end
117
+
118
+ def ui=(ui)
119
+ @ui = case ui
120
+ when "none", "N"
121
+ ::Cvss3::Metrics::USER_INTERACTION[:none]
122
+ when "required", "R"
123
+ ::Cvss3::Metrics::USER_INTERACTION[:required]
124
+ else
125
+ raise "Bad Argument"
126
+ end
127
+ end
128
+
129
+ def ui
130
+ ui = get_key("USER_INTERACTION", @ui) if !@ui.nil?
131
+ end
132
+
133
+ def pr=(pr)
134
+ @pr = case pr
135
+ when "none", "N"
136
+ ::Cvss3::Metrics::PRIVILEGE_REQUIRED[:none]
137
+ when "low", "L"
138
+ ::Cvss3::Metrics::PRIVILEGE_REQUIRED[:low]
139
+ when "high", "H"
140
+ ::Cvss3::Metrics::PRIVILEGE_REQUIRED[:high]
141
+ else
142
+ raise "Bad Argument"
143
+ end
144
+ end
145
+
146
+ def pr
147
+ if @sc == "changed"
148
+ pr = get_key("PRIVILEGE_REQUIRED_CHANGED", @pr) if !@pr.nil?
149
+ else
150
+ pr = get_key("PRIVILEGE_REQUIRED", @pr) if !@pr.nil?
151
+ end
152
+ end
153
+
154
+ def sc=(sc)
155
+ @sc = case sc
156
+ when "changed", "C"
157
+ "changed"
158
+ when "unchanged", "U"
159
+ "unchanged"
160
+ else
161
+ raise "Bad Argument"
162
+ end
163
+
164
+ if @sc == "changed"
165
+ @pr = case get_key("PRIVILEGE_REQUIRED", @pr).nil? ? get_key("PRIVILEGE_REQUIRED_CHANGED", @pr) : get_key("PRIVILEGE_REQUIRED", @pr)
166
+ when "none", "N",
167
+ ::Cvss3::Metrics::PRIVILEGE_REQUIRED_CHANGED[:none]
168
+ when "low", "L"
169
+ ::Cvss3::Metrics::PRIVILEGE_REQUIRED_CHANGED[:low]
170
+ when "high", "H"
171
+ ::Cvss3::Metrics::PRIVILEGE_REQUIRED_CHANGED[:high]
172
+ else
173
+ raise "Bad Argument"
174
+ end
175
+ else
176
+ self.pr = get_key("PRIVILEGE_REQUIRED", @pr).nil? ? get_key("PRIVILEGE_REQUIRED_CHANGED", @pr) : get_key("PRIVILEGE_REQUIRED", @pr)
177
+ end
178
+ end
179
+
180
+ def sc
181
+ sc = ::Cvss3::Metrics::SCOPE_KEY[@sc.to_sym] if !@sc.nil?
182
+ end
183
+
184
+ def ci=(ci)
185
+ @ci = case ci
186
+ when "none", "N"
187
+ ::Cvss3::Metrics::CIA_IMPACT[:none]
188
+ when "low", "L"
189
+ ::Cvss3::Metrics::CIA_IMPACT[:low]
190
+ when "high", "H"
191
+ ::Cvss3::Metrics::CIA_IMPACT[:high]
192
+ else
193
+ raise "Bad Argument"
194
+ end
195
+ end
196
+
197
+ def ci
198
+ ci = get_key("CIA_IMPACT", @ci) if !@ci.nil?
199
+ end
200
+
201
+ def ii=(ii)
202
+ @ii = case ii
203
+ when "none", "N"
204
+ ::Cvss3::Metrics::CIA_IMPACT[:none]
205
+ when "low", "L"
206
+ ::Cvss3::Metrics::CIA_IMPACT[:low]
207
+ when "high", "H"
208
+ ::Cvss3::Metrics::CIA_IMPACT[:high]
209
+ else
210
+ raise "Bad Argument"
211
+ end
212
+ end
213
+
214
+ def ii
215
+ ii = get_key("CIA_IMPACT", @ii) if !@ii.nil?
216
+ end
217
+
218
+ def ai=(ai)
219
+ @ai = case ai
220
+ when "none", "N"
221
+ ::Cvss3::Metrics::CIA_IMPACT[:none]
222
+ when "low", "L"
223
+ ::Cvss3::Metrics::CIA_IMPACT[:low]
224
+ when "high", "H"
225
+ ::Cvss3::Metrics::CIA_IMPACT[:high]
226
+ else
227
+ raise "Bad Argument"
228
+ end
229
+ end
230
+
231
+ def ai
232
+ ai = get_key("CIA_IMPACT", @ai) if !@ai.nil?
233
+ end
234
+
235
+ def mav=(mav)
236
+ @mav = case mav
237
+ when "physical", "P"
238
+ ::Cvss3::Metrics::ATTACK_VECTOR[:physical]
239
+ when "local", "L"
240
+ ::Cvss3::Metrics::ATTACK_VECTOR[:local]
241
+ when "adjacent network", "A"
242
+ ::Cvss3::Metrics::ATTACK_VECTOR[:adjacent_network]
243
+ when "network", "N"
244
+ ::Cvss3::Metrics::ATTACK_VECTOR[:network]
245
+ when "not_defined", "ND"
246
+ nil
247
+ else
248
+ raise "Bad Argument"
249
+ end
250
+ end
251
+
252
+ def mav(raw=false)
253
+ if raw
254
+ @mav ||= @av
255
+ else
256
+ mav = get_key("ATTACK_VECTOR", @mav) if !@mav.nil?
257
+ end
258
+ end
259
+
260
+ def mac=(mac)
261
+ @mac = case mac
262
+ when "high", "H"
263
+ ::Cvss3::Metrics::ATTACK_COMPLEXITY[:high]
264
+ when "low", "L"
265
+ ::Cvss3::Metrics::ATTACK_COMPLEXITY[:low]
266
+ when "not_defined", "ND"
267
+ nil
268
+ else
269
+ raise "Bad Argument"
270
+ end
271
+ end
272
+
273
+ def mac(raw=false)
274
+ if raw
275
+ @mac ||= @ac
276
+ else
277
+ mac = get_key("ATTACK_COMPLEXITY", @mac) if !@mac.nil?
278
+ end
279
+ end
280
+
281
+ def mui=(mui)
282
+ @mui = case mui
283
+ when "none", "N"
284
+ ::Cvss3::Metrics::USER_INTERACTION[:none]
285
+ when "required", "R"
286
+ ::Cvss3::Metrics::USER_INTERACTION[:required]
287
+ when "not_defined", "ND"
288
+ nil
289
+ else
290
+ raise "Bad Argument"
291
+ end
292
+ end
293
+
294
+ def mui(raw=false)
295
+ if raw
296
+ @mui ||= @ui
297
+ else
298
+ mui = get_key("USER_INTERACTION", @mui) if !@mui.nil?
299
+ end
300
+ end
301
+
302
+ def mpr=(mpr)
303
+ @mpr = case mpr
304
+ when "none", "N"
305
+ ::Cvss3::Metrics::PRIVILEGE_REQUIRED[:none]
306
+ when "low", "L"
307
+ ::Cvss3::Metrics::PRIVILEGE_REQUIRED[:low]
308
+ when "high", "H"
309
+ ::Cvss3::Metrics::PRIVILEGE_REQUIRED[:high]
310
+ when "not_defined", "ND"
311
+ nil
312
+ else
313
+ raise "Bad Argument"
314
+ end
315
+ end
316
+
317
+ def mpr(raw=false)
318
+ if raw
319
+ @mpr ||= @pr
320
+ else
321
+ if @ms == "changed"
322
+ mpr = get_key("PRIVILEGE_REQUIRED_CHANGED", @mpr) if !@mpr.nil?
323
+ else
324
+ mpr = get_key("PRIVILEGE_REQUIRED", @mpr) if !@mpr.nil?
325
+ end
326
+ end
327
+ end
328
+
329
+ def ms=(ms)
330
+ @ms = case ms
331
+ when "changed", "C"
332
+ "changed"
333
+ when "unchanged", "U"
334
+ "unchanged"
335
+ when "not_defined", "ND"
336
+ nil
337
+ else
338
+ raise "Bad Argument"
339
+ end
340
+
341
+ if @ms == "changed"
342
+ @mpr = case get_key("PRIVILEGE_REQUIRED", self.mpr(true)).nil? ? get_key("PRIVILEGE_REQUIRED_CHANGED", self.mpr(true)) : get_key("PRIVILEGE_REQUIRED", self.mpr(true))
343
+ when "none", "N",
344
+ ::Cvss3::Metrics::PRIVILEGE_REQUIRED_CHANGED[:none]
345
+ when "low", "L"
346
+ ::Cvss3::Metrics::PRIVILEGE_REQUIRED_CHANGED[:low]
347
+ when "high", "H"
348
+ ::Cvss3::Metrics::PRIVILEGE_REQUIRED_CHANGED[:high]
349
+ else
350
+ raise "Bad Argument"
351
+ end
352
+ else
353
+ self.mpr = get_key("PRIVILEGE_REQUIRED", self.mpr(true)).nil? ? get_key("PRIVILEGE_REQUIRED_CHANGED", self.mpr(true)) : get_key("PRIVILEGE_REQUIRED", self.mpr(true))
354
+ end
355
+ end
356
+
357
+ def ms(raw=false)
358
+ if raw
359
+ @ms ||= @sc
360
+ else
361
+ if @ms.nil?
362
+ ms = ::Cvss3::Metrics::SCOPE_KEY[@sc.to_sym] if !@sc.nil?
363
+ else
364
+ ms = ::Cvss3::Metrics::SCOPE_KEY[@ms.to_sym] if !@ms.nil?
365
+ end
366
+ end
367
+ end
368
+
369
+ def mc=(mc)
370
+ @mc = case mc
371
+ when "none", "N"
372
+ ::Cvss3::Metrics::CIA_IMPACT[:none]
373
+ when "low", "L"
374
+ ::Cvss3::Metrics::CIA_IMPACT[:low]
375
+ when "high", "H"
376
+ ::Cvss3::Metrics::CIA_IMPACT[:high]
377
+ when "not_defined", "ND"
378
+ nil
379
+ else
380
+ raise "Bad Argument"
381
+ end
382
+ end
383
+
384
+ def mc(raw=false)
385
+ if raw
386
+ @mv ||= @ci
387
+ else
388
+ mc = get_key("CIA_IMPACT", @mc) if !@mc.nil?
389
+ end
390
+ end
391
+
392
+ def mi=(mi)
393
+ @mi = case mi
394
+ when "none", "N"
395
+ ::Cvss3::Metrics::CIA_IMPACT[:none]
396
+ when "low", "L"
397
+ ::Cvss3::Metrics::CIA_IMPACT[:low]
398
+ when "high", "H"
399
+ ::Cvss3::Metrics::CIA_IMPACT[:high]
400
+ when "not_defined", "ND"
401
+ nil
402
+ else
403
+ raise "Bad Argument"
404
+ end
405
+ end
406
+
407
+ def mi(raw=false)
408
+ if raw
409
+ @mi ||= @ii
410
+ else
411
+ mi = get_key("CIA_IMPACT", @mi) if !@mi.nil?
412
+ end
413
+ end
414
+
415
+ def ma=(ma)
416
+ @ma = case ma
417
+ when "none", "N"
418
+ ::Cvss3::Metrics::CIA_IMPACT[:none]
419
+ when "low", "L"
420
+ ::Cvss3::Metrics::CIA_IMPACT[:low]
421
+ when "high", "H"
422
+ ::Cvss3::Metrics::CIA_IMPACT[:high]
423
+ when "not_defined", "ND"
424
+ nil
425
+ else
426
+ raise "Bad Argument"
427
+ end
428
+ end
429
+
430
+ def ma(raw=false)
431
+ if raw
432
+ @ma ||= @ai
433
+ else
434
+ ma = get_key("CIA_IMPACT", @ma) if !@ma.nil?
435
+ end
436
+ end
437
+
438
+ def ex=(ex)
439
+ @ex = case ex
440
+ when "unproven", "U" then ::Cvss3::Metrics::EXPLOITABILITY[:unproven]
441
+ when "proof-of-concept", "P", "POC" then ::Cvss3::Metrics::EXPLOITABILITY[:poc]
442
+ when "functional", "F" then ::Cvss3::Metrics::EXPLOITABILITY[:functional]
443
+ when "high", "H" then ::Cvss3::Metrics::EXPLOITABILITY[:high]
444
+ when "not defined", "ND", "X" then ::Cvss3::Metrics::EXPLOITABILITY[:not_defined]
445
+ else
446
+ raise "Bad Argument"
447
+ end
448
+ end
449
+
450
+ def ex
451
+ ex = get_key("EXPLOITABILITY", @ex) if !@ex.nil?
452
+ end
453
+
454
+ def rl=(rl)
455
+ @rl = case rl
456
+ when "official-fix", "O" then ::Cvss3::Metrics::REMEDIATION_LEVEL[:official]
457
+ when "temporary-fix", "T", "TF" then ::Cvss3::Metrics::REMEDIATION_LEVEL[:temporary]
458
+ when "workaround", "W" then ::Cvss3::Metrics::REMEDIATION_LEVEL[:workaround]
459
+ when "unavailable", "U" then ::Cvss3::Metrics::REMEDIATION_LEVEL[:unavailable]
460
+ when "not defined", "ND", "X" then ::Cvss3::Metrics::REMEDIATION_LEVEL[:not_defined]
461
+ else
462
+ raise "Bad Argument"
463
+ end
464
+ end
465
+
466
+ def rl
467
+ rl = get_key("REMEDIATION_LEVEL", @rl) if !@rl.nil?
468
+ end
469
+
470
+ def rc=(rc)
471
+ @rc = case rc
472
+ when "unknown", "U" then ::Cvss3::Metrics::REPORT_CONFIDENCE[:unknown]
473
+ when "reasonable", "R" then ::Cvss3::Metrics::REPORT_CONFIDENCE[:reasonable]
474
+ when "confirmed", "C" then ::Cvss3::Metrics::REPORT_CONFIDENCE[:confirmed]
475
+ when "not defined", "ND", "X" then ::Cvss3::Metrics::REPORT_CONFIDENCE[:not_defined]
476
+ else
477
+ raise "Bad Argument"
478
+ end
479
+ end
480
+
481
+ def rc
482
+ rc = get_key("REPORT_CONFIDENCE", @rc) if !@av.nil?
483
+ end
484
+
485
+ def cr=(cr)
486
+ @cr = case cr
487
+ when "low", "L" then ::Cvss3::Metrics::CIA_REQUIREMENT[:low]
488
+ when "medium", "M" then ::Cvss3::Metrics::CIA_REQUIREMENT[:medium]
489
+ when "high", "H" then ::Cvss3::Metrics::CIA_REQUIREMENT[:high]
490
+ when "not defined", "ND", "X" then ::Cvss3::Metrics::CIA_REQUIREMENT[:not_defined]
491
+ else
492
+ raise "Bad Argument"
493
+ end
494
+ end
495
+
496
+ def cr
497
+ cr = get_key("CIA_REQUIREMENT", @cr) if !@cr.nil?
498
+ end
499
+
500
+ def ir=(ir)
501
+ @ir = case ir
502
+ when "low", "L" then ::Cvss3::Metrics::CIA_REQUIREMENT[:low]
503
+ when "medium", "M" then ::Cvss3::Metrics::CIA_REQUIREMENT[:medium]
504
+ when "high", "H" then ::Cvss3::Metrics::CIA_REQUIREMENT[:high]
505
+ when "not defined", "ND", "X" then ::Cvss3::Metrics::CIA_REQUIREMENT[:not_defined]
506
+ else
507
+ raise "Bad Argument"
508
+ end
509
+ end
510
+
511
+ def ir
512
+ ir = get_key("CIA_REQUIREMENT", @ir) if !@ir.nil?
513
+ end
514
+
515
+ def ar=(ar)
516
+ @ar = case ar
517
+ when "low", "L" then ::Cvss3::Metrics::CIA_REQUIREMENT[:low]
518
+ when "medium", "M" then ::Cvss3::Metrics::CIA_REQUIREMENT[:medium]
519
+ when "high", "H" then ::Cvss3::Metrics::CIA_REQUIREMENT[:high]
520
+ when "not defined", "ND", "X" then ::Cvss3::Metrics::CIA_REQUIREMENT[:not_defined]
521
+ else
522
+ raise "Bad Argument"
523
+ end
524
+ end
525
+
526
+ def ar
527
+ ar = get_key("CIA_REQUIREMENT", @ar) if !@ar.nil?
528
+ end
529
+
530
+
531
+ def init(ex = "ND", rl = "ND", rc = "ND", cd = "ND", td = "ND", cr = "ND", ir = "ND", ar = "ND",
532
+ mav = "ND", mac = "ND", mpv = "ND", mui = "ND", mc = "ND", mi = "ND", ma = "ND")
533
+ self.ex = ex
534
+ self.rl = rl
535
+ self.rc = rc
536
+
537
+ self.cr = cr
538
+ self.ir = ir
539
+ self.ar = ar
540
+
541
+ self.mav = mav
542
+ self.mac = mac
543
+ self.mpr = mpv
544
+ self.mui = mui
545
+
546
+ self.mc = mc
547
+ self.mi = mi
548
+ self.ma = ma
549
+ end
550
+
551
+ end
@@ -1,5 +1,5 @@
1
1
  module Cvss2
2
2
  class Rating
3
- VERSION = "0.2.2"
3
+ VERSION = "0.5.3"
4
4
  end
5
5
  end
@@ -2,7 +2,7 @@ require 'minitest/autorun'
2
2
  require 'active_support'
3
3
  require 'cvss2_rating'
4
4
 
5
- class CvssRatingTest < MiniTest::Unit::TestCase
5
+ class CvssRatingTest < MiniTest::Test
6
6
  def setup
7
7
  @cvss = Cvss2::Rating.new
8
8
  @cvss.av = "N"
@@ -0,0 +1,235 @@
1
+ require 'minitest/autorun'
2
+ require 'active_support'
3
+ require 'cvss3_rating'
4
+
5
+ class Cvss3RatingTest < MiniTest::Test
6
+ def setup
7
+ @cvss = Cvss3::Rating.new
8
+ @cvss.av = "P"
9
+ @cvss.ac = "H"
10
+ @cvss.ui = "R"
11
+ @cvss.pr = "L"
12
+ @cvss.sc = "C"
13
+ @cvss.ci = "H"
14
+ @cvss.ii = "low"
15
+ @cvss.ai = "N"
16
+
17
+ @cvss_2 = Cvss3::Rating.new
18
+ @cvss_2.av = "P"
19
+ @cvss_2.ac = "H"
20
+ @cvss_2.ui = "R"
21
+ @cvss_2.pr = "H"
22
+ @cvss_2.sc = "C"
23
+ @cvss_2.ci = "H"
24
+ @cvss_2.ii = "low"
25
+ @cvss_2.ai = "N"
26
+ @cvss_2.ex = "U"
27
+ @cvss_2.rl = "O"
28
+ @cvss_2.rc = "U"
29
+ @cvss_2.cr = "L"
30
+ @cvss_2.ir = "L"
31
+ @cvss_2.ar = "L"
32
+ end
33
+
34
+ def test_cvss_rating_from_vector
35
+ cvss = Cvss3::Rating.new
36
+ cvss.parse("AV:P/AC:H/PR:L/UI:R/S:C/C:H/I:L/A:N")
37
+
38
+ assert_equal @cvss.ai, cvss.ai
39
+
40
+ assert_equal @cvss.ii, cvss.ii
41
+
42
+ assert_equal @cvss.av, cvss.av
43
+
44
+ assert_equal @cvss.ui, cvss.ui
45
+
46
+ assert_equal @cvss.key, cvss.key
47
+
48
+ cvss = Cvss3::Rating.new
49
+ cvss.parse("AV:P/AC:H/PR:H/UI:R/S:C/C:H/I:L/A:N/E:U/RL:O/RC:U/CR:L/IR:L/AR:L")
50
+
51
+ assert_equal @cvss_2.ai, cvss.ai
52
+
53
+ assert_equal @cvss_2.ii, cvss.ii
54
+
55
+ assert_equal @cvss_2.av, cvss.av
56
+
57
+ assert_equal @cvss_2.key, cvss.key
58
+ end
59
+
60
+ def test_valid_vector
61
+ cvss = Cvss3::Rating.new
62
+
63
+ err = assert_raises RuntimeError do
64
+ cvss.parse("AV:P/AC:H/PR:L/UI:R/S:U/C:H/I:X/A:N")
65
+ end
66
+
67
+ assert_match /Bad Argument/, err.message
68
+
69
+ err = assert_raises RuntimeError do
70
+ cvss.parse("CVSS:9.9/AV:P/AC:H/PR:L/UI:R/S:U/C:H/I:L/A:N")
71
+ end
72
+
73
+ assert_match /Bad CVSS 3.0 Vector String/, err.message
74
+ end
75
+
76
+ def test_cvss_rating_parameters
77
+ cvss = Cvss3::Rating.new
78
+
79
+ cvss.av = "physical"
80
+
81
+ assert_equal @cvss.av, cvss.av
82
+
83
+ cvss.pr = 'low'
84
+
85
+ assert_equal @cvss.pr, cvss.pr
86
+
87
+ cvss.ci = 'high'
88
+
89
+ assert_equal @cvss.ci, cvss.ci
90
+
91
+ cvss.ai = 'none'
92
+
93
+ assert_equal @cvss.ai, cvss.ai
94
+
95
+ end
96
+
97
+ def test_cvss_risk_rating
98
+ cvss = Cvss3::Rating.new
99
+
100
+ assert_equal "None", cvss.risk_score(0.0)
101
+
102
+ assert_equal "Low", cvss.risk_score(2.0)
103
+
104
+ assert_equal "Medium", cvss.risk_score(5.1)
105
+
106
+ assert_equal "High", cvss.risk_score(7.1)
107
+
108
+ assert_equal "Critical", cvss.risk_score(10.0)
109
+
110
+ assert_equal nil, cvss.risk_score(11.0)
111
+ end
112
+
113
+ def test_base_score
114
+ cvss = Cvss3::Rating.new
115
+ cvss.parse("AV:P/AC:H/PR:L/UI:R/S:U/C:H/I:N/A:N")
116
+
117
+ score = cvss.cvss_base_score
118
+
119
+ assert_equal 3.9, score[0]
120
+
121
+ assert_equal "Low", score[1]
122
+
123
+ cvss = Cvss3::Rating.new
124
+ cvss.parse("AV:P/AC:H/PR:H/UI:R/S:C/C:H/I:L/A:N/E:U/RL:O/RC:U/CR:L/IR:L/AR:L")
125
+
126
+ score = cvss.cvss_base_score
127
+
128
+ assert_equal 5.4, score[0]
129
+
130
+ assert_equal "Medium", score[1]
131
+
132
+ end
133
+
134
+ def test_temporal_score
135
+ cvss = Cvss3::Rating.new
136
+ cvss.parse("AV:P/AC:H/PR:L/UI:R/S:U/C:H/I:N/A:N")
137
+
138
+ cvss.cvss_base_score
139
+
140
+ score = cvss.cvss_temporal_score
141
+
142
+ assert_equal 3.9, score[0]
143
+
144
+ assert_equal "Low", score[1]
145
+
146
+ cvss = Cvss3::Rating.new
147
+ cvss.parse("AV:P/AC:H/PR:H/UI:R/S:C/C:H/I:L/A:N/E:U/RL:O/RC:U/CR:L/IR:L/AR:L")
148
+
149
+ cvss.cvss_base_score
150
+
151
+ score = cvss.cvss_temporal_score
152
+
153
+ assert_equal 4.3, score[0]
154
+
155
+ assert_equal "Medium", score[1]
156
+ end
157
+
158
+ def test_environmental_score
159
+ cvss = Cvss3::Rating.new
160
+ cvss.parse("AV:P/AC:H/PR:L/UI:R/S:U/C:H/I:N/A:N")
161
+
162
+ cvss.cvss_base_score
163
+
164
+ score = cvss.cvss_environmental_score
165
+
166
+ assert_equal 3.9, score[0]
167
+
168
+ assert_equal "Low", score[1]
169
+
170
+ cvss = Cvss3::Rating.new
171
+ cvss.parse("AV:P/AC:H/PR:H/UI:R/S:C/C:H/I:L/A:N/E:U/RL:O/RC:U/CR:L/IR:L/AR:L")
172
+
173
+ cvss.cvss_base_score
174
+
175
+ score = cvss.cvss_environmental_score
176
+
177
+ assert_equal 2.4, score[0]
178
+
179
+ assert_equal "Low", score[1]
180
+
181
+ cvss = Cvss3::Rating.new
182
+ cvss.parse("AV:P/AC:H/PR:H/UI:R/S:C/C:H/I:L/A:N/E:U/RL:O/RC:U/IR:L/AR:L/MAV:A/MPR:N")
183
+
184
+ cvss.cvss_base_score
185
+
186
+ score = cvss.cvss_environmental_score
187
+
188
+ assert_equal 4.8, score[0]
189
+
190
+ assert_equal "Medium", score[1]
191
+
192
+ cvss = Cvss3::Rating.new
193
+ cvss.parse("CVSS:3.0/AV:P/AC:H/PR:H/UI:R/S:C/C:H/I:L/A:N/E:U/RL:O/RC:U/MAV:N/MS:U")
194
+
195
+ cvss.cvss_base_score
196
+
197
+ score = cvss.cvss_environmental_score
198
+
199
+ assert_equal 3.9, score[0]
200
+
201
+ assert_equal "Low", score[1]
202
+ end
203
+
204
+ def test_all_scores
205
+ cvss = Cvss3::Rating.new
206
+ cvss.parse("AV:P/AC:H/PR:H/UI:R/S:U/C:N/I:N/A:N/E:X/RL:X/RC:X")
207
+
208
+ score = cvss.cvss_base_score
209
+
210
+ assert_equal 0.0, score[0]
211
+
212
+ score = cvss.cvss_temporal_score
213
+
214
+ assert_equal 0.0, score[0]
215
+
216
+ score = cvss.cvss_environmental_score
217
+
218
+ assert_equal 0.0, score[0]
219
+
220
+ cvss.parse("AV:L/AC:L/PR:H/UI:R/S:U/C:H/I:N/A:H/E:H/RL:W/RC:U/CR:H/IR:H/AR:M/MAV:L/MAC:L/MPR:H/MUI:N/MS:C/MC:N/MI:H/MA:L")
221
+
222
+ score = cvss.cvss_base_score
223
+
224
+ assert_equal 5.8, score[0]
225
+
226
+ score = cvss.cvss_temporal_score
227
+
228
+ assert_equal 5.2, score[0]
229
+
230
+ score = cvss.cvss_environmental_score
231
+
232
+ assert_equal 7.4, score[0]
233
+ end
234
+
235
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cvss_rating
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.5.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen Kapp
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-19 00:00:00.000000000 Z
11
+ date: 2015-08-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -67,7 +67,7 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  description: CVSS Risk Rating Calculation and Vector parsing, implements CVSS 2.0
70
- rating
70
+ & 3.0 rating
71
71
  email:
72
72
  - mort666@virus.org
73
73
  executables: []
@@ -82,8 +82,13 @@ files:
82
82
  - Rakefile
83
83
  - cvss_rating.gemspec
84
84
  - lib/cvss2_rating.rb
85
+ - lib/cvss3_rating.rb
86
+ - lib/cvss_rating/cvss3_formulas.rb
87
+ - lib/cvss_rating/cvss3_metrics.rb
88
+ - lib/cvss_rating/cvss3_vectors.rb
85
89
  - lib/cvss_rating/version.rb
86
90
  - test/cvss2_rating_test.rb
91
+ - test/cvss3_rating_test.rb
87
92
  homepage: https://github.com/mort666/cvss_rating
88
93
  licenses:
89
94
  - MIT
@@ -110,3 +115,4 @@ specification_version: 4
110
115
  summary: CVSS Risk Rating Calculation and Vector parsing
111
116
  test_files:
112
117
  - test/cvss2_rating_test.rb
118
+ - test/cvss3_rating_test.rb