Skip to content

Commit afb202b

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 798eba6 commit afb202b

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
@@ -137,12 +137,16 @@ func (v *Provider) SetLogger(logger *zap.SugaredLogger) {
137137

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

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

pkg/provider/gitlab/gitlab_test.go

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1083,34 +1083,40 @@ func TestGetFileInsideRepo(t *testing.T) {
10831083
func TestValidate(t *testing.T) {
10841084
tests := []struct {
10851085
name string
1086-
wantErr bool
1086+
wantErr string
10871087
secretToken string
10881088
eventToken string
10891089
}{
10901090
{
1091-
name: "valid event",
1092-
wantErr: false,
1091+
name: "valid event with matching tokens",
1092+
wantErr: "",
10931093
secretToken: "test",
10941094
eventToken: "test",
10951095
},
10961096
{
1097-
name: "fail validation, no secret defined",
1098-
wantErr: true,
1097+
name: "invalid when webhook secret not configured",
1098+
wantErr: "no webhook secret configured",
10991099
secretToken: "",
11001100
eventToken: "test",
11011101
},
11021102
{
1103-
name: "fail validation",
1104-
wantErr: true,
1103+
name: "invalid when tokens do not match",
1104+
wantErr: "token does not match configured secret",
11051105
secretToken: "secret",
11061106
eventToken: "test",
11071107
},
11081108
{
1109-
name: "fail validation, missing event token",
1110-
wantErr: true,
1109+
name: "invalid when X-Gitlab-Token header missing",
1110+
wantErr: "no X-Gitlab-Token header detected",
11111111
secretToken: "secret",
11121112
eventToken: "",
11131113
},
1114+
{
1115+
name: "invalid when both token and secret are empty (security fix)",
1116+
wantErr: "no X-Gitlab-Token header detected",
1117+
secretToken: "",
1118+
eventToken: "",
1119+
},
11141120
}
11151121
for _, tt := range tests {
11161122
t.Run(tt.name, func(t *testing.T) {
@@ -1127,8 +1133,12 @@ func TestValidate(t *testing.T) {
11271133
WebhookSecret: tt.secretToken,
11281134
}
11291135

1130-
if err := v.Validate(context.TODO(), nil, event); (err != nil) != tt.wantErr {
1131-
t.Errorf("Validate() error = %v, wantErr %v", err, tt.wantErr)
1136+
err := v.Validate(context.TODO(), nil, event)
1137+
if tt.wantErr != "" {
1138+
assert.Assert(t, err != nil)
1139+
assert.ErrorContains(t, err, tt.wantErr)
1140+
} else {
1141+
assert.NilError(t, err)
11321142
}
11331143
})
11341144
}

0 commit comments

Comments
 (0)