Class: HeimdallTools::JfrogXrayMapper

Inherits:
Object
  • Object
show all
Defined in:
lib/heimdall_tools/jfrog_xray_mapper.rb

Instance Method Summary collapse

Constructor Details

#initialize(xray_json, _name = nil) ⇒ JfrogXrayMapper

Returns a new instance of JfrogXrayMapper.



30
31
32
33
34
35
36
37
38
39
# File 'lib/heimdall_tools/jfrog_xray_mapper.rb', line 30

def initialize(xray_json, _name = nil)
  @xray_json = xray_json

  begin
    @cwe_nist_mapping = parse_mapper
    @project = JSON.parse(xray_json)
  rescue StandardError => e
    raise "Invalid JFrog Xray JSON file provided Exception: #{e}"
  end
end

Instance Method Details

#collapse_duplicates(controls) ⇒ Object

Xray 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.



98
99
100
101
102
103
104
105
106
107
108
# File 'lib/heimdall_tools/jfrog_xray_mapper.rb', line 98

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

#desc_tags(data, label) ⇒ Object



91
92
93
# File 'lib/heimdall_tools/jfrog_xray_mapper.rb', line 91

def desc_tags(data, label)
  { data: data || NA_STRING, label: label || NA_STRING }
end

#finding(vulnerability) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/heimdall_tools/jfrog_xray_mapper.rb', line 41

def finding(vulnerability)
  finding = {}
  finding['status'] = 'failed'
  finding['code_desc'] = []
  finding['code_desc'] << "source_comp_id : #{vulnerability['source_comp_id']}"
  finding['code_desc'] << "vulnerable_versions : #{vulnerability['component_versions']['vulnerable_versions']}"
  finding['code_desc'] << "fixed_versions : #{vulnerability['component_versions']['fixed_versions']}"
  finding['code_desc'] << "issue_type : #{vulnerability['issue_type']}"
  finding['code_desc'] << "provider : #{vulnerability['provider']}"
  finding['code_desc'] = finding['code_desc'].join("\n")
  finding['run_time'] = NA_FLOAT

  # Xray results does not profile scan timestamp; using current time to satisfy HDF format
  finding['start_time'] = NA_STRING
  [finding]
end

#format_control_desc(vulnerability) ⇒ Object



58
59
60
61
62
63
64
# File 'lib/heimdall_tools/jfrog_xray_mapper.rb', line 58

def format_control_desc(vulnerability)
  text = []
  info = vulnerability['component_versions']['more_details']
  text << info['description'].to_s
  text << "cves: #{info['cves']}" unless info['cves'].nil?
  text.join('<br>')
end

#impact(severity) ⇒ Object



79
80
81
# File 'lib/heimdall_tools/jfrog_xray_mapper.rb', line 79

def impact(severity)
  IMPACT_MAPPING[severity.downcase.to_sym]
end

#nist_tag(cweid) ⇒ Object



66
67
68
69
70
# File 'lib/heimdall_tools/jfrog_xray_mapper.rb', line 66

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) ⇒ Object



72
73
74
75
76
77
# File 'lib/heimdall_tools/jfrog_xray_mapper.rb', line 72

def parse_identifiers(vulnerability, ref)
  # Extracting id number from reference style CWE-297
  vulnerability['component_versions']['more_details']['cves'][0][ref.downcase].map { |e| e.split("#{ref}-")[1] }
rescue StandardError
  []
end

#parse_mapperObject



83
84
85
86
87
88
89
# File 'lib/heimdall_tools/jfrog_xray_mapper.rb', line 83

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_hdfObject



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/heimdall_tools/jfrog_xray_mapper.rb', line 110

def to_hdf
  controls = []
  vulnerability_count = 0
  @project['data'].uniq.each do |vulnerability|
    printf("\rProcessing: %s", $spinner.next)

    vulnerability_count +=1
    item = {}
    item['tags']               = {}
    item['descriptions']       = []
    item['refs']               = NA_ARRAY
    item['source_location']    = NA_HASH
    item['descriptions']       = NA_ARRAY

    # Xray JSONs might note have `id` fields populated.
    # If thats a case MD5 hash is used to collapse vulnerability findings of the same type.
    item['id']                 = vulnerability['id'].empty? ? OpenSSL::Digest::MD5.digest(vulnerability['summary'].to_s).unpack1('H*').to_s : vulnerability['id']
    item['title']              = vulnerability['summary'].to_s
    item['desc']               = format_control_desc(vulnerability)
    item['impact']             = impact(vulnerability['severity'].to_s)
    item['code']               = NA_STRING
    item['results']            = finding(vulnerability)

    item['tags']['nist']       = nist_tag(parse_identifiers(vulnerability, 'CWE'))
    item['tags']['cweid']      = parse_identifiers(vulnerability, 'CWE')

    controls << item
  end

  controls = collapse_duplicates(controls)
  results = HeimdallDataFormat.new(profile_name: 'JFrog Xray Scan',
                                   version: NA_STRING,
                                   title: 'JFrog Xray Scan',
                                   summary: 'Continuous Security and Universal Artifact Analysis',
                                   controls: controls)
  results.to_hdf
end