cve_schema 0.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.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/.document +3 -0
  3. data/.github/workflows/ruby.yml +28 -0
  4. data/.gitignore +6 -0
  5. data/.rspec +1 -0
  6. data/.yardopts +1 -0
  7. data/ChangeLog.md +26 -0
  8. data/Gemfile +14 -0
  9. data/LICENSE.txt +20 -0
  10. data/README.md +50 -0
  11. data/Rakefile +23 -0
  12. data/benchmark.rb +47 -0
  13. data/cve_schema.gemspec +61 -0
  14. data/gemspec.yml +19 -0
  15. data/lib/cve_schema.rb +2 -0
  16. data/lib/cve_schema/cve.rb +257 -0
  17. data/lib/cve_schema/cve/affects.rb +55 -0
  18. data/lib/cve_schema/cve/configuration.rb +14 -0
  19. data/lib/cve_schema/cve/credit.rb +14 -0
  20. data/lib/cve_schema/cve/data_meta.rb +185 -0
  21. data/lib/cve_schema/cve/description.rb +24 -0
  22. data/lib/cve_schema/cve/exploit.rb +14 -0
  23. data/lib/cve_schema/cve/has_lang_value.rb +93 -0
  24. data/lib/cve_schema/cve/id.rb +79 -0
  25. data/lib/cve_schema/cve/impact.rb +75 -0
  26. data/lib/cve_schema/cve/impact/cvss_v2.rb +318 -0
  27. data/lib/cve_schema/cve/impact/cvss_v3.rb +388 -0
  28. data/lib/cve_schema/cve/na.rb +8 -0
  29. data/lib/cve_schema/cve/problem_type.rb +56 -0
  30. data/lib/cve_schema/cve/product.rb +79 -0
  31. data/lib/cve_schema/cve/reference.rb +82 -0
  32. data/lib/cve_schema/cve/solution.rb +14 -0
  33. data/lib/cve_schema/cve/source.rb +75 -0
  34. data/lib/cve_schema/cve/timeline.rb +65 -0
  35. data/lib/cve_schema/cve/timestamp.rb +25 -0
  36. data/lib/cve_schema/cve/vendor.rb +83 -0
  37. data/lib/cve_schema/cve/version.rb +126 -0
  38. data/lib/cve_schema/cve/work_around.rb +14 -0
  39. data/lib/cve_schema/exceptions.rb +20 -0
  40. data/lib/cve_schema/version.rb +6 -0
  41. data/spec/affects_spec.rb +28 -0
  42. data/spec/configuration_spec.rb +6 -0
  43. data/spec/credit_spec.rb +6 -0
  44. data/spec/cve_schema_spec.rb +8 -0
  45. data/spec/cve_spec.rb +414 -0
  46. data/spec/data_meta_spec.rb +167 -0
  47. data/spec/description.rb +24 -0
  48. data/spec/exploit_spec.rb +6 -0
  49. data/spec/fixtures/CVE-2020-1994.json +140 -0
  50. data/spec/fixtures/CVE-2020-2005.json +152 -0
  51. data/spec/fixtures/CVE-2020-2050.json +233 -0
  52. data/spec/fixtures/CVE-2020-4700.json +99 -0
  53. data/spec/has_lang_value_spec.rb +56 -0
  54. data/spec/id_spec.rb +91 -0
  55. data/spec/impact/cvss_v3_spec.rb +118 -0
  56. data/spec/impact_spec.rb +45 -0
  57. data/spec/na_spec.rb +14 -0
  58. data/spec/problem_type_spec.rb +26 -0
  59. data/spec/product_spec.rb +73 -0
  60. data/spec/reference_spec.rb +70 -0
  61. data/spec/shared_examples.rb +19 -0
  62. data/spec/solution_spec.rb +6 -0
  63. data/spec/source_spec.rb +84 -0
  64. data/spec/spec_helper.rb +4 -0
  65. data/spec/timeline_spec.rb +86 -0
  66. data/spec/timestamp_spec.rb +24 -0
  67. data/spec/vendor_spec.rb +73 -0
  68. data/spec/version_spec.rb +104 -0
  69. data/spec/work_around_spec.rb +6 -0
  70. metadata +133 -0
