gitlab-secret_detection 0.11.1 → 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f72d7d8262749305fdf1811df74637af4f7ba4bbf693fc41d2cdb34d1ca25238
|
4
|
+
data.tar.gz: 6896b4eb32dc734640c0dc125dd75e79b765f27aa618f73fec81c83c0c20df93
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2d35dfa136b9524f851a6ed20885aa6d50b9334f12166fd9d131ff523ed38bed1264bad953fd6fa58e63fe2c5f9c62be129d3be231258eef25990803b9b67d4e
|
7
|
+
data.tar.gz: 331a74ba7a779f275717c769c0f63785d7e74d25b07da5d07f44c08a1a0c7f343eec3ba7fd8285d549d298fac4d93bdc3f2bc122ea7cb30bd567e4c75e43efdb
|
@@ -7,14 +7,16 @@ module Gitlab
|
|
7
7
|
#
|
8
8
|
# +status+:: One of values from Gitlab::SecretDetection::Core::Status indicating the scan operation's status
|
9
9
|
# +results+:: Array of Gitlab::SecretDetection::Core::Finding values. Default value is nil.
|
10
|
-
# +metadata+:: Hash object containing additional meta information about the response. It is currently used
|
11
10
|
# to embed more information on error.
|
11
|
+
# +applied_exclusions+:: Array of Exclusions that were applied during this scan.
|
12
|
+
# +metadata+:: Hash object containing additional meta information about the response. It is currently used
|
12
13
|
class Response
|
13
|
-
attr_reader :status, :results, :metadata
|
14
|
+
attr_reader :status, :results, :applied_exclusions, :metadata
|
14
15
|
|
15
|
-
def initialize(status
|
16
|
+
def initialize(status:, results: [], applied_exclusions: [], metadata: {})
|
16
17
|
@status = status
|
17
18
|
@results = results
|
19
|
+
@applied_exclusions = applied_exclusions
|
18
20
|
@metadata = metadata
|
19
21
|
end
|
20
22
|
|
@@ -25,15 +27,21 @@ module Gitlab
|
|
25
27
|
def to_h
|
26
28
|
{
|
27
29
|
status:,
|
28
|
-
|
29
|
-
|
30
|
+
results: results&.map(&:to_h),
|
31
|
+
applied_exclusions:,
|
32
|
+
metadata:
|
30
33
|
}
|
31
34
|
end
|
32
35
|
|
33
36
|
protected
|
34
37
|
|
35
38
|
def state
|
36
|
-
[
|
39
|
+
[
|
40
|
+
status,
|
41
|
+
results,
|
42
|
+
applied_exclusions,
|
43
|
+
metadata
|
44
|
+
]
|
37
45
|
end
|
38
46
|
end
|
39
47
|
end
|
@@ -90,7 +90,7 @@ module Gitlab
|
|
90
90
|
subprocess: RUN_IN_SUBPROCESS
|
91
91
|
)
|
92
92
|
|
93
|
-
return Core::Response.new(Core::Status::INPUT_ERROR) unless validate_scan_input(payloads)
|
93
|
+
return Core::Response.new(status: Core::Status::INPUT_ERROR) unless validate_scan_input(payloads)
|
94
94
|
|
95
95
|
# assign defaults since grpc passing zero timeout value to `Timeout.timeout(..)` makes it effectively useless.
|
96
96
|
timeout = DEFAULT_SCAN_TIMEOUT_SECS unless timeout.positive?
|
@@ -102,24 +102,26 @@ module Gitlab
|
|
102
102
|
|
103
103
|
matched_payloads = filter_by_keywords(keyword_matcher, payloads)
|
104
104
|
|
105
|
-
next Core::Response.new(Core::Status::NOT_FOUND) if matched_payloads.empty?
|
105
|
+
next Core::Response.new(status: Core::Status::NOT_FOUND) if matched_payloads.empty?
|
106
106
|
|
107
107
|
scan_args = {
|
108
|
-
payloads: matched_payloads,
|
108
|
+
payloads: matched_payloads,
|
109
|
+
payload_timeout:,
|
109
110
|
pattern_matcher: build_pattern_matcher(tags:),
|
110
|
-
raw_value_exclusions:,
|
111
|
+
raw_value_exclusions:,
|
112
|
+
rule_exclusions:
|
111
113
|
}
|
112
114
|
|
113
|
-
secrets = subprocess ? run_scan_within_subprocess(**scan_args) : run_scan(**scan_args)
|
115
|
+
secrets, applied_exclusions = subprocess ? run_scan_within_subprocess(**scan_args) : run_scan(**scan_args)
|
114
116
|
|
115
117
|
scan_status = overall_scan_status(secrets)
|
116
118
|
|
117
|
-
Core::Response.new(scan_status, secrets)
|
119
|
+
Core::Response.new(status: scan_status, results: secrets, applied_exclusions:)
|
118
120
|
end
|
119
121
|
rescue Timeout::Error => e
|
120
122
|
logger.error "Secret detection operation timed out: #{e}"
|
121
123
|
|
122
|
-
Core::Response.new(Core::Status::SCAN_TIMEOUT)
|
124
|
+
Core::Response.new(status: Core::Status::SCAN_TIMEOUT)
|
123
125
|
end
|
124
126
|
|
125
127
|
private
|
@@ -208,25 +210,42 @@ module Gitlab
|
|
208
210
|
# literal values to exclude from the input before the scan, also SD rules to exclude during
|
209
211
|
# the scan when performed on the payloads.
|
210
212
|
def run_scan(
|
211
|
-
payloads:,
|
212
|
-
|
213
|
+
payloads:,
|
214
|
+
payload_timeout:,
|
215
|
+
pattern_matcher:,
|
216
|
+
raw_value_exclusions: [],
|
217
|
+
rule_exclusions: []
|
218
|
+
)
|
219
|
+
all_applied_exclusions = Set.new
|
220
|
+
|
221
|
+
all_findings = payloads.flat_map do |payload|
|
213
222
|
Timeout.timeout(payload_timeout) do
|
214
|
-
find_secrets_in_payload(
|
223
|
+
findings, applied_exclusions = find_secrets_in_payload(
|
215
224
|
payload:,
|
216
225
|
pattern_matcher:,
|
217
|
-
raw_value_exclusions:,
|
226
|
+
raw_value_exclusions:,
|
227
|
+
rule_exclusions:
|
218
228
|
)
|
229
|
+
all_applied_exclusions.merge(applied_exclusions)
|
230
|
+
findings
|
219
231
|
end
|
220
232
|
rescue Timeout::Error => e
|
221
233
|
logger.error "Secret Detection scan timed out on the payload(id:#{payload.id}): #{e}"
|
234
|
+
|
222
235
|
Core::Finding.new(payload.id,
|
223
236
|
Core::Status::PAYLOAD_TIMEOUT)
|
224
237
|
end
|
238
|
+
[all_findings.freeze, all_applied_exclusions.to_a.freeze]
|
225
239
|
end
|
226
240
|
|
227
241
|
def run_scan_within_subprocess(
|
228
|
-
payloads:,
|
229
|
-
|
242
|
+
payloads:,
|
243
|
+
payload_timeout:,
|
244
|
+
pattern_matcher:,
|
245
|
+
raw_value_exclusions: [],
|
246
|
+
rule_exclusions: []
|
247
|
+
)
|
248
|
+
all_applied_exclusions = Set.new
|
230
249
|
payload_sizes = payloads.map(&:size)
|
231
250
|
grouped_payload_indices = group_by_chunk_size(payload_sizes)
|
232
251
|
|
@@ -239,19 +258,22 @@ module Gitlab
|
|
239
258
|
) do |grouped_payload|
|
240
259
|
grouped_payload.flat_map do |payload|
|
241
260
|
Timeout.timeout(payload_timeout) do
|
242
|
-
find_secrets_in_payload(
|
261
|
+
findings, applied_exclusions = find_secrets_in_payload(
|
243
262
|
payload:,
|
244
263
|
pattern_matcher:,
|
245
264
|
raw_value_exclusions:, rule_exclusions:
|
246
265
|
)
|
266
|
+
all_applied_exclusions.merge(applied_exclusions)
|
267
|
+
findings
|
247
268
|
end
|
248
269
|
rescue Timeout::Error => e
|
249
270
|
logger.error "Secret Detection scan timed out on the payload(id:#{payload.id}): #{e}"
|
271
|
+
|
250
272
|
Core::Finding.new(payload.id, Core::Status::PAYLOAD_TIMEOUT)
|
251
273
|
end
|
252
274
|
end
|
253
275
|
|
254
|
-
found_secrets.freeze
|
276
|
+
[found_secrets.freeze, all_applied_exclusions.to_a.freeze]
|
255
277
|
end
|
256
278
|
|
257
279
|
# Finds secrets in the given payload guarded with a timeout as a circuit breaker. It accepts
|
@@ -259,6 +281,7 @@ module Gitlab
|
|
259
281
|
# the scan.
|
260
282
|
def find_secrets_in_payload(payload:, pattern_matcher:, raw_value_exclusions: [], rule_exclusions: [])
|
261
283
|
findings = []
|
284
|
+
applied_exclusions = Set.new
|
262
285
|
|
263
286
|
payload_offset = payload.respond_to?(:offset) ? payload.offset : 0
|
264
287
|
|
@@ -268,6 +291,7 @@ module Gitlab
|
|
268
291
|
unless raw_value_exclusions.empty?
|
269
292
|
raw_value_exclusions.each do |value|
|
270
293
|
line.gsub!(value, '') # replace input that doesn't contain allowed value in it
|
294
|
+
applied_exclusions << value # TODO we need the id of the exclusion
|
271
295
|
end
|
272
296
|
end
|
273
297
|
|
@@ -284,18 +308,30 @@ module Gitlab
|
|
284
308
|
matches.each do |match_idx|
|
285
309
|
rule = rules[match_idx]
|
286
310
|
|
287
|
-
next if
|
311
|
+
next if applied_rule_exclusion?(rule[:id], rule_exclusions, applied_exclusions)
|
312
|
+
|
313
|
+
title = rule[:title].nil? ? rule[:description] : rule[:title]
|
288
314
|
|
289
|
-
findings << Core::Finding.new(
|
290
|
-
|
315
|
+
findings << Core::Finding.new(
|
316
|
+
payload.id,
|
317
|
+
Core::Status::FOUND,
|
318
|
+
line_no,
|
319
|
+
rule[:id],
|
320
|
+
title
|
321
|
+
)
|
291
322
|
end
|
292
323
|
end
|
293
324
|
|
294
|
-
findings.freeze
|
325
|
+
[findings.freeze, applied_exclusions]
|
295
326
|
rescue StandardError => e
|
296
327
|
logger.error "Secret Detection scan failed on the payload(id:#{payload.id}): #{e}"
|
297
328
|
|
298
|
-
Core::Finding.new(payload.id, Core::Status::SCAN_ERROR)
|
329
|
+
[[Core::Finding.new(payload.id, Core::Status::SCAN_ERROR)], []]
|
330
|
+
end
|
331
|
+
|
332
|
+
def applied_rule_exclusion?(type, rule_exclusions, applied_exclusions)
|
333
|
+
applied_exclusion = rule_exclusions&.find { |rule_exclusion| rule_exclusion == type }
|
334
|
+
applied_exclusion && (applied_exclusions << applied_exclusion)
|
299
335
|
end
|
300
336
|
|
301
337
|
# Validates the given payloads by verifying the type and
|
@@ -17,10 +17,11 @@ module Gitlab
|
|
17
17
|
# Time to wait for the response from the service
|
18
18
|
REQUEST_TIMEOUT_SECONDS = 10 # 10 seconds
|
19
19
|
|
20
|
-
def initialize(host, secure: false, compression: true)
|
20
|
+
def initialize(host, secure: false, compression: true, logger: nil)
|
21
21
|
@host = host
|
22
22
|
@secure = secure
|
23
23
|
@compression = compression
|
24
|
+
@logger = logger.nil? ? LOGGER : logger
|
24
25
|
end
|
25
26
|
|
26
27
|
# Triggers Secret Detection service's `/Scan` gRPC endpoint. To keep it consistent with SDS gem interface,
|
@@ -116,14 +117,18 @@ module Gitlab
|
|
116
117
|
def with_rescued_errors
|
117
118
|
yield
|
118
119
|
rescue ::GRPC::Unauthenticated
|
119
|
-
SecretDetection::Core::Response.new(SecretDetection::Core::Status::AUTH_ERROR)
|
120
|
+
SecretDetection::Core::Response.new(status: SecretDetection::Core::Status::AUTH_ERROR)
|
120
121
|
rescue ::GRPC::InvalidArgument => e
|
121
122
|
SecretDetection::Core::Response.new(
|
122
|
-
SecretDetection::Core::Status::INPUT_ERROR,
|
123
|
+
status: SecretDetection::Core::Status::INPUT_ERROR,
|
124
|
+
results: nil,
|
125
|
+
metadata: { message: e.details, **e.metadata }
|
123
126
|
)
|
124
127
|
rescue ::GRPC::Unknown, ::GRPC::BadStatus => e
|
125
128
|
SecretDetection::Core::Response.new(
|
126
|
-
SecretDetection::Core::Status::SCAN_ERROR,
|
129
|
+
status: SecretDetection::Core::Status::SCAN_ERROR,
|
130
|
+
results: nil,
|
131
|
+
metadata: { message: e.details }
|
127
132
|
)
|
128
133
|
end
|
129
134
|
|
@@ -131,13 +136,13 @@ module Gitlab
|
|
131
136
|
response = grpc_response.to_h
|
132
137
|
|
133
138
|
SecretDetection::Core::Response.new(
|
134
|
-
response[:status],
|
135
|
-
response[:results],
|
136
|
-
response[:metadata]
|
139
|
+
status: response[:status],
|
140
|
+
results: response[:results],
|
141
|
+
metadata: response[:metadata]
|
137
142
|
)
|
138
143
|
rescue StandardError => e
|
139
|
-
logger.error("Failed to convert to core response: #{e}")
|
140
|
-
SecretDetection::Core::Response.new(SecretDetection::Core::Status::SCAN_ERROR)
|
144
|
+
@logger.error("Failed to convert to core response: #{e}")
|
145
|
+
SecretDetection::Core::Response.new(status: SecretDetection::Core::Status::SCAN_ERROR)
|
141
146
|
end
|
142
147
|
end
|
143
148
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gitlab-secret_detection
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.13.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- group::secret detection
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2024-12-
|
13
|
+
date: 2024-12-11 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: grpc
|