Qubes OS patches dom0 code execution flaw in qvm-copy-to-vm

On 2026-08-28 the Qubes OS Security Team published Qubes Security Bulletin 118 (QSB-118), disclosing an arbitrary code execution vulnerability in dom0, the most privileged domain in Qubes OS, reachable through the qvm-copy-to-vm tool's error reporting path. qvm-copy-to-vm copies a file from dom0 to a chosen qube using a simplified archive format called the qfile protocol. At the end of the transfer the receiving qube sends a confirmation back to dom0 containing a checksum, an error code, and the name of the last file it received. If the error code is nonzero, dom0 shows a GUI dialog naming the affected file, using the name the qube reported.

The flaw sits in how that filename is handled. The wait_for_result() function in dom0 runs the untrusted filename through sanitize_remote_filename() before displaying it, but that function only replaces non-ASCII characters and double quotation marks with underscores; it leaves shell metacharacters untouched. The sanitized string is then passed through call_error_handler() and gui_fatal() to display_error(), which builds a shell command string embedding the filename and hands it to system(). Because shell metacharacters survive sanitization, a malicious qube can name a file so that its reported filename is interpreted as extra shell syntax, letting the qube's command execute inside dom0 with dom0's privileges.

The practical scenario the bulletin describes: an attacker has already compromised a qube, and the Qubes user then runs qvm-copy-to-vm from dom0 to send a file into that compromised qube. When the qube reports back a crafted error and filename, the injected command runs in dom0, giving the attacker control of the whole Qubes OS system. The bulletin notes that the reverse direction is not affected: the VM-side error-reporting code (produce_message() in gui-fatal.c) shows the dialog by forking and calling execlp() on zenity or kdialog directly, never through system(), so it cannot be hijacked the same way.

All Qubes OS releases are affected. The fix ships as qubes-core-dom0-linux version 4.3.22 for dom0 on Qubes 4.3; the bulletin says the package is currently in the security-testing repository and will migrate to the stable repository after a short period of community testing, after which it installs through the normal Qubes Update tool. No user action beyond updating as usual is required. The Qubes Security Team credits the discovery to a researcher named Tim C., with no further identifying detail given, and the bulletin carries the cryptographic signatures of two Qubes maintainers, Marek Marczykowski-Górecki and Simon Gaiser (also known as HW42), following the project's standard practice of signing QSBs so users can verify their authenticity.

Key facts

  • Qubes Security Bulletin 118 (QSB-118), published 2026-08-28, discloses a dom0 arbitrary code execution bug in the qvm-copy-to-vm error reporting path.
  • sanitize_remote_filename() strips only non-ASCII characters and double quotes from an attacker-controlled filename, leaving shell metacharacters intact before the name reaches a system() call in dom0.
  • A qube the attacker has already compromised can exploit this when the user runs qvm-copy-to-vm from dom0 into it, letting the qube inject a command into dom0 and take control of the whole Qubes OS system.
  • The VM-side variant of the same tool is not affected, because its error dialog code calls execlp() directly instead of system().
  • All Qubes OS releases are affected; the fix is qubes-core-dom0-linux 4.3.22 for Qubes 4.3, moving from the security-testing to the stable repository after a short community testing period, and no special user action is needed beyond a normal update.

Why it matters

Dom0 is the one domain Qubes OS's entire security model treats as fully trusted: every other qube exists precisely so that a compromise stays contained away from dom0. This bug breaks that containment through an entirely ordinary action, copying a file out of dom0 into a qube, turning a routine file-copy error message into a path for a qube to run commands inside the domain the whole system is built to protect.

Who it affects

Every Qubes OS release, per the bulletin's own affected-systems statement. In practice the exposure is narrower: it triggers only when a user runs qvm-copy-to-vm from dom0 to a qube that is already compromised and the transfer then reports an error. Qubes users who never copy files from dom0 into other qubes, or whose qubes are not already compromised, are not exposed through this specific path.

How to use it

The fix is packaged as qubes-core-dom0-linux version 4.3.22 for dom0 on Qubes 4.3. It is currently in the security-testing repository and will move to the stable repository after a short period of community testing, after which it installs through the normal Qubes Update tool or its command-line equivalents. The bulletin states no other user action is required beyond continuing to update normally.

How solid is it

This is an official Qubes Security Bulletin, published by the Qubes Security Team and signed with the PGP keys of two named Qubes maintainers, Marek Marczykowski-Górecki and Simon Gaiser. The bulletin reproduces the actual vulnerable source, in linux-utils/qrexec-lib/pack.c and core-admin-linux/file-copy-vm/qfile-dom0-agent.c, and traces the exact call chain from wait_for_result() through sanitize_remote_filename(), call_error_handler(), gui_fatal(), and display_error() into the unguarded system() call. It also explains, with the VM-side source, why the same class of bug does not apply in the other direction.

Risks and caveats

The bulletin does not assign a CVE number to this vulnerability, and it gives no affiliation or further identity for the discoverer beyond the name Tim C. It states no fixed date for when the patch reaches the stable repository, only 'a short period of testing by the community.' It does not say the vulnerability has been exploited in the wild; it documents the mechanism and the fix, not an observed attack. It also does not explain how an attacker would first compromise the qube in this scenario, that step is a precondition to the exploit, not something the bulletin walks through.

“the attacker can exploit this vulnerability in order to inject an arbitrary command into dom0, which allows the attacker to take control of Qubes OS.”

— Qubes Security Bulletin 118