Update: Please note that QSB-071 was updated on 2021-09-17. See below for the updated version, including the changelog.

We have just published Qubes Security Bulletin (QSB) 071: Fatal options filtering flaw in Split GPG. The text of this QSB is reproduced below. This QSB and its accompanying signatures will always be available in the Qubes Security Pack (qubes-secpack).

View QSB-071 in the qubes-secpack:


In addition, you may wish to:

             ---===[ Qubes Security Bulletin 071 ]===---


              Fatal options filtering flaw in Split GPG


2021-09-09: Original QSB published
2021-09-17: Updated impact section

User action required

Users must install the following specific packages in order to address the
issues discussed in this bulletin:

  For Qubes 4.0, in templates and standalones:
  - qubes-gpg-split 2.0.53

  For Qubes 4.1, in templates and standalones:
  - qubes-gpg-split 2.0.53

Due to the ease with which this flaw can be exploited, we are immediately
migrating these packages to the current (stable) repository, bypassing the
usual testing period. These packages are to be installed via the Qubes Update
tool or its command-line equivalents. [1]


Split GPG [2] is designed to isolate private keys from the application using
them in order to protect them from being extracted and to allow the user to
retain control over when they are used. This isolation is implemented by
forwarding calls to `gpg` into a backend qube that holds the private keys and
allowing only specific `gpg` options. This option filtering mechanism rejects
options like `--export-secret-keys` and others that might leak private keys to
the frontend qube. Unfortunately, several options were declared incorrectly,
which allowed this filtering mechanism to be bypassed.


An attacker controlling a frontend qube (where `qubes-gpg-client` is executed)
can execute arbitrary commands and extract arbitrary files (including secret
keys) from the backend qube.


Several `gpg` options were declared incorrectly in Split GPG, which resulted in
Split GPG interpreting them differently than `gpg`. If Split GPG interpreted
one option as an argument to another option, Split GPG would allow it, since
option filtering is performed at the level of the options themselves, not their
arguments. This would allow options misinterpreted as arguments to bypass the
filtering mechanism. Specifically:

- All `--s2k-*` options were declared as not taking arguments when in fact they
  do take arguments.
- `--export-ssh-key` was declared as taking an argument when it doesn't take
  one directly; it does change the meanings of positional arguments, however.
- `--with-colons` was aliased with `-k`, which differs in its argument
- `--default-recipient`, which takes an argument, was interpreted as
  `--default-recipient-self`, which does not take an argument.
- `--display` was interpreted as `--display-charset`, which resulted in
  `--display` being allowed when it should have been denied.

For our immediate, initial response, we have corrected all of these
inconsistencies and added automated testing to verify that GnuPG and Split GPG
both understand the options in the same way.

More generally, we will prioritize finishing Split GPG 2 [3], which does not
rely on option filtering at all. Instead, it uses `gpg-agent`'s protocol to
delegate only secret key processing to the backend qube. In addition to
obviating the need for fragile option filtering, this dramatically reduces the
attack surface, as most of the untrusted data processing is done in the
frontend qube and never reaches the backend qube.


This issue was discovered by Demi Marie Obenour.


[1] https://www.qubes-os.org/doc/updating-qubes-os/
[2] https://www.qubes-os.org/doc/split-gpg/
[3] https://github.com/QubesOS/qubes-issues/issues/474

The Qubes Security Team