Repository navigation
Check access to the escalated item before escalating - #46
Merged
Merged
Conversation
The escalation form and modal only checked the global assign right, so a user could escalate a ticket, change or problem of an entity they have no access to. Escalation also relied on the generic CommonDBTM rights: its table has no entity, so the API let any ticket holder create, list, edit or delete escalations of any entity. As it has `is_private` and `users_id` fields, the core also granted every right to the author of a private one. - Escalation::canEscalate(): escalation enabled, item visible (which checks its entity) and assignable; used by the form, the modal, the button and canCreateItem() - front/escalation.form.php goes through Escalation::check(CREATE) - reading, editing and deleting escalations on their own is refused: they are only shown in the timeline of their item - maybePrivate() is false: `is_private` means internal, not personal - prepareInputForAdd() refuses items of entities where escalation is not enabled; the rights of the user are not checked there, business rules escalate whatever the user who triggers them
Lainow
requested review from
a team,
Mary-Clb,
jdurand-teclib and
stonebuzz
and removed request for
a team
November 5, 2026 15:21
stonebuzz
previously approved these changes
Nov 5, 2026
| return $item instanceof CommonITILObject && self::canEscalate($item); | ||
| } | ||
|
|
||
| public function canViewItem(): bool |
Contributor
There was a problem hiding this comment.
canViewItem() is never reached in production: canView() returns false so can($id, READ) short-circuits, and the timeline uses getEscalationsOf(), which duplicates the private rule (SEEPRIVATE) on its own.
Only the tests call it, so the two privacy rules can drift; either drop it or make it the single source of the rule.
Contributor
Author
There was a problem hiding this comment.
Done, i've deleted canViewItem()
It was never reached: canView() is false, so can($id, READ) stops there, and the timeline applies the private rule through getEscalationsOf().
stonebuzz
approved these changes
Nov 5, 2026
stonebuzz
requested review from
Rom1-B
and removed request for
Mary-Clb and
jdurand-teclib
November 6, 2026 07:12
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The escalation form (
front/escalation.form.php) and its modal (ajax/escalation_form.php) only checkedcanAssign(), a global profile right: a user allowed to assign items in one entity could escalate any ticket, change or problem of another entity by its id. The comment was then added to its timeline, its assigned groups replaced and, depending on the configuration, its technicians removed and its status changed.Escalationalso relied on the genericCommonDBTMrights with$rightname = 'ticket'. Its table has noentities_id, so through the legacy API any user with the ticket right could create escalations on items of any entity (even where escalation is disabled), list every escalation (private ones included), and edit or delete them. As the table hasis_privateandusers_id,CommonDBTM::can()also granted every right, creation included, to the author of a private escalation.Changes
Escalation::canEscalate(): escalation enabled for the item entity, item visible to the user (can($id, READ), which checks its entity) and assignable. Used by the form, the modal, the "Escalate" button andcanCreateItem().Escalation::check(-1, CREATE), the same check as the API.canView()/canUpdate()/canDelete()/canPurge()are false, as forGroup_Link): they are only shown in the timeline of their item, which reads them directly.canViewItem()still tells whether the item, and the private followups for a private one, can be seen.maybePrivate()is false:is_privatemeans internal, not personal.prepareInputForAdd()refuses items of entities where escalation is not enabled. The rights of the user are deliberately not checked there: business rules (EscalationRule) escalate items whatever the user who triggers them, e.g. the mail collector.Tests
New tests in
EscalationTest, for tickets, changes and problems: