Module: MyPrecious::CVEs
- Extended by:
- DataCaching
- Defined in:
- lib/myprecious/cves.rb
Defined Under Namespace
Classes: Applicability_V4_0, CVERecord
Constant Summary
collapse
- MIN_GAP_SECONDS =
5
- CONFIG_FILE =
'.myprecious-cves.rb'
- CVE_DATA_CACHE_DIR =
MyPrecious.data_cache(DATA_DIR / "cve-data")
Class Attribute Summary collapse
Class Method Summary
collapse
print_error_info
Class Attribute Details
.config_dir ⇒ Object
Returns the value of attribute config_dir.
20
21
22
|
# File 'lib/myprecious/cves.rb', line 20
def config_dir
@config_dir
end
|
Class Method Details
.config ⇒ Object
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
# File 'lib/myprecious/cves.rb', line 78
def self.config
if !@config && config_dir
if (config_path = config_dir / CONFIG_FILE).exist?
@config = begin
config_prog_output, status = Open3.capture2(RbConfig.ruby, config_path.to_s)
if status.success?
JSON.parse(config_prog_output)
else
$stderr.puts "#{config_path} did not exit cleanly (code ${status.exitstatus})"
{}
end
rescue StandardError
end
unless @config.kind_of?(Hash)
$stderr.puts "#{config_path} did not output a JSON configuration"
@config = {}
end
else
@config = {}
end
end
@config ||= {}
end
|
.get_for(package_name, version = '*') ⇒ Object
If you don’t specify version, you get to match against the applicable configurations on your own to determine which CVEs returned apply to the versions of the named package in which you are interested
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
# File 'lib/myprecious/cves.rb', line 40
def self.get_for(package_name, version='*')
nvd_url = URI("https://services.nvd.nist.gov/rest/json/cves/1.0")
nvd_url.query = URI.encode_www_form(
cpeMatchString: "cpe:2.3:a:*:#{package_name.downcase}:#{version}:*:*:*:*:*:*:*",
)
cache = CVE_DATA_CACHE_DIR / "#{Digest::SHA256.hexdigest(nvd_url.to_s)}.json"
cve_data = apply_cache(cache) do
wait_time = MIN_GAP_SECONDS - (DateTime.now - last_query_time) * 24 * 3600
if wait_time > 0
sleep(wait_time)
end
response = RestClient.get(nvd_url.to_s)
queried!
JSON.parse(response.body)
end
begin
return cve_data['result']['CVE_Items'].map do |e|
applicability = objectify_configurations(package_name, e['configurations'])
score = (((e['impact'] || {})['baseMetricV3'] || {})['cvssV3'] || {})['baseScore']
cve = CVERecord.new(
e['cve']['CVE_data_meta']['ID'],
applicability.respond_to?(:vendors) ? applicability.vendors : nil,
score
)
[cve, applicability]
end.reject {|cve, a| a.respond_to?(:applies_to?) && !a.applies_to?(version)}
rescue StandardError => e
$stderr.puts "[WARN] #{e}\n\n#{JSON.dump(cve_data)}\n\n"
[]
end
end
|
.last_query_time ⇒ Object
27
28
29
|
# File 'lib/myprecious/cves.rb', line 27
def self.last_query_time
@last_query_time ||= DateTime.now - 1
end
|
.objectify_configurations(package_name, configs) ⇒ Object
103
104
105
106
107
108
109
|
# File 'lib/myprecious/cves.rb', line 103
def self.objectify_configurations(package_name, configs)
if configs.kind_of?(Hash) && configs['CVE_data_version'] == "4.0"
Applicability_V4_0.new(package_name, configs)
else
configs
end
end
|
.queried! ⇒ Object
31
32
33
|
# File 'lib/myprecious/cves.rb', line 31
def self.queried!
@last_query_time = DateTime.now
end
|