Repository navigation
Before you upgrade — read this
- Back up the database and the application key together. This release encrypts more data
with the application key (address-book peer passwords/hashes and pending OIDC results, in
addition to the authenticator secrets encrypted since v1.4). The key isAPP_KEYif you set
one, otherwise the key the container generated and persisted atstorage/app/.appkey.
A database restored without its matching key cannot decrypt those values — address-book
peers would lose their saved passwords, and authenticator (TOTP) secrets would be unreadable.
Keep the key and the database in the same backup, and give every API replica the same
APP_KEY(andAPP_PREVIOUS_KEYSwhen rotating). - Migrations run automatically when the container starts (the entrypoint runs
php artisan migrate --force, as in earlier releases). Five new migrations run once:Migration What it does Reversible add_presets_applied_at_to_devices_tableRecords when a device's enrollment-time presets were applied. Devices that have already reported inventory are marked as done. Yes add_approval_to_oauth_sessions_tableAdds the OIDC approval-step columns. Yes hash_client_and_deploy_tokensReplaces every stored client bearer token and deploy token with its SHA-256 digest in place (tokens already issued keep working), keys pending OIDC logins by a digest of the polling code, and encrypts an undelivered OIDC result. No — see below encrypt_address_book_peer_secretsEncrypts address_book_peers.passwordand.hashwith the application key. Idempotent.Yes, while the key is available add_two_factor_last_counter_to_users_tableTOTP replay protection. Yes - Upgrade in a short maintenance window, not as a mixed-version rolling update. Stop old
replicas, back up, start one upgraded instance (it migrates), then start the rest. An old
replica still running after the token migration cannot authenticate anyone (the plaintext token
column no longer exists), and an old replica would write unencrypted peer secrets. - Downgrading after the upgrade signs everyone out. The token digests cannot be turned back
into tokens, so rolling back to v1.6.x requires every client to sign in again and every deploy
token to be recreated. Restore the pre-upgrade backup instead if you must go back.
docker compose pull && docker compose up -dWhat changed
Device presets can no longer move an enrolled device (High)
/api/sysinfo accepts the OPTION_PRESET_* values a custom client or rustdesk --assign bakes in
(strategy, device group, address book, displayed name/note). Previously they were re-applied on
every upload and overrode admin assignments, so anyone who could read a machine's RustDesk id
and uuid (any local user) could move it into any strategy — and read that strategy's options,
including default-connect-password and proxy credentials — or into any device group, creating
groups at will.
Now presets are an enrollment-time action, which is how they were documented ("devices
auto-file … on first contact"):
- They apply on the device's first accepted sysinfo upload only.
- They fill blanks and never overwrite: an existing direct strategy, a non-default device
group, or an admin-set name/note is kept. strategy_nameanddevice_group_nameare matched against existing strategies/groups;
unknown names are ignored, and a device can never create a device group.- The client still receives
SYSINFO_UPDATEDas before.
Legitimate enrollment is unchanged: a new machine deployed with a custom client or --assign
still lands in its preset strategy and group. Behaviour change to note: if you relied on a
custom client's device_group_name preset creating a group, create that group in the console
first. To re-file a device that is already enrolled, use the console, the v1 API, or
rustdesk --assign (deploy-token authenticated) — not a new sysinfo upload.
Delegated administrators stay inside their scope (Medium-High)
- A strategy that is also assigned directly to a device outside a delegated admin's scope is
no longer considered in scope for that admin. rustdesk --assign//api/devices/cliand/api/devices/deploywith a delegated admin's
deploy token now respect that admin's scope: only in-scope strategies, only existing in-scope
device groups (no group creation), and no adoption of a device owned outside the scope. Full
administrators' tokens behave exactly as before.- Strategy options that point a client at other infrastructure or through a credentialed proxy —
custom-rendezvous-server,relay-server,api-server,key,proxy-url,proxy-username,
proxy-password— can now be added, changed or removed only by full administrators (console
and v1 API). Delegated editors can still save strategies that contain them unchanged.
OIDC device sign-in needs an explicit approval (High impact)
Signing in to RustDesk with an OIDC/OAuth provider now shows an approval page after the
provider sign-in: the requesting device's name, OS, RustDesk ID, the IP address that started the
request, and the time. No token is issued until the person presses Approve sign-in on this
device (a POST bound to a one-time value in the page and a same-site cookie). "Deny" discards the
request. This stops a phishing link built from an attacker's own sign-in request from silently
handing the victim's token to the attacker's device.
The RustDesk client's polling (/api/oidc/auth-query) and every JSON shape are unchanged — the
client simply keeps waiting until the user approves. Also:
/api/oidc/authis rate-limited per source (20 per minute; IPv6 per /64).- The runtime Nginx access log no longer records the query strings of
/api/oidc/auth-queryand
the OIDC callback, which carry the polling secret. If you run your own proxy in front, consider
doing the same there: the protocol fixes these values in the query string.
Credentials are no longer stored in plaintext (Medium)
- Client bearer tokens and deploy tokens are stored as SHA-256 digests and looked up by digest.
Existing tokens are hashed by the migration and keep working. - New deploy tokens created without an expiry date now expire after
RUSTDESK_DEPLOY_TOKEN_TTL_DAYSdays (default 365;0restores never-expiring tokens).
Existing deploy tokens keep the expiry they had. - Pending OIDC logins are keyed by a digest of the polling code; an undelivered result is
encrypted with the application key. - Address-book peer
passwordandhashare encrypted with the application key. The client
API returns exactly the same values as before. See "Before you upgrade" about the key.
Standalone web viewer removed from the public origin (Medium)
The bare development page /assets/webclient/src/ui/viewer.html now returns 404 from the
runtime image; the in-console Connect flow (which injects the server's own connection
settings) is unaffected. The standalone page, where it is still used for development, always
requires an encrypted, key-verified session and no longer takes the server host or key from the
URL. The injected viewer configuration is also escaped more strictly, and the viewer iframe no
longer requests clipboard-read permission it never used.
Login hardening (Medium / Low)
- Per-account ceiling: failed password attempts are counted per account name across all
source addresses (default 20 per 15 minutes, shared by the client API and the admin console) and
refused beyond that — checked before any LDAP bind, so this server cannot be used to lock
Active Directory accounts faster than the ceiling allows. A successful sign-in resets the count.
Tune withRUSTDESK_LOGIN_ACCOUNT_MAX_FAILURES(0 disables) and
RUSTDESK_LOGIN_ACCOUNT_DECAY_MINUTES. - IPv6 callers are rate-limited per /64 instead of per address.
- No account-state disclosure before a correct password: "Account disabled", "Account not
verified" and "must sign in via SSO" are shown only after the right password; unknown accounts
cost the same hashing time as known ones. - Console honours email login verification: accounts whose login verification is set to
email now receive a code by email when signing in to the admin console too (previously only the
RustDesk client asked for it). Mail must be working for those accounts; if the code cannot be
sent, sign-in fails closed. Before upgrading, check that mail delivery works for any
administrator whose login verification is "email"; if an administrator is locked out,
php artisan rustdesk:admin:reset <username> --generate --clear-2fa(inside the container)
sets a new password and turns login verification off for that account. - TOTP codes are single-use: a code (or an older one) that was already accepted cannot be
replayed within its validity window, in the client and in the console.
Browser security headers (Low)
Console responses now carry X-Content-Type-Options: nosniff,
Referrer-Policy: strict-origin-when-cross-origin, X-Frame-Options: SAMEORIGIN and
Content-Security-Policy: frame-ancestors 'self', plus Strict-Transport-Security on HTTPS
requests only. The in-console viewer (same origin) still works.
New settings
| Variable | Default | Meaning |
|---|---|---|
RUSTDESK_DEPLOY_TOKEN_TTL_DAYS |
365 |
Lifetime of a new deploy token created without an expiry date; 0 = never expires |
RUSTDESK_LOGIN_ACCOUNT_MAX_FAILURES |
20 |
Failed first-factor attempts per account (all sources) before refusing; 0 disables |
RUSTDESK_LOGIN_ACCOUNT_DECAY_MINUTES |
15 |
Window for the per-account ceiling |
TRUSTED_PROXIES=* remains the bundled default. As before, it is safe only when the application
port is reachable exclusively through a proxy that overwrites X-Forwarded-For; every IP-based
control (login limits, API-key and recording-upload IP allowlists) depends on it. See
Wiki/core/15-security.md → Inbound Proxy Boundary.
Not changed in this release
- The web viewer's managed mode still downgrades to an unverified session when no
RUSTDESK_PUBLIC_KEYis configured (the diagnostics page warns about it); making that fail
closed would break deployments without a configured key. - A malicious remote machine can still ask the viewer to show its elevation (UAC) credential form,
and peer clipboard content is applied without a notice — both match the native client and are
tracked for a later web-client release.