yavdb 0.1.0.pre.alpha.2

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.
@@ -0,0 +1,102 @@
1
+ # yavdb - The Free and Open Source vulnerability database
2
+ # Copyright (C) 2017-present Rodrigo Fernandes
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU Affero General Public License as
6
+ # published by the Free Software Foundation, either version 3 of the
7
+ # License, or (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU Affero General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Affero General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ module YAVDB
18
+ # TODO: Enable `Style/StructInheritance` - check `attr_reader:` or `initialize` method
19
+ class Advisory <
20
+
21
+ Struct.new(
22
+ :id, # [String]
23
+ :title, # [String]
24
+ :description, # [String]
25
+ :affected_package, # [String]
26
+ :vulnerable_versions, # [Array<String>] (Optional)
27
+ :unaffected_versions, # [Array<String>] (Optional)
28
+ :patched_versions, # [Array<String>] (Optional)
29
+ :severity, # [String] (Optional)
30
+ :package_manager, # [String]
31
+ :cve, # [Array<String>] (Optional)
32
+ :cwe, # [Array<String>] (Optional)
33
+ :osvdb, # [String] (Optional)
34
+ :cvss_v2_vector, # [String] (Optional)
35
+ :cvss_v2_score, # [String] (Optional)
36
+ :cvss_v3_vector, # [String] (Optional)
37
+ :cvss_v3_score, # [String] (Optional)
38
+ :disclosed_date, # [Date]
39
+ :created_date, # [Date]
40
+ :last_modified_date, # [Date]
41
+ :credit, # [Array<String>]
42
+ :references, # [Array<String>]
43
+ :source_url # [String]
44
+ )
45
+
46
+ def self.load(path)
47
+ data = YAML.load_file(path)
48
+
49
+ raise("Advisory data in #{path.dump} was not an Array") unless data.is_a?(Array)
50
+
51
+ data.map do |advisory|
52
+ raise("Advisory data in #{path.dump} was not a Hash") unless advisory.is_a?(Hash)
53
+
54
+ new(
55
+ advisory['id'],
56
+ advisory['title'],
57
+ advisory['description'],
58
+ advisory['affected_package'],
59
+ advisory['vulnerable_versions'],
60
+ advisory['unaffected_versions'],
61
+ advisory['patched_versions'],
62
+ advisory['severity'],
63
+ advisory['package_manager'],
64
+ advisory['cve'],
65
+ advisory['cwe'],
66
+ advisory['osvdb'],
67
+ advisory['cvss_v2_vector'],
68
+ advisory['cvss_v2_score'],
69
+ advisory['cvss_v3_vector'],
70
+ advisory['cvss_v3_score'],
71
+ advisory['disclosed_date'],
72
+ advisory['created_date'],
73
+ advisory['last_modified_date'],
74
+ advisory['credit'],
75
+ advisory['references'],
76
+ advisory['source_url']
77
+ )
78
+ end
79
+ end
80
+
81
+ def to_map
82
+ map = {}
83
+ members.each do |m|
84
+ next unless self[m] && (
85
+ (self[m].is_a?(String) && !self[m].empty?) ||
86
+ (self[m].is_a?(Array) && self[m].any?))
87
+
88
+ map[m.to_s] = self[m] if self[m]
89
+ end
90
+ map
91
+ end
92
+
93
+ def to_json(*args)
94
+ to_map.to_json(*args)
95
+ end
96
+
97
+ def to_yaml(*args)
98
+ to_map.to_yaml(*args)
99
+ end
100
+
101
+ end
102
+ end
@@ -0,0 +1,35 @@
1
+ # yavdb - The Free and Open Source vulnerability database
2
+ # Copyright (C) 2017-present Rodrigo Fernandes
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU Affero General Public License as
6
+ # published by the Free Software Foundation, either version 3 of the
7
+ # License, or (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU Affero General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Affero General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ require_relative '../utils/git'
18
+
19
+ module YAVDB
20
+ module SourceTypes
21
+ module GitRepo
22
+
23
+ def self.search(file_pattern, repo_url, repo_branch = 'master', with_cache = true)
24
+ repo_path = YAVDB::Utils::Git.get_contents(repo_url, repo_branch, with_cache)
25
+
26
+ file_paths = Dir.chdir(repo_path) do
27
+ Dir.glob(file_pattern).select { |f| File.file?(f) }
28
+ end
29
+
30
+ Hash[repo_path => file_paths]
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,87 @@
1
+ # yavdb - The Free and Open Source vulnerability database
2
+ # Copyright (C) 2017-present Rodrigo Fernandes
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU Affero General Public License as
6
+ # published by the Free Software Foundation, either version 3 of the
7
+ # License, or (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU Affero General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Affero General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ require 'date'
18
+ require 'yaml'
19
+
20
+ require_relative '../dtos/advisory'
21
+ require_relative '../source_types/git_repo'
22
+
23
+ module YAVDB
24
+ module Sources
25
+ module FriendsOfPHP
26
+ class Client
27
+
28
+ REPOSITORY_URLS = [
29
+ 'https://github.com/FriendsOfPHP/security-advisories',
30
+ 'https://github.com/Cotya/magento-security-advisories'
31
+ ].freeze
32
+
33
+ PACKAGE_MANAGER = 'packagist'.freeze
34
+
35
+ def self.advisories
36
+ REPOSITORY_URLS.map do |url|
37
+ YAVDB::SourceTypes::GitRepo.search('*/*/*.yaml', url).map do |repo_path, file_paths|
38
+ Dir.chdir(repo_path) do
39
+ file_paths.map do |file_path|
40
+ advisory_hash = YAML.load_file(file_path)
41
+ url = "#{url}/blob/master/#{file_path}"
42
+ create(url, advisory_hash)
43
+ end
44
+ end
45
+ end
46
+ end.flatten
47
+ end
48
+
49
+ def self.create(url, advisory_hash)
50
+ date = Date.parse('1970-01-01')
51
+
52
+ versions = advisory_hash['branches'].map do |_, info|
53
+ date = Date.strptime(info['time'].to_s, '%Y-%m-%d %H:%M:%S %z') if info['time']
54
+ info['versions'].join(' ')
55
+ end.flatten
56
+
57
+ package_name = advisory_hash['reference'].gsub(%r{composer:\/\/(.*)}, '\1')
58
+ YAVDB::Advisory.new(
59
+ "friendsofphp:packagist:#{package_name}:#{date}",
60
+ advisory_hash['title'],
61
+ nil, #:description
62
+ package_name,
63
+ versions, #:vulnerable_versions
64
+ nil, #:unaffected_versions
65
+ nil, #:patched_versions
66
+ nil, #:severity
67
+ PACKAGE_MANAGER,
68
+ [advisory_hash['cve']].reject { |cve| cve == '~' },
69
+ nil, #:cwe
70
+ nil, #:osvdb
71
+ nil, #:cvss_v2_vector
72
+ nil, #:cvss_v2
73
+ nil, #:cvss_v3_vector
74
+ nil, #:cvss_v3
75
+ date,
76
+ date,
77
+ date,
78
+ ['FriendsOfPHP'],
79
+ [advisory_hash['link']],
80
+ url
81
+ )
82
+ end
83
+
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,120 @@
1
+ # yavdb - The Free and Open Source vulnerability database
2
+ # Copyright (C) 2017-present Rodrigo Fernandes
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU Affero General Public License as
6
+ # published by the Free Software Foundation, either version 3 of the
7
+ # License, or (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU Affero General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Affero General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ require 'oga'
18
+ require 'oga/xml/entities'
19
+ require 'date'
20
+
21
+ require_relative '../dtos/advisory'
22
+ require_relative '../utils/http'
23
+
24
+ module YAVDB
25
+ module Sources
26
+ module NodeSecurityIO
27
+ class Client
28
+
29
+ API_URL = 'https://api.nodesecurity.io/advisories'
30
+ WEBSITE_URL = 'https://nodesecurity.io/advisories'
31
+
32
+ def self.advisories
33
+ fetch_advisories.map do |advisory_hash|
34
+ create(advisory_hash)
35
+ end
36
+ end
37
+
38
+ class << self
39
+
40
+ private
41
+
42
+ def fetch_advisories
43
+ offset = 0
44
+ advisories = []
45
+
46
+ loop do
47
+ nodesecurity = YAVDB::Utils::HTTP.get_page_contents("#{API_URL}?offset=#{offset}", true, 'nodesecurity.io/advisories')
48
+ advisories_json = JSON.parse(nodesecurity.join)
49
+
50
+ advisories_json['count'].positive? ? advisories = advisories.concat(advisories_json['results']) : break
51
+
52
+ offset += advisories_json['count']
53
+ end
54
+
55
+ advisories
56
+ end
57
+
58
+ def create(advisory_hash)
59
+ publish_date = Date.parse(advisory_hash['publish_date'])
60
+ created_at = Date.parse(advisory_hash['created_at'])
61
+ updated_at = Date.parse(advisory_hash['updated_at'])
62
+
63
+ vulnerable_versions =
64
+ if advisory_hash['vulnerable_versions'].nil? || advisory_hash['vulnerable_versions'].empty?
65
+ '*'
66
+ else
67
+ advisory_hash['vulnerable_versions']
68
+ end
69
+
70
+ YAVDB::Advisory.new(
71
+ "nodesecurity:npm:#{advisory_hash['module_name']}:#{publish_date}",
72
+ advisory_hash['title'],
73
+ advisory_hash['overview'],
74
+ advisory_hash['module_name'],
75
+ [vulnerable_versions],
76
+ nil, #:unaffected_versions
77
+ advisory_hash['patched_versions'],
78
+ severity(advisory_hash['cvss_score']),
79
+ 'npm',
80
+ advisory_hash['cves'],
81
+ nil, #:cwe
82
+ nil, #:osvdb
83
+ nil, #:cvss_v2_vector
84
+ nil, #:cvss_v2_score
85
+ advisory_hash['cvss_vector'],
86
+ advisory_hash['cvss_score'],
87
+ publish_date,
88
+ created_at,
89
+ updated_at,
90
+ [advisory_hash['author']],
91
+ clean_references(advisory_hash['references']),
92
+ "#{WEBSITE_URL}/#{advisory_hash['id']}"
93
+ )
94
+ end
95
+
96
+ def severity(cvss_score)
97
+ case cvss_score
98
+ when 0.0..3.3 then
99
+ 'low'
100
+ when 3.3..6.6 then
101
+ 'medium'
102
+ else
103
+ 'high'
104
+ end
105
+ end
106
+
107
+ def clean_references(references)
108
+ if references
109
+ [references.gsub(%r{.*?(http.+)}, '\1')]
110
+ else
111
+ []
112
+ end
113
+ end
114
+
115
+ end
116
+
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,137 @@
1
+ # yavdb - The Free and Open Source vulnerability database
2
+ # Copyright (C) 2017-present Rodrigo Fernandes
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU Affero General Public License as
6
+ # published by the Free Software Foundation, either version 3 of the
7
+ # License, or (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU Affero General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Affero General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ require 'oga'
18
+ require 'oga/xml/entities'
19
+
20
+ require_relative '../dtos/advisory'
21
+ require_relative '../utils/http'
22
+
23
+ module YAVDB
24
+ module Sources
25
+ module OSSIndex
26
+ class Client
27
+
28
+ API_URL = 'https://ossindex.net'
29
+ PACKAGE_MANAGERS = ['npm', 'maven', 'composer', 'nuget', 'rubygems', 'pypi']
30
+ PACKAGE_MANAGER_ALIAS = Hash['composer' => 'packagist']
31
+
32
+ def self.advisories
33
+ PACKAGE_MANAGERS.map do |package_manager|
34
+ packages = fetch_packages(package_manager)
35
+ parse_vulnerabilities(package_manager, packages)
36
+ end.flatten
37
+ end
38
+
39
+ class << self
40
+
41
+ private
42
+
43
+ def fetch_packages(package_manager)
44
+ next_url = start_url(package_manager)
45
+ packages = []
46
+
47
+ while next_url
48
+ ossindex = YAVDB::Utils::HTTP.get_page_contents(next_url, true, 'ossindex/advisories')
49
+ ossindex_json = JSON.parse(ossindex.join)
50
+ page_packages = ossindex_json['packages']
51
+
52
+ packages.concat(page_packages)
53
+
54
+ next_url = ossindex_json['next']
55
+ end
56
+
57
+ packages
58
+ end
59
+
60
+ def parse_vulnerabilities(package_manager, packages)
61
+ packages
62
+ .map do |package|
63
+ package['vulnerabilities'].map do |advisory|
64
+ create(package_manager, package, advisory)
65
+ end
66
+ end.flatten
67
+ end
68
+
69
+ def create(package_manager, package, advisory)
70
+ published_date = Date.strptime((advisory['published'] / 1000).to_s, '%s')
71
+ updated_date = Date.strptime((advisory['updated'] / 1000).to_s, '%s')
72
+
73
+ cve = if advisory['cve']
74
+ [advisory['cve']].map(&:strip).reject(&:empty?)
75
+ else
76
+ []
77
+ end
78
+
79
+ package_manager = PACKAGE_MANAGER_ALIAS[package_manager] || package_manager
80
+
81
+ package_name =
82
+ if package_manager == 'maven'
83
+ "#{package['group']}:#{package['name']}"
84
+ elsif package_manager == 'packagist'
85
+ "#{package['group']}/#{package['name']}"
86
+ else
87
+ package['name']
88
+ end
89
+
90
+ versions = advisory['versions']
91
+ .map { |v| v.split('||') }
92
+ .flatten
93
+ .map(&:strip)
94
+ .reject(&:empty?)
95
+ .reject { |v| v == '-' }
96
+ versions = ['*'] unless versions.any?
97
+
98
+ YAVDB::Advisory.new(
99
+ "ossindex:#{package_manager}:#{package_name}:#{published_date}",
100
+ advisory['title'],
101
+ advisory['description'],
102
+ package_name,
103
+ versions,
104
+ nil, #:unaffected_versions
105
+ nil, #:patched_versions
106
+ nil, #:severity
107
+ package_manager,
108
+ cve,
109
+ nil, #:cwe
110
+ nil, #:osvdb
111
+ nil, #:cvss_v2_vector
112
+ nil, #:cvss_v2_score
113
+ nil, #:cvss_v3_vector
114
+ nil, #:cvss_v3_score
115
+ published_date,
116
+ published_date,
117
+ updated_date,
118
+ ['OSSIndex'],
119
+ advisory['references'],
120
+ website_url(package['id'])
121
+ )
122
+ end
123
+
124
+ def start_url(package_manager)
125
+ "#{API_URL}/v2.0/vulnerability/pm/#{package_manager}/fromtill/0/-1"
126
+ end
127
+
128
+ def website_url(id)
129
+ "#{API_URL}/resource/package/#{id}/vulnerabilities"
130
+ end
131
+
132
+ end
133
+
134
+ end
135
+ end
136
+ end
137
+ end