tabby-rdp 0.5.0 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/CHANGELOG.md +516 -0
  2. package/README.md +216 -58
  3. package/TROUBLESHOOTING.md +77 -0
  4. package/dist/accountForm.js +0 -1
  5. package/dist/accountRevisions.js +46 -0
  6. package/dist/accounts.js +2 -2
  7. package/dist/audio.js +0 -1
  8. package/dist/authorities.js +331 -0
  9. package/dist/byteQueue.js +102 -0
  10. package/dist/clipboard.js +106 -0
  11. package/dist/connectionStatus.js +0 -1
  12. package/dist/desk.js +16 -47
  13. package/dist/deskScript.js +196 -6
  14. package/dist/desktop.service.js +1499 -269
  15. package/dist/desktopForm.js +53 -18
  16. package/dist/desktops.js +232 -24
  17. package/dist/diskStorage.js +212 -0
  18. package/dist/drives.js +271 -30
  19. package/dist/fileTransfer.js +960 -132
  20. package/dist/gateway.js +216 -57
  21. package/dist/header.js +76 -5
  22. package/dist/help.js +16 -47
  23. package/dist/hostCompat.js +86 -0
  24. package/dist/hyperv.js +65 -15
  25. package/dist/index.js +7 -4
  26. package/dist/keyboard.js +0 -1
  27. package/dist/microphone.js +57 -13
  28. package/dist/ntlm.js +0 -1
  29. package/dist/osd.js +56 -15
  30. package/dist/packageChangeDialog.js +186 -0
  31. package/dist/probe.js +15 -3
  32. package/dist/rdcleanpath.js +319 -44
  33. package/dist/rdpFile.js +22 -7
  34. package/dist/rdpProfile.js +39 -21
  35. package/dist/releaseSettings.js +72 -0
  36. package/dist/releases.js +408 -0
  37. package/dist/remoteSetup.js +103 -23
  38. package/dist/sessionLog.js +53 -0
  39. package/dist/settingsPage.js +148 -122
  40. package/dist/signin.js +478 -48
  41. package/dist/ssh.js +99 -18
  42. package/dist/sshChannelStream.js +40 -6
  43. package/dist/targets.js +194 -40
  44. package/dist/ui.js +88 -20
  45. package/dist/unshowable.js +41 -0
  46. package/dist/updates.js +79 -56
  47. package/dist/vms.js +17 -3
  48. package/dist/wake.js +15 -8
  49. package/docs/desk.md +157 -0
  50. package/package.json +14 -4
  51. package/remote/trd-pty.py +74 -13
  52. package/vendor/SHA256SUMS +26 -0
  53. package/vendor/ironrdp_web_bg.wasm +0 -0
  54. package/dist/accountForm.js.map +0 -1
  55. package/dist/accounts.js.map +0 -1
  56. package/dist/audio.js.map +0 -1
  57. package/dist/connectionStatus.js.map +0 -1
  58. package/dist/desk.js.map +0 -1
  59. package/dist/deskScript.js.map +0 -1
  60. package/dist/desktop.service.js.map +0 -1
  61. package/dist/desktopForm.js.map +0 -1
  62. package/dist/desktops.js.map +0 -1
  63. package/dist/drives.js.map +0 -1
  64. package/dist/fileTransfer.js.map +0 -1
  65. package/dist/gateway.js.map +0 -1
  66. package/dist/header.js.map +0 -1
  67. package/dist/help.js.map +0 -1
  68. package/dist/hyperv.js.map +0 -1
  69. package/dist/index.js.map +0 -1
  70. package/dist/keyboard.js.map +0 -1
  71. package/dist/microphone.js.map +0 -1
  72. package/dist/ntlm.js.map +0 -1
  73. package/dist/osd.js.map +0 -1
  74. package/dist/probe.js.map +0 -1
  75. package/dist/rdcleanpath.js.map +0 -1
  76. package/dist/rdpFile.js.map +0 -1
  77. package/dist/rdpProfile.js.map +0 -1
  78. package/dist/remoteSetup.js.map +0 -1
  79. package/dist/settingsPage.js.map +0 -1
  80. package/dist/signin.js.map +0 -1
  81. package/dist/ssh.js.map +0 -1
  82. package/dist/sshChannelStream.js.map +0 -1
  83. package/dist/targets.js.map +0 -1
  84. package/dist/ui.js.map +0 -1
  85. package/dist/updates.js.map +0 -1
  86. package/dist/vms.js.map +0 -1
  87. package/dist/wake.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,521 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.2
