CVE-2026-109393 Overview
CVE-2026-109393 is an Insecure Direct Object Reference (IDOR) vulnerability [CWE-639] in QloApps through version 1.7.0. The flaw resides in back-office AJAX handlers within AdminOrdersController, AdminBookingDocumentController, AdminProductsController, and AdminAddHotelController. These handlers skip htl_access hotel permission checks before processing sequential identifiers supplied by the client. Hotel-restricted employees can submit identifiers belonging to other hotels to read, upload, and delete booking documents, and delete rooms, room images, and hotel images outside their assigned scope.
Critical Impact
Authenticated back-office employees with hotel-scoped roles can escalate access horizontally across tenants, exposing booking documents and destroying inventory data belonging to other hotels.
Affected Products
- QloApps versions up to and including 1.7.0
- QloApps back-office AdminOrdersController and AdminBookingDocumentController
- QloApps back-office AdminProductsController and AdminAddHotelController
Discovery Timeline
- 2026-10-12 - CVE-2026-109393 published to NVD
- 2026-10-12 - Last updated in NVD database
Technical Details for CVE-2026-109393
Vulnerability Analysis
QloApps implements multi-tenant hotel administration where employee profiles are restricted to specific hotels through the htl_access scoping mechanism. Several AJAX endpoints in the back-office controllers accept object identifiers directly from request parameters such as id_htl_booking, id_image, id_room, and id_hotel. The handlers load the referenced object and perform the requested action without verifying that the current employee's profile has access to the hotel that owns the object. The vulnerability is classified as an Insecure Direct Object Reference [CWE-639].
Root Cause
The root cause is a missing authorization check between object loading and action execution. Code paths validate that the identifier resolves to a loaded object using Validate::isLoadedObject() but do not call HotelBranchInformation::getProfileAccessedHotels() to confirm the object belongs to a hotel the employee can administer. Sequential, predictable primary keys make target enumeration straightforward.
Attack Vector
An authenticated back-office employee with access to at least one hotel sends AJAX requests to the vulnerable controllers while substituting another hotel's object identifier. The server returns, modifies, or deletes the targeted resource. Impacted actions include reading rendered booking documents, uploading or deleting booking documents, and deleting product images, room images, and hotel images.
// Patched check in AdminOrdersController.php (Booking Documents AJAX)
$idHtlBooking = (int) Tools::getValue('id_htl_booking');
$objHotelBookingDetail = new HotelBookingDetail($idHtlBooking);
if (Validate::isLoadedObject($objHotelBookingDetail)
&& in_array(
$objHotelBookingDetail->id_hotel,
(array) HotelBranchInformation::getProfileAccessedHotels(
$this->context->employee->id_profile, 1, 1
)
)
) {
$response['html'] = $this->getRenderedBookingDocuments($idHtlBooking);
$response['status'] = true;
}
// Source: https://github.com/Qloapps/QloApps/commit/83eb851cf106b51a4478f84a6d1658d7c8076258
The patch adds an in_array() check that compares the booking's id_hotel against the employee's accessible hotels. A parallel fix in AdminProductsController.php resolves the product's room type to its owning hotel and denies deletion when the hotel is outside the employee's scope.
// Patched image-delete check in AdminProductsController.php
$image = new Image((int)Tools::getValue('id_image'));
$objRoomType = new HotelRoomType();
$roomTypeInfo = Validate::isLoadedObject($image)
? $objRoomType->getRoomTypeInfoByIdProduct($image->id_product)
: false;
if (!$roomTypeInfo
|| !in_array(
$roomTypeInfo['id_hotel'],
(array) HotelBranchInformation::getProfileAccessedHotels(
$this->context->employee->id_profile, 1, 1
)
)) {
return die(json_encode(array('error' => $this->l('You do not have the right permission'))));
}
// Source: https://github.com/Qloapps/QloApps/commit/83eb851cf106b51a4478f84a6d1658d7c8076258
Detect Identity Attacks the Moment Authentication Fails
Singularity™ Identity surfaces credential misuse, lateral movement, and privilege escalation in real time, so you can contain the breach before it spreads.
Stop Identity AttacksDetection Methods for CVE-2026-109393
Indicators of Compromise
- Back-office AJAX requests to AdminOrdersController, AdminBookingDocumentController, AdminProductsController, or AdminAddHotelController containing id_htl_booking, id_image, id_room, or id_hotel values that reference hotels outside the employee's htl_access scope.
- Unexpected deletion events for room records, room images, or hotel images attributed to employees without administrative rights over the target hotel.
- Spikes in booking-document download or upload actions originating from a single employee session across multiple hotel identifiers.
Detection Strategies
- Enable PHP and web server access logging on QloApps and correlate AJAX endpoint hits with the authenticated employee's assigned hotels.
- Baseline per-employee ranges of id_hotel, id_room, and id_htl_booking values and alert on identifiers outside that baseline.
- Review database audit trails for deletions of hotel_image, room_image, and htl_booking_document records that were not initiated by a hotel-privileged account.
Monitoring Recommendations
- Forward QloApps application logs to a centralized log platform and build queries for the four affected controllers.
- Alert on repeated error responses from the patched handlers containing the string You do not have the right permission, which indicates attempted cross-tenant access post-patch.
- Monitor file system changes under booking document upload directories for writes attributed to unexpected employee IDs.
How to Mitigate CVE-2026-109393
Immediate Actions Required
- Upgrade QloApps to a release that includes commit 83eb851cf106b51a4478f84a6d1658d7c8076258 from the QloApps Pull Request #1922.
- Audit employee profiles and remove unused hotel-restricted accounts to limit the authenticated attack surface.
- Review historical back-office activity for suspicious cross-hotel AJAX requests and preserve logs for incident response.
Patch Information
The fix is published in the upstream repository as commit 83eb851 with the message "Fixed: Security and Access related bugs." Review the QloApps Security Commit and the merged QloApps Pull Request #1922 for the full diff. The VulnCheck Advisory on QloApps documents the affected handlers.
Workarounds
- Restrict back-office access to trusted administrators until the patch is applied, reducing exposure from hotel-scoped accounts.
- Place the QloApps back-office behind a web application firewall rule that validates id_hotel, id_htl_booking, and related parameters against the authenticated session's permitted hotel list.
- Disable or network-restrict the vulnerable AJAX endpoints if administrative use of booking document and image management can be deferred.
# Apply the upstream security fix on an existing QloApps 1.7.0 checkout
cd /var/www/qloapps
git fetch origin
git cherry-pick 83eb851cf106b51a4478f84a6d1658d7c8076258
php bin/console cache:clear || rm -rf var/cache/*
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

