cvelist 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +7 -0
  2. data/.document +3 -0
  3. data/.github/workflows/ruby.yml +29 -0
  4. data/.gitignore +6 -0
  5. data/.rspec +1 -0
  6. data/.yardopts +1 -0
  7. data/ChangeLog.md +10 -0
  8. data/Gemfile +13 -0
  9. data/LICENSE.txt +20 -0
  10. data/README.md +82 -0
  11. data/Rakefile +13 -0
  12. data/benchmark.rb +38 -0
  13. data/cvelist.gemspec +61 -0
  14. data/gemspec.yml +21 -0
  15. data/lib/cvelist.rb +2 -0
  16. data/lib/cvelist/cve.rb +83 -0
  17. data/lib/cvelist/directory.rb +80 -0
  18. data/lib/cvelist/exceptions.rb +31 -0
  19. data/lib/cvelist/malformed_cve.rb +42 -0
  20. data/lib/cvelist/range_dir.rb +121 -0
  21. data/lib/cvelist/repository.rb +240 -0
  22. data/lib/cvelist/version.rb +4 -0
  23. data/lib/cvelist/year_dir.rb +178 -0
  24. data/spec/cve_methods_examples.rb +130 -0
  25. data/spec/cve_spec.rb +51 -0
  26. data/spec/cvelist_spec.rb +8 -0
  27. data/spec/directory_spec.rb +83 -0
  28. data/spec/fixtures/CVE-2020-1994.json +140 -0
  29. data/spec/fixtures/cvelist/.gitkeep +0 -0
  30. data/spec/fixtures/cvelist/1999/.gitkeep +0 -0
  31. data/spec/fixtures/cvelist/2000/.gitkeep +0 -0
  32. data/spec/fixtures/cvelist/2001/.gitkeep +0 -0
  33. data/spec/fixtures/cvelist/2002/.gitkeep +0 -0
  34. data/spec/fixtures/cvelist/2003/.gitkeep +0 -0
  35. data/spec/fixtures/cvelist/2004/.gitkeep +0 -0
  36. data/spec/fixtures/cvelist/2005/.gitkeep +0 -0
  37. data/spec/fixtures/cvelist/2006/.gitkeep +0 -0
  38. data/spec/fixtures/cvelist/2007/.gitkeep +0 -0
  39. data/spec/fixtures/cvelist/2008/.gitkeep +0 -0
  40. data/spec/fixtures/cvelist/2009/.gitkeep +0 -0
  41. data/spec/fixtures/cvelist/2010/.gitkeep +0 -0
  42. data/spec/fixtures/cvelist/2011/.gitkeep +0 -0
  43. data/spec/fixtures/cvelist/2012/.gitkeep +0 -0
  44. data/spec/fixtures/cvelist/2013/.gitkeep +0 -0
  45. data/spec/fixtures/cvelist/2014/.gitkeep +0 -0
  46. data/spec/fixtures/cvelist/2015/.gitkeep +0 -0
  47. data/spec/fixtures/cvelist/2016/.gitkeep +0 -0
  48. data/spec/fixtures/cvelist/2017/.gitkeep +0 -0
  49. data/spec/fixtures/cvelist/2018/.gitkeep +0 -0
  50. data/spec/fixtures/cvelist/2019/.gitkeep +0 -0
  51. data/spec/fixtures/cvelist/2020/.gitkeep +0 -0
  52. data/spec/fixtures/cvelist/2021/.gitkeep +0 -0
  53. data/spec/fixtures/cvelist/2021/0xxx/.gitkeep +0 -0
  54. data/spec/fixtures/cvelist/2021/1xxx/.gitkeep +0 -0
  55. data/spec/fixtures/cvelist/2021/20xxx/.gitkeep +0 -0
  56. data/spec/fixtures/cvelist/2021/21xxx/.gitkeep +0 -0
  57. data/spec/fixtures/cvelist/2021/2xxx/.gitkeep +0 -0
  58. data/spec/fixtures/cvelist/2021/2xxx/CVE-2021-2000.json +18 -0
  59. data/spec/fixtures/cvelist/2021/2xxx/CVE-2021-2001.json +18 -0
  60. data/spec/fixtures/cvelist/2021/2xxx/CVE-2021-2002.json +18 -0
  61. data/spec/fixtures/cvelist/2021/2xxx/CVE-2021-2003.json +18 -0
  62. data/spec/fixtures/cvelist/2021/2xxx/CVE-2021-2004.json +18 -0
  63. data/spec/fixtures/cvelist/2021/2xxx/CVE-2021-2005.json +18 -0
  64. data/spec/fixtures/cvelist/2021/2xxx/CVE-2021-2006.json +18 -0
  65. data/spec/fixtures/cvelist/2021/2xxx/CVE-2021-2007.json +18 -0
  66. data/spec/fixtures/cvelist/2021/2xxx/CVE-2021-2008.json +18 -0
  67. data/spec/fixtures/cvelist/2021/2xxx/CVE-2021-2009.json +18 -0
  68. data/spec/fixtures/cvelist/2021/2xxx/CVE-2021-2998.json +3 -0
  69. data/spec/fixtures/cvelist/2021/2xxx/CVE-2021-2999.json +2 -0
  70. data/spec/range_dir_spec.rb +55 -0
  71. data/spec/repository_spec.rb +248 -0
  72. data/spec/spec_helper.rb +4 -0
  73. data/spec/year_dir_spec.rb +96 -0
  74. 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
@@ -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,8 @@
1
+ require 'spec_helper'
2
+ require 'cvelist'
3
+
4
+ describe CVEList do
5
+ it "should have a VERSION constant" do
6
+ expect(subject.const_get('VERSION')).to_not be_empty
7
+ end
8
+ 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