Avoid client config during server update checks - #698
Conversation
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
📝 WalkthroughWalkthroughThe version check now posts to a fixed endpoint with server-specific metadata. It uses a machine ID when available and a stable hashed anonymous ID otherwise. Tests verify the request type, device ID presence, and anonymous ID stability. ChangesVersion check request
Estimated code review effort: 2 (Simple) | ~10 minutes Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/common.rs (1)
397-410: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winAdd a regression test for the no-write guarantee.
The tests validate request fields and fallback repeatability. They do not exercise the filesystem behavior that motivated this PR. A future call to
hbb_common::version_check_requestcould recreateRustDesk.tomlor a second keypair while these tests remain green.Add an isolated subprocess or temporary-directory test with the server data/config directory read-only. Assert that no client configuration or extra keypair is created. The production entrypoint invokes
check_software_update()during startup insrc/main.rs, Lines 10-45.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/common.rs` around lines 397 - 410, Add a regression test covering the no-write guarantee of the startup update-check flow, using an isolated temporary directory and subprocess with the server data/config directory read-only. Invoke the production startup path that calls check_software_update(), then assert that RustDesk.toml, client configuration, and any additional keypair are not created; keep the existing server_version_check_request and anonymous_server_device_id tests unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/common.rs`:
- Around line 329-333: Update server_update_device_id to pseudonymize the value
returned by machine_uid::get() before converting it into the transmitted
device_id, using a purpose-specific domain-separated hash; preserve the existing
fallback behavior when the UID cannot be obtained.
---
Nitpick comments:
In `@src/common.rs`:
- Around line 397-410: Add a regression test covering the no-write guarantee of
the startup update-check flow, using an isolated temporary directory and
subprocess with the server data/config directory read-only. Invoke the
production startup path that calls check_software_update(), then assert that
RustDesk.toml, client configuration, and any additional keypair are not created;
keep the existing server_version_check_request and anonymous_server_device_id
tests unchanged.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
| fn server_update_device_id() -> Vec<u8> { | ||
| #[cfg(not(any(target_os = "android", target_os = "ios")))] | ||
| if let Ok(id) = machine_uid::get() { | ||
| return id.into(); | ||
| } |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- relevant files ---'
git ls-files | rg '(^|/)(src/common\.rs|Cargo\.toml|Cargo\.lock|README|.*update.*)$' | head -80
printf '%s\n' '--- target implementation ---'
cat -n src/common.rs | sed -n '250,370p'
printf '%s\n' '--- dependency and request references ---'
rg -n -C 3 'machine[_-]uid|VersionCheckRequest|device_id|server_update_device_id|update' Cargo.toml Cargo.lock src tests 2>/dev/null | head -240Repository: rustdesk/rustdesk-server
Length of output: 15648
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- local version-check definitions and usages ---'
rg -n -C 5 'struct VersionCheckRequest|VersionCheckRequest|version_check_request|device_id' . --glob '!target/**' --glob '!ui/target/**' | head -400
printf '%s\n' '--- dependency declarations ---'
cat -n Cargo.toml | sed -n '1,70p'
sed -n '1680,1715p' Cargo.lock
sed -n '2350,2385p' Cargo.lock
printf '%s\n' '--- update-related documentation ---'
rg -ni -C 3 'version/latest|version check|software update|device.?id|machine.?uid|fingerprint|telemetry|privacy' . --glob '!target/**' --glob '!ui/target/**' | head -300Repository: rustdesk/rustdesk-server
Length of output: 12195
🌐 Web query:
machine-uid 0.2.0 docs.rs confidential identifier get API
💡 Result:
The machine-uid crate (version 0.2.0 and later) provides a Rust API to retrieve a native machine identifier from the operating system without requiring root privileges [1][2][3]. The primary function for retrieving the ID is machine_uid::get, which is a re-export of machine_uid::machine_id::get_machine_id [4][5][6]. This function returns a Result<String, Box> [5]. Example usage: extern crate machine_uid; fn main { let id: String = machine_uid::get.unwrap; println!("{}", id); } The crate documentation explicitly states that the retrieved machine ID should be considered confidential and must not be exposed in untrusted environments [1][4]. While the ID uniquely identifies a host, it is not necessarily immutable, as it can be re-generated by a root user [1][6]. The crate retrieves this identifier from the following platform-specific sources: - Linux (or systemd-based systems): /var/lib/dbus/machine-id or /etc/machine-id [1][4] - BSD: /etc/hostid or kenv -q smbios.system.uuid [1][4] - macOS: gethostuuid(3) [3][4] - Windows: The MachineGuid value in the registry at HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography [1][3][4] - illumos: gethostid(3C) [3][4] Version 0.2.0 was notable for adding support for Windows [7][3]. As of August 2026, the crate has seen multiple updates and is currently at version 0.6.0 [2][3][8].
Citations:
- 1: https://docs.rs/crate/machine-uid/0.2.0
- 2: https://crates.io/crates/machine-uid/0.2.0
- 3: https://crates.io/crates/machine-uid
- 4: https://docs.rs/machine-uid/latest/machine_uid/
- 5: https://docs.rs/machine-uid/latest/machine_uid/machine_id/fn.get_machine_id.html
- 6: https://docs.rs/machine-uid
- 7: https://github.com/Hanaasagi/machine-uid
- 8: https://docs.rs/crate/machine-uid/latest/source/
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- hbb_common layout ---'
git ls-files libs/hbb_common | head -120
printf '%s\n' '--- VersionCheckRequest definitions ---'
rg -n -i -C 8 'version.?check|device.?id|struct .*Request' libs/hbb_common src --glob '*.rs' --glob '*.proto' --glob '*.toml' | head -500
printf '%s\n' '--- generated/build inputs ---'
rg -n -i -C 5 'VersionCheck|device_id|version/latest|VER_TYPE_RUSTDESK' libs/hbb_common build.rs src --glob '!target/**' | head -400
printf '%s\n' '--- endpoint references outside this repository ---'
rg -n -i 'api\.rustdesk\.com|version/latest|VersionCheckRequest|VER_TYPE_RUSTDESK_SERVER' .github debian docs README* 2>/dev/null || trueRepository: rustdesk/rustdesk-server
Length of output: 9563
🌐 Web query:
site:github.com/rustdesk/rustdesk VersionCheckRequest device_id version_check_request
💡 Result:
The VersionCheckRequest is a function and associated data structure used in RustDesk, an open-source remote desktop software, to check for application updates [1][2][3]. When the RustDesk client starts, it executes a routine that calls the version_check_request function [1][3]. This function generates a request payload containing telemetry and system metadata, which is then sent via an HTTP POST request to the update endpoint, typically https://api.rustdesk.com/version/latest [4][1][5]. The data transmitted in this request includes: - OS information (e.g., windows) [4] - OS version details [4] - System architecture (e.g., x86_64) [4] - A persistent device ID (fingerprint) [4][6] - Client type (e.g., rustdesk-client) [4] The server processes this request and returns a response, which the client parses as a VersionCheckResponse to determine if a newer version of the software is available [1][3]. If a newer version is identified, the client may notify the user or trigger update-related events [1][3]. This mechanism has been a topic of discussion within the RustDesk community due to privacy concerns regarding the transmission of persistent device identifiers and system metadata during the update check process [4][6]. Some users have sought ways to disable these calls or implement their own local update checking mechanisms [6][7].
Citations:
- 1: https://github.com/rustdesk/rustdesk/blob/master/src/common.rs
- 2: https://github.com/rustdesk/rustdesk/blob/03e351ac/src/common.rs
- 3: https://github.com/rustdesk/rustdesk/blob/2fbc0625de22527b2fe7f51709f4673ab4b4b029/src/common.rs
- 4: Update check sends persistent device fingerprint although response appears identical rustdesk#15114
- 5: https://github.com/rustdesk/rustdesk/blob/caadd72a/src/common.rs
- 6: Mysterious https request rustdesk#11055
- 7: Option to disable check for new version call to https://api.rustdesk.com/version/latest #562
🌐 Web query:
site:github.com/rustdesk/rustdesk-server "VER_TYPE_RUSTDESK_SERVER" "device_id"
💡 Result:
VER_TYPE_RUSTDESK_SERVER is an internal constant used within the RustDesk server source code to facilitate software version checking [1]. Specifically, it is used as a parameter when the server performs a request to check for available software updates [1]. By passing this identifier to the version check service, the server helps ensure it retrieves the appropriate release information relevant to the RustDesk server environment [1]. Regarding the term device_id in the context of RustDesk: 1. Internal Representation: In the RustDesk server database, peers are uniquely identified by a guid (globally unique identifier) and an id [2][3]. The id corresponds to the RustDesk ID visible in the client application [2]. 2. Configuration: In modern versions of the RustDesk client, the ID is often stored as an encrypted value (enc_id) within the local configuration file (RustDesk.toml) to prevent unauthorized manual modification [4]. 3. Relationship: The device_id (or RustDesk ID) acts as the primary key for identifying clients and servers within the rendezvous (hbbs) server's peer database, allowing the system to route connections correctly [2][3]. There is no direct functional link between the internal code constant VER_TYPE_RUSTDESK_SERVER and an individual client's device_id; they serve distinct purposes—the former for software lifecycle management and the latter for network identification [1][2].
Citations:
- 1: https://github.com/rustdesk/rustdesk-server/blob/815c7288/src/common.rs
- 2: https://github.com/rustdesk/rustdesk-server/blob/815c7288/src/database.rs
- 3: https://github.com/rustdesk/rustdesk-server/blob/815c7288/src/peer.rs
- 4: change id #22
🌐 Web query:
github rustdesk hbb_common VersionCheckRequest device_id version_check_request source
💡 Result:
In the RustDesk codebase, VersionCheckRequest is a data structure defined in the hbb_common library used to facilitate software update checks [1]. It is part of the mechanism that sends device and system information to the RustDesk API server (typically https://api.rustdesk.com/version/latest) to determine if a newer version of the software is available [1][2][3]. The VersionCheckRequest struct is defined as follows: #[derive(Debug, Default, Deserialize, Serialize)] pub struct VersionCheckRequest { #[serde(default)] pub os: String, #[serde(default)] pub os_version: String, #[serde(default)] pub arch: String, #[serde(default)] pub device_id: Vec, #[serde(default)] pub typ: String, } The version_check_request helper function, also located in hbb_common, populates this request with current system details [1]: - os: The operating system distribution identifier [1]. - os_version: The version string of the OS [1]. - arch: The CPU architecture of the host system [1]. - device_id: A unique device fingerprint generated using the fingerprinting module within hbb_common [1][4]. This fingerprinting system creates unique identifiers based on hardware and software characteristics—such as CPU brand, MAC address, and memory information—to identify unique installations [4][5]. - typ: A string indicating the type of application performing the check (e.g., the RustDesk client) [1][2]. This request is sent via an HTTP POST request to the update server to help the client receive relevant update information [2].
Citations:
- 1: https://github.com/rustdesk/hbb_common/blob/53709d8f/src/lib.rs
- 2: https://github.com/rustdesk/rustdesk/blob/03e351ac/src/common.rs
- 3: Option to disable check for new version call to https://api.rustdesk.com/version/latest #562
- 4: https://deepwiki.com/rustdesk/hbb_common/6.3-fingerprinting
- 5: https://deepwiki.com/rustdesk/hbb_common
🌐 Web query:
github rustdesk api.rustdesk.com/version/latest device_id hash fingerprint server implementation
💡 Result:
The endpoint api.rustdesk.com/version/latest is used by the RustDesk client to check for software updates [1][2]. When a request is made to this URL, the client transmits a JSON payload containing device metadata, including a persistent device ID and operating system information [1][3]. Device Identification and Fingerprinting The device_id included in the version check request is generated using a fingerprinting system [1]. This system collects various host system characteristics—such as CPU architecture, OS platform, memory, and MAC address—and combines them into a unique identifier [4]. The implementation uses a combination of SHA-512 hashing and AES-128 encryption to secure the generated fingerprint [4]. This persistent identifier allows the system to distinguish between unique client installations [3][4]. Server Implementation and Purpose The endpoint is primarily a public resource maintained by RustDesk to inform clients of the latest available version [3][2]. The server receives the POST request with the metadata and responds with a JSON object, typically containing the URL for the most recent release [3]. Important Distinctions It is critical to distinguish this version-check mechanism from the RustDesk peer-to-peer security and authentication architecture [5][6]: 1. Version Checking: This involves an HTTP POST to api.rustdesk.com using the device fingerprint as described above [1][3]. It is not used for peer authentication. 2. Peer Authentication (HBBS/HBBR): RustDesk uses an Ed25519-based Public Key Infrastructure (PKI) for securing peer-to-peer connections [5][6]. During a session, clients verify the server (or peer) identity using signed public keys [5][7]. Once the connection is established, symmetric encryption is negotiated via Curve25519 for secure communication [7]. 3. Fingerprints in Connections: In the context of P2P connections, a fingerprint is also used (often displayed to the user) to represent the remote peer's Ed25519 public key [5]. This is part of a Trust-on-First-Use (TOFU) mechanism to help users detect potential man-in-the-middle attacks, which is unrelated to the persistent hardware device ID sent during version checks [5]. The device_id transmitted to the API is solely for version-check telemetry and does not perform authentication or server-side authorization [3]. Users concerned about this telemetry have noted that the information appears to be logged or collected by the API server, and some have opted to block requests to this domain or overwrite the update URL to mitigate privacy concerns [3][8].
Citations:
- 1: https://github.com/rustdesk/hbb_common/blob/53709d8f/src/lib.rs
- 2: https://github.com/rustdesk/rustdesk/blob/03e351ac/src/common.rs
- 3: Update check sends persistent device fingerprint although response appears identical rustdesk#15114
- 4: https://deepwiki.com/rustdesk/hbb_common/6.3-fingerprinting
- 5: https://deepwiki.com/rustdesk/rustdesk/2.5-security-and-authentication
- 6: https://deepwiki.com/rustdesk/rustdesk-server/2.5-security-architecture
- 7: https://deepwiki.com/rustdesk/rustdesk/2.3-client-server-communication
- 8: Option to disable check for new version call to https://api.rustdesk.com/version/latest #562
🌐 Web query:
github rustdesk discussion 15114 version check device id privacy machine uid
💡 Result:
The RustDesk GitHub discussion #15114 addresses privacy concerns regarding the application's update check routine [1]. Users reported that during this process, the client transmits a persistent device fingerprint, along with operating system metadata, to the update endpoint [1]. Key aspects of the discussion include: - Transmission of Data: The RustDesk client sends an automated request containing system details—such as OS, OS version, architecture, and a device ID—to the server to check for updates [1]. - Privacy Concerns: Community members expressed concern that this process transmits persistent identifiers that are not strictly necessary for update selection, as the server response (a public GitHub release URL) appears identical regardless of the metadata sent [1]. - Potential Implications: While not suggesting malicious intent, participants noted that transmitting these persistent identifiers creates a technical capability for device-specific or targeted update delivery, which may raise regulatory or privacy issues [1]. Related to the broader topic of device identification, RustDesk uses machine-specific identifiers (UUIDs/Machine IDs) to manage connections [2][3]. On Windows, the client has historically utilized the registry-based MachineGuid for generating these identifiers [2]. Users have noted that this can lead to identical UUIDs on cloned machines that have not been properly sysprepped [2][4]. To differentiate devices, the application also relies on a randomly generated unique public key (PK) stored in configuration files [3]. Additionally, a security vulnerability (CVE-2026-30785) has been documented concerning the handling of the machine UID, password security, and config encryption in RustDesk versions through 1.4.5 [5]. Users concerned about telemetry and data transmission frequently discuss these issues in the context of maintaining privacy and trust, particularly when using RustDesk in self-hosted or local network environments [6][7].
Citations:
- 1: Update check sends persistent device fingerprint although response appears identical rustdesk#15114
- 2: Some cloned machines can get the same UUID rustdesk#11515
- 3: Multiple RustDesk IDs on the Same Device rustdesk#14200
- 4: Some cloned machines can get the same UUID rustdesk#11506
- 5: https://nvd.nist.gov/vuln/detail/CVE-2026-30785
- 6: The telemetry makes this insecure and untrustworthy. rustdesk#14132
- 7: Direct connections should not cause error "Login required for public server" rustdesk#14804
Pseudonymize the machine UID before transmission.
machine_uid::get() returns a host-unique identifier that its documentation marks confidential. id.into() copies it unchanged into VersionCheckRequest.device_id, which the update request sends to https://api.rustdesk.com/version/latest. Hash it with a purpose-specific domain before transmission, or document an explicit trust-boundary exception.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/common.rs` around lines 329 - 333, Update server_update_device_id to
pseudonymize the value returned by machine_uid::get() before converting it into
the transmitted device_id, using a purpose-specific domain-separated hash;
preserve the existing fallback behavior when the UID cannot be obtained.
Source: MCP tools
Summary
hbbsversion checks.Fixes #653
Test plan
cargo test -p hbbs common::tests --no-default-featureshbbsin a read-only/bind-mounted config scenario and confirm update check no longer writes client config.Summary by CodeRabbit
New Features
Bug Fixes