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
|
# frozen_string_literal: true
module VulnerabilityFindingHelpers
extend ActiveSupport::Concern
# Manually resolvable report types cannot be considered fixed once removed from the
# target branch due to requiring active triage, such as rotation of an exposed token.
REPORT_TYPES_REQUIRING_MANUAL_RESOLUTION = %w[secret_detection].freeze
def requires_manual_resolution?
REPORT_TYPES_REQUIRING_MANUAL_RESOLUTION.include?(report_type)
end
def matches_signatures(other_signatures, other_uuid)
other_signature_types = other_signatures.index_by(&:algorithm_type)
# highest first
match_result = nil
signatures.sort_by(&:priority).reverse_each do |signature|
matching_other_signature = other_signature_types[signature.algorithm_type]
next if matching_other_signature.nil?
match_result = matching_other_signature == signature
break
end
if match_result.nil?
[uuid, *signature_uuids].include?(other_uuid)
else
match_result
end
end
def signature_uuids
signatures.map do |signature|
hex_sha = signature.signature_hex
::Security::VulnerabilityUUID.generate(
report_type: report_type,
location_fingerprint: hex_sha,
primary_identifier_fingerprint: primary_identifier&.fingerprint,
project_id: project_id
)
end
end
def build_vulnerability_finding(security_finding)
report_finding = report_finding_for(security_finding)
return Vulnerabilities::Finding.new unless report_finding
finding_data = report_finding.to_hash.except(
:compare_key, :identifiers, :location, :scanner, :links, :signatures, :flags, :evidence
)
identifiers = report_finding.identifiers.uniq(&:fingerprint).map do |identifier|
Vulnerabilities::Identifier.new(identifier.to_hash.merge({ project: project }))
end
signatures = report_finding.signatures.map do |signature|
Vulnerabilities::FindingSignature.new(signature.to_hash)
end
evidence = Vulnerabilities::Finding::Evidence.new(data: report_finding.evidence.data) if report_finding.evidence
Vulnerabilities::Finding.new(finding_data).tap do |finding|
finding.uuid = security_finding.uuid
finding.location_fingerprint = report_finding.location.fingerprint
finding.vulnerability = vulnerability_for(security_finding.uuid)
finding.project = project
finding.sha = pipeline.sha
finding.scanner = security_finding.scanner
finding.finding_evidence = evidence
if calculate_false_positive?
finding.vulnerability_flags = report_finding.flags.map do |flag|
Vulnerabilities::Flag.new(flag)
end
end
finding.identifiers = identifiers
finding.primary_identifier = identifiers.first
finding.signatures = signatures
end
end
def calculate_false_positive?
project.licensed_feature_available?(:sast_fp_reduction)
end
end
|