Skip to content

Avoid client config during server update checks - #698

Open
xhon-pelushi wants to merge 1 commit into
rustdesk:masterfrom
xhon-pelushi:fix-653-server-version-check-config
Open

Avoid client config during server update checks#698
xhon-pelushi wants to merge 1 commit into
rustdesk:masterfrom
xhon-pelushi:fix-653-server-version-check-config

Conversation

@xhon-pelushi

@xhon-pelushi xhon-pelushi commented Aug 12, 2026

Copy link
Copy Markdown

Summary

  • Build the server update-check request without going through the shared client fingerprint path.
  • Avoids initializing/writing client config under Docker bind mounts during hbbs version checks.

Fixes #653

Test plan

  • cargo test -p hbbs common::tests --no-default-features
  • Run hbbs in a read-only/bind-mounted config scenario and confirm update check no longer writes client config.

Summary by CodeRabbit

  • New Features

    • Software update checks now use server-specific requests.
    • Update requests identify the device using an available machine ID or a stable anonymous identifier.
  • Bug Fixes

    • Improved consistency and reliability of update-check request identification.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your trial has ended. Reactivate Greptile to resume code reviews.

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The 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.

Changes

Version check request

Layer / File(s) Summary
Build and validate the server request
src/common.rs
The version check uses a fixed endpoint and locally constructs the request. It selects a machine ID or derives a stable 32-byte anonymous device ID. Tests verify the request fields and ID stability.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: rustdesk

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: avoiding client configuration during server update checks.
Linked Issues check ✅ Passed The changes bypass the shared client fingerprint path and use server update requests, addressing issue #653 requirements.
Out of Scope Changes check ✅ Passed The request construction and stability tests are directly related to preventing client configuration during hbbs update checks.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/common.rs (1)

397-410: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add 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_request could recreate RustDesk.toml or 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 in src/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

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 81698a26-c447-41d8-b835-146f475a3dff

📥 Commits

Reviewing files that changed from the base of the PR and between a7736be and 158564e.

📒 Files selected for processing (1)
  • src/common.rs

Comment thread src/common.rs
Comment on lines +329 to +333
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();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 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 -240

Repository: 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 -300

Repository: 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:


🏁 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 || true

Repository: 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:


🌐 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:


🌐 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:


🌐 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:


🌐 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:


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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

hbbs writes client-style config file to data directory via Docker bind mount

1 participant