class HeimdallTools::SnykMapper
Public Class Methods
new(synk_json, _name = nil)
click to toggle source
# File lib/heimdall_tools/snyk_mapper.rb, line 32 def initialize(synk_json, _name = nil) @synk_json = synk_json begin @cwe_nist_mapping = parse_mapper @projects = JSON.parse(synk_json) # Cover single and multi-project scan use cases. unless @projects.is_a?(Array) @projects = [@projects] end rescue StandardError => e raise "Invalid Snyk JSON file provided Exception: #{e}" end end
Public Instance Methods
collapse_duplicates(controls)
click to toggle source
Snyk report could have multiple vulnerability entries for multiple findings of same issue type. The meta data is identical across entries method collapse_duplicates
return unique controls with applicable findings collapsed into it.
# File lib/heimdall_tools/snyk_mapper.rb, line 106 def collapse_duplicates(controls) unique_controls = [] controls.map { |x| x['id'] }.uniq.each do |id| collapsed_results = controls.select { |x| x['id'].eql?(id) }.map { |x| x['results'] } unique_control = controls.find { |x| x['id'].eql?(id) } unique_control['results'] = collapsed_results.flatten unique_controls << unique_control end unique_controls end
extract_scaninfo(project)
click to toggle source
# File lib/heimdall_tools/snyk_mapper.rb, line 48 def extract_scaninfo(project) info = {} begin info['policy'] = project['policy'] reg = Regexp.new(SNYK_VERSION_REGEX, Regexp::IGNORECASE) info['version'] = info['policy'].scan(reg).join info['projectName'] = project['projectName'] info['summary'] = project['summary'] info rescue StandardError => e raise "Error extracting project info from Synk JSON file provided Exception: #{e}" end end
finding(vulnerability)
click to toggle source
# File lib/heimdall_tools/snyk_mapper.rb, line 63 def finding(vulnerability) finding = {} finding['status'] = 'failed' finding['code_desc'] = "From : [ #{vulnerability['from'].join(' , ')} ]" finding['run_time'] = NA_FLOAT # Snyk results does not profile scan timestamp; using current time to satisfy HDF format finding['start_time'] = NA_STRING [finding] end
impact(severity)
click to toggle source
# File lib/heimdall_tools/snyk_mapper.rb, line 87 def impact(severity) IMPACT_MAPPING[severity.to_sym] end
nist_tag(cweid)
click to toggle source
# File lib/heimdall_tools/snyk_mapper.rb, line 74 def nist_tag(cweid) entries = @cwe_nist_mapping.select { |x| cweid.include?(x[:cweid].to_s) && !x[:nistid].nil? } tags = entries.map { |x| x[:nistid] } tags.empty? ? DEFAULT_NIST_TAG : tags.flatten.uniq end
parse_identifiers(vulnerability, ref)
click to toggle source
# File lib/heimdall_tools/snyk_mapper.rb, line 80 def parse_identifiers(vulnerability, ref) # Extracting id number from reference style CWE-297 vulnerability['identifiers'][ref].map { |e| e.split("#{ref}-")[1] } rescue StandardError [] end
parse_mapper()
click to toggle source
# File lib/heimdall_tools/snyk_mapper.rb, line 91 def parse_mapper csv_data = CSV.read(CWE_NIST_MAPPING_FILE, **{ encoding: 'UTF-8', headers: true, header_converters: :symbol, converters: :all }) csv_data.map(&:to_hash) end
to_hdf()
click to toggle source
# File lib/heimdall_tools/snyk_mapper.rb, line 118 def to_hdf project_results = {} @projects.each do |project| controls = [] project['vulnerabilities'].each do |vulnerability| printf("\rProcessing: %s", $spinner.next) item = {} item['tags'] = {} item['descriptions'] = [] item['refs'] = NA_ARRAY item['source_location'] = NA_HASH item['descriptions'] = NA_ARRAY item['title'] = vulnerability['title'].to_s item['id'] = vulnerability['id'].to_s item['desc'] = vulnerability['description'].to_s item['impact'] = impact(vulnerability['severity']) item['code'] = '' item['results'] = finding(vulnerability) item['tags']['nist'] = nist_tag(parse_identifiers(vulnerability, 'CWE')) item['tags']['cweid'] = parse_identifiers(vulnerability, 'CWE') item['tags']['cveid'] = parse_identifiers(vulnerability, 'CVE') item['tags']['ghsaid'] = parse_identifiers(vulnerability, 'GHSA') controls << item end controls = collapse_duplicates(controls) scaninfo = extract_scaninfo(project) results = HeimdallDataFormat.new(profile_name: scaninfo['policy'], version: scaninfo['version'], title: "Snyk Project: #{scaninfo['projectName']}", summary: "Snyk Summary: #{scaninfo['summary']}", controls: controls, target_id: scaninfo['projectName']) project_results[scaninfo['projectName']] = results.to_hdf end project_results end