Security hardening and performance improvements
- Add visibility check to attachment downloads (prevents unauthorized access) - Fix ticket ID collision with uniqueness verification loop - Harden CSP: replace unsafe-inline with nonce-based script execution - Add IP-based rate limiting (supplements session-based) - Add visibility checks to bulk operations - Validate internal visibility requires groups - Optimize user activity query (JOINs vs subqueries) - Update documentation with design decisions and security info Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -41,26 +41,42 @@ try {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Verify the associated ticket exists (access control)
|
||||
// Verify the associated ticket exists and user has access
|
||||
$conn = new mysqli(
|
||||
$GLOBALS['config']['DB_HOST'],
|
||||
$GLOBALS['config']['DB_USER'],
|
||||
$GLOBALS['config']['DB_PASS'],
|
||||
$GLOBALS['config']['DB_NAME']
|
||||
);
|
||||
if (!$conn->connect_error) {
|
||||
$ticketModel = new TicketModel($conn);
|
||||
$ticket = $ticketModel->getTicketById($attachment['ticket_id']);
|
||||
$conn->close();
|
||||
|
||||
if (!$ticket) {
|
||||
http_response_code(404);
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['success' => false, 'error' => 'Associated ticket not found']);
|
||||
exit;
|
||||
}
|
||||
if ($conn->connect_error) {
|
||||
http_response_code(500);
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['success' => false, 'error' => 'Database connection failed']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$ticketModel = new TicketModel($conn);
|
||||
$ticket = $ticketModel->getTicketById($attachment['ticket_id']);
|
||||
|
||||
if (!$ticket) {
|
||||
$conn->close();
|
||||
http_response_code(404);
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['success' => false, 'error' => 'Associated ticket not found']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Check if user has access to this ticket based on visibility settings
|
||||
if (!$ticketModel->canUserAccessTicket($ticket, $_SESSION['user'])) {
|
||||
$conn->close();
|
||||
http_response_code(403);
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['success' => false, 'error' => 'Access denied to this ticket']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$conn->close();
|
||||
|
||||
// Build file path
|
||||
$uploadDir = $GLOBALS['config']['UPLOAD_DIR'] ?? dirname(__DIR__) . '/uploads';
|
||||
$filePath = $uploadDir . '/' . $attachment['ticket_id'] . '/' . $attachment['filename'];
|
||||
|
||||
Reference in New Issue
Block a user