{"id":"GHSA-49vv-25qx-mg44","summary":"OpenRemote has Improper Access Control via updateUserRealmRoles function","details":"### Summary\nA user who has `write:admin` in one Keycloak realm can call the Manager API to update **Keycloak realm roles** for users in **another** realm, including **`master`**. The handler uses the `{realm}` path segment when talking to the identity provider but does not check that the caller may administer that realm. This could result in a privilege escalation to `master` realm administrator if the attacker controls any user in `master` realm.\n\n### Details\nIn `manager/src/main/java/org/openremote/manager/security/UserResourceImpl.java`, there is no check to validate if the caller should be able to administer a realm they're trying to update.\n\n```340:353:manager/src/main/java/org/openremote/manager/security/UserResourceImpl.java\n    @Override\n    public void updateUserRealmRoles(RequestParams requestParams, String realm, String userId, String[] roles) {\n        try {\n            identityService.getIdentityProvider().updateUserRealmRoles(\n                realm,\n                userId,\n                roles);\n        } catch (ClientErrorException ex) {\n            ex.printStackTrace(System.out);\n            throw new WebApplicationException(ex.getCause(), ex.getResponse().getStatus());\n        } catch (Exception ex) {\n            throw new WebApplicationException(ex);\n        }\n    }\n```\n\n### PoC\n1. Create a **new** Keycloak realm other than `master`. Add a user and grant that user the OpenRemote client role `write:admin`. Remember the realm name (call it `NEW_REALM`).\n2. In Keycloak realm `master`, pick a **low-privilege** user (no `admin` realm role). Copy that user’s UUID (`\u003cmaster-user-uuid\u003e`).\n3. Authenticate as the user from step 1 and obtain a Bearer access token (`\u003ctoken\u003e`) for `NEW_REALM`.\n4. Replace placeholders and run:\n```bash\ncurl -k -X PUT \"https://\u003chost\u003e/api/\u003cNEW_REALM\u003e/user/master/userRealmRoles/\u003cmaster-user-uuid\u003e\" \\\n  -H \"Authorization: Bearer \u003ctoken\u003e\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '[\"admin\"]'\n```\n5. In the Keycloak Admin Console, realm master, that user, Role mapping. Confirm the admin realm role is assigned.\n### Impact\nAn attacker with the OpenRemote client role write:admin in any realm can call this API with {realm} set to another realm (for example master) and change Keycloak realm roles for users there. That can grant admin on master to a user UUID they target, which gives Keycloak administrator access for the master realm.","aliases":["CVE-2026-41166"],"modified":"2026-05-05T16:00:53.382967Z","published":"2026-04-22T14:38:23Z","database_specific":{"github_reviewed":true,"github_reviewed_at":"2026-04-22T14:38:23Z","nvd_published_at":"2026-04-22T21:17:09Z","cwe_ids":["CWE-284"],"severity":"HIGH"},"references":[{"type":"WEB","url":"https://github.com/openremote/openremote/security/advisories/GHSA-49vv-25qx-mg44"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-41166"},{"type":"PACKAGE","url":"https://github.com/openremote/openremote"},{"type":"WEB","url":"https://github.com/openremote/openremote/releases/tag/1.22.1"}],"affected":[{"package":{"name":"io.openremote:openremote-manager","ecosystem":"Maven","purl":"pkg:maven/io.openremote/openremote-manager"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"1.22.1"}]}],"versions":["1.10.0","1.11.0","1.11.1","1.11.2","1.11.3","1.12.0","1.12.1","1.12.3","1.13.0","1.13.1","1.14.0","1.15.0","1.15.1","1.15.2","1.16.1","1.17.0","1.17.1","1.17.2","1.17.3","1.18.0","1.19.0","1.2.0","1.2.1","1.2.2","1.2.3","1.2.4","1.20.0","1.20.1","1.20.2","1.21.0","1.22.0","1.3.0","1.3.1","1.3.2","1.3.3","1.3.4","1.3.5","1.4.0","1.5.0","1.6.0","1.6.2","1.6.3","1.6.4","1.6.5","1.7.0","1.8.0","1.8.1","1.9.0"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/04/GHSA-49vv-25qx-mg44/GHSA-49vv-25qx-mg44.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:H/A:L"}]}