From 5fa837fb0309a939a4b80925183fbee0486c5e1d Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Tue, 16 Jun 2026 13:44:59 +0300 Subject: [PATCH] fix(iot-hub): restrict installed-items list sort property to a server-side allow-list Unvalidated sortProperty on GET /api/iot-hub/installedItems was passed straight into Spring Data's Sort.by, so a client could trigger a 500 PropertyReferenceException by naming an unknown entity field. Add ALLOWED_SORT_PROPERTIES on IotHubInstalledItemEntity (createdTime, itemName, itemType, version) and call validatePageLink in the service so the failure is a 400 with a clear message. --- .../dao/iot_hub/IotHubInstalledItemServiceImpl.java | 4 ++++ .../server/dao/model/sql/IotHubInstalledItemEntity.java | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/dao/src/main/java/org/thingsboard/server/dao/iot_hub/IotHubInstalledItemServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/iot_hub/IotHubInstalledItemServiceImpl.java index d89c21f548..7e86bcb0b9 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/iot_hub/IotHubInstalledItemServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/iot_hub/IotHubInstalledItemServiceImpl.java @@ -23,12 +23,15 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.iot_hub.IotHubInstalledItem; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; +import org.thingsboard.server.dao.model.sql.IotHubInstalledItemEntity; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.UUID; +import static org.thingsboard.server.dao.service.Validator.validatePageLink; + @Service @RequiredArgsConstructor @Slf4j @@ -49,6 +52,7 @@ class IotHubInstalledItemServiceImpl implements IotHubInstalledItemService { @Override public PageData findByTenantId(TenantId tenantId, List itemTypes, UUID itemId, PageLink pageLink) { + validatePageLink(pageLink, IotHubInstalledItemEntity.ALLOWED_SORT_PROPERTIES); return iotHubInstalledItemDao.findByTenantId(tenantId, itemTypes, itemId, pageLink); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/IotHubInstalledItemEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/IotHubInstalledItemEntity.java index e0cd2f1c17..118a175a36 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/IotHubInstalledItemEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/IotHubInstalledItemEntity.java @@ -31,7 +31,11 @@ import org.thingsboard.server.common.data.iot_hub.IotHubInstalledItemDescriptor; import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.List; import java.util.Objects; +import java.util.Set; import java.util.UUID; @Getter @@ -41,6 +45,10 @@ import java.util.UUID; @Table(name = ModelConstants.IOT_HUB_INSTALLED_ITEM_TABLE_NAME) public class IotHubInstalledItemEntity extends BaseSqlEntity { + public static final Set ALLOWED_SORT_PROPERTIES = Collections.unmodifiableSet( + new LinkedHashSet<>(List.of("createdTime", "itemName", "itemType", "version")) + ); + @Column(name = ModelConstants.IOT_HUB_INSTALLED_ITEM_TENANT_ID_COLUMN, nullable = false, columnDefinition = "UUID") private UUID tenantId;