I have a question regarding the security of storing a VM’s output into a dom0 variable.
I wrote a shell script in dom0 to automate my backup process. It interacts with a backup VM (sys-backup) and a USB VM (sys-usb) with a YubiKey. To make the automation work, the script captures the command output from the VM (like encryption keys or backup targets) and stores it into a dom0 variable, which is then passed as an argument to subsequent dom0 backup commands (like qvm-backup).
However, I am feeling a bit anxious about this approach. Conceptually, storing a VM’s output into a dom0 variable feels almost identical to copy-pasting untrusted data directly into dom0. If the VM were to be compromised, this could potentially open the door to a command injection attack or shell exploitation in dom0.
My questions are:
- Is this variable assignment pattern inherently dangerous in Qubes OS?
- Since I absolutely need these variables to run dom0-specific backup commands, is there any way to make this process safer?
- How can I properly sanitize or validate the VM’s output within dom0 before storing it as a variable to prevent any malicious shell execution?
Here is the script
#!/bin/bash
qvm-shutdown --all --wait
qvm-start sys-backup sys-usb
sleep 30
YUBIKEY=$(qvm-usb l | grep “Yubikey” | awk ‘{print $1}’)
USBS=$(qvm-block l | grep “Storage” | awk ‘{print $1}’)
BACKUP_VMS=$(qvm-ls --raw-list | grep -E “^(vault|anon-whonix)”)
BACKUP_PW=“changeme”
echo $BACKUP_PW | qvm-backup --dest-vm sys-backup --passphrase-file - -y /home/user/ $BACKUP_VMS
SYS_BACKUP_PATH=$(qvm-run -p sys-backup “echo qubes-backup-*”)
USB_BACKUP_PATH=/mnt/$SYS_BACKUP_PATH
qvm-usb attach sys-backup $YUBIKEY
for i in ${USBS[@]}; do
qvm-block attach sys-backup $i
qvm-run -p sys-backup '
YK_CHALLENGE="changeme"
LUKS_PW=$(ykman otp calculate 2 "$(echo -n "$YK_CHALLENGE" | xxd -p)" |tr -d "\n" )
printf "%s" "$LUKS_PW" | sudo cryptsetup luksOpen /dev/xvdi backup_usb --key-file -
sudo mount /dev/mapper/backup_usb /mnt
BACKUP_PATH=$(echo /home/user/qubes-backup-*)
cp "$BACKUP_PATH" /mnt/
sudo sync'
USB_NAME=$(qvm-block l | grep $i | awk '{print $6,$7,$8}')
if echo $BACKUP_PW | qvm-backup-restore --dest-vm sys-backup --verify-only --passphrase-file - $USB_BACKUP_PATH; then
notify-send "Backup $USB_NAME: SUCCESS & VERIFIED" -u critical -i dialog-information
else
notify-send "Backup $USB_NAME: VERIFICATION FAILED" -u critical -i error
fi
qvm-run -p sys-backup '
sudo umount /mnt
sudo cryptsetup luksClose backup_usb'
qvm-block detach sys-backup $i
done
qvm-shutdown --all --wait
qvm-start sys-usb sys-whonix