From 55c2d5c596346cac640e0bcba8b544317682b422 Mon Sep 17 00:00:00 2001 From: Jared Vititoe Date: Sat, 11 Apr 2026 14:29:09 -0400 Subject: [PATCH] Fix visibility bypass in export and insecure cookie in preferences MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit api/export_tickets.php: getAllTickets() was called without $currentUser, so visibility filtering was skipped — any authenticated user could export all tickets including confidential/internal ones. api/user_preferences.php: the single-preference setcookie() call was missing httponly/secure flags (batch path had them correctly). Also cast preference values to string before passing to setPreference(string). Co-Authored-By: Claude Sonnet 4.6 --- api/export_tickets.php | 4 ++-- api/user_preferences.php | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/api/export_tickets.php b/api/export_tickets.php index e6eec31..3c6d14a 100644 --- a/api/export_tickets.php +++ b/api/export_tickets.php @@ -72,8 +72,8 @@ try { } } else { // Get all tickets with filters (no pagination for export) - // getAllTickets already applies visibility filtering via getVisibilityFilter - $result = $ticketModel->getAllTickets(1, 10000, $status, 'created_at', 'desc', $category, $type, $search); + // Pass $currentUser so visibility filtering is applied correctly + $result = $ticketModel->getAllTickets(1, 10000, $status, 'created_at', 'desc', $category, $type, $search, [], $currentUser); $tickets = $result['tickets']; } diff --git a/api/user_preferences.php b/api/user_preferences.php index 8b0d362..d807d13 100644 --- a/api/user_preferences.php +++ b/api/user_preferences.php @@ -43,7 +43,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { foreach ($data['preferences'] as $key => $value) { $key = trim($key); if (!in_array($key, $validKeys)) continue; - $prefsModel->setPreference($userId, $key, $value); + $prefsModel->setPreference($userId, $key, (string)$value); if ($key === 'rows_per_page') { setcookie('ticketsPerPage', $value, ['expires' => time() + (86400 * 365), 'path' => '/', 'httponly' => true, 'secure' => true, 'samesite' => 'Lax']); } @@ -73,11 +73,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { } try { - $success = $prefsModel->setPreference($userId, $key, $value); + $success = $prefsModel->setPreference($userId, $key, (string)$value); // Also update cookie for rows_per_page for backwards compatibility if ($key === 'rows_per_page') { - setcookie('ticketsPerPage', $value, time() + (86400 * 365), '/'); + setcookie('ticketsPerPage', (string)$value, ['expires' => time() + (86400 * 365), 'path' => '/', 'httponly' => true, 'secure' => true, 'samesite' => 'Lax']); } apiRespond(['success' => $success]);