cve_schema 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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