## Copyright (c) 2013-2021 Hal Brodigan (postmodern.mod3 at gmail.com)## bundler-audit is free software: you can redistribute it and/or modify# it under the terms of the GNU General Public License as published by# the Free Software Foundation, either version 3 of the License, or# (at your option) any later version.## bundler-audit is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the# GNU General Public License for more details.## You should have received a copy of the GNU General Public License# along with bundler-audit. If not, see <https://www.gnu.org/licenses/>.#require'yaml'moduleBundlermoduleAudit## Represents an advisory loaded from the {Database}.#classAdvisory<Struct.new(:path,:id,:url,:title,:date,:description,:cvss_v2,:cvss_v3,:cve,:osvdb,:ghsa,:unaffected_versions,:patched_versions)## Loads the advisory from a YAML file.## @param [String] path# The path to the advisory YAML file.## @return [Advisory]## @api semipublic#defself.load(path)id=File.basename(path).chomp('.yml')data=File.open(path)do|yaml|YAML.safe_load(yaml,permitted_classes: [Date])endunlessdata.kind_of?(Hash)raise("advisory data in #{path.dump} was not a Hash")endparse_versions=lambda{|versions|Array(versions).mapdo|version|Gem::Requirement.new(*version.split(', '))end}returnnew(path,id,data['url'],data['title'],data['date'],data['description'],data['cvss_v2'],data['cvss_v3'],data['cve'],data['osvdb'],data['ghsa'],parse_versions[data['unaffected_versions']],parse_versions[data['patched_versions']])end## The CVE identifier.## @return [String, nil]#defcve_id"CVE-#{cve}"ifcveend## The OSVDB identifier.## @return [String, nil]#defosvdb_id"OSVDB-#{osvdb}"ifosvdbend## The GHSA (GitHub Security Advisory) identifier## @return [String, nil]## @since 0.7.0#defghsa_id"GHSA-#{ghsa}"ifghsaend## Return a compacted list of all ids## @return [Array<String>]## @since 0.7.0#defidentifiers[cve_id,osvdb_id,ghsa_id].compactend## Determines how critical the vulnerability is.## @return [:none, :low, :medium, :high, :critical, nil]# The criticality of the vulnerability based on the CVSS score.#defcriticalityifcvss_v3casecvss_v3when0.0then:nonewhen0.1..3.9then:lowwhen4.0..6.9then:mediumwhen7.0..8.9then:highwhen9.0..10.0then:criticalendelsifcvss_v2casecvss_v2when0.0..3.9then:lowwhen4.0..6.9then:mediumwhen7.0..10.0then:highendendend## Checks whether the version is not affected by the advisory.## @param [Gem::Version] version# The version to compare against {#unaffected_versions}.## @return [Boolean]# Specifies whether the version is not affected by the advisory.## @since 0.2.0#defunaffected?(version)unaffected_versions.any?do|unaffected_version|unaffected_version===versionendend## Checks whether the version is patched against the advisory.## @param [Gem::Version] version# The version to compare against {#patched_versions}.## @return [Boolean]# Specifies whether the version is patched against the advisory.## @since 0.2.0#defpatched?(version)patched_versions.any?do|patched_version|patched_version===versionendend## Checks whether the version is vulnerable to the advisory.## @param [Gem::Version] version# The version to compare against {#patched_versions}.## @return [Boolean]# Specifies whether the version is vulnerable to the advisory or not.#defvulnerable?(version)!patched?(version)&&!unaffected?(version)end## Compares two advisories.## @param [Advisory] other## @return [Boolean]#def==(other)id==other.idend## Converts the advisory to a Hash.## @return [Hash{Symbol => Object}]#defto_hsuper.merge({criticality: criticality})endaliasto_sidendendend