Checks whether the current system is running inside a virtual machine, using a
weighted set of heuristics (CPU flags, systemd-detect-virt, MAC address and
disk model signatures, DMI/BIOS vendor strings, kernel modules and guest
tools). Available as a command-line tool and as a cross-platform desktop GUI,
on both Linux and Windows.
This is a Cargo workspace:
vm-check-core: the detection engine (a library). All platform-specific checks and the confidence-scoring logic live here.vm-check-cli: the command-line interface (binaryvm-check).vm-check-gui: the desktop GUI (binaryvm-check-gui), built with egui.
-
A Rust toolchain. That's all you need to build
vm-check-cli. -
Building
vm-check-guion Linux additionally needs some system development packages for the windowing/GUI stack. On Debian/Ubuntu:sudo apt install libgtk-3-dev libxkbcommon-dev libxcb-shape0-dev libxcb-xfixes0-dev libxcb-render0-dev
These are only needed to build the GUI; the resulting binary doesn't need
libgtkat runtime, just a running X11 or Wayland session. -
Building on Windows needs no extra system packages beyond the Rust toolchain (the MSVC or GNU
x86_64-pc-windowstarget, whicheverrustupinstalled):cargo buildhandles the rest. -
Cross-compiling for Windows from Linux (
--target x86_64-pc-windows-gnu) additionally needs the MinGW-w64 linker. On Debian/Ubuntu:sudo apt install gcc-mingw-w64-x86-64 rustup target add x86_64-pc-windows-gnu
cargo build --release --workspaceBinaries are produced at target/release/vm-check (CLI) and
target/release/vm-check-gui (GUI); on Windows these are vm-check.exe and
vm-check-gui.exe.
Each release has ready-to-run archives attached:
vm-check-linux-x86_64.tar.gz and vm-check-windows-x86_64.zip. Extract and
run: no installer, nothing to register with the system.
vm-check # run all checks, prompting once if elevated checks are needed
vm-check --no-elevate # skip checks that need root/sudo (dmesg, dmidecode) entirely
vm-check -y # don't prompt, run elevated checks automatically
vm-check --json # machine-readable output for scripting/CI
vm-check -v # show extra detail (matched strings, skip reasons) per checkExit codes: 0 likely physical, 1 likely a virtual machine, 2 uncertain,
3 internal error.
On Windows, run it the same way from cmd.exe or PowerShell:
.\vm-check.exe
.\vm-check.exe --jsonRun vm-check-gui and click "Run checks". On Windows, double-click
vm-check-gui.exe (no console window is needed) or launch it from
PowerShell/cmd.exe.
Only two checks need elevated privileges, and only on Linux: dmesg (reading
the kernel ring buffer) and dmidecode (which falls back to sudo only if
the unprivileged DMI sysfs read fails). Every other check, including all
Windows checks (WMI queries, HKLM registry reads), runs fine as a normal
user; Windows never needs Administrator / UAC elevation for any check.
- CLI, Linux: if any privileged checks apply,
vm-checkasks once ("N check(s) need elevated privileges, run them? [Y/n]") and shells out tosudoonly for those specific checks. Use-y/--yesto skip the prompt and proceed, or--no-elevateto skip those checks entirely (nosudoinvocation at all). - GUI, Linux: privileged checks are opt-in via a checkbox in the window.
Since a windowed app can't sensibly show an interactive terminal
sudoprompt, the practical way to include them is to relaunch the whole GUI as root, e.g.sudo vm-check-gui, and then tick the checkbox.
cargo test --workspaceThis runs:
vm-check-core: unit tests for every detection heuristic (including the German translations) against a mocked evidence source (MockLinuxEvidence/MockWindowsEvidence), so no real host/VM state is needed, plus tests forSystemEvidence's real file/subprocess I/O against the actual machine running the tests.vm-check-cli: unit tests for argument-independent logic (confirm_elevation, output formatting, exit codes), and integration tests invm-check-cli/tests/cli.rsthat spawn the compiledvm-checkbinary, sincemain()callsstd::process::exitand can't be exercised in-process.vm-check-gui: unit tests for the background check-running logic and the language/theme/persistence logic (i18n.rs,App::from_storage/saveagainst a mockedeframe::Storage), plus UI tests that driveApp's rendering through egui's own in-memoryContext::run, which performs a full immediate-mode layout pass without a display or GPU.
CI (.github/workflows/ci.yml) runs this test suite plus cargo fmt --check
and cargo clippy -D warnings on every push, on both Linux and Windows.
cargo install cargo-llvm-cov
rustup component add llvm-tools-preview
cargo llvm-cov --workspace --summary-onlyPhysical Linux host, every check passes:
Windows VM guest, every check fails:
| Light theme, physical Linux host | Dark theme, same host | Windows VM guest |
|---|---|---|
![]() |
![]() |
![]() |




