Skip to content

Commit

Permalink
fix(webhook): validate payload prior to handling repo events
Browse files Browse the repository at this point in the history
  • Loading branch information
ecrupper committed Feb 28, 2025
1 parent 257886e commit 3140d92
Showing 1 changed file with 29 additions and 34 deletions.
63 changes: 29 additions & 34 deletions api/webhook/post.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,37 @@ func PostWebhook(c *gin.Context) {
h, r, b := webhook.Hook, webhook.Repo, webhook.Build

l.Debugf("hook generated from SCM: %v", h)

// check if repo was parsed from webhook
if r == nil {
retErr := fmt.Errorf("%s: failed to parse repo from webhook", baseErr)
util.HandleError(c, http.StatusBadRequest, retErr)

return
}

l.Debugf("repo generated from SCM: %v", r)

// get repo from database using payload org/name
repo, err := database.FromContext(c).GetRepoForOrg(ctx, r.GetOrg(), r.GetName())
if err != nil {
retErr := fmt.Errorf("%s: failed to get repo %s: %w", baseErr, r.GetFullName(), err)
util.HandleError(c, http.StatusBadRequest, retErr)

return
}

// verify the webhook from the source control provider using DB repo hash
if c.Value("webhookvalidation").(bool) {
err = scm.FromContext(c).VerifyWebhook(ctx, dupRequest, repo)
if err != nil {
retErr := fmt.Errorf("unable to verify webhook: %w", err)
util.HandleError(c, http.StatusUnauthorized, retErr)

return
}
}

// if event is repository event, handle separately and return
if strings.EqualFold(h.GetEvent(), constants.EventRepository) {
r, err = handleRepositoryEvent(ctx, l, db, m, h, r)
Expand Down Expand Up @@ -194,14 +223,6 @@ func PostWebhook(c *gin.Context) {
build ref: %s`,
b.GetAuthor(), b.GetBranch(), b.GetCommit(), b.GetRef())

// check if repo was parsed from webhook
if r == nil {
retErr := fmt.Errorf("%s: failed to parse repo from webhook", baseErr)
util.HandleError(c, http.StatusBadRequest, retErr)

return
}

defer func() {
// send API call to update the webhook
//
Expand All @@ -220,18 +241,6 @@ func PostWebhook(c *gin.Context) {
}).Info("hook updated")
}()

// send API call to capture parsed repo from webhook
repo, err := database.FromContext(c).GetRepoForOrg(ctx, r.GetOrg(), r.GetName())
if err != nil {
retErr := fmt.Errorf("%s: failed to get repo %s: %w", baseErr, r.GetFullName(), err)
util.HandleError(c, http.StatusBadRequest, retErr)

h.SetStatus(constants.StatusFailure)
h.SetError(retErr.Error())

return
}

// attach a sender SCM id if the webhook payload from the SCM has no sender id
// the code in ProcessWebhook implies that the sender may not always be present
// fallbacks like pusher/commit_author do not have an id
Expand Down Expand Up @@ -335,20 +344,6 @@ func PostWebhook(c *gin.Context) {
"repo": repo.GetName(),
}).Info("hook created")

// verify the webhook from the source control provider
if c.Value("webhookvalidation").(bool) {
err = scm.FromContext(c).VerifyWebhook(ctx, dupRequest, repo)
if err != nil {
retErr := fmt.Errorf("unable to verify webhook: %w", err)
util.HandleError(c, http.StatusUnauthorized, retErr)

h.SetStatus(constants.StatusFailure)
h.SetError(retErr.Error())

return
}
}

// check if the repo is active
if !repo.GetActive() {
retErr := fmt.Errorf("%s: %s is not an active repo", baseErr, repo.GetFullName())
Expand Down

0 comments on commit 3140d92

Please sign in to comment.