{"schema":"threatline.record/2","record":{"id":"GHSA-2j4x-qh6q-q8mm","aliases":["GHSA-2j4x-qh6q-q8mm"],"summary":"Cross-realm gateway websocket events are not checked against the GatewayConnector realm","details":"### Summary\r\n\r\nOnce a gateway websocket session is established only the gateway ID is used to lookup the GatewayConnector to handle the event, this means that if a user in realm A with `WRITE:ADMIN` role knows the ID of a gateway in realm B they can create a service user for that gateway ID in realm A and then via a websocket client they can connect to the GatewayConnector for realm B thus allowing them to impersonate that gateway across realms.\r\n\r\n### Details\r\n\r\n`GatewayService.onGatewayMessageIntercept()` does a simple username ID check in `isGatewayClientId()` but does not pass the authenticated gateway service user's realm to `GatewayService.processGatewayConnected(), GatewayService.processGatewayDisconnected(), GatewayService.processGatewayMessage()` which means that provided a service user in Realm A is correctly named with the ID of a gateway in Realm B, any messages received for the user will be forwarded to the `GatewayConnector`.\r\n\r\n### Proof of concept\r\n\r\n- Find the gateway ID of a gateway asset in Realm B (potentially from logs or other exploitable means)\r\n- As a user with `WRITE:ADMIN` in realm A create a service user with the username `gateway-GATEWAY_ID_IN_LOWER_CASE`\r\n- Use a websocket client to connect to the manager websocket server and send any information to perform CRUD operations on Gateway descendant assets in Realm B\r\n\r\n### Impact\r\n\r\nThe rogue user would be able to create SSH tunnels during initial sync handshake thus gaining access to the local network of the gateway.\r\n\r\nThe rogue user can completely overwrite the Gateway Asset descendant assets but cannot read existing assets, this is more a destructive impact as existing assets will be lost.\r\n\r\nThe rogue user in Realm A would need `WRITE:ADMIN` role and know the gateway ID from Realm B which mitigates the attack \r\n","categories":["Unclassified"],"product":" io.openremote:openremote-manager","vendor":"","ecosystem":null,"affected_ranges":[{"source":"GitHub Advisory Database","source_url":"https://github.com/openremote/core/security/advisories/GHSA-2j4x-qh6q-q8mm","source_modified_at":"2026-10-08T12:31:38Z","fetched_at":"2026-10-28T08:18:35.509402Z","package":{"ecosystem":"maven","name":" io.openremote:openremote-manager"},"range":"<1.31.0"}],"fixed_versions":[{"source":"GitHub Advisory Database","source_url":"https://github.com/openremote/core/security/advisories/GHSA-2j4x-qh6q-q8mm","source_modified_at":"2026-10-08T12:31:38Z","fetched_at":"2026-10-28T08:18:35.509402Z","package":{"ecosystem":"maven","name":" io.openremote:openremote-manager"},"version":"1.31.0"}],"cvss":2.1,"severity":"Low","kev":{"listed":false},"epss":{"probability":null,"percentile":null,"score_date":null},"published_at":"2026-10-08T12:31:38Z","modified_at":"2026-10-08T12:31:38Z","provenance":[{"source":"GitHub Advisory Database","url":"https://github.com/openremote/core/security/advisories/GHSA-2j4x-qh6q-q8mm","fetched_at":"2026-10-28T08:18:35.509402Z","source_modified_at":"2026-10-08T12:31:38Z"}],"sources":["GitHub Advisory Database"],"references":[],"locations":[],"motoko_assessment":{"status":"requires_architecture_review","automatic_remediation":false},"classification":{"method":"product-first software-layer rules","rules_version":"2.1","matched_on":null,"confidence":"unknown","reviewed":false},"change_timestamp":"2026-10-08T12:31:38Z","content_hash":"85ff5a6ca22d52319d6696498b109fba96f316b37b8b79d16836215d443793bd"}}