@@ -0,0 +1,118 @@
1
+ require 'spec_helper'
2
+ require 'shared_examples'
3
+ require 'cve_schema/cve/impact/cvss_v3'
4
+
5
+ describe CVESchema::CVE::Impact::CVSSv3 do
6
+ describe "#initialize" do
7
+ context "when given the bm: keyword" do
8
+ let(:bm) { double(:BM) }
9
+
10
+ subject { described_class.new(bm: bm) }
11
+
12
+ it "must set #bm" do
13
+ expect(subject.bm).to be(bm)
14
+ end
15
+ end
16
+
17
+ context "when given the tm: keyword" do
18
+ let(:tm) { double(:TM) }
19
+
20
+ subject { described_class.new(tm: tm) }
21
+
22
+ it "must set #tm" do
23
+ expect(subject.tm).to be(tm)
24
+ end
25
+ end
26
+
27
+ context "when given the em: keyword" do
28
+ let(:em) { double(:EM) }
29
+
30
+ subject { described_class.new(em: em) }
31
+
32
+ it "must set #em" do
33
+ expect(subject.em).to be(em)
34
+ end
35
+ end
36
+ end
37
+
38
+ describe ".load" do
39
+ include_examples ".load"
40
+
41
+ let(:cve_id) { 'CVE-2020-4700' }
42
+ let(:json_node) { json_tree['impact']['cvssv3'] }
43
+
44
+ context '"BM":' do
45
+ it { expect(subject.bm).to be_kind_of(described_class::BM) }
46
+ end
47
+
48
+ context '"TM":' do
49
+ it { expect(subject.bm).to be_kind_of(described_class::BM) }
50
+ end
51
+
52
+ context '"EM":' do
53
+ pending 'need to find a CVE containing "EM":' do
54
+ it { expect(subject.bm).to be_kind_of(described_class::BM) }
55
+ end
56
+ end
57
+ end
58
+
59
+ describe described_class::BM do
60
+ describe "#initialize" do
61
+ end
62
+
63
+ describe ".load" do
64
+ include_examples ".load"
65
+
66
+ let(:cve_id) { 'CVE-2020-4700' }
67
+ let(:json_node) { json_tree['impact']['cvssv3']['BM'] }
68
+
69
+ {'AV' => :av, 'AC' => :ac, 'PR' => :pr, 'UI' => :ui, 'S' => :s, 'C' => :c, 'I' => :i, 'A' => :a}.each do |json_key,attr|
70
+ context "\"#{json_key}\":" do
71
+ it "must set ##{attr}" do
72
+ expect(subject.send(attr)).to eq(json_node[json_key].to_sym)
73
+ end
74
+ end
75
+ end
76
+
77
+ context '"SCORE":' do
78
+ it "must set #score" do
79
+ expect(subject.score).to eq(json_node['SCORE'])
80
+ end
81
+ end
82
+ end
83
+ end
84
+
85
+ describe described_class::TM do
86
+ describe "#initialize" do
87
+ end
88
+
89
+ describe ".load" do
90
+ include_examples ".load"
91
+
92
+ let(:cve_id) { 'CVE-2020-4700' }
93
+ let(:json_node) { json_tree['impact']['cvssv3']['TM'] }
94
+
95
+ {'E' => :e, 'RL' => :rl, 'RC' => :rc}.each do |json_key,attr|
96
+ context "\"#{json_key}\":" do
97
+ it "must set ##{attr}" do
98
+ expect(subject.send(attr)).to eq(json_node[json_key].to_sym)
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
104
+
105
+ describe described_class::EM do
106
+ describe "#initialize" do
107
+ end
108
+
109
+ describe ".load" do
110
+ include_examples ".load"
111
+
112
+ let(:cve_id) { 'CVE-2020-4700' }
113
+ let(:json_node) { json_tree['impact']['cvssv3']['EM'] }
114
+
115
+ pending 'need to find a CVE containing "EM":'
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+ require 'shared_examples'
3
+ require 'cve_schema/cve/impact'
4
+
5
+ describe CVESchema::CVE::Impact do
6
+ describe "#initialize" do
7
+ context "when cvss_v2: is given" do
8
+ let(:cvssv2) { double(:CVSSv2) }
9
+
10
+ subject { described_class.new(cvssv2: cvssv2) }
11
+
12
+ it "must set #cvssv2" do
13
+ expect(subject.cvss_v2).to be(cvssv2)
14
+ end
15
+ end
16
+
17
+ context "when cvssv3: is given" do
18
+ let(:cvssv3) { double(:CVSSv3) }
19
+
20
+ subject { described_class.new(cvssv3: cvssv3) }
21
+
22
+ it "must set #cvss_v3" do
23
+ expect(subject.cvss_v3).to be(cvssv3)
24
+ end
25
+ end
26
+ end
27
+
28
+ describe ".load" do
29
+ include_examples ".load"
30
+
31
+ let(:json_node) { json_tree['impact'] }
32
+
33
+ context '"cvssv2":' do
34
+ pending 'need to find a CVE with a "cvssv2": key' do
35
+ it { expect(subject.cvssv2).to be_kind_of(described_class::CVSSv2) }
36
+ end
37
+ end
38
+
39
+ context '"cvssv3":' do
40
+ let(:cve_id) { 'CVE-2020-4700' }
41
+
42
+ it { expect(subject.cvssv3).to be_kind_of(described_class::CVSSv3) }
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+ require 'cve_schema/cve/na'
3
+
4
+ describe "CVESchema::CVE::NA" do
5
+ subject { CVESchema::CVE::NA }
6
+
7
+ it "must equal 'n/a'" do
8
+ expect(subject).to eq('n/a')
9
+ end
10
+
11
+ it "must be froozen" do
12
+ expect(subject).to be_frozen
13
+ end
14
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+ require 'shared_examples'
3
+ require 'cve_schema/cve/problem_type'
4
+
5
+ describe CVESchema::CVE::ProblemType do
6
+ describe "#initialize" do
7
+ let(:description) { double(:description) }
8
+
9
+ subject { described_class.new(description) }
10
+
11
+ it "must set #description" do
12
+ expect(subject.description).to be(description)
13
+ end
14
+ end
15
+
16
+ describe ".load" do
17
+ include_examples ".load"
18
+
19
+ let(:json_node) { json_tree['problemtype']['problemtype_data'][0] }
20
+
21
+ context '"description":' do
22
+ it { expect(subject.description).to_not be_empty }
23
+ it { expect(subject.description).to all(be_kind_of(CVESchema::CVE::Description)) }
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+ require 'shared_examples'
3
+ require 'cve_schema/cve/product'
4
+
5
+ describe CVESchema::CVE::Product do
6
+ let(:product_name) { 'Example' }
7
+ let(:version) { ['1.2.3', '2.0.0'] }
8
+
9
+ describe "#initialize" do
10
+ describe "required keywords" do
11
+ it "must require a product_name:" do
12
+ expect {
13
+ described_class.new(version: version)
14
+ }.to raise_error(ArgumentError)
15
+ end
16
+ end
17
+
18
+ context "when a product_name: keyword is given" do
19
+ subject { described_class.new(product_name: product_name) }
20
+
21
+ it "must set #product_name" do
22
+ expect(subject.product_name).to eq(product_name)
23
+ end
24
+ end
25
+
26
+ context "when a verisons: keyword is given" do
27
+ subject do
28
+ described_class.new(product_name: product_name, version: version)
29
+ end
30
+
31
+ it "must set #product_name" do
32
+ expect(subject.version).to eq(version)
33
+ end
34
+ end
35
+ end
36
+
37
+ describe ".load" do
38
+ include_examples ".load"
39
+
40
+ let(:json_node) do
41
+ json_tree['affects']['vendor']['vendor_data'][0]['product']['product_data'][0]
42
+ end
43
+
44
+ context '"product_name":' do
45
+ it "must set #product_name" do
46
+ expect(subject.product_name).to eq(json_node['product_name'])
47
+ end
48
+ end
49
+
50
+ context '"version":' do
51
+ it { expect(subject.version).to_not be_empty }
52
+ it { expect(subject.version).to all(be_kind_of(CVESchema::CVE::Version)) }
53
+ end
54
+ end
55
+
56
+ describe "#na?" do
57
+ subject do
58
+ described_class.new(product_name: product_name, version: version)
59
+ end
60
+
61
+ context "when value is 'n/a'" do
62
+ let(:product_name) { 'n/a' }
63
+
64
+ it { expect(subject.na?).to be(true) }
65
+ end
66
+
67
+ context "when value is not 'n/a'" do
68
+ let(:product_name) { 'foo' }
69
+
70
+ it { expect(subject.na?).to be(false) }
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,70 @@
1
+ require 'spec_helper'
2
+ require 'shared_examples'
3
+ require 'cve_schema/cve/reference'
4
+
5
+ describe CVESchema::CVE::Reference do
6
+ describe "#initialize" do
7
+ let(:url) { 'https://example.com/foo.html' }
8
+ let(:name) { 'foo' }
9
+ let(:refsource) { :MISC }
10
+
11
+ context "required keywords" do
12
+ context "when the url: keyword is not given" do
13
+ it do
14
+ expect {
15
+ described_class.new(name: name, refsource: refsource)
16
+ }.to raise_error(ArgumentError)
17
+ end
18
+ end
19
+ end
20
+
21
+ subject { described_class.new(url: url) }
22
+
23
+ it "must set #url" do
24
+ expect(subject.url).to be(url)
25
+ end
26
+
27
+ context "when the name: keyword is given" do
28
+ subject { described_class.new(url: url, name: name) }
29
+
30
+ it "must set #name" do
31
+ expect(subject.name).to be(name)
32
+ end
33
+ end
34
+
35
+ context "when the refsource: keyword is given" do
36
+ subject { described_class.new(url: url, refsource: refsource) }
37
+
38
+ it "must set #refsource" do
39
+ expect(subject.refsource).to be(refsource)
40
+ end
41
+ end
42
+ end
43
+
44
+ describe ".load" do
45
+ include_examples ".load"
46
+
47
+ let(:json_node) { json_tree['references']['reference_data'][0] }
48
+
49
+ context '"refsource":' do
50
+ let(:json_value) { json_node['refsource'] }
51
+ let(:expected) { json_value.to_sym }
52
+
53
+ it 'must parse the "refsource": value and set #refsource' do
54
+ expect(subject.refsource).to eq(expected)
55
+ end
56
+ end
57
+
58
+ context '"url":' do
59
+ it "muset set #url" do
60
+ expect(subject.url).to eq(json_node['url'])
61
+ end
62
+ end
63
+
64
+ context '"name":' do
65
+ it "must set #name" do
66
+ expect(subject.name).to eq(json_node['name'])
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ require 'json'
4
+
5
+ RSpec.shared_examples ".from_json" do
6
+ let(:cve_id) { 'CVE-2020-1994' }
7
+ let(:file) { File.expand_path("../fixtures/#{cve_id}.json",__FILE__) }
8
+
9
+ let(:json_tree) { JSON.parse(File.read(file)) }
10
+ let(:json_node) { json_tree }
11
+
12
+ subject { described_class.from_json(json_node) }
13
+ end
14
+
15
+ RSpec.shared_examples ".load" do
16
+ include_examples ".from_json"
17
+
18
+ subject { described_class.load(json_node) }
19
+ end
@@ -0,0 +1,6 @@
1
+ require 'spec_helper'
2
+ require 'cve_schema/cve/solution'
3
+
4
+ describe CVESchema::CVE::Solution do
5
+ it { expect(described_class).to include(CVESchema::CVE::HasLangValue) }
6
+ end
@@ -0,0 +1,84 @@
1
+ require 'spec_helper'
2
+ require 'shared_examples'
3
+ require 'cve_schema/cve/source'
4
+
5
+ describe CVESchema::CVE::Source do
6
+ describe "#initialize" do
7
+ let(:defect) { ['PAN-123391'] }
8
+ let(:discovery) { :USER }
9
+ let(:advisory) { 'VENDOR-12345' }
10
+
11
+ context "required keywords" do
12
+ context "when the discovery: keyword is not given" do
13
+ it do
14
+ expect {
15
+ described_class.new(defect: defect, advisory: advisory)
16
+ }.to raise_error(ArgumentError)
17
+ end
18
+ end
19
+ end
20
+
21
+ subject do
22
+ described_class.new(discovery: discovery)
23
+ end
24
+
25
+ it "must set #discovery" do
26
+ expect(subject.discovery).to be(discovery)
27
+ end
28
+
29
+ context "when the defect: keyword is given" do
30
+ subject do
31
+ described_class.new(
32
+ discovery: discovery,
33
+ defect: defect
34
+ )
35
+ end
36
+
37
+ it "must set #defect" do
38
+ expect(subject.defect).to be(defect)
39
+ end
40
+ end
41
+
42
+ context "when the advisory: keyword is given" do
43
+ subject do
44
+ described_class.new(
45
+ discovery: discovery,
46
+ advisory: advisory
47
+ )
48
+ end
49
+
50
+ it "must set #advisory" do
51
+ expect(subject.advisory).to be(advisory)
52
+ end
53
+ end
54
+ end
55
+
56
+ describe ".load" do
57
+ include_examples ".load"
58
+
59
+ let(:json_node) { json_tree['source'] }
60
+
61
+ context '"defect":' do
62
+ it "must set #defect" do
63
+ expect(subject.defect).to eq(json_node['defect'])
64
+ end
65
+ end
66
+
67
+ context '"discovery":' do
68
+ let(:json_value) { json_node['discovery'] }
69
+ let(:expected) { json_value.to_sym }
70
+
71
+ it "must set #discovery" do
72
+ expect(subject.discovery).to eq(expected.to_sym)
73
+ end
74
+ end
75
+
76
+ context '"advisory":' do
77
+ pending 'need to find a CVE with the "advisory": key' do
78
+ it "must set #advisory" do
79
+ expect(subject.advisory).to eq(json_node['advisory'])
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end