From 808ef2534e325c4c01863fdb47efbe5e6c62e53d Mon Sep 17 00:00:00 2001 From: kolaente Date: Wed, 3 Jun 2026 20:27:05 +0200 Subject: [PATCH] fix(task-comments): derive update event doer from authenticated user TaskComment.Update used tc.Author as the TaskCommentUpdatedEvent doer, but that field is bound from the request body. A client could omit it (nil doer, breaking the event) or spoof another user. Resolve the doer from the session auth via GetUserOrLinkShareUser instead, mirroring Create and Delete. CanUpdate already guarantees the authenticated user is the comment's author, so this is both correct and consistent. Affects v1 and v2, which share the model. --- pkg/models/task_comments.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/pkg/models/task_comments.go b/pkg/models/task_comments.go index 5ad811073..a61356404 100644 --- a/pkg/models/task_comments.go +++ b/pkg/models/task_comments.go @@ -167,7 +167,7 @@ func (tc *TaskComment) Delete(s *xorm.Session, a web.Auth) error { // @Failure 404 {object} web.HTTPError "The task comment was not found." // @Failure 500 {object} models.Message "Internal error" // @Router /tasks/{taskID}/comments/{commentID} [post] -func (tc *TaskComment) Update(s *xorm.Session, _ web.Auth) error { +func (tc *TaskComment) Update(s *xorm.Session, a web.Auth) error { updated, err := s. ID(tc.ID). Cols("comment"). @@ -185,10 +185,19 @@ func (tc *TaskComment) Update(s *xorm.Session, _ web.Auth) error { return err } + // The doer must come from the authenticated user, not from the request + // body: tc.Author is bound from the payload and could be omitted (nil) or + // spoofed. CanUpdate already guarantees the authenticated user is the + // comment's author, so resolving the doer from the session is correct. + doer, err := GetUserOrLinkShareUser(s, a) + if err != nil { + return err + } + events.DispatchOnCommit(s, &TaskCommentUpdatedEvent{ Task: &task, Comment: tc, - Doer: tc.Author, + Doer: doer, }) return nil }