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.

[View source]

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.

[View source]

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

[View source]

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

[View source]

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

[View source]

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

[View source]

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

[View source]

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

[View source]

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

[View source]

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

[View source]

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