Repository navigation
fix(websocket): the commands of a user go to the devices of the user only - #1072
Conversation
…only The client names the channel of the 53 device events (input.*, shell.command, device.install, connect.start, fs.retrieve, screen.capture, ...) and a device runs every command of its channel. The channel of a device is base64(sha1(serial)), so any signed-in user controlled any device: also the devices of the other users and of the automation of the grid, with a shell, installs, files and remote ADB. The client also subscribed to any channel, e.g. the private group channel of another user, where the devices of the user publish their logs. lib/units/websocket/zebrunner-channels.ts, the middleware of the socket of every client (socket.use): - a command goes to the channel of a present device the user uses or to the group channel of the user; an admin sends to any device - group.invite goes to a device of the groups of the user - tx.punch, tx.cleanup and the response channel of a transaction are channels of transactions (tx.<uuid>) only - the devices of the user are loaded from the database (the owner index) again after 2 s, or after 250 ms for a device not among them (a device taken just now); the messages of a client are checked in their order - a refused message is logged once a minute (zebrunner-guard) and dropped A test checks that every event of WebsocketClientEvents is classified, so a new upstream event cannot skip the check. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
❌ STF CI report5 failing · 6 test tiers (6 pass / 0 fail / 0 skip) · 10 Android versions (10 with a usable device in STF) · 6 iOS versions (1 passing) Test tiers
Android device matrix
Image = a system image is published for that API and arch. Boot = emulator reached iOS simulator matrix
WebDriverAgent on an iPhone simulator against the WDA client of the ios-device unit (test/zebrunner-ios). A red column: Simulator, the simulator did not boot · WDA, WebDriverAgent did not start · Session, no WDA session · Appium kept, the session of an Appium test was not kept · Size, wrong screen size · Orientation, no orientation or battery · Home, the home button did not work · Touch, tap or swipe failed · Screenshot, no screenshot · Settings, Settings did not open or the app was lost · Clipboard, the pasteboard was not written or read · URL, Safari did not open the address · Stream, no MJPEG frame · Stable, the unit would have stopped Failures
Logs, screenshots, logcat and Playwright traces are attached to the run as artifacts · full run · commit |
Problem
The client of the websocket names the channel of 53 events and the websocket pushes their message to it:
input.*,shell.command,device.install/uninstall,connect.start(remote ADB),fs.retrieve/fs.list,screen.capture,clipboard.copy,forward.*,group.kick, ... A device runs every message of its channel without an owner check, and the channel of a device isbase64(sha1(serial))(the solo plugins of Android and iOS), computable from the serial every user sees.So any signed-in user controlled any device: a shell, installs, files, the screen, remote ADB - also of a device used by another user or reserved by the grid for an automation session (its tests sabotaged, its app data read).
The client also subscribed the websocket to any channel (
tx.punch, the response channel of every transaction), e.g. the private group channel of another user, where the devices of the user publish their logs and notifications.Changes
lib/units/websocket/zebrunner-channels.ts- the middleware of the socket of every client (socket.use, one line inindex.ts):group.invitegroup.invitegroups.subscribed, as the device list); an admin: anytx.punch,tx.cleanup, the response channel of the transaction eventstx.<uuid>getAll(email, {index: 'owner'}), present devices only): loaded again after 2 s (a released device gets no command later than 2 s after it), or after 250 ms for a channel not among them (a device taken just now gets its first command; a client cannot load the database in a loop).lib/db/zebrunner.ts:ownedDeviceChannels,visibleDeviceChannel.The UI sends every command to
device.channelof a device it uses and its transactions aretx.<uuid>(res/app/src/core/transaction.ts): nothing changes for it. The REST API checks the owner by the serial already.Tests
test/units/zebrunner/websocket-channels.mts(13): every event ofWebsocketClientEventsofindex.tsis classified (a new upstream event fails the test until it is); commands to the device of the user and to its group channel pass, to another device and without a channel are refused, an admin passes; invite by the groups; transaction channels only; the order kept while the devices are loaded (one load); a released device refused after 2 s, a device taken just now passes; a database error drops; a real socket.io server and client; the queries of the databasestf migrate): only the present devices of the user, the visibility by the groupsnpm run lint,npm run test:unit(512 passing)