TicketModel: visibility-filter group matching disagrees with single-ticket access check #28

Closed
opened 2026-08-31 21:29:39 -04:00 by jared · 1 comment
Owner

Severity: High

models/TicketModel.php has two different code paths for group-based internal-ticket visibility that don't agree:

  • getVisibilityFilter() (~line 728, used for dashboard list/stats queries) matches via FIND_IN_SET(?, REPLACE(t.visibility_groups, ' ', '')) — strips spaces from the column but not from the bound $group parameter.
  • canUserAccessTicket() (~lines 678-685, used for single-ticket access checks) does plain explode(',', ...) + trim() per element, with no space-stripping at all.

Impact: For a group name containing a space (e.g. an LLDAP group named "IT Support"), a member of that group can open an internal ticket directly by ID/URL (canUserAccessTicket → true) but the same ticket never appears in their dashboard list or stats counts (getVisibilityFilter → false, since "IT Support" never matches the space-stripped column value). Data is invisible-to-browse but directly reachable — a visibility/access-control inconsistency.

Fix: Make both paths use the same normalization (either strip spaces from both sides consistently, or don't strip at all and require exact group-name matches).

**Severity:** High `models/TicketModel.php` has two different code paths for group-based internal-ticket visibility that don't agree: - `getVisibilityFilter()` (~line 728, used for dashboard list/stats queries) matches via `FIND_IN_SET(?, REPLACE(t.visibility_groups, ' ', ''))` — strips spaces from the **column** but not from the bound `$group` parameter. - `canUserAccessTicket()` (~lines 678-685, used for single-ticket access checks) does plain `explode(',', ...)` + `trim()` per element, with no space-stripping at all. **Impact:** For a group name containing a space (e.g. an LLDAP group named `"IT Support"`), a member of that group can open an internal ticket directly by ID/URL (`canUserAccessTicket` → true) but the same ticket never appears in their dashboard list or stats counts (`getVisibilityFilter` → false, since `"IT Support"` never matches the space-stripped column value). Data is invisible-to-browse but directly reachable — a visibility/access-control inconsistency. **Fix:** Make both paths use the same normalization (either strip spaces from both sides consistently, or don't strip at all and require exact group-name matches).
jared added the data-integritypriority/highsecurity labels 2026-09-08 10:15:43 -04:00
Author
Owner

Fixed and verified against real MariaDB (schema/migration/access-control cases). Merged to main in commit 3664719.

Fixed and verified against real MariaDB (schema/migration/access-control cases). Merged to main in commit 3664719.
jared closed this issue 2026-09-08 21:33:42 -04:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: LotusGuild/tinker_tickets#28