Skip to content

Security: Systemic missing authorization — cross-team ticket/lead manipulation + hardcoded API token #825

@lighthousekeeper1212

Description

@lighthousekeeper1212

Summary

A security audit identified 16 authorization vulnerabilities (5 Critical, 9 High, 2 Medium) allowing cross-team data access and manipulation.

Root Cause: 1-of-N Authorization Inconsistency

Controllers that use $this->authorize() on show() skip it on update(), reopen(), destroy(). Assignment to team is authorized, but assignment to user is not.

Critical Findings

1. Ticket Update Missing Authorization (CRITICAL)

TicketsController.php:62-76show() calls $this->authorize('view', $ticket), but update() does NOT. Any authenticated user can modify any ticket's requester, priority, type, subject, and summary.

2. Ticket User Assignment Missing Auth (CRITICAL)

TicketsAssignController.php:15 — Team assignment checks $this->authorize('assignToTeam', $ticket), but user assignment has NO check. Any user can reassign any ticket to any user. 1-of-N inconsistency: team assignment IS checked, user assignment is NOT.

3. Lead Update — Mass Assignment + No Auth (CRITICAL)

LeadsController.php:25-30:

public function update(Lead $lead) {
    $lead->update(request()->all());
}

No authorization. Combined with BaseModel having $guarded = [], any user can overwrite ALL lead columns including user_id and team_id, effectively stealing leads.

4. Team Edit/Update/Delete Missing Auth (CRITICAL)

TeamsController.php:35-59store() correctly calls $this->authorize('create', Team::class), but edit(), update(), and destroy() have NO authorization. Routes are outside the can:see-admin middleware group. Any agent can modify or delete any team. Note: update() regenerates the team token on every call, breaking existing invite links.

5. Default Hardcoded API Token (CRITICAL)

config/handesk.php:4:

'api_token' => env('API_TOKEN', 'the-api-token'),

Deployments not explicitly setting API_TOKEN are completely open. The API allows creating users, teams, viewing any ticket, and modifying ticket status. User listing also leaks per-agent token fields enabling agent impersonation.

Additional HIGH Findings

  • Ticket reopen (TicketsController:55) — no auth, any user reopens any ticket
  • Ticket escalate/de-escalate (TicketsEscalateController:9) — no auth
  • Ticket tags (TicketsTagsController:9) — no auth
  • Lead assign user (LeadAssignController:15) — same team-vs-user inconsistency
  • Lead tags (LeadTagsController:9) — no auth
  • Lead tasks (LeadTasksController:9) — no auth on view/create + mass assignment
  • Task update/delete (TasksController:18) — cross-user IDOR (list is scoped, CRUD is not)
  • Attachment download (AttachmentsController:11) — no ownership check, any user downloads any file
  • API user creation (Api/UsersController:20) — no admin check, bypasses web admin requirement

Recommended Fixes

  1. Add $this->authorize() calls to all controller methods, not just show()
  2. Set $guarded on BaseModel to protect sensitive fields (user_id, team_id, etc.)
  3. Change default API token to a random string or require explicit configuration
  4. Move team routes inside the can:see-admin middleware group
  5. Add ownership checks to assignment endpoints

Disclosure

Filed in good faith to improve security. No exploit code provided.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions