Skip to content

Commit 7427b70

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 7c8fb46 commit 7427b70

2 files changed

Lines changed: 28 additions & 14 deletions

File tree

pkg/provider/gitlab/gitlab.go

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

135135
func (v *Provider) Validate(_ context.Context, _ *params.Run, event *info.Event) error {
136136
token := event.Request.Header.Get("X-Gitlab-Token")
137-
if event.Provider.WebhookSecret == "" && token != "" {
138-
return fmt.Errorf("gitlab failed validation: failed to find webhook secret")
137+
if token == "" {
138+
return fmt.Errorf("no X-Gitlab-Token header detected: webhook validation requires a token for security")
139+
}
140+
141+
if event.Provider.WebhookSecret == "" {
142+
return fmt.Errorf("no webhook secret configured: set webhook secret in repository CR or secret")
139143
}
140144

141145
if subtle.ConstantTimeCompare([]byte(event.Provider.WebhookSecret), []byte(token)) == 0 {
142-
return fmt.Errorf("gitlab failed validation: event's secret doesn't match with webhook secret")
146+
return fmt.Errorf("gitlab webhook validation failed: token does not match configured secret")
143147
}
144148
return nil
145149
}

pkg/provider/gitlab/gitlab_test.go

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -938,34 +938,40 @@ func TestGetFileInsideRepo(t *testing.T) {
938938
func TestValidate(t *testing.T) {
939939
tests := []struct {
940940
name string
941-
wantErr bool
941+
wantErr string
942942
secretToken string
943943
eventToken string
944944
}{
945945
{
946-
name: "valid event",
947-
wantErr: false,
946+
name: "valid event with matching tokens",
947+
wantErr: "",
948948
secretToken: "test",
949949
eventToken: "test",
950950
},
951951
{
952-
name: "fail validation, no secret defined",
953-
wantErr: true,
952+
name: "invalid when webhook secret not configured",
953+
wantErr: "no webhook secret configured",
954954
secretToken: "",
955955
eventToken: "test",
956956
},
957957
{
958-
name: "fail validation",
959-
wantErr: true,
958+
name: "invalid when tokens do not match",
959+
wantErr: "token does not match configured secret",
960960
secretToken: "secret",
961961
eventToken: "test",
962962
},
963963
{
964-
name: "fail validation, missing event token",
965-
wantErr: true,
964+
name: "invalid when X-Gitlab-Token header missing",
965+
wantErr: "no X-Gitlab-Token header detected",
966966
secretToken: "secret",
967967
eventToken: "",
968968
},
969+
{
970+
name: "invalid when both token and secret are empty (security fix)",
971+
wantErr: "no X-Gitlab-Token header detected",
972+
secretToken: "",
973+
eventToken: "",
974+
},
969975
}
970976
for _, tt := range tests {
971977
t.Run(tt.name, func(t *testing.T) {
@@ -982,8 +988,12 @@ func TestValidate(t *testing.T) {
982988
WebhookSecret: tt.secretToken,
983989
}
984990

985-
if err := v.Validate(context.TODO(), nil, event); (err != nil) != tt.wantErr {
986-
t.Errorf("Validate() error = %v, wantErr %v", err, tt.wantErr)
991+
err := v.Validate(context.TODO(), nil, event)
992+
if tt.wantErr != "" {
993+
assert.Assert(t, err != nil)
994+
assert.ErrorContains(t, err, tt.wantErr)
995+
} else {
996+
assert.NilError(t, err)
987997
}
988998
})
989999
}

0 commit comments

Comments
 (0)