Skip to content

Commit 9a230ff

Browse files
committed
fix: Enforce mandatory webhook secret for GitLab validation
Enforced strict validation to require both the X-Gitlab-Token header and a configured webhook secret. This prevented unauthenticated requests that were previously accepted when both values were empty. Signed-off-by: Chmouel Boudjnah <chmouel@redhat.com>
1 parent 555aeb0 commit 9a230ff

File tree

2 files changed

+28
-14
lines changed

2 files changed

+28
-14
lines changed

pkg/provider/gitlab/gitlab.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,12 +156,16 @@ func (v *Provider) SetLogger(logger *zap.SugaredLogger) {
156156

157157
func (v *Provider) Validate(_ context.Context, _ *params.Run, event *info.Event) error {
158158
token := event.Request.Header.Get("X-Gitlab-Token")
159-
if event.Provider.WebhookSecret == "" && token != "" {
160-
return fmt.Errorf("gitlab failed validation: failed to find webhook secret")
159+
if token == "" {
160+
return fmt.Errorf("no X-Gitlab-Token header detected: webhook validation requires a token for security")
161+
}
162+
163+
if event.Provider.WebhookSecret == "" {
164+
return fmt.Errorf("no webhook secret configured: set webhook secret in repository CR or secret")
161165
}
162166

163167
if subtle.ConstantTimeCompare([]byte(event.Provider.WebhookSecret), []byte(token)) == 0 {
164-
return fmt.Errorf("gitlab failed validation: event's secret doesn't match with webhook secret")
168+
return fmt.Errorf("gitlab webhook validation failed: token does not match configured secret")
165169
}
166170
return nil
167171
}

pkg/provider/gitlab/gitlab_test.go

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1168,34 +1168,40 @@ func TestGetFileInsideRepo(t *testing.T) {
11681168
func TestValidate(t *testing.T) {
11691169
tests := []struct {
11701170
name string
1171-
wantErr bool
1171+
wantErr string
11721172
secretToken string
11731173
eventToken string
11741174
}{
11751175
{
1176-
name: "valid event",
1177-
wantErr: false,
1176+
name: "valid event with matching tokens",
1177+
wantErr: "",
11781178
secretToken: "test",
11791179
eventToken: "test",
11801180
},
11811181
{
1182-
name: "fail validation, no secret defined",
1183-
wantErr: true,
1182+
name: "invalid when webhook secret not configured",
1183+
wantErr: "no webhook secret configured",
11841184
secretToken: "",
11851185
eventToken: "test",
11861186
},
11871187
{
1188-
name: "fail validation",
1189-
wantErr: true,
1188+
name: "invalid when tokens do not match",
1189+
wantErr: "token does not match configured secret",
11901190
secretToken: "secret",
11911191
eventToken: "test",
11921192
},
11931193
{
1194-
name: "fail validation, missing event token",
1195-
wantErr: true,
1194+
name: "invalid when X-Gitlab-Token header missing",
1195+
wantErr: "no X-Gitlab-Token header detected",
11961196
secretToken: "secret",
11971197
eventToken: "",
11981198
},
1199+
{
1200+
name: "invalid when both token and secret are empty (security fix)",
1201+
wantErr: "no X-Gitlab-Token header detected",
1202+
secretToken: "",
1203+
eventToken: "",
1204+
},
11991205
}
12001206
for _, tt := range tests {
12011207
t.Run(tt.name, func(t *testing.T) {
@@ -1212,8 +1218,12 @@ func TestValidate(t *testing.T) {
12121218
WebhookSecret: tt.secretToken,
12131219
}
12141220

1215-
if err := v.Validate(context.TODO(), nil, event); (err != nil) != tt.wantErr {
1216-
t.Errorf("Validate() error = %v, wantErr %v", err, tt.wantErr)
1221+
err := v.Validate(context.TODO(), nil, event)
1222+
if tt.wantErr != "" {
1223+
assert.Assert(t, err != nil)
1224+
assert.ErrorContains(t, err, tt.wantErr)
1225+
} else {
1226+
assert.NilError(t, err)
12171227
}
12181228
})
12191229
}

0 commit comments

Comments
 (0)