AuditLogModel::getTicketTimeline() requires, for entity_type='comment' rows, that JSON_EXTRACT(details, '$.ticket_id') match the ticket being viewed. logCommentCreate() and the delete-comment audit log call (api/delete_comment.php) both correctly include ticket_id in details. But api/update_comment.php's log call only sets ['comment_text_preview' => ...] — no ticket_id.
Impact: The audit row is written fine (so it shows up in the admin's global Audit Log browser, filterable by entity_type=comment), but getTicketTimeline()'s join condition never matches it, so a comment edit is silently invisible in the ticket page's own timeline — a real accountability gap. A user can edit a comment's content and the ticket's own history shows no trace, while deleting the same comment WOULD be visible on the timeline.
Fix: Add 'ticket_id' => $comment['ticket_id'] to the details array in update_comment.php's audit log call — the endpoint already loads $comment earlier in the file for the access check, so ticket_id is already available at that point.
**Severity:** Medium
`AuditLogModel::getTicketTimeline()` requires, for `entity_type='comment'` rows, that `JSON_EXTRACT(details, '$.ticket_id')` match the ticket being viewed. `logCommentCreate()` and the delete-comment audit log call (`api/delete_comment.php`) both correctly include `ticket_id` in `details`. But `api/update_comment.php`'s log call only sets `['comment_text_preview' => ...]` — **no `ticket_id`**.
**Impact:** The audit row is written fine (so it shows up in the admin's global Audit Log browser, filterable by `entity_type=comment`), but `getTicketTimeline()`'s join condition never matches it, so a comment edit is silently invisible in the ticket page's own timeline — a real accountability gap. A user can edit a comment's content and the ticket's own history shows no trace, while deleting the same comment WOULD be visible on the timeline.
**Fix:** Add `'ticket_id' => $comment['ticket_id']` to the details array in `update_comment.php`'s audit log call — the endpoint already loads `$comment` earlier in the file for the access check, so `ticket_id` is already available at that point.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Severity: Medium
AuditLogModel::getTicketTimeline()requires, forentity_type='comment'rows, thatJSON_EXTRACT(details, '$.ticket_id')match the ticket being viewed.logCommentCreate()and the delete-comment audit log call (api/delete_comment.php) both correctly includeticket_idindetails. Butapi/update_comment.php's log call only sets['comment_text_preview' => ...]— noticket_id.Impact: The audit row is written fine (so it shows up in the admin's global Audit Log browser, filterable by
entity_type=comment), butgetTicketTimeline()'s join condition never matches it, so a comment edit is silently invisible in the ticket page's own timeline — a real accountability gap. A user can edit a comment's content and the ticket's own history shows no trace, while deleting the same comment WOULD be visible on the timeline.Fix: Add
'ticket_id' => $comment['ticket_id']to the details array inupdate_comment.php's audit log call — the endpoint already loads$commentearlier in the file for the access check, soticket_idis already available at that point.