Skip to content

Commit 94c61b3

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 94c61b3

File tree

2 files changed

+629
-91
lines changed

2 files changed

+629
-91
lines changed

pkg/cmd/tknpac/cel/parser.go

Lines changed: 181 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -136,58 +136,103 @@ 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()
146+
}
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+
}
155171
}
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+
issue := gitEvent.GetIssue()
200+
if issue == nil || issue.GetPullRequestLinks() == nil {
172201
return fmt.Errorf("issue comment is not from a pull request")
173202
}
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()
203+
if repo := gitEvent.GetRepo(); repo != nil {
204+
if owner := repo.GetOwner(); owner != nil {
205+
event.Organization = owner.GetLogin()
206+
}
207+
event.Repository = repo.GetName()
208+
event.URL = repo.GetHTMLURL()
209+
event.DefaultBranch = repo.GetDefaultBranch()
210+
}
211+
if sender := gitEvent.GetSender(); sender != nil {
212+
event.Sender = sender.GetLogin()
213+
}
179214
event.TriggerTarget = triggertype.PullRequest
180-
event.TriggerComment = gitEvent.GetComment().GetBody()
181-
event.PullRequestNumber = gitEvent.GetIssue().GetNumber()
215+
if comment := gitEvent.GetComment(); comment != nil {
216+
event.TriggerComment = comment.GetBody()
217+
}
218+
event.PullRequestNumber = issue.GetNumber()
182219
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()
220+
if repo := gitEvent.GetRepo(); repo != nil {
221+
if owner := repo.GetOwner(); owner != nil {
222+
event.Organization = owner.GetLogin()
223+
}
224+
event.Repository = repo.GetName()
225+
event.URL = repo.GetHTMLURL()
226+
event.DefaultBranch = repo.GetDefaultBranch()
227+
}
228+
if comment := gitEvent.GetComment(); comment != nil {
229+
event.SHA = comment.GetCommitID()
230+
event.TriggerComment = comment.GetBody()
231+
}
232+
if sender := gitEvent.GetSender(); sender != nil {
233+
event.Sender = sender.GetLogin()
234+
}
189235
event.TriggerTarget = triggertype.Push
190-
event.TriggerComment = gitEvent.GetComment().GetBody()
191236
default:
192237
return fmt.Errorf("unsupported GitHub event type: %T", gitEvent)
193238
}
@@ -242,8 +287,11 @@ func (p *GitLabParser) PopulateEvent(event *info.Event, parsedEvent any) error {
242287
case *gitlab.MergeEvent:
243288
event.Organization = extractOrgFromPath(gitEvent.Project.PathWithNamespace)
244289
event.Repository = extractRepoFromPath(gitEvent.Project.PathWithNamespace)
245-
event.Sender = gitEvent.User.Username
246290
event.URL = gitEvent.Project.WebURL
291+
event.DefaultBranch = gitEvent.Project.DefaultBranch
292+
if gitEvent.User != nil {
293+
event.Sender = gitEvent.User.Username
294+
}
247295
event.SHA = gitEvent.ObjectAttributes.LastCommit.ID
248296
event.SHAURL = gitEvent.ObjectAttributes.LastCommit.URL
249297
event.SHATitle = gitEvent.ObjectAttributes.LastCommit.Title
@@ -257,7 +305,6 @@ func (p *GitLabParser) PopulateEvent(event *info.Event, parsedEvent any) error {
257305
}
258306
event.PullRequestNumber = gitEvent.ObjectAttributes.IID
259307
event.PullRequestTitle = gitEvent.ObjectAttributes.Title
260-
event.DefaultBranch = gitEvent.Project.DefaultBranch
261308
event.TriggerTarget = triggertype.PullRequest
262309
if gitEvent.ObjectAttributes.Action == "close" {
263310
event.TriggerTarget = triggertype.PullRequestClosed
@@ -272,34 +319,38 @@ func (p *GitLabParser) PopulateEvent(event *info.Event, parsedEvent any) error {
272319
lastCommitIdx := len(gitEvent.Commits) - 1
273320
event.Organization = extractOrgFromPath(gitEvent.Project.PathWithNamespace)
274321
event.Repository = extractRepoFromPath(gitEvent.Project.PathWithNamespace)
275-
event.Sender = gitEvent.UserUsername
276322
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
282323
event.HeadURL = gitEvent.Project.WebURL
283324
event.BaseURL = gitEvent.Project.WebURL
284325
event.DefaultBranch = gitEvent.Project.DefaultBranch
326+
event.Sender = gitEvent.UserUsername
327+
if gitEvent.Commits[lastCommitIdx] != nil {
328+
event.SHA = gitEvent.Commits[lastCommitIdx].ID
329+
event.SHAURL = gitEvent.Commits[lastCommitIdx].URL
330+
event.SHATitle = gitEvent.Commits[lastCommitIdx].Title
331+
}
332+
event.HeadBranch = gitEvent.Ref
333+
event.BaseBranch = gitEvent.Ref
285334
event.TriggerTarget = triggertype.Push
286335
case *gitlab.TagEvent:
287336
if len(gitEvent.Commits) == 0 {
288337
return fmt.Errorf("no commits attached to this tag event")
289338
}
290339
lastCommitIdx := len(gitEvent.Commits) - 1
340+
event.Sender = gitEvent.UserUsername
291341
event.Organization = extractOrgFromPath(gitEvent.Project.PathWithNamespace)
292342
event.Repository = extractRepoFromPath(gitEvent.Project.PathWithNamespace)
293-
event.Sender = gitEvent.UserUsername
343+
event.DefaultBranch = gitEvent.Project.DefaultBranch
294344
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
300345
event.HeadURL = gitEvent.Project.WebURL
301346
event.BaseURL = gitEvent.Project.WebURL
302-
event.DefaultBranch = gitEvent.Project.DefaultBranch
347+
event.HeadBranch = gitEvent.Ref
348+
event.BaseBranch = gitEvent.Ref
349+
if gitEvent.Commits[lastCommitIdx] != nil {
350+
event.SHA = gitEvent.Commits[lastCommitIdx].ID
351+
event.SHAURL = gitEvent.Commits[lastCommitIdx].URL
352+
event.SHATitle = gitEvent.Commits[lastCommitIdx].Title
353+
}
303354
event.TriggerTarget = triggertype.Push
304355
default:
305356
return fmt.Errorf("unsupported GitLab event type: %T", gitEvent)
@@ -578,55 +629,94 @@ func (p *GiteaParser) ParsePayload(eventType string, body []byte) (any, error) {
578629
func (p *GiteaParser) PopulateEvent(event *info.Event, parsedEvent any) error {
579630
switch gitEvent := parsedEvent.(type) {
580631
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
632+
if gitEvent.Repository != nil {
633+
if gitEvent.Repository.Owner != nil {
634+
event.Organization = gitEvent.Repository.Owner.UserName
635+
}
636+
event.Repository = gitEvent.Repository.Name
637+
event.URL = gitEvent.Repository.HTMLURL
638+
event.DefaultBranch = gitEvent.Repository.DefaultBranch
639+
}
640+
if gitEvent.Sender != nil {
641+
event.Sender = gitEvent.Sender.UserName
642+
}
643+
if gitEvent.PullRequest != nil {
644+
if gitEvent.PullRequest.Head != nil {
645+
event.SHA = gitEvent.PullRequest.Head.Sha
646+
if gitEvent.PullRequest.HTMLURL != "" && gitEvent.PullRequest.Head.Sha != "" {
647+
event.SHAURL = fmt.Sprintf("%s/commit/%s", gitEvent.PullRequest.HTMLURL, gitEvent.PullRequest.Head.Sha)
648+
}
649+
event.HeadBranch = gitEvent.PullRequest.Head.Ref
650+
if gitEvent.PullRequest.Head.Repository != nil {
651+
event.HeadURL = gitEvent.PullRequest.Head.Repository.HTMLURL
652+
}
653+
}
654+
if gitEvent.PullRequest.Base != nil {
655+
event.BaseBranch = gitEvent.PullRequest.Base.Ref
656+
if gitEvent.PullRequest.Base.Repository != nil {
657+
event.BaseURL = gitEvent.PullRequest.Base.Repository.HTMLURL
658+
}
659+
}
660+
event.PullRequestNumber = int(gitEvent.Index)
661+
event.PullRequestTitle = gitEvent.PullRequest.Title
662+
for _, label := range gitEvent.PullRequest.Labels {
663+
if label != nil {
664+
event.PullRequestLabel = append(event.PullRequestLabel, label.Name)
665+
}
666+
}
667+
}
594668
event.TriggerTarget = triggertype.PullRequest
595669
if gitEvent.Action == giteaStructs.HookIssueClosed {
596670
event.TriggerTarget = triggertype.PullRequestClosed
597671
}
598-
for _, label := range gitEvent.PullRequest.Labels {
599-
event.PullRequestLabel = append(event.PullRequestLabel, label.Name)
600-
}
601672
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 == "" {
673+
if gitEvent.Repo != nil {
674+
if gitEvent.Repo.Owner != nil {
675+
event.Organization = gitEvent.Repo.Owner.UserName
676+
}
677+
event.Repository = gitEvent.Repo.Name
678+
event.URL = gitEvent.Repo.HTMLURL
679+
event.HeadURL = gitEvent.Repo.HTMLURL
680+
event.BaseURL = gitEvent.Repo.HTMLURL
681+
event.DefaultBranch = gitEvent.Repo.DefaultBranch
682+
}
683+
if gitEvent.Sender != nil {
684+
event.Sender = gitEvent.Sender.UserName
685+
}
686+
if gitEvent.HeadCommit != nil {
687+
event.SHA = gitEvent.HeadCommit.ID
688+
if event.SHA == "" {
689+
event.SHA = gitEvent.Before
690+
}
691+
event.SHAURL = gitEvent.HeadCommit.URL
692+
event.SHATitle = gitEvent.HeadCommit.Message
693+
} else if gitEvent.Before != "" {
608694
event.SHA = gitEvent.Before
609695
}
610-
event.SHAURL = gitEvent.HeadCommit.URL
611-
event.SHATitle = gitEvent.HeadCommit.Message
612696
event.HeadBranch = gitEvent.Ref
613697
event.BaseBranch = gitEvent.Ref
614-
event.HeadURL = gitEvent.Repo.HTMLURL
615-
event.BaseURL = gitEvent.Repo.HTMLURL
616-
event.DefaultBranch = gitEvent.Repo.DefaultBranch
617698
event.TriggerTarget = triggertype.Push
618699
case *giteaStructs.IssueCommentPayload:
619-
if gitEvent.Issue.PullRequest == nil {
700+
issue := gitEvent.Issue
701+
if issue == nil || 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+
event.PullRequestNumber = extractPullRequestNumber(issue.URL)
630720
default:
631721
return fmt.Errorf("unsupported Gitea event type: %T", gitEvent)
632722
}

0 commit comments

Comments
 (0)