yavdb 0.1.0.pre.alpha.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.circleci/config.yml +48 -0
- data/.gitignore +115 -0
- data/.rspec +3 -0
- data/.rubocop.yml +339 -0
- data/.ruby-version +1 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +85 -0
- data/LICENSE +661 -0
- data/README.md +87 -0
- data/Rakefile +6 -0
- data/bin/console +7 -0
- data/bin/setup +8 -0
- data/bin/vulndb +3 -0
- data/bin/vulnerabilitydb +3 -0
- data/bin/yavdb +5 -0
- data/lib/yavdb.rb +68 -0
- data/lib/yavdb/cli.rb +60 -0
- data/lib/yavdb/constants.rb +34 -0
- data/lib/yavdb/crawler.rb +52 -0
- data/lib/yavdb/database.rb +95 -0
- data/lib/yavdb/dtos/advisory.rb +102 -0
- data/lib/yavdb/source_types/git_repo.rb +35 -0
- data/lib/yavdb/sources/friends_of_php.rb +87 -0
- data/lib/yavdb/sources/nodesecurity_io.rb +120 -0
- data/lib/yavdb/sources/ossindex.rb +137 -0
- data/lib/yavdb/sources/ruby_advisory.rb +117 -0
- data/lib/yavdb/sources/snyk_io.rb +311 -0
- data/lib/yavdb/sources/victims.rb +105 -0
- data/lib/yavdb/utils/cache.rb +96 -0
- data/lib/yavdb/utils/exec.rb +36 -0
- data/lib/yavdb/utils/git.rb +61 -0
- data/lib/yavdb/utils/http.rb +56 -0
- data/lib/yavdb/utils/semver.rb +79 -0
- data/lib/yavdb/utils/zip.rb +64 -0
- data/lib/yavdb/version.rb +21 -0
- data/yavdb.gemspec +44 -0
- metadata +267 -0
@@ -0,0 +1,96 @@
|
|
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 'json'
|
18
|
+
require 'digest'
|
19
|
+
require 'fileutils'
|
20
|
+
require 'securerandom'
|
21
|
+
|
22
|
+
module YAVDB
|
23
|
+
module Utils
|
24
|
+
module Cache
|
25
|
+
|
26
|
+
CACHE_MAIN_KEY = 'general'
|
27
|
+
|
28
|
+
def self.cache_contents(group_key, key, &body)
|
29
|
+
get(group_key, key) || put(group_key, key, body.call)
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.cache_path(group_key, key, &body)
|
33
|
+
key_path = generate_cache_identifier(group_key, key)
|
34
|
+
body.call(key_path) unless File.exist?(key_path)
|
35
|
+
key_path
|
36
|
+
end
|
37
|
+
|
38
|
+
class << self
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def get(group_key, key)
|
43
|
+
key_path = generate_cache_identifier(group_key, key)
|
44
|
+
File.open(key_path, 'rb') { |file| Marshal.load(file.read) } if File.exist?(key_path)
|
45
|
+
end
|
46
|
+
|
47
|
+
def put(group_key, key, value)
|
48
|
+
key_path = generate_cache_identifier(group_key, key)
|
49
|
+
File.open(key_path, 'wb') { |file| file.write(Marshal.dump(value)) }
|
50
|
+
value
|
51
|
+
end
|
52
|
+
|
53
|
+
def generate_cache_identifier(group_key, key)
|
54
|
+
group_key = sanitize_key(group_key)
|
55
|
+
key = sanitize_key(key)
|
56
|
+
|
57
|
+
group_path = if group_key
|
58
|
+
File.expand_path(File.join(YAVDB::Constants::DEFAULT_CACHE_PATH, group_key))
|
59
|
+
else
|
60
|
+
File.expand_path(File.join(YAVDB::Constants::DEFAULT_CACHE_PATH, CACHE_MAIN_KEY))
|
61
|
+
end
|
62
|
+
|
63
|
+
FileUtils.mkdir_p(group_path) unless File.exist?(group_path)
|
64
|
+
|
65
|
+
File.expand_path(File.join(group_path, key))
|
66
|
+
end
|
67
|
+
|
68
|
+
def sanitize_key(key)
|
69
|
+
sanitized_key = key
|
70
|
+
.gsub(%r{[^[:alnum:]]}, '-')
|
71
|
+
.gsub(%r{(-)+}, '-')
|
72
|
+
.gsub(%r{^-}, '')
|
73
|
+
.gsub(%r{-$}, '')
|
74
|
+
|
75
|
+
if sanitized_key == '-'
|
76
|
+
hex_key = Digest::SHA256.hexdigest(key)
|
77
|
+
|
78
|
+
puts "Could not sanitize key(#{key}) using #{hex_key} instead"
|
79
|
+
|
80
|
+
hex_key
|
81
|
+
elsif sanitized_key.empty?
|
82
|
+
random_string = SecureRandom.hex
|
83
|
+
|
84
|
+
puts "Could not sanitize key(#{key}) using #{random_string} instead"
|
85
|
+
|
86
|
+
random_string
|
87
|
+
else
|
88
|
+
sanitized_key
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,36 @@
|
|
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 'English'
|
18
|
+
|
19
|
+
require_relative '../constants'
|
20
|
+
|
21
|
+
module YAVDB
|
22
|
+
module Utils
|
23
|
+
module Executor
|
24
|
+
|
25
|
+
def self.run(cmd)
|
26
|
+
puts "[Running] #{cmd}" if Constants::DEBUG
|
27
|
+
output = `#{cmd}`
|
28
|
+
{
|
29
|
+
:output => output,
|
30
|
+
:success? => $CHILD_STATUS.success?
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,61 @@
|
|
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 'tmpdir'
|
18
|
+
|
19
|
+
require_relative '../constants'
|
20
|
+
require_relative '../utils/exec'
|
21
|
+
require_relative '../utils/cache'
|
22
|
+
|
23
|
+
module YAVDB
|
24
|
+
module Utils
|
25
|
+
module Git
|
26
|
+
|
27
|
+
def self.get_contents(repo_url, repo_branch, with_cache = true, group_cache_key = 'git')
|
28
|
+
puts "Requesting #{repo_url}" if Constants::DEBUG
|
29
|
+
|
30
|
+
if with_cache
|
31
|
+
YAVDB::Utils::Cache.cache_path(group_cache_key, repo_url) do |repo_path|
|
32
|
+
download_or_update(repo_path, repo_url, repo_branch)
|
33
|
+
repo_path
|
34
|
+
end
|
35
|
+
else
|
36
|
+
repo_path = Dir.mktmpdir(group_cache_key)
|
37
|
+
download_or_update(repo_path, repo_url, repo_branch)
|
38
|
+
repo_path
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.download_or_update(repo_path, repo_url, repo_branch, force_update = true)
|
43
|
+
puts "Downloading #{repo_url}" if Constants::DEBUG
|
44
|
+
|
45
|
+
if File.exist?(repo_path) && Dir.entries(repo_path) != ['.', '..']
|
46
|
+
if File.directory?(File.expand_path(File.join(repo_path, '.git')))
|
47
|
+
Dir.chdir(repo_path) do
|
48
|
+
YAVDB::Utils::Executor.run("git fetch --all && git reset --hard origin/#{repo_branch}") if force_update
|
49
|
+
end
|
50
|
+
else
|
51
|
+
puts "Repository directory already exists and is not a valid git repository in #{repo_path}"
|
52
|
+
exit(1)
|
53
|
+
end
|
54
|
+
else
|
55
|
+
YAVDB::Utils::Executor.run("git clone #{repo_url} -b #{repo_branch} #{repo_path}")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,56 @@
|
|
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 'net/https'
|
18
|
+
|
19
|
+
require_relative '../utils/cache'
|
20
|
+
|
21
|
+
module YAVDB
|
22
|
+
module Utils
|
23
|
+
module HTTP
|
24
|
+
|
25
|
+
def self.get_page_contents(url, with_cache = true, group_cache_key = 'http')
|
26
|
+
puts "Requesting #{url}"
|
27
|
+
|
28
|
+
if with_cache
|
29
|
+
YAVDB::Utils::Cache.cache_contents(group_cache_key, url) { do_request(url) }
|
30
|
+
else
|
31
|
+
do_request(url)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class << self
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def do_request(url)
|
40
|
+
puts "Fetching #{url}"
|
41
|
+
|
42
|
+
url = URI.parse(url)
|
43
|
+
response = Net::HTTP.get_response(url)
|
44
|
+
case response
|
45
|
+
when Net::HTTPNotFound then
|
46
|
+
raise ArgumentError, 'page not found'
|
47
|
+
else
|
48
|
+
response.body.lines
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,79 @@
|
|
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
|
+
module Utils
|
19
|
+
module SemVer
|
20
|
+
|
21
|
+
SEMANTIC_INTERVAL_REGEX = %r{([(\[].+?[)\]])}
|
22
|
+
|
23
|
+
def self.clean_versions(versions)
|
24
|
+
return if versions.nil? || (!versions.is_a?(String) && !versions.is_a?(Array))
|
25
|
+
|
26
|
+
versions = to_array(versions).map do |version|
|
27
|
+
if semantic_interval?(version)
|
28
|
+
convert_to_semver(version)
|
29
|
+
else
|
30
|
+
split_versions(version)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
versions
|
35
|
+
.flatten
|
36
|
+
.map(&:strip)
|
37
|
+
.select { |str| str != '-' && !str.empty? }
|
38
|
+
end
|
39
|
+
|
40
|
+
class << self
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def to_array(versions)
|
45
|
+
versions = [versions] if versions.is_a?(String)
|
46
|
+
|
47
|
+
versions
|
48
|
+
.flatten
|
49
|
+
.reject { |str| str.strip.empty? }
|
50
|
+
end
|
51
|
+
|
52
|
+
def semantic_interval?(version)
|
53
|
+
version =~ SEMANTIC_INTERVAL_REGEX
|
54
|
+
end
|
55
|
+
|
56
|
+
def convert_to_semver(version)
|
57
|
+
ver_tmp = version
|
58
|
+
.scan(SEMANTIC_INTERVAL_REGEX)
|
59
|
+
.flatten
|
60
|
+
.map { |v| SemanticInterval.parse(v) }
|
61
|
+
|
62
|
+
if ver_tmp.any?
|
63
|
+
ver_tmp
|
64
|
+
else
|
65
|
+
version
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def split_versions(version)
|
70
|
+
version
|
71
|
+
.strip
|
72
|
+
.split(',')
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,64 @@
|
|
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 'fileutils'
|
18
|
+
|
19
|
+
require_relative '../constants'
|
20
|
+
require_relative '../utils/cache'
|
21
|
+
require_relative '../utils/exec'
|
22
|
+
|
23
|
+
module YAVDB
|
24
|
+
module Utils
|
25
|
+
module Zip
|
26
|
+
|
27
|
+
def self.get_contents(zip_url, with_cache = true, group_cache_key = 'zip')
|
28
|
+
puts "Requesting #{zip_url}" if Constants::DEBUG
|
29
|
+
|
30
|
+
if with_cache
|
31
|
+
YAVDB::Utils::Cache.cache_path(group_cache_key, zip_url) do |zip_path|
|
32
|
+
do_request(zip_path, zip_url)
|
33
|
+
zip_path
|
34
|
+
end
|
35
|
+
else
|
36
|
+
zip_path = Dir.mktmpdir(group_cache_key)
|
37
|
+
do_request(zip_path, zip_url)
|
38
|
+
zip_path
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class << self
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def do_request(zip_path, zip_url)
|
47
|
+
puts "Downloading #{zip_url}" if Constants::DEBUG
|
48
|
+
|
49
|
+
resource_path = "#{zip_path}/resource.zip"
|
50
|
+
|
51
|
+
FileUtils.rm_rf(zip_path)
|
52
|
+
FileUtils.mkdir_p(zip_path)
|
53
|
+
|
54
|
+
YAVDB::Utils::Executor.run %(wget -O #{resource_path} #{zip_url})
|
55
|
+
YAVDB::Utils::Executor.run %(unzip #{resource_path} -d #{zip_path})
|
56
|
+
|
57
|
+
FileUtils.rm(resource_path)
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,21 @@
|
|
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
|
+
|
19
|
+
VERSION = '0.1.0-alpha.2'
|
20
|
+
|
21
|
+
end
|
data/yavdb.gemspec
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
|
4
|
+
require 'yavdb/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'yavdb'
|
8
|
+
spec.version = YAVDB::VERSION
|
9
|
+
spec.authors = ['Rodrigo Fernandes']
|
10
|
+
spec.email = ['rodrigo.fernandes@tecnico.ulisboa.pt']
|
11
|
+
spec.summary = 'The Free and Open Source vulnerability database.'
|
12
|
+
spec.description = '
|
13
|
+
Yet Another Vulnerability Database
|
14
|
+
The Free and Open Source vulnerability database.
|
15
|
+
'
|
16
|
+
spec.homepage = 'https://github.com/rtfpessoa/yavdb'
|
17
|
+
spec.license = 'AGPL-3.0+'
|
18
|
+
|
19
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|database)/}) }
|
20
|
+
spec.bindir = 'bin'
|
21
|
+
spec.executables = ['yavdb', 'vulndb', 'vulnerabilitydb']
|
22
|
+
spec.require_paths = ['lib']
|
23
|
+
|
24
|
+
spec.required_ruby_version = '>= 2.3.7'
|
25
|
+
|
26
|
+
# Development
|
27
|
+
spec.add_development_dependency 'bundler', ['~> 1.16']
|
28
|
+
spec.add_development_dependency 'codacy-coverage'
|
29
|
+
spec.add_development_dependency 'rake', ['~> 12.3']
|
30
|
+
spec.add_development_dependency 'rspec', ['~> 3.8']
|
31
|
+
spec.add_development_dependency 'rspec_junit_formatter', ['~> 0.4']
|
32
|
+
spec.add_development_dependency 'simplecov'
|
33
|
+
|
34
|
+
# Linters
|
35
|
+
spec.add_development_dependency 'rubocop', ['~> 0.58']
|
36
|
+
spec.add_development_dependency 'rubocop-rspec', ['~> 1.27']
|
37
|
+
|
38
|
+
# Runtime
|
39
|
+
spec.add_runtime_dependency 'json', ['~> 2.1']
|
40
|
+
spec.add_runtime_dependency 'kramdown', ['~> 1.17']
|
41
|
+
spec.add_runtime_dependency 'oga', ['~> 2.15']
|
42
|
+
spec.add_runtime_dependency 'semantic_interval', ['~> 0.1']
|
43
|
+
spec.add_runtime_dependency 'thor', ['~> 0.20']
|
44
|
+
end
|