Skip to content

Commit 8531b07

Browse files
committed
fix(cel): add nil checks to prevent panics in webhook parsers
Add comprehensive nil pointer checks in PopulateEvent methods for webhook parsers to prevent panics when accessing nested fields that may be nil or missing from webhook payloads. Jira: https://issues.redhat.com/browse/SRVKP-9396 Signed-off-by: Akshay Pant <[email protected]>
1 parent 4d75ddc commit 8531b07

File tree

2 files changed

+631
-91
lines changed

2 files changed

+631
-91
lines changed

pkg/cmd/tknpac/cel/parser.go

Lines changed: 183 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -136,58 +136,104 @@ func (p *GitHubParser) ParsePayload(eventType string, body []byte) (any, error)
136136
func (p *GitHubParser) PopulateEvent(event *info.Event, parsedEvent any) error {
137137
switch gitEvent := parsedEvent.(type) {
138138
case *github.PullRequestEvent:
139-
event.Organization = gitEvent.GetRepo().GetOwner().GetLogin()
140-
event.Repository = gitEvent.GetRepo().GetName()
141-
event.Sender = gitEvent.GetSender().GetLogin()
142-
event.URL = gitEvent.GetRepo().GetHTMLURL()
143-
event.SHA = gitEvent.GetPullRequest().GetHead().GetSHA()
144-
event.SHAURL = fmt.Sprintf("%s/commit/%s", gitEvent.GetPullRequest().GetHTMLURL(), gitEvent.GetPullRequest().GetHead().GetSHA())
145-
event.PullRequestTitle = gitEvent.GetPullRequest().GetTitle()
146-
event.HeadBranch = gitEvent.GetPullRequest().GetHead().GetRef()
147-
event.BaseBranch = gitEvent.GetPullRequest().GetBase().GetRef()
148-
event.HeadURL = gitEvent.GetPullRequest().GetHead().GetRepo().GetHTMLURL()
149-
event.BaseURL = gitEvent.GetPullRequest().GetBase().GetRepo().GetHTMLURL()
150-
event.DefaultBranch = gitEvent.GetRepo().GetDefaultBranch()
151-
event.PullRequestNumber = gitEvent.GetPullRequest().GetNumber()
152-
event.TriggerTarget = triggertype.PullRequest
153-
for _, label := range gitEvent.GetPullRequest().Labels {
154-
event.PullRequestLabel = append(event.PullRequestLabel, label.GetName())
139+
if repo := gitEvent.GetRepo(); repo != nil {
140+
if owner := repo.GetOwner(); owner != nil {
141+
event.Organization = owner.GetLogin()
142+
}
143+
event.Repository = repo.GetName()
144+
event.URL = repo.GetHTMLURL()
145+
event.DefaultBranch = repo.GetDefaultBranch()
155146
}
147+
if pr := gitEvent.GetPullRequest(); pr != nil {
148+
if head := pr.GetHead(); head != nil {
149+
event.SHA = head.GetSHA()
150+
if pr.GetHTMLURL() != "" && head.GetSHA() != "" {
151+
event.SHAURL = fmt.Sprintf("%s/commit/%s", pr.GetHTMLURL(), head.GetSHA())
152+
}
153+
event.HeadBranch = head.GetRef()
154+
if headRepo := head.GetRepo(); headRepo != nil {
155+
event.HeadURL = headRepo.GetHTMLURL()
156+
}
157+
}
158+
if base := pr.GetBase(); base != nil {
159+
event.BaseBranch = base.GetRef()
160+
if baseRepo := base.GetRepo(); baseRepo != nil {
161+
event.BaseURL = baseRepo.GetHTMLURL()
162+
}
163+
}
164+
event.PullRequestTitle = pr.GetTitle()
165+
event.PullRequestNumber = pr.GetNumber()
166+
for _, label := range pr.Labels {
167+
if label != nil {
168+
event.PullRequestLabel = append(event.PullRequestLabel, label.GetName())
169+
}
170+
}
171+
}
172+
if sender := gitEvent.GetSender(); sender != nil {
173+
event.Sender = sender.GetLogin()
174+
}
175+
event.TriggerTarget = triggertype.PullRequest
156176
case *github.PushEvent:
157-
event.Organization = gitEvent.GetRepo().GetOwner().GetLogin()
158-
event.Repository = gitEvent.GetRepo().GetName()
159-
event.Sender = gitEvent.GetSender().GetLogin()
160-
event.URL = gitEvent.GetRepo().GetHTMLURL()
161-
event.SHA = gitEvent.GetHeadCommit().GetID()
162-
event.SHAURL = gitEvent.GetHeadCommit().GetURL()
163-
event.SHATitle = gitEvent.GetHeadCommit().GetMessage()
177+
if repo := gitEvent.GetRepo(); repo != nil {
178+
if owner := repo.GetOwner(); owner != nil {
179+
event.Organization = owner.GetLogin()
180+
}
181+
event.Repository = repo.GetName()
182+
event.URL = repo.GetHTMLURL()
183+
event.DefaultBranch = repo.GetDefaultBranch()
184+
event.HeadURL = repo.GetHTMLURL()
185+
event.BaseURL = repo.GetHTMLURL()
186+
}
187+
if headCommit := gitEvent.GetHeadCommit(); headCommit != nil {
188+
event.SHA = headCommit.GetID()
189+
event.SHAURL = headCommit.GetURL()
190+
event.SHATitle = headCommit.GetMessage()
191+
}
192+
if sender := gitEvent.GetSender(); sender != nil {
193+
event.Sender = sender.GetLogin()
194+
}
164195
event.HeadBranch = gitEvent.GetRef()
165196
event.BaseBranch = gitEvent.GetRef()
166-
event.HeadURL = gitEvent.GetRepo().GetHTMLURL()
167-
event.BaseURL = gitEvent.GetRepo().GetHTMLURL()
168-
event.DefaultBranch = gitEvent.GetRepo().GetDefaultBranch()
169197
event.TriggerTarget = triggertype.Push
170198
case *github.IssueCommentEvent:
171-
if gitEvent.GetIssue().GetPullRequestLinks() == nil {
199+
if issue := gitEvent.GetIssue(); issue == nil || issue.GetPullRequestLinks() == nil {
172200
return fmt.Errorf("issue comment is not from a pull request")
173201
}
174-
event.Organization = gitEvent.GetRepo().GetOwner().GetLogin()
175-
event.Repository = gitEvent.GetRepo().GetName()
176-
event.Sender = gitEvent.GetSender().GetLogin()
177-
event.URL = gitEvent.GetRepo().GetHTMLURL()
178-
event.DefaultBranch = gitEvent.GetRepo().GetDefaultBranch()
202+
if repo := gitEvent.GetRepo(); repo != nil {
203+
if owner := repo.GetOwner(); owner != nil {
204+
event.Organization = owner.GetLogin()
205+
}
206+
event.Repository = repo.GetName()
207+
event.URL = repo.GetHTMLURL()
208+
event.DefaultBranch = repo.GetDefaultBranch()
209+
}
210+
if sender := gitEvent.GetSender(); sender != nil {
211+
event.Sender = sender.GetLogin()
212+
}
179213
event.TriggerTarget = triggertype.PullRequest
180-
event.TriggerComment = gitEvent.GetComment().GetBody()
181-
event.PullRequestNumber = gitEvent.GetIssue().GetNumber()
214+
if comment := gitEvent.GetComment(); comment != nil {
215+
event.TriggerComment = comment.GetBody()
216+
}
217+
if issue := gitEvent.GetIssue(); issue != nil {
218+
event.PullRequestNumber = issue.GetNumber()
219+
}
182220
case *github.CommitCommentEvent:
183-
event.Organization = gitEvent.GetRepo().GetOwner().GetLogin()
184-
event.Repository = gitEvent.GetRepo().GetName()
185-
event.Sender = gitEvent.GetSender().GetLogin()
186-
event.URL = gitEvent.GetRepo().GetHTMLURL()
187-
event.SHA = gitEvent.GetComment().GetCommitID()
188-
event.DefaultBranch = gitEvent.GetRepo().GetDefaultBranch()
221+
if repo := gitEvent.GetRepo(); repo != nil {
222+
if owner := repo.GetOwner(); owner != nil {
223+
event.Organization = owner.GetLogin()
224+
}
225+
event.Repository = repo.GetName()
226+
event.URL = repo.GetHTMLURL()
227+
event.DefaultBranch = repo.GetDefaultBranch()
228+
}
229+
if comment := gitEvent.GetComment(); comment != nil {
230+
event.SHA = comment.GetCommitID()
231+
event.TriggerComment = comment.GetBody()
232+
}
233+
if sender := gitEvent.GetSender(); sender != nil {
234+
event.Sender = sender.GetLogin()
235+
}
189236
event.TriggerTarget = triggertype.Push
190-
event.TriggerComment = gitEvent.GetComment().GetBody()
191237
default:
192238
return fmt.Errorf("unsupported GitHub event type: %T", gitEvent)
193239
}
@@ -242,8 +288,11 @@ func (p *GitLabParser) PopulateEvent(event *info.Event, parsedEvent any) error {
242288
case *gitlab.MergeEvent:
243289
event.Organization = extractOrgFromPath(gitEvent.Project.PathWithNamespace)
244290
event.Repository = extractRepoFromPath(gitEvent.Project.PathWithNamespace)
245-
event.Sender = gitEvent.User.Username
246291
event.URL = gitEvent.Project.WebURL
292+
event.DefaultBranch = gitEvent.Project.DefaultBranch
293+
if gitEvent.User != nil {
294+
event.Sender = gitEvent.User.Username
295+
}
247296
event.SHA = gitEvent.ObjectAttributes.LastCommit.ID
248297
event.SHAURL = gitEvent.ObjectAttributes.LastCommit.URL
249298
event.SHATitle = gitEvent.ObjectAttributes.LastCommit.Title
@@ -257,7 +306,6 @@ func (p *GitLabParser) PopulateEvent(event *info.Event, parsedEvent any) error {
257306
}
258307
event.PullRequestNumber = gitEvent.ObjectAttributes.IID
259308
event.PullRequestTitle = gitEvent.ObjectAttributes.Title
260-
event.DefaultBranch = gitEvent.Project.DefaultBranch
261309
event.TriggerTarget = triggertype.PullRequest
262310
if gitEvent.ObjectAttributes.Action == "close" {
263311
event.TriggerTarget = triggertype.PullRequestClosed
@@ -272,34 +320,38 @@ func (p *GitLabParser) PopulateEvent(event *info.Event, parsedEvent any) error {
272320
lastCommitIdx := len(gitEvent.Commits) - 1
273321
event.Organization = extractOrgFromPath(gitEvent.Project.PathWithNamespace)
274322
event.Repository = extractRepoFromPath(gitEvent.Project.PathWithNamespace)
275-
event.Sender = gitEvent.UserUsername
276323
event.URL = gitEvent.Project.WebURL
277-
event.SHA = gitEvent.Commits[lastCommitIdx].ID
278-
event.SHAURL = gitEvent.Commits[lastCommitIdx].URL
279-
event.SHATitle = gitEvent.Commits[lastCommitIdx].Title
280-
event.HeadBranch = gitEvent.Ref
281-
event.BaseBranch = gitEvent.Ref
282324
event.HeadURL = gitEvent.Project.WebURL
283325
event.BaseURL = gitEvent.Project.WebURL
284326
event.DefaultBranch = gitEvent.Project.DefaultBranch
327+
event.Sender = gitEvent.UserUsername
328+
if gitEvent.Commits[lastCommitIdx] != nil {
329+
event.SHA = gitEvent.Commits[lastCommitIdx].ID
330+
event.SHAURL = gitEvent.Commits[lastCommitIdx].URL
331+
event.SHATitle = gitEvent.Commits[lastCommitIdx].Title
332+
}
333+
event.HeadBranch = gitEvent.Ref
334+
event.BaseBranch = gitEvent.Ref
285335
event.TriggerTarget = triggertype.Push
286336
case *gitlab.TagEvent:
287337
if len(gitEvent.Commits) == 0 {
288338
return fmt.Errorf("no commits attached to this tag event")
289339
}
290340
lastCommitIdx := len(gitEvent.Commits) - 1
341+
event.Sender = gitEvent.UserUsername
291342
event.Organization = extractOrgFromPath(gitEvent.Project.PathWithNamespace)
292343
event.Repository = extractRepoFromPath(gitEvent.Project.PathWithNamespace)
293-
event.Sender = gitEvent.UserUsername
344+
event.DefaultBranch = gitEvent.Project.DefaultBranch
294345
event.URL = gitEvent.Project.WebURL
295-
event.SHA = gitEvent.Commits[lastCommitIdx].ID
296-
event.SHAURL = gitEvent.Commits[lastCommitIdx].URL
297-
event.SHATitle = gitEvent.Commits[lastCommitIdx].Title
298-
event.HeadBranch = gitEvent.Ref
299-
event.BaseBranch = gitEvent.Ref
300346
event.HeadURL = gitEvent.Project.WebURL
301347
event.BaseURL = gitEvent.Project.WebURL
302-
event.DefaultBranch = gitEvent.Project.DefaultBranch
348+
event.HeadBranch = gitEvent.Ref
349+
event.BaseBranch = gitEvent.Ref
350+
if gitEvent.Commits[lastCommitIdx] != nil {
351+
event.SHA = gitEvent.Commits[lastCommitIdx].ID
352+
event.SHAURL = gitEvent.Commits[lastCommitIdx].URL
353+
event.SHATitle = gitEvent.Commits[lastCommitIdx].Title
354+
}
303355
event.TriggerTarget = triggertype.Push
304356
default:
305357
return fmt.Errorf("unsupported GitLab event type: %T", gitEvent)
@@ -578,55 +630,95 @@ func (p *GiteaParser) ParsePayload(eventType string, body []byte) (any, error) {
578630
func (p *GiteaParser) PopulateEvent(event *info.Event, parsedEvent any) error {
579631
switch gitEvent := parsedEvent.(type) {
580632
case *giteaStructs.PullRequestPayload:
581-
event.Organization = gitEvent.Repository.Owner.UserName
582-
event.Repository = gitEvent.Repository.Name
583-
event.Sender = gitEvent.Sender.UserName
584-
event.URL = gitEvent.Repository.HTMLURL
585-
event.SHA = gitEvent.PullRequest.Head.Sha
586-
event.SHAURL = fmt.Sprintf("%s/commit/%s", gitEvent.PullRequest.HTMLURL, gitEvent.PullRequest.Head.Sha)
587-
event.HeadBranch = gitEvent.PullRequest.Head.Ref
588-
event.BaseBranch = gitEvent.PullRequest.Base.Ref
589-
event.HeadURL = gitEvent.PullRequest.Head.Repository.HTMLURL
590-
event.BaseURL = gitEvent.PullRequest.Base.Repository.HTMLURL
591-
event.PullRequestNumber = int(gitEvent.Index)
592-
event.PullRequestTitle = gitEvent.PullRequest.Title
593-
event.DefaultBranch = gitEvent.Repository.DefaultBranch
633+
if gitEvent.Repository != nil {
634+
if gitEvent.Repository.Owner != nil {
635+
event.Organization = gitEvent.Repository.Owner.UserName
636+
}
637+
event.Repository = gitEvent.Repository.Name
638+
event.URL = gitEvent.Repository.HTMLURL
639+
event.DefaultBranch = gitEvent.Repository.DefaultBranch
640+
}
641+
if gitEvent.Sender != nil {
642+
event.Sender = gitEvent.Sender.UserName
643+
}
644+
if gitEvent.PullRequest != nil {
645+
if gitEvent.PullRequest.Head != nil {
646+
event.SHA = gitEvent.PullRequest.Head.Sha
647+
if gitEvent.PullRequest.HTMLURL != "" && gitEvent.PullRequest.Head.Sha != "" {
648+
event.SHAURL = fmt.Sprintf("%s/commit/%s", gitEvent.PullRequest.HTMLURL, gitEvent.PullRequest.Head.Sha)
649+
}
650+
event.HeadBranch = gitEvent.PullRequest.Head.Ref
651+
if gitEvent.PullRequest.Head.Repository != nil {
652+
event.HeadURL = gitEvent.PullRequest.Head.Repository.HTMLURL
653+
}
654+
}
655+
if gitEvent.PullRequest.Base != nil {
656+
event.BaseBranch = gitEvent.PullRequest.Base.Ref
657+
if gitEvent.PullRequest.Base.Repository != nil {
658+
event.BaseURL = gitEvent.PullRequest.Base.Repository.HTMLURL
659+
}
660+
}
661+
event.PullRequestNumber = int(gitEvent.Index)
662+
event.PullRequestTitle = gitEvent.PullRequest.Title
663+
for _, label := range gitEvent.PullRequest.Labels {
664+
if label != nil {
665+
event.PullRequestLabel = append(event.PullRequestLabel, label.Name)
666+
}
667+
}
668+
}
594669
event.TriggerTarget = triggertype.PullRequest
595670
if gitEvent.Action == giteaStructs.HookIssueClosed {
596671
event.TriggerTarget = triggertype.PullRequestClosed
597672
}
598-
for _, label := range gitEvent.PullRequest.Labels {
599-
event.PullRequestLabel = append(event.PullRequestLabel, label.Name)
600-
}
601673
case *giteaStructs.PushPayload:
602-
event.Organization = gitEvent.Repo.Owner.UserName
603-
event.Repository = gitEvent.Repo.Name
604-
event.Sender = gitEvent.Sender.UserName
605-
event.URL = gitEvent.Repo.HTMLURL
606-
event.SHA = gitEvent.HeadCommit.ID
607-
if event.SHA == "" {
674+
if gitEvent.Repo != nil {
675+
if gitEvent.Repo.Owner != nil {
676+
event.Organization = gitEvent.Repo.Owner.UserName
677+
}
678+
event.Repository = gitEvent.Repo.Name
679+
event.URL = gitEvent.Repo.HTMLURL
680+
event.HeadURL = gitEvent.Repo.HTMLURL
681+
event.BaseURL = gitEvent.Repo.HTMLURL
682+
event.DefaultBranch = gitEvent.Repo.DefaultBranch
683+
}
684+
if gitEvent.Sender != nil {
685+
event.Sender = gitEvent.Sender.UserName
686+
}
687+
if gitEvent.HeadCommit != nil {
688+
event.SHA = gitEvent.HeadCommit.ID
689+
if event.SHA == "" {
690+
event.SHA = gitEvent.Before
691+
}
692+
event.SHAURL = gitEvent.HeadCommit.URL
693+
event.SHATitle = gitEvent.HeadCommit.Message
694+
} else if gitEvent.Before != "" {
608695
event.SHA = gitEvent.Before
609696
}
610-
event.SHAURL = gitEvent.HeadCommit.URL
611-
event.SHATitle = gitEvent.HeadCommit.Message
612697
event.HeadBranch = gitEvent.Ref
613698
event.BaseBranch = gitEvent.Ref
614-
event.HeadURL = gitEvent.Repo.HTMLURL
615-
event.BaseURL = gitEvent.Repo.HTMLURL
616-
event.DefaultBranch = gitEvent.Repo.DefaultBranch
617699
event.TriggerTarget = triggertype.Push
618700
case *giteaStructs.IssueCommentPayload:
619-
if gitEvent.Issue.PullRequest == nil {
701+
if gitEvent.Issue == nil || gitEvent.Issue.PullRequest == nil {
620702
return fmt.Errorf("issue comment is not from a pull request")
621703
}
622-
event.Organization = gitEvent.Repository.Owner.UserName
623-
event.Repository = gitEvent.Repository.Name
624-
event.Sender = gitEvent.Sender.UserName
625-
event.URL = gitEvent.Repository.HTMLURL
626-
event.DefaultBranch = gitEvent.Repository.DefaultBranch
704+
if gitEvent.Repository != nil {
705+
if gitEvent.Repository.Owner != nil {
706+
event.Organization = gitEvent.Repository.Owner.UserName
707+
}
708+
event.Repository = gitEvent.Repository.Name
709+
event.URL = gitEvent.Repository.HTMLURL
710+
event.DefaultBranch = gitEvent.Repository.DefaultBranch
711+
}
712+
if gitEvent.Sender != nil {
713+
event.Sender = gitEvent.Sender.UserName
714+
}
627715
event.TriggerTarget = triggertype.PullRequest
628-
event.TriggerComment = gitEvent.Comment.Body
629-
event.PullRequestNumber = extractPullRequestNumber(gitEvent.Issue.URL)
716+
if gitEvent.Comment != nil {
717+
event.TriggerComment = gitEvent.Comment.Body
718+
}
719+
if gitEvent.Issue != nil {
720+
event.PullRequestNumber = extractPullRequestNumber(gitEvent.Issue.URL)
721+
}
630722
default:
631723
return fmt.Errorf("unsupported Gitea event type: %T", gitEvent)
632724
}

0 commit comments

Comments
 (0)