4
+
5
+ **Added**
6
+ - **Updates settings** include stable and preview channels (beta releases and release candidates), automatic and
7
+ manual checks, compatible version selection, rollback and uninstall controls. Changes require confirmation and
8
+ take effect after restarting Tabby. Update preferences and installation history stay on this computer.
9
+ - **Installation progress stays in the confirmation dialog**, with elapsed time and a verified success or failure
10
+ result. The dialog remains visible if Settings closes. The installed version is checked before reporting success.
11
+
12
+ **Fixed**
13
+ - **Commands through the system SSH report SSH's own failure** when it exits before reading their input,
14
+ instead of letting a broken-pipe error escape unhandled. Commands that ignore their input still return their output.
15
+ - **Plugin startup waits for Tabby's configuration** before migrating update preferences, avoiding an error that
16
+ could disable third-party plugins for the session.
17
+
18
+ **Changed**
19
+ - **Troubleshooting opens the Markdown guide** from the links at the top of Remote Desktop settings. The former
20
+ Troubleshooting tab is now Updates; connection logs are under Desktops. Empty lists use concise status messages.
21
+ - **Settings descriptions are shorter**, and help icons appear consistently after their descriptions.
22
+ - **Troubleshooting and desk cleanup guides are included in the npm package.**
23
+ - **Host compatibility checks share one layer**, with host and runtime versions, the host's declared xterm dependency,
24
+ and observed capabilities included in copied connection logs. Modal drag fallbacks and terminal input handling use
25
+ shared adapters that check the host's actual features, including on forks and nightly builds.
26
+ - **CI and the release workflow check out the code with actions/checkout 7.0.1** (#56), pinned to its commit as before,
27
+ in place of 4.4.0. Nothing in the package changes.
28
+
29
+ ## 0.5.1
30
+
31
+ Security fixes from an audit of 0.5.0: saved passwords and certificates, what a host says about its desktops, `desk`,
32
+ shared folders and file transfers, what a server, gateway or SSH host can make Tabby do, and what a connected desktop
33
+ can do. Clipboard sharing can be narrowed or turned off, and a release ships IronRDP only as its sources build it.
34
+
35
+ **Security**
36
+ - **An imported .rdp profile no longer signs in with a saved account on its own.** If you had set a default account
37
+ for a profile group or for remote desktops in general, a profile made from an .rdp file used to adopt it and send
38
+ its password to the address and gateway the file named, with no sign-in prompt. Once such a profile had been saved
39
+ in Tabby's profile editor (which drops the values that equal the defaults then), it could also take a default
40
+ gateway account set since, which went to the gateway the file named the same way, and a default kind of xrdp, which
41
+ would have had the password go without Network Level Authentication, unasked. An imported profile now has no
42
+ account, no gateway account and the Windows kind whatever the defaults say (`null` for each, which Tabby's profile
43
+ editor keeps when it saves), so it asks for its sign-in, unless a password was saved already for that same address
44
+ reached the same way (through the same gateway, or none; not one 0.5.0 saved there for a desktop reached through a
45
+ gateway, which is forgotten: below); pick a saved account or a kind in its profile settings if you want one.
46
+ Profiles imported before this update and not saved in the profile editor since are changed the same way, when Tabby
47
+ starts and whenever its config changes (config sync included): they ask for their account once instead of taking a
48
+ default one. And removing a saved account now leaves the profiles that used it asking for an account, as its
49
+ confirmation says, rather than taking their group's default.
50
+ - **A certificate this computer can't verify is confirmed before anything of your sign-in goes to the server.** A
51
+ remote desktop you connect to directly (an RDP profile, quick connect, an imported .rdp file, a restored tab)
52
+ remembered the first certificate it met without asking, and so did an RD Gateway, so someone in the middle of that
53
+ first connection, or a file naming a gateway of its own, could take the sign-in: a proof of your password that can be
54
+ attacked offline. Now a certificate valid for the server's name by the certificate authorities this computer trusts
55
+ (the public ones, and with a recent Tabby those of the system's own store too, such as an organisation's) connects
56
+ without a question, and any other is shown the first time, before anything of your sign-in goes to the server (the
57
+ connection request and the TLS handshake have): the address, why it can't be verified, its SHA-256 fingerprint and
58
+ what it says of itself (whom it was issued to and by, and when it is valid, which the desktop's log has too), with
59
+ Cancel as what Enter picks. Why it can't be verified is the plugin's own reading, since the TLS library reports only
60
+ the last of its checks that failed, which whoever makes the certificate can choose. First, unless its chain leads to
61
+ an authority this computer trusts, where that chain stands: self-signed (Windows' own RDP certificate included,
62
+ whatever its key usage), from an authority this computer doesn't trust, or no way to one from what the server sent
63
+ (only an authority counts as an issuer, so one signed with the key of a certificate issued to a server leads to
64
+ none; and an authority is known by its name and key, as the TLS library knows it, so its root sent along
65
+ cross-signed by another counts). Then, whatever the chain: issued for another name (checked by the plugin, since
66
+ Node checks the name only once a chain checks out), expired or not valid yet (by its own dates), and marked for
67
+ other uses than a server's. Only one for that name whose chain leads to an authority this computer trusts is said to
68
+ be like some organisations' Remote Desktop certificates. What it says of itself is marked as its own word, which
69
+ nothing has checked, unless an authority vouched for it or its chain leads to one this computer trusts (another
70
+ machine's certificate then shows that machine's name), and the TLS library didn't refuse it for a reason of its own (a
71
+ limit set on the authority, say): an issuer you would expect there proves nothing, since anyone can make a certificate
72
+ that names it; only the fingerprint, checked some other way, does. For a server without Network Level Authentication
73
+ it says that signing in sends the password itself, not a proof of it. A certificate
74
+ whose only use is Remote Desktop Authentication (as Active Directory's Remote Desktop templates issue them) isn't
75
+ valid for a server by these rules, whatever issued it, and is asked about too, at each renewal as well.
76
+ Automatic reconnects stop at the question. A certificate you trust is remembered as yours, and a different one there
77
+ later stops the connection whatever vouches for it; one an authority vouched for may be replaced by another it
78
+ vouches for (a renewal), which connects and is noted in the desktop's log. The same one connects only while that word
79
+ holds: once it has expired, or its authority is gone from this computer's store, it is asked about as at first, since
80
+ you never confirmed it, and trusting it then makes it yours. Trusting a certificate never allows signing in without
81
+ Network Level Authentication. Desktops behind an SSH host still remember their first certificate without asking: SSH
82
+ vouches for the host they are reached through, though not for what answers behind it.
83
+ Certificates remembered before this update stay remembered: a desktop's is held to that certificate as before
84
+ (unless an authority vouches for it, when it counts as met for the first time now), and a gateway's may still be
85
+ replaced by one an authority vouches for. The .rdp import dialog says plainly that a gateway is signed in to first.
86
+ - **A machine reached with `ssh` typed in an SSH tab is filed under that tab's host.** What the plugin keeps per
87
+ desktop (a saved password, the remembered certificate, permission to sign in without Network Level Authentication)
88
+ was found for such a machine by a name the host there reported, so a hostile host could pass a desktop of its own
89
+ off as another one you had used, behind another host too, and have that desktop's saved password sent to it. Such a
90
+ machine's desktop is now kept under the host it is reached through: a host can only ever name desktops of its own.
91
+ Desktops reached this way ask for their sign-in once more and remember their certificate anew (a sharpness set for
92
+ one is set again): what was saved for them can't be told apart from what a host could claim, so none of it is used.
93
+ The same machine opened in a tab of its own now counts as another desktop: a tab with that one open isn't switched
94
+ to. Desktops configured behind a host belong to tabs connected to that host, not to a machine reached through
95
+ another one, whose name there is that host's word: only that machine's own desktop opens through it. And the names
96
+ hosts are kept under are now written so that no two can be the same: a host whose user or host name has a `%`, `#`
97
+ or `>` in it (an IPv6 address with its zone, `fe80::1%en0`) is kept under a new name, and what was kept for it moves
98
+ along, its remembered certificates and sharpness at once and a saved password at its next sign-in; desk's key and
99
+ the choices made "from now on" for it are asked about again. A host whose user name has a `#` gets its desktops'
100
+ passwords asked for again instead, and those kept under its old name are forgotten once a tab to that host is open
101
+ again: from the keychain the next time a saved password is looked up, saved or forgotten and it answers, and from
102
+ Tabby's Vault (if it is on) the next such time the Vault is open. There they read as no desktop's, so removing or
103
+ editing one of its desktops left them in place, kept for good. Where the old name could be another account's new
104
+ one, nothing moves, and that host's desktops ask again: `alice%23ops@host` is how `alice#ops@host` is written now,
105
+ and an old name with a numeric IPv6 zone whose first two digits are 10 to 19, 23, 25 or 40 (`%12`, say) reads as such
106
+ a name too. What a hostile host may have planted under another desktop's name before this update can't be told
107
+ apart, and stays: a certificate that isn't the server's still stops the connection.
108
+ - **Desktop asks when a console's `ssh` would lead it elsewhere.** Which `ssh` runs in an SSH tab's console is what
109
+ the host there says, so a host could have **Desktop** open a machine of its choosing in place of its own, without a
110
+ word. Desktop now asks which desktop to open: the tab's own (the first choice), or that machine's, this time or
111
+ **from now on**. Only "from now on" opens that machine's desktop at once the next times `ssh` leads there from that
112
+ host. An `ssh` to a name with characters that could hide part of it or show it in another order (control and format
113
+ characters, and the others that don't show, as the .rdp import has them) isn't offered. A "from now on" is taken back
114
+ in Tabby's config file (`remoteDesktop.nestedSSH`). A desktop picked in the tab's menus is always the tab's host's,
115
+ also where a machine's own desktop is open in the pane, which the menus then offer to replace with the host's own
116
+ (and `desk` opens the desktop of the machine it ran on), and a sign-in form for a machine reached through a host
117
+ names that host.
118
+ - **A saved desktop password is no longer reused for a different gateway.** A remembered password was kept by the
119
+ desktop's address alone, so a profile that named the same address through another gateway could send it there without
120
+ asking. Saved passwords are now tied to the way they were entered for: through that gateway (in any spelling of it),
121
+ whether it takes the desktop's sign-in or an account of its own, or through none. A desktop reached through a gateway
122
+ asks for its password once after this update; the password 0.5.0 saved for it, under the address alone, which a
123
+ desktop at that address without a gateway (a quick connect, another profile, an .rdp file naming it) would now find
124
+ and use unasked, is forgotten after the update, for each desktop configured to go through a gateway by then, so that
125
+ desktop asks once too: once in each computer's keychain and once in Tabby's Vault, the first time a password is looked
126
+ up, saved or forgotten (marked done in the keychain itself, and for the Vault in the config, which config sync takes
127
+ to other computers with the Vault). Until that has been done (a keychain that doesn't answer, a Vault whose passphrase
128
+ prompt was cancelled), such a password isn't used. Changing its gateway, user name, domain or account forgets the
129
+ password and asks again, as does removing the desktop; a sign-in that was under way when that happened (the server
130
+ took its time) isn't saved when it ends, which would undo it. A new address takes it along, through the same gateway,
131
+ unless a desktop is known at that address already, and behind an SSH host only along with its desktop's remembered
132
+ certificate (below). Each store of passwords, Tabby's Vault and the keychain, forgets such a password on its own: at
133
+ once where it can be read, and where it can't be just then (the Vault locked and its prompt cancelled, the keychain
134
+ not answering) the password isn't used, and goes the next time that store can be read while the Tabby window is open;
135
+ an edit or a removal says so, naming that store. Should the window be closed first, it is found again by a desktop at
136
+ that address (**Sign in again…** in the desktop's menu replaces it). The desktop's remembered certificate stays
137
+ meanwhile, so that a password still kept there goes only to the machine it was saved for: a removal keeps it while a
138
+ store waits (Settings › Remote Desktop › Certificates can forget it), and a new address leaves it at the old one too,
139
+ as well as taking it along, which also keeps another desktop's password at that address, reached another way, from
140
+ going to a machine that isn't the one it was saved for.
141
+ - **Desktops that are xrdp only by a host's word ask before the password goes without Network Level Authentication.**
142
+ 0.5.0 stopped before sending the password to a server without NLA, except for desktops of the xrdp kind, which sign
143
+ in that way by design. But a VM a host lists, a machine reached through a host, and the host's own desktop are xrdp
144
+ only because that host says so: a host could call any server it offers xrdp and get the password typed for it as it
145
+ is, and a host you sign in to with an SSH key need not have that password. Now only desktops you made xrdp ones (a
146
+ desktop or profile of that kind) go on unasked; the others, the xrdp of the host you SSH into included, ask once, in
147
+ xrdp's terms, and the answer is remembered for that desktop (with its certificate, below). A VM saved from a host's
148
+ list is asked about the same way, one saved before this update too, until you pick its kind in its edit form, where
149
+ the host's word is a choice of its own; the question says so. (A desktop of yours of the xrdp kind that starts a VM
150
+ by name looks like such a VM, and asks once too.)
151
+ - **"Send the password anyway" is kept with the certificate it was given for.** Permission to sign in without Network
152
+ Level Authentication was kept for the desktop alone, from before any certificate had been seen: an attempt that didn't
153
+ get as far as one left it for whatever answered there next, which then got the password unasked, its certificate
154
+ trusted as a first use. And it outlived **Trust the new certificate** and a new address in the edit form. It is now
155
+ kept with the certificate accepted for that sign-in, and holds for that certificate only; trusting a changed one, a
156
+ new address or forgetting the certificate takes it back, so another server there asks again, and the
157
+ changed-certificate question says so. 0.5.0 kept the answer only until Tabby restarted (under Fixed, below), so none
158
+ of its answers carries over; development builds since kept them without a certificate, and those ask once more.
159
+ - **A VM a host lists can no longer be given another desktop's saved password.** A found VM's address is part of the
160
+ name its saved password is looked up by, and a host could list one at an address made up to read as a desktop
161
+ configured behind it whose sign-in goes to an RD Gateway: opening that VM sent the desktop's saved password to
162
+ wherever the host had it lead. A found VM's address is now an IPv4 address, the only kind the scan reports; others
163
+ aren't listed.
164
+ - **`desk` requests need the machine's key, and act only in the pane you're in.** With `desk` on, anything shown in a
165
+ console could ask Tabby to open that machine's desktop and run its setup there, as typing `desk` does: a file shown
166
+ with `cat`, a log being followed, another machine's output. Tabby now acts only on a request that carries the key of
167
+ the machine it is for, which only your account there can read and which the machine's setup gives Tabby when its
168
+ desktop is opened with `desk` on. A setup run with `desk` off makes Tabby forget that machine's key as it starts,
169
+ whatever the machine then says, so also when the setup fails or never finishes; one during which `desk` is turned off
170
+ does when it ends or fails with `desk` still off (with `desk` on again by then, it changes nothing: a setup since
171
+ keeps what it found), as does one that finds xrdp or Windows there instead of GNOME. Requests without a known key are
172
+ dropped as they are read, with nothing shown, even while `desk` is off; of the others, a terminal passes on one every
173
+ 2 seconds, and a pane handles one at a time (timed by a clock that only goes forward: the time of day set back doesn't
174
+ keep `desk` quiet meanwhile). A request from a pane that isn't the one in front, or that stops being it by the time
175
+ the desktop would show (Tabby first asks the machine which one it is), gets a note there instead: shown there, the
176
+ desktop would take the keyboard (and this computer's clipboard) from the pane you are typing in, even from another
177
+ tab. The key tells `desk` apart from look-alike output, not from the machine itself, which can always send it, nor
178
+ from a recording of `desk`'s output shown again there: open the desktop of a machine you don't trust with `desk` off.
179
+ After updating, open each machine's desktop once before using `desk` there: that installs the new `desk` and lets
180
+ Tabby recognize it. Tabby keeps a fingerprint of each key, not the key.
181
+ - **`desk` attaches the desktop's terminal only to your own sessions.** A request could name a tmux session that
182
+ another user of the machine had opened to others, and the terminal on the desktop attached to it, where that user
183
+ would see what you type. Now it attaches only to your own trd-pty sessions and to tmux servers in tmux's own folder
184
+ for you, where no other user can replace a folder on the way; anything else gets a terminal in the folder instead.
185
+ trd-pty, `desk`'s session helper, also checks that a session runs as you before sending it anything, doesn't use
186
+ `/tmp` where another user could swap its folder, and starts no session (logins fall back to tmux) on a system that
187
+ can't say which user is at the other end of a connection.
188
+ - **A desktop that finishes connecting while you're in another pane no longer takes the keyboard**, nor does a sign-in
189
+ form (its own, or its gateway's) or a question (a certificate to trust) that shows up for it meanwhile, nor the tip
190
+ shown on the first connection when it closes. They took it from whatever pane you had moved to, in another tab too
191
+ (Tabby keeps those in the page, out of sight), so what you typed there went to that desktop, and this computer's
192
+ clipboard went with the keyboard. The remote decides how long connecting takes, and when a dropped connection comes
193
+ back. They now get the keyboard when their pane does, and a question waiting where it isn't in view brings a note
194
+ that stays a few seconds.
195
+ - **Pasting a copied folder (⌘V) no longer sends what its links lead to outside it.** A folder can hold links to
196
+ anywhere (one unpacked from an archive, or a repository), and the paste sent the files behind them too, a folder
197
+ of keys as easily as a document. A link in a copied folder is now followed only when it leads somewhere in that
198
+ folder; the others are left out, and the message on the desktop says how many. When that leaves no file to send,
199
+ nothing is pasted (⌘V would have pasted whatever the remote had), and the message says why; the same where what was
200
+ copied is gone, or is links that lead nowhere or folders with nothing in them. Folders dropped on a
201
+ desktop weren't affected: Tabby's browser engine doesn't follow their links. Reading a copied folder holds Tabby up
202
+ while it goes on, so besides its limits on what it sends (10,000 files and folders, 20 deep) it now stops at limits
203
+ on what it looks at (20,000 names and folders, 2,000 links), and looks at nothing past them: a folder of a million
204
+ names or links no longer holds Tabby up for long, and the message says when something was left out. A folder found
205
+ swapped for another while it was read stops the paste, as one that can't be read does (⌘V pasted whatever the remote
206
+ had).
207
+ - **A release ships IronRDP only as its sources build it.** The remote desktop itself (IronRDP's WebAssembly and
208
+ JavaScript, in `vendor/`) is committed prebuilt and runs with Tabby's access to this computer, and nothing checked
209
+ that it was what IronRDP and the plugin's patches build to: a changed or out-of-date build would have been published
210
+ as it was. The build now records what it was made from and each file's hash (`vendor/SHA256SUMS`), every change is
211
+ checked against that, and a release is staged only after CI has rebuilt IronRDP from source and found every file
212
+ identical, byte for byte. The base commit has to be one of IronRDP's own (GitHub serves a fork's commits through
213
+ IronRDP's address too), and the build's tools are pinned: wasm-bindgen is built from its own lock file rather than
214
+ from the newest releases of what it uses (one of the right version built without it is built again; this release's
215
+ WebAssembly is built so, and differs from 0.5.0's only in the version of a library of wasm-bindgen's it names), and on
216
+ the Apple Silicon Mac `vendor/` is built on, binaryen's optimizer is checked against its hash before it runs, and is
217
+ all that is kept of its release: the folder it is in goes ahead on PATH, so nothing else may be there. The package's
218
+ IronRDP files, and every other committed file in it, are checked against the tagged commit in the repository, not
219
+ against the copy of the list it carries, before it is staged, and a staged release can be checked the same way before
220
+ it is approved, its built `dist/` against a build of your own. The patches' own tests now run in CI as well.
221
+ - **An SSH host can no longer freeze or crash Tabby with what it prints.** The plugin runs small commands on your SSH
222
+ hosts (looking for VMs does so by itself while an SSH tab is active), and it kept all that a host printed in answer,
223
+ then read it in a way that took far longer the more there was: a host that answered with a few megabytes of made-up
224
+ VMs could freeze Tabby for a minute or more, a single long line could do it for hours, and a larger answer could
225
+ crash it, closing every tab. An answer is now cut off at 4 MB (the plugin's commands print a few lines), kept as its
226
+ bytes however small the pieces it comes in, and read in time that grows only with its size: the VM scans, Hyper-V's
227
+ answers and the line that says how an `ssh` typed on a host ended are read line by line or by hand, not with
228
+ patterns that a long line could make retry each way of splitting it. At most 256 VMs are listed for a host, and its
229
+ menu says so when that cuts the list short. A command's minute now runs from the moment its channel is asked for, so
230
+ a host that stops answering partway through starting one no longer keeps a VM scan or a desktop's setup waiting for
231
+ good. A host whose scan fails waits a minute before it is asked again, as one that answered does. A command run
232
+ through the `ssh` typed in a terminal that takes longer than a minute is now an error, rather than taken as finished
233
+ with what it printed so far, and a tunnel through it keeps only the end of what ssh prints (a host's sign-in banner
234
+ can be as long as it likes). The list of this computer's processes, read to find the `ssh` in a local terminal, is
235
+ read the same way: a program with a long run of spaces in its arguments could freeze Tabby while it was looked at.
236
+ A host's reason for an error is shown and logged as far as 1,000 characters (a Hyper-V host's answer, 1,024), and a
237
+ line logged from a host's answer is kept as a copy of its own, not as part of the answer, which could keep megabytes
238
+ in memory for each line. To find an `ssh` typed in a pane (to open the desktop of the machine it went to), the
239
+ plugin has the host print a mark in the terminal of each `ssh` running there, which tells which one is the pane's;
240
+ it kept every such mark the host printed while it answered, up to a minute, which could fill Tabby's memory as
241
+ well. It now keeps only marks of the form its script prints, 64 at most.
242
+ - **A remote desktop's server can no longer freeze Tabby by sending its data in tiny pieces.** Each piece was joined
243
+ to everything still waiting, so a message sent a byte at a time cost the square of its size, all of it on the thread
244
+ that runs Tabby's window: a few megabytes could hold Tabby still for tens of seconds at a time, and more for far
245
+ longer. Pieces are now joined once, when the message is complete, and the server's sign-in messages (a few
246
+ kilobytes) may be 256 KB at most, instead of 16 MB. The same goes for what an RD Gateway sends. What waits for the
247
+ rest of a message is copied into storage of its own rather than kept as it came, since a piece can be a few bytes of
248
+ a much larger read: a gateway could otherwise have every read kept whole for a byte of a packet it never finishes,
249
+ a gigabyte for one packet. What comes through an SSH host while the desktop's side isn't reading is kept the same
250
+ way, as its bytes rather than the pieces they came in: 64 MB of it a byte at a time could take gigabytes. A server
251
+ that answers the connection request with something other than RDP (a web server on that port, say) is refused at
252
+ once, rather than waited on for the length its answer seemed to give.
253
+ - **A remote desktop has a limit on the files it keeps open through a shared folder.** The server decides how many files
254
+ it opens there and when it closes them, and a hostile one could keep opening until Tabby's window could open no file
255
+ or connection in any tab, or crashed. A desktop now has at most 1,024 files open at once (programs there keep far
256
+ fewer), and all the desktops in a Tabby window 2,048 together, since they share the window's files; more are refused
257
+ until some are closed. That leaves most of what a Tabby window may have open to its other tabs where it may have far
258
+ more: on macOS (some 138,000, measured) and on Windows (8,192). On Linux that wasn't measured: where a Tabby window
259
+ may have 4,096 files open or fewer, these 2,048 are half of that or more. A file counts until it has been closed, not
260
+ from when the server asks for that (closing waits for what is under way on the file), and a file still being opened
261
+ when the connection ended was left open until Tabby quit; it is closed now.
262
+ - **The desktop name overlay's settings can't become part of Tabby's window.** A color for the overlay could get past
263
+ the plugin's check and be read as page content, which in Tabby's window runs as code; it took someone able to change
264
+ your Tabby config (through config sync, say). The overlay is now built without reading anything as page content,
265
+ and only plain colors are used (a name, `#hex`, `rgb()` and the like). Other odd values are handled too: an overlay
266
+ font or size such as `constructor` is ignored, where it used to break the overlay and with it the connection of the
267
+ desktop it was naming; an overlay duration or an idle shutdown time that is neither a number nor text no longer
268
+ stops every desktop from connecting, nor does a desktop's port, address, name or other field of that kind (in its
269
+ entry or its profile) stop that desktop and those listed with it. Such a field, or an item in the desktops list that
270
+ is no entry at all (an empty one), no longer takes away the right-click menu of every SSH tab (Tabby's own items
271
+ with it) or the lists of the settings page, nor does a profile's address, port, user name or gateway of that kind
272
+ keep Tabby's profile selector from opening; a desktop behind a host with such a field can still be edited and
273
+ removed, shown by what of it is text, or by its address. Whatever goes wrong with the overlay, reading its settings
274
+ included, is logged rather than failing the connection; and a shortcut in the config that isn't text no longer
275
+ breaks the settings page.
276
+ - **The GNOME desktop's generated password no longer shows in the host's process list on every connect.** Checking it
277
+ went through a command whose arguments other users of the host can see, and with the password one of them could sign
278
+ in to that desktop. It is now compared in the shell, and set through `grdctl`'s input where `grdctl` reads it from
279
+ there; a `grdctl` that doesn't still gets it as an argument each time it is set that way (when the setup can't tell
280
+ whether it is set already, too), so on a host shared with others the password can still be caught then.
281
+ - **A shared folder's hard links can't be used to change files elsewhere.** A file with more than one name (a hard link,
282
+ as pnpm's `node_modules` and some backup tools make) is the same file under each name, possibly outside the shared
283
+ folder, so through a read-write share the remote could change it there too. Such files (as their count of names is
284
+ when the file is opened) are now read-only from the remote; reading them is as before.
285
+ - **The microphone shows in Tabby's header whenever a desktop gets it**, whatever tab is in front, and in full screen,
286
+ which hides Tabby's header, at the top of the window in the middle (over the desktop in view, clear of a maximized
287
+ window's close button and GNOME's system menu); its menu shows that desktop, or stops sending the microphone there. A
288
+ desktop that starts receiving the microphone while it isn't showing also brings a note. The remote decides when it
289
+ takes the microphone, and the red dot on the desktop was the only sign in Tabby: out of sight while the console was in
290
+ front or the tab in the background, and partly covered by a note from the remote. Capturing still carries on while the
291
+ desktop is hidden, so hiding it doesn't cut a call short. **Stop** holds for that desktop until you turn **Send the
292
+ microphone** back on in its menu (or that Tabby window is closed), reconnects included, so a server can't get the
293
+ microphone back by dropping the connection; the same switch keeps a desktop from getting it beforehand. Turning the
294
+ Microphone setting off now stops it at once on every desktop, one still connecting included, also when it is changed
295
+ in another window or the config file; turning it on still applies on the next connection. Importing an .rdp file says
296
+ when the desktop will get the microphone, and no longer calls a file's request for it not applied while the setting is
297
+ on.
298
+ - **Clipboard sharing can be narrowed or turned off.** The clipboard always went both ways: a desktop that had the
299
+ keyboard got what was on this computer's clipboard, whatever was copied meanwhile and what was copied elsewhere
300
+ before clicking back into it, passwords from a password manager included, and could put anything on this computer's
301
+ clipboard, such as a command waiting to be pasted into a terminal. Settings › Remote Desktop › Settings ›
302
+ **Clipboard sharing** now offers both ways (the default, as before), only from the remote desktop to this computer,
303
+ or off, for text, pictures and files alike; a desktop can have its own, in its profile's settings (or its group's or
304
+ type's defaults) or in the form of a desktop behind an SSH host, and the Clipboard menu on such a desktop says so.
305
+ Only from the remote desktop stops the reading of this computer's clipboard altogether, so a desktop connected that
306
+ way only gets an empty one from this side; off leaves the clipboard channel out of the connection. **Paste to all
307
+ desktops** leaves out the desktops that don't take this computer's clipboard and says which, and files go only where
308
+ the clipboard does. Applies on the next connection; narrowing it also stops the sending right away to open desktops
309
+ that follow the setting, however it was changed (here, in another window, in the config file or by config sync),
310
+ takes back the files offered to them (a paste still pulling them fails), and stops a paste to all desktops or a save
311
+ of several files that is under way before its next step. Narrowing applies in full once those desktops reconnect. An
312
+ .rdp file's `redirectclipboard:i:0` (`0`, `00`, `+0` or `-0`, on any of its lines) now turns the clipboard off for the
313
+ profile it makes, where the import used to note it as not applied; a file can't turn it on, and without it the
314
+ profile follows its group's and type's defaults, which the import's question names. Importing such a file for a
315
+ desktop that already has a profile sharing the clipboard asks whether to turn it off there, rather than opening that
316
+ profile as it is. A desktop configured twice behind a host gets the narrower clipboard of the two, and a desktop
317
+ opened with a narrower clipboard while it is open already (from another profile for it, say) narrows the open one
318
+ until it is closed, its reconnects included and when it is shown again after its server ended it; its Clipboard menu
319
+ says so.
320
+ - **Paste to all desktops and Type into all desktops leave out the desktops that aren't showing.** In a split tab, a
321
+ desktop whose console was in front of it (or behind a pane maximized over it, nearly transparent) still got the
322
+ paste and every key typed into the others, passwords included, with nothing on screen saying so: its label was on
323
+ the hidden desktop. Now only the desktops showing get them, and the menus count only those; a key held down when a
324
+ desktop is hidden is still let go there.
325
+ - **An open remote desktop tab connects with its profile as saved.** Reconnect, Try again, automatic reconnects and a
326
+ reconnect at a new size used the profile as it was when the tab opened, so a new address or account only applied once
327
+ the tab was closed and the profile opened again. A tab whose profile now goes through an SSH profile no longer
328
+ connects directly.
329
+ - **Files saved from a remote desktop are marked as downloaded**, as a browser marks its downloads, so the system's
330
+ checks of downloads apply to them: on macOS, Gatekeeper's, for apps, scripts and installers opened from Finder; on
331
+ Windows, SmartScreen's and Office's Protected View. They were saved without the mark, so none applied. Not every kind
332
+ of file, or every way of opening one, gets those checks. A file that can't be marked (on a disk that keeps no such
333
+ marks) is saved anyway, and the message says the system may not warn before opening it, also when a later file
334
+ fails to save. A file that fails to be saved whole (on a full disk, say) isn't left there part saved. And what the
335
+ remote sends now goes into new folders of its own (one whose name is taken in Downloads gets a number, as a file
336
+ does, and each is made as it is chosen), never into a folder that was there before or made since, such as an app of
337
+ yours, which the system wouldn't check again.
338
+ - **Names of files saved from a remote desktop can't be disguised with invisible characters.** The remote chooses the
339
+ names, and invisible characters in one can change how it reads (one that reverses the text after it can make an
340
+ app's name end in ".pdf"). Those and control characters are now taken out (but for the invisible tags of a flag such
341
+ as England's, Scotland's or Wales', in such a flag: a region's code after a black flag, not text of any length), and
342
+ names are saved composed (NFC). On Windows, characters it doesn't allow in names become `_`, dots or spaces at the
343
+ end go, and a device's name (`CON`, `NUL.txt`), which would write to the device rather than a file, gets a `_` in
344
+ front. Letters that look like others can still mislead.
345
+ - **The .rdp import dialog can't be dressed up to read as a different address.** A file's address, gateway, user name
346
+ and domain are shown faithfully: control characters, right-to-left overrides, and zero-width and other characters
347
+ that don't show (variation selectors, tags, fillers, blanks other than the space) are refused (but for the joiners
348
+ between letters that Persian and Indic scripts write names with, in a user name or a domain), and a name written
349
+ with international letters is shown and saved as the punycode it actually resolves to, a gateway's port kept, so a
350
+ look-alike can't pose as a name you trust. The account is named with its domain (`CORP\alice`), and such
351
+ characters in the file's own name show as �.
352
+ - **The user name no longer goes out before the server is checked.** The first thing sent to a server, before
353
+ encryption, the certificate check and the stop at a server without NLA, carried the account's user name (a routing
354
+ cookie IronRDP adds), readable on the way and kept by servers the plugin then refused. The plugin's proxy now leaves
355
+ it out, and sends no request that still names the user. Servers don't need it: it is for load balancers that route by
356
+ user name, which the plugin doesn't support.
357
+ - **The fallback to TLS without forward secrecy can no longer be set off by words.** Windows' own certificate rules
358
+ out modern TLS in Tabby, so for it the proxy falls back to TLS 1.2 with RSA key exchange, which has no forward
359
+ secrecy. It did so whenever an error's message named the reason, and a gateway or an SSH host can word its own
360
+ errors; something on the network could also make the first handshake fail. It now falls back only on the TLS
361
+ library's own refusal, not on an error with its code that the SSH channel or the gateway underneath passed on, and
362
+ keeps to it only for a certificate that shows it rules out modern TLS, as Windows' does (one whose key usage can't
363
+ be read doesn't). Otherwise the connection stops, saying something may be interfering, and the next one starts
364
+ without the fallback. Later attempts of the same connection start with the fallback only once it worked with a
365
+ certificate that was accepted, and go back to modern TLS first after an attempt with it that doesn't get that far
366
+ (it fails, the server doesn't answer in time, or the attempt is closed first). A server whose TLS fails through the
367
+ system `ssh` no longer leaves an error behind that nothing handles.
368
+ - **An RD Gateway's answer is no longer kept, however long it says it is.** A gateway, or whatever answered in its
369
+ place on a first connection, could announce an answer of any length and send data until the step's time ran out,
370
+ all of it kept and copied over and over, with Tabby crawling meanwhile. The page that comes with a gateway's refusal
371
+ is now counted off and dropped as it arrives, its length must be a number and at most 256 KB, and the gateway's
372
+ control messages are held to the 125 bytes the standard allows. A gateway that takes the connection and never
373
+ starts TLS is given up on after 20 seconds, like the other steps, instead of being waited for, and a desktop closed
374
+ while its gateway's sign-in is under way ends it, sending nothing more and closing its connection, rather than letting
375
+ it run to those timeouts. A gateway could also freeze Tabby, or fill its memory, in ways that didn't depend on a
376
+ length: a header line with a stray line break after a long run of spaces held Tabby still for seconds while it was
377
+ matched; an administrator's message, which the log shows 300 characters of, was searched to its end, seconds for a
378
+ long one, at any time during a session; and each of its pings was answered with a pong that waited to be sent, so a
379
+ gateway that sent pings and read nothing had them pile up without end. Header lines are now split at their colon, and
380
+ refused with a line break of their own; only as much of a message as the log shows is read; and only the latest ping's
381
+ pong waits to go out, as the standard allows. And a gateway's messages (or a server's doings) can no longer grow a
382
+ desktop's log without end: only its first ten messages are logged, and the log keeps its first 200 lines and at least
383
+ its latest 2,000, saying how many it left out between them.
384
+ - **A remote desktop can't fill a shared folder's disk in an instant.** One request could make a file any size
385
+ without sending what is in it: on disks without sparse files (HFS+, NTFS, exFAT) that took the space at once, from
386
+ the whole disk, and elsewhere it made files that look petabytes long. Now the part of a file the remote sent no data
387
+ for may be no larger than the free space of the disk the file is on (a disk mounted inside a shared folder counts
388
+ for itself), less 1 GB (on a disk under 20 GB, a twentieth of its size). That part is counted from what the file
389
+ has on disk, so growing a file again and again doesn't get past it, and desktops in a Tabby window take turns growing
390
+ files on a disk, each checking the free space as the growth before it left it. Where files can have holes (APFS,
391
+ ext4), the limit is for each file on its own, and what it allows takes no space until written. The remote is told that
392
+ much less is free, so Explorer says before a copy that it won't fit. What the remote writes isn't limited: it takes
393
+ space as any copy does.
394
+ - **A remote desktop gets files sent from here 16 MB at a time at most, and pasted ones are read in the
395
+ background.** It could ask for all of a large file at once, as often as it liked: a pasted one was read in Tabby's
396
+ window, holding it up meanwhile (a third of a second and a gigabyte of memory for a 1 GB file), a dropped or picked
397
+ one into memory. A request for more than 16 MB of a file now gets an error, not part of it, which a remote could
398
+ take for all of it (FUSE, through which xrdp and GNOME Remote Desktop read pasted files, asks for 1 MB at most, 16
399
+ MB on systems with 64 KB pages). At most 64 MB is read for a desktop at a time; more requests wait their turn, and
400
+ past 256 waiting they get an error, as does a request on a stream that has one under way (the remote numbers its
401
+ streams, and couldn't tell which of two requests on one an answer is for). An answer counts only for the request it
402
+ was made for, matched by a number of the plugin's own, not the remote's: one for a request that is no more (expired,
403
+ or gone with the files offered) goes to no one. What is read for a
404
+ desktop's remote, parts of files and a shared folder's reads, waits in Tabby's window until its server reads it, and a
405
+ server that kept asking, and read what came back slowly or not at all, could fill the window's memory in seconds. Now
406
+ what is read for it, beyond what has gone out through the desktop's connection (everything the connection sends
407
+ counts, its other messages too), is at most 64 MB and one part more (16 MB at most), and about 8 MB more may wait on
408
+ the way to the server. A server that reads nothing at all gets no more than that; while one that reads keeps asking,
409
+ what waits can grow beyond it by as much as the proxy reads of the connection's other messages meanwhile. A file's
410
+ size and errors, and a shared folder's answers other than its reads (the names in a folder, a file's details), are
411
+ answered at once, outside that: a size or an error is about as large as the request it answers. A pasted file is read
412
+ a part at a time on Node's background threads, so a slow disk or network folder no longer holds Tabby up. A request
413
+ that can't be answered (for a pasted file replaced, removed or cut short since) gets an error, where it used to get no
414
+ answer at all, or a short one. And only the file that was pasted is read: one put in its place since, a link or a
415
+ pipe, isn't.
416
+ - **Other programs can no longer keep a desktop from connecting.** A desktop's local proxy takes four connections at
417
+ a time, and anything on this computer, or a web page in a browser, could take all four without knowing the proxy's
418
+ secret token: the desktop's own client was then turned away for as long as that went on. The token is now part of
419
+ the proxy's address and checked before a connection is let in, connections from pages in a browser are refused
420
+ whatever they have (sandboxed pages, which say they come from `null`, and extensions' included; the plugin's own
421
+ client is in Tabby's window, a file's page), and the token is compared in a way whose time doesn't tell how much of
422
+ a guess was right. Since the token is in the address, the plugin takes it out of IronRDP's errors, which name the
423
+ address when it can't connect there, before they reach the desktop's status and its log (**Copy log**). A desktop
424
+ closed while its proxy was starting no longer leaves the proxy running until Tabby quits, and one closed while it
425
+ connects no longer gets a clipboard, a video decoder, sound, the microphone or shared folders that nothing would
426
+ close.
427
+ - **The release workflow no longer takes whatever is newest.** It ran GitHub's checkout and Node.js actions by version
428
+ tag, which can be moved to other code, and installed the newest npm 11, all in the job that can publish the package.
429
+ The actions are now pinned to fixed commits, which Dependabot proposes updates to, and npm is the one that comes with
430
+ Node.js 26.8.2 (npm 11.19.1) rather than a download of its own. Only the publishing job can get npm's publishing
431
+ token, and it runs none of the dependencies' code: the package is built in a job of its own, and the publishing job
432
+ stages that very file, taken by the SHA-256 that job reported (any job of the run could replace the file it passes
433
+ on), without running any of its scripts.
434
+ - **The plugin needs ws 8.21.1 or later.** Before 8.21.1, ws let a connection send a message in any number of tiny
435
+ pieces and kept them all; a program on this computer that found the plugin's local proxy could fill Tabby's memory
436
+ that way and crash it, without knowing the desktop's token. A fresh install already got a fixed ws, but the plugin
437
+ accepted 8.18 and later, so an older copy kept in Tabby's plugin folder (by another plugin, say) stayed in use.
438
+ 8.21.1 is now the minimum.
439
+ - **The update check has limits.** It asked npm for the latest version with no limit on time or size, so whatever
440
+ answered in npm's name (a network that inspects TLS, say) could keep the request open for good or send without end
441
+ into Tabby's memory. It now gives up after 15 seconds or 256 KB; the answer is a few KB.
442
+ - **A desktop that drops right after connecting no longer reconnects every second without end.** Connecting reset the
443
+ waits between automatic reconnects, so a server that ended each connection at once, or a video decoder the browser
444
+ kept taking back, had the plugin connect and sign in again every second. The waits now start over only once a
445
+ connection has stayed up for 30 seconds: until then the usual 1, 2, 4, 8, 15 and 30 seconds apply, and automatic
446
+ reconnecting stops after them. A video decoder taken back twice within ten minutes turns H.264 off for that desktop,
447
+ as a decoding failure does, until Tabby restarts or the setting is turned on again.
448
+ - **An alternate spelling of a gateway is treated as the same gateway.** Its remembered certificate and the passwords
449
+ saved for it are keyed by one canonical form (lower case, no trailing dot, international letters as punycode, IPv6
450
+ compressed), so `RDGW.Example.com` and `rdgw.example.com` don't each get trusted on first use. A gateway setting that
451
+ names no host (`gw..example`, a name with `#`, `?`, `@` or `%` in it) is refused rather than read as part of one. A
452
+ gateway written with capitals, a trailing dot or international letters whose certificate was remembered asks once to
453
+ trust it again, unless an authority this computer trusts vouches for it; its old entry leaves Settings › Remote
454
+ Desktop › Certificates.
455
+ - **Removing or editing one desktop no longer drops a gateway's certificate, or one of a desktop at another address.**
456
+ The keys that hold a desktop's remembered certificate and its "Send the password anyway" choice were matched by how
457
+ they end, so a gateway's certificate, or a desktop whose address ended the same way, could go with it; they are
458
+ matched exactly now. A new address no longer takes the place of what a desktop already there has (its certificate,
459
+ sharpness or saved password), and where a desktop is known at the new address (its certificate remembered), the
460
+ saved password doesn't move there either: that desktop's certificate would check out, and it would sign in with the
461
+ password unasked. The edited desktop asks. Desktops at the same address behind different SSH hosts are still edited
462
+ and removed together, since a desktop's keys don't say which host it was added behind; so a saved password behind a
463
+ host moves only along with the certificate remembered for its desktop, which goes along and stays at the old address
464
+ too. Without one (forgotten in Settings › Certificates, which keeps the password), it is forgotten instead: it would
465
+ otherwise go, unasked, to whatever answered first at the new address behind its host, another host's desktop's
466
+ password included.
467
+ - **A malformed .rdp file is reported instead of failing in silence.** A file whose contents named a built-in property
468
+ (a line keyed `__proto__`, say) made the import stop with nothing shown; such a file is parsed without trouble now,
469
+ and an import that does fail says why.
470
+ - **A server that chooses NLA with early user authorization is no longer cut off right after signing in** when it
471
+ also sets the plain NLA flag: the plugin's proxy now reads that choice the way IronRDP does. And the proxy's stop
472
+ before a password goes to a server without NLA can't be left out by mistake: it refuses such servers unless it is
473
+ told otherwise, rather than letting them through.
474
+ - **The idle-shutdown watcher's folder and pid file on the SSH host are private**, as the plugin's folder is when the
475
+ desktop's setup makes it. Made by the watcher first, they were readable by other users; ones made so before are
476
+ made private the next time a watcher starts, the folder in `/tmp` it uses where the home folder can't keep them
477
+ included (one that can't be made private isn't used).
478
+
479
+ **Changed**
480
+ - **The package no longer includes source maps** (`dist/*.js.map`). They pointed at TypeScript sources that were never
481
+ in the package, so they were of no use to anyone installing it, and their long encoded lines are what package
482
+ scanners flag as "long strings" (possibly packed code). The package is about 450 KB smaller unpacked. `npm run
483
+ watch` still writes them, for debugging from the repository.
484
+
485
+ **Fixed**
486
+ - **"Send the password anyway" wasn't remembered.** The choice is meant to stay with that desktop and its certificate
487
+ (listed with it under Settings › Remote Desktop › Certificates), but the setting it's kept in was missing from the
488
+ plugin's defaults, and Tabby only saves settings a plugin's defaults name. The choice held until Tabby restarted and
489
+ was never written to the config, so a desktop without Network Level Authentication asked again after every restart.
490
+ A unit test now checks that every setting the plugin writes is in its defaults.
491
+ - **Turning `desk` off no longer turns a linked `~/.bashrc` or `~/.zshrc` into a copy** of the file it linked to (nor
492
+ one with other names, hard links, into a file of its own), and removes only the line it added: a line of yours that
493
+ merely ended like it went too, and one that mentioned it kept `desk` from adding its line at all. The line from
494
+ before 0.2 is removed only as those versions wrote it. The rest of the file is written back byte for byte (a last
495
+ line without its newline gets one), into the file itself, so its mode and owner stay; a read-only file is left as it
496
+ is, and the desktop's log (Settings › Remote Desktop › Troubleshooting › Open desktops › Copy log) says so, as it
497
+ does when the line can't be added. Should the writing fail part way (a full disk), what the file should hold stays
498
+ in the plugin's folder there, and the log says where.
499
+ - **A machine reached with `ssh` typed in an SSH tab says why when that host's ssh can't reach it.** ssh ends its
500
+ messages with CR LF, and the CR kept the plugin from recognizing the line that says how that ssh ended: a refused
501
+ sign-in or a connection that failed came back as if it were the command's output, and the desktop's setup failed
502
+ saying only that it gave no result. The failure is now reported in ssh's own words.
503
+ - **View only stays on for a desktop shown again after its server ended it**, as it does when it reconnects: shown
504
+ with the Desktop toggle or picked in the menu, it came back taking the keys typed in its pane.
505
+ - **A reconnect at a new size reconnects the same desktop.** In an SSH tab with two of a host's desktops open, one in
506
+ each pane, resizing the older pane with **Reconnect at the new size** opened the host's last used desktop there,
507
+ which went to the other pane, rather than reconnecting its own.
508
+ - **trd-pty works for a user whose uid is 2^31 or more.** It read such a uid as negative on Linux, so a session and
509
+ its client refused each other: the login went on as a plain shell, without tmux either, and the session it had
510
+ started stayed behind.
511
+ - **Removing a Hyper-V VM's desktop no longer forgets what is kept for another desktop.** Its entry was read as one for
512
+ 127.0.0.1:3389, and removing it forgot the saved password and the remembered certificate of every desktop at that
513
+ address behind an SSH host. What a VM signs in with, and its certificate, are its host's, for all of that host's
514
+ VMs, and stay, as the question before removing it now says. A desktop's address is now read the same way wherever it
515
+ is used, as it connects: removing one whose address was left empty, or whose port was written as `0` or as text such
516
+ as `"03390"`, forgets what is kept for it, where it forgot nothing; and a remote desktop profile through an SSH
517
+ profile whose port is written as text, such as `"03390"`, opens, where it said the desktop was no longer configured.
518
+
3
519
  ## 0.5.0
4
520
 
5
521
  Shared folders, desktops behind an RD Gateway, Hyper-V VMs' consoles, more of what an .rdp file says, text sent as