1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
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
147
148
149
150
151
152
153
|
# frozen_string_literal: true
module Gitlab
module Ci
module Reports
module Security
class Finding
include ::VulnerabilityFindingHelpers
attr_reader :compare_key
attr_reader :confidence
attr_reader :identifiers
attr_reader :flags
attr_reader :links
attr_reader :location
attr_reader :metadata_version
attr_reader :name
attr_reader :old_location
attr_reader :project_fingerprint
attr_reader :raw_metadata
attr_reader :report_type
attr_reader :scanner
attr_reader :scan
attr_reader :severity
attr_accessor :uuid
attr_accessor :overridden_uuid
attr_reader :remediations
attr_reader :details
attr_reader :signatures
attr_reader :project_id
delegate :file_path, :start_line, :end_line, to: :location
def initialize(compare_key:, identifiers:, flags: [], links: [], remediations: [], location:, metadata_version:, name:, raw_metadata:, report_type:, scanner:, scan:, uuid:, confidence: nil, severity: nil, details: {}, signatures: [], project_id: nil, vulnerability_finding_signatures_enabled: false) # rubocop:disable Metrics/ParameterLists
@compare_key = compare_key
@confidence = confidence
@identifiers = identifiers
@flags = flags
@links = links
@location = location
@metadata_version = metadata_version
@name = name
@raw_metadata = raw_metadata
@report_type = report_type
@scanner = scanner
@scan = scan
@severity = severity
@uuid = uuid
@remediations = remediations
@details = details
@signatures = signatures
@project_id = project_id
@vulnerability_finding_signatures_enabled = vulnerability_finding_signatures_enabled
@project_fingerprint = generate_project_fingerprint
end
def to_hash
%i[
compare_key
confidence
identifiers
flags
links
location
metadata_version
name
project_fingerprint
raw_metadata
report_type
scanner
scan
severity
uuid
details
signatures
].each_with_object({}) do |key, hash|
hash[key] = public_send(key) # rubocop:disable GitlabSecurity/PublicSend
end
end
def primary_identifier
identifiers.first
end
def update_location(new_location)
@old_location = location
@location = new_location
end
def unsafe?(severity_levels)
severity.in?(severity_levels)
end
def eql?(other)
return false unless report_type == other.report_type && primary_identifier_fingerprint == other.primary_identifier_fingerprint
if @vulnerability_finding_signatures_enabled
matches_signatures(other.signatures, other.uuid)
else
location.fingerprint == other.location.fingerprint
end
end
def hash
if @vulnerability_finding_signatures_enabled && !signatures.empty?
highest_signature = signatures.max_by(&:priority)
report_type.hash ^ highest_signature.signature_hex.hash ^ primary_identifier_fingerprint.hash
else
report_type.hash ^ location.fingerprint.hash ^ primary_identifier_fingerprint.hash
end
end
def valid?
scanner.present? && primary_identifier.present? && location.present? && uuid.present?
end
def keys
@keys ||= identifiers.reject(&:type_identifier?).map do |identifier|
FindingKey.new(location_fingerprint: location&.fingerprint, identifier_fingerprint: identifier.fingerprint)
end
end
def primary_identifier_fingerprint
primary_identifier&.fingerprint
end
def <=>(other)
if severity == other.severity
compare_key <=> other.compare_key
else
::Enums::Vulnerability.severity_levels[other.severity] <=>
::Enums::Vulnerability.severity_levels[severity]
end
end
def scanner_order_to(other)
return 1 unless scanner
return -1 unless other&.scanner
scanner <=> other.scanner
end
private
def generate_project_fingerprint
Digest::SHA1.hexdigest(compare_key)
end
end
end
end
end
end
|