cvelist 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.
- checksums.yaml +7 -0
- data/.document +3 -0
- data/.github/workflows/ruby.yml +29 -0
- data/.gitignore +6 -0
- data/.rspec +1 -0
- data/.yardopts +1 -0
- data/ChangeLog.md +10 -0
- data/Gemfile +13 -0
- data/LICENSE.txt +20 -0
- data/README.md +82 -0
- data/Rakefile +13 -0
- data/benchmark.rb +38 -0
- data/cvelist.gemspec +61 -0
- data/gemspec.yml +21 -0
- data/lib/cvelist.rb +2 -0
- data/lib/cvelist/cve.rb +83 -0
- data/lib/cvelist/directory.rb +80 -0
- data/lib/cvelist/exceptions.rb +31 -0
- data/lib/cvelist/malformed_cve.rb +42 -0
- data/lib/cvelist/range_dir.rb +121 -0
- data/lib/cvelist/repository.rb +240 -0
- data/lib/cvelist/version.rb +4 -0
- data/lib/cvelist/year_dir.rb +178 -0
- data/spec/cve_methods_examples.rb +130 -0
- data/spec/cve_spec.rb +51 -0
- data/spec/cvelist_spec.rb +8 -0
- data/spec/directory_spec.rb +83 -0
- data/spec/fixtures/CVE-2020-1994.json +140 -0
- data/spec/fixtures/cvelist/.gitkeep +0 -0
- data/spec/fixtures/cvelist/1999/.gitkeep +0 -0
- data/spec/fixtures/cvelist/2000/.gitkeep +0 -0
- data/spec/fixtures/cvelist/2001/.gitkeep +0 -0
- data/spec/fixtures/cvelist/2002/.gitkeep +0 -0
- data/spec/fixtures/cvelist/2003/.gitkeep +0 -0
- data/spec/fixtures/cvelist/2004/.gitkeep +0 -0
- data/spec/fixtures/cvelist/2005/.gitkeep +0 -0
- data/spec/fixtures/cvelist/2006/.gitkeep +0 -0
- data/spec/fixtures/cvelist/2007/.gitkeep +0 -0
- data/spec/fixtures/cvelist/2008/.gitkeep +0 -0
- data/spec/fixtures/cvelist/2009/.gitkeep +0 -0
- data/spec/fixtures/cvelist/2010/.gitkeep +0 -0
- data/spec/fixtures/cvelist/2011/.gitkeep +0 -0
- data/spec/fixtures/cvelist/2012/.gitkeep +0 -0
- data/spec/fixtures/cvelist/2013/.gitkeep +0 -0
- data/spec/fixtures/cvelist/2014/.gitkeep +0 -0
- data/spec/fixtures/cvelist/2015/.gitkeep +0 -0
- data/spec/fixtures/cvelist/2016/.gitkeep +0 -0
- data/spec/fixtures/cvelist/2017/.gitkeep +0 -0
- data/spec/fixtures/cvelist/2018/.gitkeep +0 -0
- data/spec/fixtures/cvelist/2019/.gitkeep +0 -0
- data/spec/fixtures/cvelist/2020/.gitkeep +0 -0
- data/spec/fixtures/cvelist/2021/.gitkeep +0 -0
- data/spec/fixtures/cvelist/2021/0xxx/.gitkeep +0 -0
- data/spec/fixtures/cvelist/2021/1xxx/.gitkeep +0 -0
- data/spec/fixtures/cvelist/2021/20xxx/.gitkeep +0 -0
- data/spec/fixtures/cvelist/2021/21xxx/.gitkeep +0 -0
- data/spec/fixtures/cvelist/2021/2xxx/.gitkeep +0 -0
- data/spec/fixtures/cvelist/2021/2xxx/CVE-2021-2000.json +18 -0
- data/spec/fixtures/cvelist/2021/2xxx/CVE-2021-2001.json +18 -0
- data/spec/fixtures/cvelist/2021/2xxx/CVE-2021-2002.json +18 -0
- data/spec/fixtures/cvelist/2021/2xxx/CVE-2021-2003.json +18 -0
- data/spec/fixtures/cvelist/2021/2xxx/CVE-2021-2004.json +18 -0
- data/spec/fixtures/cvelist/2021/2xxx/CVE-2021-2005.json +18 -0
- data/spec/fixtures/cvelist/2021/2xxx/CVE-2021-2006.json +18 -0
- data/spec/fixtures/cvelist/2021/2xxx/CVE-2021-2007.json +18 -0
- data/spec/fixtures/cvelist/2021/2xxx/CVE-2021-2008.json +18 -0
- data/spec/fixtures/cvelist/2021/2xxx/CVE-2021-2009.json +18 -0
- data/spec/fixtures/cvelist/2021/2xxx/CVE-2021-2998.json +3 -0
- data/spec/fixtures/cvelist/2021/2xxx/CVE-2021-2999.json +2 -0
- data/spec/range_dir_spec.rb +55 -0
- data/spec/repository_spec.rb +248 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/year_dir_spec.rb +96 -0
- metadata +165 -0
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.shared_examples "CVE methods" do
|
4
|
+
describe "#each" do
|
5
|
+
let(:malformed_cves) { %w[CVE-2021-2999.json CVE-2021-2998.json] }
|
6
|
+
let(:malformed_cve_paths) do
|
7
|
+
Dir[File.join(path,"{**/}{#{malformed_cves.join(',')}}")]
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:cve_paths) { Dir[File.join(path,'{**/}CVE-*.json')] }
|
11
|
+
let(:valid_cve_paths) { cve_paths - malformed_cve_paths }
|
12
|
+
|
13
|
+
context "when a block is given" do
|
14
|
+
it "must yield CVE objects "do
|
15
|
+
results = []
|
16
|
+
subject.each { |cve| results << cve }
|
17
|
+
|
18
|
+
expect(results).to all(be_kind_of(CVE))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "when no block is given" do
|
23
|
+
it "must return an Enumerator object" do
|
24
|
+
expect(subject.each).to be_kind_of(Enumerator)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
it "must find the valid CVE-*.json files in the repository" do
|
29
|
+
expect(subject.each.map(&:path)).to match_array(valid_cve_paths)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "must omit malformed CVEs" do
|
33
|
+
expect(subject.each.map(&:path)).to_not include(malformed_cve_paths)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "#each_malformed" do
|
38
|
+
let(:malformed_cves) { %w[CVE-2021-2999.json CVE-2021-2998.json] }
|
39
|
+
let(:malformed_cve_paths) do
|
40
|
+
Dir[File.join(path,"{**/}{#{malformed_cves.join(',')}}")]
|
41
|
+
end
|
42
|
+
|
43
|
+
let(:cve_paths) { Dir[File.join(path,'{**/}CVE-*.json')] }
|
44
|
+
let(:valid_cve_paths) { cve_paths - malformed_cve_paths }
|
45
|
+
|
46
|
+
context "when a block is given" do
|
47
|
+
it "must yield MalformedCVE objects "do
|
48
|
+
results = []
|
49
|
+
subject.each_malformed { |cve| results << cve }
|
50
|
+
|
51
|
+
expect(results).to all(be_kind_of(MalformedCVE))
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context "when no block is given" do
|
56
|
+
it "must return an Enumerator object" do
|
57
|
+
expect(subject.each_malformed).to be_kind_of(Enumerator)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
it "must find the malformed CVE-*.json files in the repository" do
|
62
|
+
expect(subject.each_malformed.map(&:path)).to match_array(malformed_cve_paths)
|
63
|
+
end
|
64
|
+
|
65
|
+
it "must omit valid CVEs" do
|
66
|
+
expect(subject.each_malformed.map(&:path)).to_not include(valid_cve_paths)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "#has_cve?" do
|
71
|
+
let(:cve_id) { 'CVE-2021-2001' }
|
72
|
+
|
73
|
+
it "must find the .json file with the matching CVE ID in the repository" do
|
74
|
+
expect(subject.has_cve?(cve_id)).to eq(true)
|
75
|
+
end
|
76
|
+
|
77
|
+
context "when the given .json file cannot be found" do
|
78
|
+
let(:cve_id) { 'CVE-2021-2010' }
|
79
|
+
|
80
|
+
it "must return false" do
|
81
|
+
expect(subject.has_cve?(cve_id)).to eq(false)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "#[]" do
|
87
|
+
let(:cve_year) { '2021' }
|
88
|
+
let(:cve_number) { '2001' }
|
89
|
+
let(:cve_id) { "CVE-#{cve_year}-#{cve_number}" }
|
90
|
+
|
91
|
+
let(:cve_range) { '2xxx' }
|
92
|
+
let(:cve_path) do
|
93
|
+
File.join(cvelist_dir,cve_year,cve_range,"#{cve_id}.json")
|
94
|
+
end
|
95
|
+
|
96
|
+
subject { super()[cve_id] }
|
97
|
+
|
98
|
+
it "must return a CVE object" do
|
99
|
+
expect(subject).to be_kind_of(CVE)
|
100
|
+
end
|
101
|
+
|
102
|
+
it "must load the CVE from the .json file with the matching CVE ID" do
|
103
|
+
expect(subject.path).to eq(cve_path)
|
104
|
+
end
|
105
|
+
|
106
|
+
context "when the repository does not have a matching year directory" do
|
107
|
+
let(:cve_id) { 'CVE-3000-1234' }
|
108
|
+
|
109
|
+
it "must return nil" do
|
110
|
+
expect(subject).to eq(nil)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
context "when the repository does not have a matching range directory" do
|
115
|
+
let(:cve_id) { 'CVE-2021-9999' }
|
116
|
+
|
117
|
+
it "must return nil" do
|
118
|
+
expect(subject).to eq(nil)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
context "when the repository does not have the CVE .json file" do
|
123
|
+
let(:cve_id) { 'CVE-2021-2010' }
|
124
|
+
|
125
|
+
it "must return nil" do
|
126
|
+
expect(subject).to eq(nil)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
data/spec/cve_spec.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'cvelist/cve'
|
3
|
+
|
4
|
+
describe CVE do
|
5
|
+
let(:cve_id) { 'CVE-2020-1994' }
|
6
|
+
let(:file) { File.expand_path("../fixtures/#{cve_id}.json",__FILE__) }
|
7
|
+
|
8
|
+
it { expect(described_class).to be < CVESchema::CVE }
|
9
|
+
|
10
|
+
describe ".parse" do
|
11
|
+
subject { described_class }
|
12
|
+
|
13
|
+
it "must parse the given JSON" do
|
14
|
+
expect(subject.parse('[1]')).to eq([1])
|
15
|
+
end
|
16
|
+
|
17
|
+
context "when given invalid JSON" do
|
18
|
+
let(:json) { '[' }
|
19
|
+
|
20
|
+
it do
|
21
|
+
expect {
|
22
|
+
subject.parse(json)
|
23
|
+
}.to raise_error(described_class::InvalidJSON)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe ".read" do
|
29
|
+
subject { described_class }
|
30
|
+
|
31
|
+
it "must read and parse the JSON in the given file" do
|
32
|
+
expect(subject.read(file)).to eq(JSON.parse(File.read(file)))
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe ".load" do
|
37
|
+
subject { described_class.load(file) }
|
38
|
+
|
39
|
+
it "must load a CVE object from the given file" do
|
40
|
+
expect(subject).to be_kind_of(described_class)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "must set #path" do
|
44
|
+
expect(subject.path).to eq(file)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "must set other CVE fields" do
|
48
|
+
expect(subject.data_meta.id.to_s).to eq(cve_id)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'cvelist/directory'
|
3
|
+
|
4
|
+
describe Directory do
|
5
|
+
let(:fixture_dir) { File.expand_path('../fixtures',__FILE__) }
|
6
|
+
let(:path) { File.join(fixture_dir,'cvelist') }
|
7
|
+
|
8
|
+
subject { described_class.new(path) }
|
9
|
+
|
10
|
+
describe "#initialize" do
|
11
|
+
it "must set #path" do
|
12
|
+
expect(subject.path).to eq(path)
|
13
|
+
end
|
14
|
+
|
15
|
+
context "when given a relative path" do
|
16
|
+
let(:relative_path) { File.join(__FILE__,'../fixtures/cvelist') }
|
17
|
+
|
18
|
+
subject { described_class.new(relative_path) }
|
19
|
+
|
20
|
+
it "must expand the relative path" do
|
21
|
+
expect(subject.path).to eq(path)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#join" do
|
27
|
+
let(:name) { 'foo' }
|
28
|
+
|
29
|
+
it "must join the path with the directory's #path" do
|
30
|
+
expect(subject.join(name)).to eq(File.join(path,name))
|
31
|
+
end
|
32
|
+
|
33
|
+
context "when given multiple arguments" do
|
34
|
+
let(:names) { %w[foo bar baz] }
|
35
|
+
|
36
|
+
it "must join all arguments together with the directory's #path" do
|
37
|
+
expect(subject.join(*names)).to eq(File.join(path,*names))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "#file?" do
|
43
|
+
let(:name) { '.gitkeep' }
|
44
|
+
|
45
|
+
it "must test whether the given path is a file within the directory" do
|
46
|
+
expect(subject.file?(name)).to eq(true)
|
47
|
+
end
|
48
|
+
|
49
|
+
context "when the given sub-directory does not exist" do
|
50
|
+
it { expect(subject.file?('foo')).to eq(false) }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "#directory?" do
|
55
|
+
let(:name) { '2000' }
|
56
|
+
|
57
|
+
it "must test whether the given path is a directory within the directory" do
|
58
|
+
expect(subject.directory?(name)).to eq(true)
|
59
|
+
end
|
60
|
+
|
61
|
+
context "when the given sub-directory does not exist" do
|
62
|
+
it { expect(subject.directory?('foo')).to eq(false) }
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "#glob" do
|
67
|
+
let(:pattern) { '20*1' }
|
68
|
+
let(:dirs) { %w[2001 2011 2021] }
|
69
|
+
let(:paths) do
|
70
|
+
dirs.map { |dir| File.join(path,dir) }
|
71
|
+
end
|
72
|
+
|
73
|
+
it "must perform a Dir.glob within the directory" do
|
74
|
+
expect(subject.glob(pattern)).to match_array(paths)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "#to_s" do
|
79
|
+
it "must return the #path" do
|
80
|
+
expect(subject.to_s).to eq(path)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
{
|
2
|
+
"CVE_data_meta": {
|
3
|
+
"ASSIGNER": "psirt@paloaltonetworks.com",
|
4
|
+
"DATE_PUBLIC": "2020-05-13T16:00:00.000Z",
|
5
|
+
"ID": "CVE-2020-1994",
|
6
|
+
"STATE": "PUBLIC",
|
7
|
+
"TITLE": "PAN-OS: Predictable temporary file vulnerability"
|
8
|
+
},
|
9
|
+
"affects": {
|
10
|
+
"vendor": {
|
11
|
+
"vendor_data": [
|
12
|
+
{
|
13
|
+
"product": {
|
14
|
+
"product_data": [
|
15
|
+
{
|
16
|
+
"product_name": "PAN-OS",
|
17
|
+
"version": {
|
18
|
+
"version_data": [
|
19
|
+
{
|
20
|
+
"version_affected": "<",
|
21
|
+
"version_name": "8.1",
|
22
|
+
"version_value": "8.1.13"
|
23
|
+
},
|
24
|
+
{
|
25
|
+
"version_affected": "<",
|
26
|
+
"version_name": "9.0",
|
27
|
+
"version_value": "9.0.7"
|
28
|
+
},
|
29
|
+
{
|
30
|
+
"version_affected": "=",
|
31
|
+
"version_name": "7.1",
|
32
|
+
"version_value": "7.1.*"
|
33
|
+
},
|
34
|
+
{
|
35
|
+
"version_affected": "=",
|
36
|
+
"version_name": "8.0",
|
37
|
+
"version_value": "8.0.*"
|
38
|
+
},
|
39
|
+
{
|
40
|
+
"version_affected": "!>=",
|
41
|
+
"version_name": "8.1",
|
42
|
+
"version_value": "8.1.13"
|
43
|
+
},
|
44
|
+
{
|
45
|
+
"version_affected": "!>=",
|
46
|
+
"version_name": "9.0",
|
47
|
+
"version_value": "9.0.7"
|
48
|
+
},
|
49
|
+
{
|
50
|
+
"version_affected": "!>=",
|
51
|
+
"version_name": "9.1",
|
52
|
+
"version_value": "9.1.0"
|
53
|
+
}
|
54
|
+
]
|
55
|
+
}
|
56
|
+
}
|
57
|
+
]
|
58
|
+
},
|
59
|
+
"vendor_name": "Palo Alto Networks"
|
60
|
+
}
|
61
|
+
]
|
62
|
+
}
|
63
|
+
},
|
64
|
+
"credit": [
|
65
|
+
{
|
66
|
+
"lang": "eng",
|
67
|
+
"value": "This issue was found by a customer."
|
68
|
+
}
|
69
|
+
],
|
70
|
+
"data_format": "MITRE",
|
71
|
+
"data_type": "CVE",
|
72
|
+
"data_version": "4.0",
|
73
|
+
"description": {
|
74
|
+
"description_data": [
|
75
|
+
{
|
76
|
+
"lang": "eng",
|
77
|
+
"value": "A predictable temporary file vulnerability in PAN-OS allows a local authenticated user with shell access to corrupt arbitrary system files affecting the integrity of the system. This issue affects: All versions of PAN-OS 7.1 and 8.0; PAN-OS 8.1 versions earlier than 8.1.13; PAN-OS 9.0 versions earlier than 9.0.7."
|
78
|
+
}
|
79
|
+
]
|
80
|
+
},
|
81
|
+
"generator": {
|
82
|
+
"engine": "Vulnogram 0.0.9"
|
83
|
+
},
|
84
|
+
"impact": {
|
85
|
+
"cvss": {
|
86
|
+
"attackComplexity": "HIGH",
|
87
|
+
"attackVector": "LOCAL",
|
88
|
+
"availabilityImpact": "NONE",
|
89
|
+
"baseScore": 4.1,
|
90
|
+
"baseSeverity": "MEDIUM",
|
91
|
+
"confidentialityImpact": "NONE",
|
92
|
+
"integrityImpact": "HIGH",
|
93
|
+
"privilegesRequired": "HIGH",
|
94
|
+
"scope": "UNCHANGED",
|
95
|
+
"userInteraction": "NONE",
|
96
|
+
"vectorString": "CVSS:3.1/AV:L/AC:H/PR:H/UI:N/S:U/C:N/I:H/A:N",
|
97
|
+
"version": "3.1"
|
98
|
+
}
|
99
|
+
},
|
100
|
+
"problemtype": {
|
101
|
+
"problemtype_data": [
|
102
|
+
{
|
103
|
+
"description": [
|
104
|
+
{
|
105
|
+
"lang": "eng",
|
106
|
+
"value": "CWE-377 Insecure Temporary File"
|
107
|
+
}
|
108
|
+
]
|
109
|
+
}
|
110
|
+
]
|
111
|
+
},
|
112
|
+
"references": {
|
113
|
+
"reference_data": [
|
114
|
+
{
|
115
|
+
"refsource": "MISC",
|
116
|
+
"url": "https://security.paloaltonetworks.com/CVE-2020-1994",
|
117
|
+
"name": "https://security.paloaltonetworks.com/CVE-2020-1994"
|
118
|
+
}
|
119
|
+
]
|
120
|
+
},
|
121
|
+
"solution": [
|
122
|
+
{
|
123
|
+
"lang": "eng",
|
124
|
+
"value": "This issue is fixed in PAN-OS 8.1.13, PAN-OS 9.0.7, PAN-OS 9.1.0, and all later PAN-OS versions.\n\nPAN-OS 8.0 is now end-of-life as of October 31, 2019, and is no longer covered by our Product Security Assurance policies.\n\nPAN-OS 7.1 is on extended support until June 30, 2020, and is only being considered for critical security vulnerability fixes."
|
125
|
+
}
|
126
|
+
],
|
127
|
+
"source": {
|
128
|
+
"defect": [
|
129
|
+
"PAN-123391"
|
130
|
+
],
|
131
|
+
"discovery": "USER"
|
132
|
+
},
|
133
|
+
"timeline": [
|
134
|
+
{
|
135
|
+
"lang": "eng",
|
136
|
+
"time": "2020-05-13T16:00:00.000Z",
|
137
|
+
"value": "Initial publication"
|
138
|
+
}
|
139
|
+
]
|
140
|
+
}
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|