See how gnupg compares to other vendors in security performance
CMS (Cryptographic Message Syntax) parsing in gpgsm in GnuPG through 2.5.20 mishandles the CMS format for AES-GCM because aes-ICVlen is supposed to be 12 bytes but 4 bytes is accepted. NOTE: this is related to CVE-2026-34182.
Alan Coopersmith <alan.coopersmith () oracle com> writes: The common failure is accepting the sender provided length for the authentication tag, and not enforcing the minimum length specified in the RFC - allowing an attacker to specify a one-byte tag length and then use brute force to determine which of the 256 possible values matches the first byte of the actual tag. As with far too many other RFCs, the required skill for them isn't implementing them correctly, it's knowing which bits you need to ignore in order to implement them appropriately. I just checked my code and it hardcodes an allowed MAC length range of 16 ... 64 bytes for RFC 6476 use (Authenticated-Enveloped-Data, but with an explicit MAC), so no matter what any RFC says you can't feed it a MAC value less than 128 bits.
And an additional thought, these are all very high-visibility libraries and therefore obvious targets for checking whether they get it right. Given the failure rate with those, I wonder how many other lesser-known ones also got it wrong?
Peter.
https://blog.calif.io/p/how-to-format-a-ciphertext discusses how the issue that OpenSSL disclosed on June 9 as CVE-2026-34182 similarly affected the PKCS#7 / CMS parsing implementations from WolfSSL, Bouncy Castle, & GnuPG.
The common failure is accepting the sender provided length for the authentication tag, and not enforcing the minimum length specified in the RFC - allowing an attacker to specify a one-byte tag length and then use brute force to determine which of the 256 possible values matches the first byte of the actual tag.
The OpenSSL CVE-2026-34182 was already covered on oss-security in: https://www.openwall.com/lists/oss-security/2026/06/09/15
The WolfSSL CVE-2026-5500 was also already sent here in: https://www.openwall.com/lists/oss-security/2026/04/14/6
https://x.com/califio/status/2068786334844715142 notes: Both Bouncy Castle and GnuPG have acknowledged and fixed the reported issues.
CVE-2026-12802 will be published with Bouncy Castle 1.85. -- -Alan Coopersmith- alan.coopersmith () oracle com Oracle Solaris Engineering - https://blogs.oracle.com/solaris
Libgcrypt before 1.12.2 sometimes allows a heap-based buffer overflow and denial of service via crafted ECDH ciphertext to gcrypkdecrypt.
Last updated 27 May 2026
Last updated 27 May 2026
The following announcement regarding libcrypt security releases was posted to gnupg-announce and related lists today. The forward is unedited except for trimming some footers inserted by mailing list software and the PGP/MIME signature.
----- Forwarded message from Werner Koch via Gnupg-devel <gnupg-devel () gnupg org> -----
Date: Tue, 21 Apr 2026 12:28:09 +0200 From: Werner Koch via Gnupg-devel <gnupg-devel () gnupg org> To: gnupg-announce () gnupg org Cc: Werner Koch <wk () gnupg org>, info-gnu () gnu org Subject: [Announce] [Security fixes] Libgcrypt 1.12.2, 1.11.3, 1.10.x released
Hello!
We are pleased to announce the availability of couple of new Libgcrypt versions: 1.12.2, 1.11.3, and 1.10.4 . It is suggested to use 1.12.2 which is fully compatible with all earlier versions.
This version fixes a security bug [T8211] which can be used used to mount a DoS using ECDH encryption (with NIST, Brainpool, X448, or X25519 curves). Note that GnuPG versions since 2.5.7 are not affected by this bug due to the use of a different encryption API.
Another security bug [T8208] was fixed in the Dilithium signing algorithm which is available since version 1.12.0.
Noteworthy changes in version 1.12.2 (2026-04-15) ====================================
Bug fixes:
- Fix possible ECDH buffer overwrite with zeroes. [T8211]
- Add a missing bounds check to the Dilithium context handling. Reported by Calif.io in collaboration with Claude and Anthropic Research. [T8208]
- Add point validation when using the new KEM interface. [T8212]
Other:
- Fix the dead-code of strongerkeycheck for RSA. [T8171]
For a list of links to commits and bug numbers see the release info at https://dev.gnupg.org/T8114 . However, due to an ongoing AI scraper DDoS the site might not be reachable at all times or from all IPs.
Noteworthy changes in version 1.11.3 (2026-04-21) ====================================
Bug fixes:
- Fix possible ECDH buffer overwrite with zeroes. [T8211]
- Add point validation when using the new KEM interface. [T8212]
- Fix compiler error on NetBSD. [T7633]
- mceliece6688128f: Fix stack overflow crash on win64/wine [rCb17ed8d1af]
- Apply a Kyber patch from upstream. [rC5ba143d51f]
- Use CSIDLCOMMONAPPDATA instead of /etc on Windows. [rC995b870fd2]
- Use secure MPI in gcrympiassignlimbspace. [rC520c699c82]
- Fix a regression with disabled public-key algo for FIPS. [T7338,rCc6e0658004]
Other:
- Handle HAVEBROKENMLOCK for the case of building with ASAN. [T7889]
- Add stack burning for PQC algorithms. [rC289c0a596f]
Release-info: https://dev.gnupg.org/T8232
Noteworthy changes in version 1.10.4 (2026-04-21) ====================================
NOTE: The 1.10 series reaches end-of-life in 6 weeks.
Bug fixes:
- Fix possible ECDH buffer overwrite with zeroes. [T8211]
- Fix AESWRAP padding length check. [T7130]
Other:
- Handle HAVEBROKENMLOCK for the case of building with ASAN. [T7889]
Release-info: https://dev.gnupg.org/T8233
Download ========
Source code is hosted at the GnuPG FTP server and its mirrors as listed at https://gnupg.org/download/mirrors.html. On the primary server the source tarball and its digital signature are:
https://gnupg.org/ftp/gcrypt/libgcrypt/libgcrypt-1.12.2.tar.bz2 https://gnupg.org/ftp/gcrypt/libgcrypt/libgcrypt-1.12.2.tar.bz2.sig https://gnupg.org/ftp/gcrypt/libgcrypt/libgcrypt-1.11.3.tar.bz2 https://gnupg.org/ftp/gcrypt/libgcrypt/libgcrypt-1.11.3.tar.bz2.sig https://gnupg.org/ftp/gcrypt/libgcrypt/libgcrypt-1.10.4.tar.bz2 https://gnupg.org/ftp/gcrypt/libgcrypt/libgcrypt-1.10.4.tar.bz2.sig
or gzip compressed:
https://gnupg.org/ftp/gcrypt/libgcrypt/libgcrypt-1.12.2.tar.gz https://gnupg.org/ftp/gcrypt/libgcrypt/libgcrypt-1.12.2.tar.gz.sig https://gnupg.org/ftp/gcrypt/libgcrypt/libgcrypt-1.11.3.tar.gz https://gnupg.org/ftp/gcrypt/libgcrypt/libgcrypt-1.11.3.tar.gz.sig https://gnupg.org/ftp/gcrypt/libgcrypt/libgcrypt-1.10.4.tar.gz https://gnupg.org/ftp/gcrypt/libgcrypt/libgcrypt-1.10.4.tar.gz.sig
In order to check that the version of Libgcrypt you downloaded is an original and unmodified file please follow the instructions found at https://gnupg.org/download/integritycheck.html. In short, you may use one of the following methods:
- Check the supplied OpenPGP signature. For example to check the signature of the file libgcrypt-1.12.2.tar.bz2 you would use this command:
gpg --verify libgcrypt-1.12.2.tar.bz2.sig libgcrypt-1.12.2.tar.bz2
This checks whether the signature file matches the source file. You should see a message indicating that the signature is good and made by one or more of the release signing keys. Make sure that this is a valid key, either by matching the shown fingerprint against a trustworthy list of valid release signing keys or by checking that the key has been signed by trustworthy other keys. See the end of this mail for information on the signing keys.
- If you are not able to use an existing version of GnuPG, you have to verify the SHA-1 checksum. On Unix systems the command to do this is either "sha1sum" or "shasum". Assuming you downloaded the file libgcrypt-1.12.2.tar.bz2, you run the command like this:
sha1sum libgcrypt-1.12.2.tar.bz2
and check that the output matches the first line from the this list:
7b8ff21966a0b6e7a735466b9b9b55d9dac9fa87 libgcrypt-1.12.2.tar.bz2 a1b1d5561e7b743e7e4460a49015053da1901124 libgcrypt-1.12.2.tar.gz d252f6b0a62fcacb8f82bcb61440b25d698a0a05 libgcrypt-1.11.3.tar.bz2 a89b597965a76bfbe0ad11e3d6153c3709c0b07e libgcrypt-1.11.3.tar.gz d824efa873ac210e84573564df4a99f4cd5cdf77 libgcrypt-1.10.4.tar.bz2 5a5bb8d4dd69a2c7828dbf31b12df5e21e604971 libgcrypt-1.10.4.tar.gz
You should also verify that the checksums above are authentic by matching them with copies of this announcement. Those copies can be found at other mailing lists, web sites, and search engines.
Copying =======
Libgcrypt is distributed under the terms of the GNU Lesser General Public License (LGPLv2.1+). The helper programs as well as the documentation are distributed under the terms of the GNU General Public License (GPLv2+). The file LICENSES has notices about contributions that require that these additional notices are distributed.
Support =======
For help on developing with Libgcrypt you should read the included manual and if needed ask on the gcrypt-devel mailing list.
In case of problems specific to this release please first check https://dev.gnupg.org/T8114 for updated information.
Please also consult the archive of the gcrypt-devel mailing list before reporting a bug: https://gnupg.org/documentation/mailing-lists.html . We suggest to send bug reports for a new release to this list in favor of filing a bug at https://bugs.gnupg.org. If you need commercial support go to https://gnupg.com or https://gnupg.org/service.html .
Please see https://gnupg.org/documentation/security.html for information on how to report security issues and for our threat model.
If you are a developer and you need a certain feature for your project, please do not hesitate to bring it to the gcrypt-devel mailing list for discussion.
Thanks ======
Since 2001 maintenance and development of GnuPG is done by g10 Code GmbH and has mostly been financed by donations. Several full-time employed developers and contractors are working exclusively on GnuPG and closely related software like Libgcrypt, GPGME, Kleopatra and Gpg4win.
Fortunately, and this is still not common with free software, we have now established a way of financing the development while keeping all our software free and freely available for everyone. Our model is similar to the way RedHat manages RHEL and Fedora: Except for the actual binary of the MSI installer for Windows and client specific configuration files, all the software is available under the GNU GPL and other Open Source licenses. Thus customers may even build and distribute their own version of the software as long as they do not use our trademarks GnuPG Desktop® or GnuPG VS-Desktop®.
We like to thank all the nice people who are helping the GnuPG project, be it testing, coding, translating, suggesting, auditing, administering the servers, spreading the word, answering questions on the mailing lists, or helping with donations.
Thank you all
Your Libgcrypt hackers
p.s. This is an announcement only mailing list. Please send replies only to the gcrypt-devel'at'gnupg.org mailing list.
List of Release Signing Keys: To guarantee that a downloaded version has not been tampered by malicious entities we provide signature files for all tarballs and binary versions. The keys are also signed by the long term keys of their respective owners. Current releases are signed by one or more of these five keys:
ed25519 2020-08-24 [SC] [expires: 2030-06-30] 6DAA 6E64 A76D 2840 571B 4902 5288 97B8 2640 3ADA Werner Koch (dist signing 2020)
ed25519 2021-05-19 [SC] [expires: 2027-04-04] AC8E 115B F73E 2D8D 47FA 9908 E98E 9B2D 19C6 C8BD Niibe Yutaka (GnuPG Release Key)
rsa3072 2025-05-09 [SC] [expires: 2033-03-03] 3B76 1AE4 E63B F351 9CE7 D63B ECB6 64CB E133 2EEF Alexander Kulbartsch (GnuPG Release Key)
brainpoolP256r1 2021-10-15 [SC] [expires: 2029-12-31] 02F3 8DFF 731F F97C B039 A1DA 549E 695E 905B A208 GnuPG.com (Release Signing Key 2021)
brainpoolP384r1 2026-02-23 [SC] [expires: 2034-02-23] 1493 269D E61F 124A A69A 316E 3ADF 34EB DBB2 00A4 GnuPG.com (Release Signing Key 2026)
The keys are available at https://gnupg.org/signaturekey.html and in any recently released GnuPG tarball in the file g10/distsigkey.gpg . Note that this mail has been signed by a different key.
Debian Package Signing Key: The new Debian style packages are signed using this key:
ed25519 2025-07-08 [SC] [expires: 2035-07-14] 3209 7B71 9B37 45D6 E61D DA1B 85C4 5AE3 E1A2 B355 GnuPG.org Package Signing Key <package-maintainers () gnupg org>
See the package website (https://repos.gnupg.org/deb/gnupg) for a list of supported distributions and a download link for the key.
-- The pioneers of a warless world are the youth that refuse military service. - A. Einstein
----- End forwarded message -----
Sam James <sam () gentoo org> wrote: A crafted CMS (S/MIME) EnvelopedData message carrying an oversized wrapped session key can cause a stack buffer overflow in gpg-agent during the PKDECRYPT--kem=CMS handling. This can easily be used for a DoS but, worse, the memory corruption can very likley also be used to mount a remote code execution attack.
A CVE-id has not been assigned. We track this bug as T8044 under https://dev.gnupg.org/T8044. This vulnerability was discovered by: OpenAI Security Research. Their report was received on 2026-01-18; This vulnerability sounds very similar to the just announced OpenSSL vulnerability CVE-2025-15467. That vulnerability was noted as having been discovered Stanislav Fort (Aisle Research).
Is it a coincident that these two issues were detected shortly after one another by different parties?
-Jan
In GnuPG before 2.5.17, a crafted CMS (S/MIME) EnvelopedData message carrying an oversized wrapped session key can cause a stack-based buffer overflow in gpg-agent during PKDECRYPT--kem=CMS handling. This can easily be leveraged for denial of service; however, there is also memory corruption that could lead to remote code execution.
In GnuPG before 2.5.17, a stack-based buffer overflow exists in tpm2daemon during handling of the PKDECRYPT command for TPM-backed RSA and ECC keys.
In GnuPG before 2.5.17, a long signature packet length causes parsesignature to return success with sig->data[] set to a NULL value, leading to a denial of service (application crash).
In GnuPG before 2.5.17, a stack-based buffer overflow exists in tpm2daemon during handling of the PKDECRYPT command for TPM-backed RSA and ECC keys.
In GnuPG before 2.5.17, a crafted CMS (S/MIME) EnvelopedData message carrying an oversized wrapped session key can cause a stack-based buffer overflow in gpg-agent during PKDECRYPT--kem=CMS handling. This can easily be leveraged for denial of service; however, there is also memory corruption that could lead to remote code execution.
GnuPG 2.5.17 has been released to fix a possible RCE: https://dev.gnupg.org/T8044 ("gpg-agent stack buffer overflow in pkdecrypt using KEM")
[Description for this one at the end, for the full quoted advisory.]
There's two other security-relevant bugs too: https://dev.gnupg.org/T8045 ("Stack-based buffer overflow in TPM2 PKDECRYPT") A stack-based buffer overflow exists in GnuPG’s tpm2daemon when handling the PKDECRYPT command for TPM-backed RSA and ECC keys. A local attacker who can access the daemon’s Assuan socket can send an oversized ciphertext and trigger memory corruption, resulting in a crash and potentially arbitrary code execution. When a user stores private keys inside a TPM, GnuPG runs a helper process called tpm2daemon to perform cryptographic operations on their behalf. Other GnuPG components communicate with this daemon over Assuan, a local IPC protocol. During a PKDECRYPT request, tpm2daemon copies the attacker-supplied ciphertext into fixed-size TPM work buffers without validating that the ciphertext fits. If the supplied ciphertext is larger than the TPM buffer, the copy operation writes past the end of the stack buffer and corrupts adjacent stack memory. This affects both supported TPM decrypt paths: RSA (tpm2rsadecrypt) and ECC (tpm2eccdecrypt). Because the overflow occurs on the stack and is attacker-controlled, it is potentially exploitable for code execution inside the tpm2daemon process. https://dev.gnupg.org/T8049 ("Null pointer dereference with overlong signature packet") Overlong signature packet length causes parsesignature to return success with sig->data[] left NULL, leading to a crash in later consumers. The advisory is at https://dev.gnupg.org/T7996#212268 (not yet on gnupg-announce ML). Quoting that, which discusses the main bug (T8044): These versions are affected:
GnuPG 2.5.16 (released 2025-12-30) GnuPG 2.5.15 (released 2025-12-29) GnuPG 2.5.14 (released 2025-11-19) GnuPG 2.5.13 (released 2025-10-22) Gpg4win 5.0.0 (released 2026-01-14) Gpg4win 5.0.0-beta479 (released 2026-01-02) Gpg4win 5.0.0-beta476 (released 2025-12-22) Gpg4win 5.0.0-beta395 (released 2025-10-22)
All other versions are not affected.
A crafted CMS (S/MIME) EnvelopedData message carrying an oversized wrapped session key can cause a stack buffer overflow in gpg-agent during the PKDECRYPT--kem=CMS handling. This can easily be used for a DoS but, worse, the memory corruption can very likley also be used to mount a remote code execution attack.
A CVE-id has not been assigned. We track this bug as T8044 under https://dev.gnupg.org/T8044. This vulnerability was discovered by: OpenAI Security Research. Their report was received on 2026-01-18; fixed versions released 2026-01-27.
Solution:
If an affected GnuPG version is used please update ASAP to the new version 2.5.17.
If an affected version of Gpg4win is used please update ASAP to the new version 5.0.1.
If an immediate update is not possible please remove the gpgsm or gpgsm.exe binary, this way the the bug can't be remotely triggered. sam
Hi!
On Mon, 29 Dec 2025 10:51, Werner Koch said: https://dev.gnupg.org/T7900 which is the parent ticket for all these Unfortunately this ticket and some other tickets where only accessible by registered users or even more restricted. This is now fixed [1].
FWIW, here is a replyt which I posted on Mastodon:
Actually there is only one major bug (T7906 - armor parser) which was fixed early November. T7901 requires a 2nd pre-image attack on SHA1 - which does not yet exist. T7907 (plaintext recovery) is simply untrue; see https://dev.gnupg.org/T7907#210501
BTW, of course we sign our commits and most of us even use hardware tokens.
Shalom-Salam,
Werner
[1] Phabricator has a two-level permission system and in the web interface only the first level is easy to see in the overview. Some of us played it safe and restricted at both levels. -- The pioneers of a warless world are the youth that refuse military service. - A. Einstein
Henrik Ahlgren <pablo () seestieto com> writes: Perhaps the Debian developer keyring would serve as a compelling example? They even organize actual key-signing parties, which many cryptography experts today appear to regard as "LARPing" or otherwise ridiculous. That sounds almost exactly like a CA key signing ceremony rather than any kind of WoT thing...
Peter.
Henrik Ahlgren <pablo () seestieto com> writes: Peter Gutmann <pgut001 () cs auckland ac nz> writes: Does anything actually use the cobweb of trust, or do you just assume the key you've got is good because doing anything else is too hard? Perhaps the Debian developer keyring would serve as a compelling example? They even organize actual key-signing parties, which many cryptography experts today appear to regard as "LARPing" or otherwise ridiculous. Or the Linux kernel [1].
Collin
[1] https://www.kernel.org/doc/html/v6.19-rc2/process/maintainer-pgp-guide.html#using-the-kernel-org-web-of-trust-repository
On 12/29/25 01:15, Stephan Verbücheln wrote: GnuPG follows a traditional versioning scheme where even numbers (e.g. 2.2 and 2.4) are release branches and odd numbers (2.3 and 2.5) are developer branches. So what we have to wait for is 2.4.9 fixing the vulnerabilities. Is that still true?
https://gnupg.org/ states:
Note that the 2.5 series is now declared the stable version of GnuPG. Be aware that the oldstable 2.4 series will reach end-of-life in just 6 months.
-- -Alan Coopersmith- alan.coopersmith () oracle com Oracle Solaris Engineering - https://blogs.oracle.com/solaris
Demi Marie Obenour writes: Can we agree to use OpenSSH signatures ASAP? PGP signatures are fine, for authenticating binaries we just need to use them in a way where there's only one simple, unambiguous, and minimal-attack- surface way to apply them, as well as a means of having them work over longer time periods (see below). The alternative is to try to boil the ocean, which would take a Heartbleed-style catastrophe to motivate. Interesting! Which ones don't work? I'm using it to generate test data which will no doubt trigger odd behaviour in some cases, and didn't record info about individual problems, just "type this command to get this output" once I figured out what was required. An example is:
gpg -b -z 0 --openpgp --homedir . -o signed4.pgp test.txt
(the --openpgp is for a GPG bug, without it it'll generate v3 sigs as if --force-v3-sigs had been specified).
but for most of them all I've recorded is just whatever magic incantation eventually worked to generate the required test data. Is that what gpgv and sqv are? It depends on how much of the rest of GPG is still present. If it's just a stripped-down front-end to the whole thing then it may still be subject to the same vulns. I think the hard part of doing this isn't the signature handling itself, but rather the incredibly complex web of trust. Does anything actually use the cobweb of trust, or do you just assume the key you've got is good because doing anything else is too hard? Certainly for authenticating Linux installs and updates the practice seems to be "grab the key from this source via TLS, swear a lot because it's KEYEXPIRED, spend ages Googling how to get the latest key, realise you have to install intermediate updates to work your way up to what's current but the only remaining source for those is a server in Botswana and all the apt options have changed and you need to read a garbled blog post someone wrote at 3am when they ran into the
[ 25 more lines of pain snipped ]
just run with --allow-unauthenticated and ensuing zero security so you can finally update your stuff before you die of old age". That's one thing Microsoft did well with Authenticode, you don't get all your updates blocked because your valid keys instantly became invalid after some timer ticked past midnight. I've actually done something like this myself, wrote simple apps pgpencrypt and pgpdecrypt (size around 50kB) Are these available anywhere? They're just some very quick things I threw together ten or more years ago, motivated by:
/ Used to decrypt files that the four assorted command-line versions of PGP can't handle /
(this was before GPG became the de facto universal standard). I can send you the code privately if you like, but it probably won't be very useful. Yeah, that's embarrassing. I wouldn't say it's embarrassing, more that it's a confirmation of Shamir's Law, "crypto is bypassed, not attacked". To find the biggest holes in a crypto app you need a pentester, not a cryptographer.
Peter.
On 12/29/25 11:57, Lexi Groves (49016) wrote: Hi! Thanks for the comment. Some clarifications from us: (snip) > Given a signed document, you can either check the signature or check the signature and recover the original document. To check the signature use the --verify option. To verify the signature and extract the document use the --decrypt option. The signed document to verify and recover is input and the recovered document is output. > > > > > > blake% gpg --output doc --decrypt doc.sig > > gpg: Signature made Fri Jun 4 12:02:38 1999 CDT using DSA key ID BB7576AC > > gpg: Good signature from "Alice (Judge) <alice () cyb org>" > >
We assumed that the manual was the source of truth and assumed that using --decrypt was the standard way to do this; we may have been biased here, because apparently the common knowledge about this (according to some other documentation that we did not see) was using --output/-o. However, due to the nature of the attack, setting the wrong output file while hashing the correct file, --output works the same way:
$ gpg --output x --verify msg.txt.sig msg.txt gpg: Signature made Mon 29 Dec 2025 02:59:11 PM CET gpg: using EDDSA key EE6EADB4CBB063887A3BE2B413AEBEC571BA1447 gpg: Good signature from "39c3 demo <demo () gpg fail>" [ultimate] $ cat msg.txt asdf $ cat x Malicious Does this work with 'gpgv'?
I think most software update tools use msg.txt directly and so are not vulnerable, unless the signature uses text mode in which case a different attack might work. Can you see if APT is vulnerable?
(snip) Item 5: Memory Corruption in ASCII-Armor Parsing > > This is a serious memory-safety error in GPG.
Yes. We did not have the time to try to exploit it, but we agreed that there is potential for remote code execution. We think that it is irresponsible to not release the fix on the 2.4 branch, which is what most users in the wild use. I totally agree. This is why I referred to this vulnerability as a zero-day.
(snip) Item 9: GnuPG Output Fails To Distinguish Signature Verification Success From Message Content > > I think this is actually an old problem, previously affecting Thunderbird and Git IIRC, and the existing --status-fd mechanism in GPG is meant for exactly this case, at least for automated processing.
The general concept yes, we just found that in practice --verify just does not work with encrypted and signed payloads, which further makes this harder to avoid on the CLI specifically. Also GnuPG does not fail on the first write error to the status line unless --exit-on-status-write-error is passed. Even then, some errors are not handled properly and can cause corrupt output (possibly right before an exit). -- Sincerely, Demi Marie Obenour (she/her/hers)
On 12/29/25 19:57, Peter Gutmann wrote: Stephan Verbücheln writes: The overall status is not good though. I'm more concerned about a slightly different aspect, that two researchers (apparently) walked up to GPG and quickly found a pile of bugs, many relating to authentication [0]. OpenPGP sigs are the de facto universal standard for authenticating code and binaries in the non-Windows world, the equivalent of Windows Authenticode, and GPG is the tool that's used for that. The one with all the bugs in its authentication handling. I agree. Can we agree to use OpenSSH signatures ASAP? Those actually are decently designed, though I do wish that they had the ability to include structured metadata. One could abuse the "reserved" field for this, though. Of course, it should only be parsed after verifying the signature. There are two issues that cause this, the first being that GPG is staggeringly complex. It's not a sign-and-encrypt app any more but an entire suite that runs daemons/services, spawns off subprograms, creates and uses a ton of files in its own proprietary data formats, and has a million command-line options that change across releases (I use it for generating OpenPGP test vectors so I get to try lots of options that, by the looks of it, no-one else uses because some of them function other than expected or not at all). Interesting! Which ones don't work? The second one is the format, best summed up by Thomas Ptacek's comment at https://news.ycombinator.com/item?id=46404339 which begins:
A thru-line of some of the gnarliest vulnerabilities here is PGP's insane packet system, where a PGP message is a practically arbitrary stream of packets, some control and some data, with totally incoherent cryptographic bindings. It's like something in between XMLDSIG (which pulls cryptographic control data out of random places in XML messages according to attacker- controlled tags) and SSL2 (with no coherent authentication of the complete handshake).
For an example of this, consider compressed signed data, so you've got an EDI transaction that you want to compress (it's a large blob of fixed-format text) and then sign. With CMS (Cryptographic Message Syntax) you get:
Sign( Compress( Message ) )
With OpenPGP it's a crapshoot. You'd expect something like the above but what GPG does is:
Compress( One-pass Sig || Message || Signature )
which is valid but pretty unexpected. And then any application needs to have complex and awkward logic to process these things as per tptacek's comment. Sequoia actually uses a full parser generator (LALRPOP) to deal with this.That is the only reasonable approach I know of. Incidentally, this should also be able to handle CMS just fine. The only caveat is the parser needs to be able to tell the lexer to return a single token for a certificate or CRL, and that requires an ugly lexer hack that depends on the parser not reading too many tokens ahead of time. To appreciate just how bad it really is, grab a copy of RFC 9580 and see how long it takes you to write down the sequence of fields (not packets, fields) that you'd expect to see in a message encrypted with RSA and signed with Ed25519 (to grab the two opposite ends of the cryptographic spectrum) as well as the cryptographic bindings between them, i.e. which bits get hashed/signed/ processed, and also provide a confidence level in your work. I suspect most people won't even get to that, the answer would be "I can't figure it out".
A solution for mission-critical use like authenticating downloaded binaries would be to do two things:
1. Create an app that does just that and nothing else: Here is a blob of data, here is a detached signature, is it valid for the data? Is that what gpgv and sqv are? I think the hard part of doing this isn't the signature handling itself, but rather the incredibly complex web of trust. Detached signatures seem to be the only semi-reasonable part of OpenPGP. 2. Define a fixed format for Authenticode-style signatures in OpenPGP form that allows one and only one agglutination of OpenPGP packets and fields in packets that are considered a valid signature. I actually did that myself as part of <https://github.com/QubesOS/qubes-rpm-oxide>. The OpenPGP parser built in to RPM wasn't something I wanted to expose to untrusted input, and the RPM version in Qubes OS dom0 was end of life. I added a validator that checked for the only expected format: one signature packet.
I haven't looked much into how OpenPGP encryption works and I agree that it's a much worse mess. I've actually done something like this myself, wrote simple apps pgpencrypt and pgpdecrypt (size around 50kB) that do exactly what the name says and nothing else so I don't have to remember a million command-line options and deal with a pile of files and settings. It's just "pgpencrypt file", and there's little facility to perform attacks like in the talk because there's no extra capabilities there to attack. Are these available anywhere?
(snip) [0] The talk doesn't cover how much effort was involved, the speakers mention they're not cryptographers but pen-testers so no crypto knowledge was required. Yeah, that's embarrassing. -- Sincerely, Demi Marie Obenour (she/her/hers)
In GnuPG through 2.4.8, armorfilter in g10/armor.c has two increments of an index variable where one is intended, leading to an out-of-bounds write for crafted input.
On 12/29/25 10:57, Lexi Groves (49016) wrote: Hi! Thanks for the comment. Some clarifications from us:
Item 1: Multiple Plaintext Attack on Detached PGP Signatures in GnuPG
[...] $ gpg --output x --verify msg.txt.sig msg.txt gpg: Signature made Mon 29 Dec 2025 02:59:11 PM CET gpg: Good signature from "39c3 demo <demo () gpg fail>" [ultimate] $ cat msg.txt asdf $ cat x Malicious
[...]
Item 3: Cleartext Signature Plaintext Truncated for Hash Calculation
$ gpg --export exfil () gpg fail | sq packet dump
Public-Key Packet, new CTB, 2 header bytes + 51 bytes Curve: Ed25519 Fingerprint: 06993EC337C276ECFD8C598AB613D42DB68D9E1D [...]
Signature Packet, new CTB, 3 header bytes + 371 bytes Type: DirectKey Unhashed area: Here's the zlib header! ↓
I agree that that is much more plausible.
2. Encrypt (yes, encrypt) the result of 1. with the key 3. XOR the current ciphertext with the result of 2.
Said "trampoline" does the following: So what we insert via XORing is:
This sets us up so our PGP packet stream does not get corrupted.
Clever, very clever. :-)
[...]
[...]
This logic error should still be fixed, of course. Item 13: GnuPG Trust Packet Parsing Enables Adding Arbitrary Subkeys What should be highlighted especially here are the manual page entries:
--keyring file $GNUPGHOME is used). fied keyring alone, use --keyring along with --no-default-keyring.
--import-options restore overridden.
[...]
Best, Lexi Groves (49016) -- Jacob
On 12/29/25 04:51, Werner Koch wrote: Item 5: Memory Corruption in ASCII-Armor Parsing
This is a serious memory-safety error in GPG. Yes, and actually the only serious bug from their list. This one (T7906) was fixed in the repo on November 4 (T7906) and released with 2.5.14 on 2025-11-19:
gpg: Fix possible memory corruption in the armor parser. [T7906]
and in the ExtendedLTS version 2.2.51 already on: 2025-10-28:
gpg: Fix possible memory corruption in the armor parser. [rG1e929abd20]
Another release of 2.4 is still pending but given that its end-of-life is in 6 months, it would anyway better to switch to 2.5. Whether this bug is really exploitable is still questionable but of course we decided to fix that. Thus the claim by Demi Marie "one of which allows remote code execution. [All are zero-days to the best of my knowledge.]" is over the top. Even the report marks this bug as a "may":
Impact While this may allow remote code execution (RCE), it definitively causes memory corruption.
Good research. I wasn't aware of the fix commits. The fixed bugs are indeed not zero-day vulnerabilities from an upstream perspective. They are, however, zero-day vulnerabilities for many distro users. In particular, Fedora 42, 43, and Rawhide do not have the fixes.
While upstream did use the word "may", it also states: From here it is a challenge in memory corruption exploitation with a very large space of reachable primitives. I concluded from this that exploitation is just a matter of effort. -- Sincerely, Demi Marie Obenour (she/her/hers)
Stephan Verbücheln writes: The overall status is not good though. I'm more concerned about a slightly different aspect, that two researchers (apparently) walked up to GPG and quickly found a pile of bugs, many relating to authentication [0]. OpenPGP sigs are the de facto universal standard for authenticating code and binaries in the non-Windows world, the equivalent of Windows Authenticode, and GPG is the tool that's used for that. The one with all the bugs in its authentication handling.
There are two issues that cause this, the first being that GPG is staggeringly complex. It's not a sign-and-encrypt app any more but an entire suite that runs daemons/services, spawns off subprograms, creates and uses a ton of files in its own proprietary data formats, and has a million command-line options that change across releases (I use it for generating OpenPGP test vectors so I get to try lots of options that, by the looks of it, no-one else uses because some of them function other than expected or not at all).
The second one is the format, best summed up by Thomas Ptacek's comment at https://news.ycombinator.com/item?id=46404339 which begins:
A thru-line of some of the gnarliest vulnerabilities here is PGP's insane packet system, where a PGP message is a practically arbitrary stream of packets, some control and some data, with totally incoherent cryptographic bindings. It's like something in between XMLDSIG (which pulls cryptographic control data out of random places in XML messages according to attacker- controlled tags) and SSL2 (with no coherent authentication of the complete handshake).
For an example of this, consider compressed signed data, so you've got an EDI transaction that you want to compress (it's a large blob of fixed-format text) and then sign. With CMS (Cryptographic Message Syntax) you get:
Sign( Compress( Message ) )
With OpenPGP it's a crapshoot. You'd expect something like the above but what GPG does is:
Compress( One-pass Sig || Message || Signature )
which is valid but pretty unexpected. And then any application needs to have complex and awkward logic to process these things as per tptacek's comment.
To appreciate just how bad it really is, grab a copy of RFC 9580 and see how long it takes you to write down the sequence of fields (not packets, fields) that you'd expect to see in a message encrypted with RSA and signed with Ed25519 (to grab the two opposite ends of the cryptographic spectrum) as well as the cryptographic bindings between them, i.e. which bits get hashed/signed/ processed, and also provide a confidence level in your work. I suspect most people won't even get to that, the answer would be "I can't figure it out".
A solution for mission-critical use like authenticating downloaded binaries would be to do two things:
1. Create an app that does just that and nothing else: Here is a blob of data, here is a detached signature, is it valid for the data?
2. Define a fixed format for Authenticode-style signatures in OpenPGP form that allows one and only one agglutination of OpenPGP packets and fields in packets that are considered a valid signature.
I've actually done something like this myself, wrote simple apps pgpencrypt and pgpdecrypt (size around 50kB) that do exactly what the name says and nothing else so I don't have to remember a million command-line options and deal with a pile of files and settings. It's just "pgpencrypt file", and there's little facility to perform attacks like in the talk because there's no extra capabilities there to attack.
As an aside, did anyone notice the problem in the code snippet on slide 91 of the talk? It looks like they've paraphrased but typo'd the original code, which correctly uses | instead of &.
Peter.
[0] The talk doesn't cover how much effort was involved, the speakers mention they're not cryptographers but pen-testers so no crypto knowledge was required.
Henrik Ahlgren <pablo () seestieto com> writes: "Lexi Groves (49016)" <contact () gpg fail> writes: Yes. We found this advice in The GNU Privacy Handbook, Chapter 1. Getting Started, Making and verifying signatures: I'd just like to point out that the GNU Privacy Handbook (GPH) was published in 1999, and I have not encountered any more recent revisions. I got this impression but couldn't find anything specifically saying it was archived.
I filed a bug earlier and included https://dev.gnupg.org/T7993#210212 for one issue in it, but if it's not been revised since, perhaps it should be archived with a banner on each page or something, as it's readily found via search engines at the moment. I believe GnuPG did not even support RSA until version 1.0.3 and AES/Rijndael until version 1.0.4, which were released in 2000, meaning the handbook exclusively addresses DSA and ElGamal, making it 25 years out of date. The GnuPG versions in the output got me suspicious enough ;) The GnuPG Manual (https://gnupg.org/documentation/manuals/gnupg/) is much more current, but sadly it is not structured as a user guide that would introduce a new user to PGP concepts and best practices, etc. sam
"Lexi Groves (49016)" <contact () gpg fail> writes: Yes. We found this advice in The GNU Privacy Handbook, Chapter 1. Getting Started, Making and verifying signatures: I'd just like to point out that the GNU Privacy Handbook (GPH) was published in 1999, and I have not encountered any more recent revisions. I believe GnuPG did not even support RSA until version 1.0.3 and AES/Rijndael until version 1.0.4, which were released in 2000, meaning the handbook exclusively addresses DSA and ElGamal, making it 25 years out of date.
The GnuPG Manual (https://gnupg.org/documentation/manuals/gnupg/) is much more current, but sadly it is not structured as a user guide that would introduce a new user to PGP concepts and best practices, etc.
Hi! Thanks for the comment. Some clarifications from us:
Item 1: Multiple Plaintext Attack on Detached PGP Signatures in GnuPG
> > > blake% gpg --output doc --decrypt doc.sig > gpg: Good signature from "Alice (Judge) <alice () cyb org>" > $ gpg --output x --verify msg.txt.sig msg.txt gpg: Signature made Mon 29 Dec 2025 02:59:11 PM CET gpg: using EDDSA key EE6EADB4CBB063887A3BE2B413AEBEC571BA1447 gpg: Good signature from "39c3 demo <demo () gpg fail>" [ultimate] $ cat msg.txt asdf $ cat x Malicious
Item 3: Cleartext Signature Plaintext Truncated for Hash Calculation
$ gpg --export exfil () gpg fail | sq packet dump
Public-Key Packet, new CTB, 2 header bytes + 51 bytes Curve: Ed25519 Fingerprint: 06993EC337C276ECFD8C598AB613D42DB68D9E1D [...]
Signature Packet, new CTB, 3 header bytes + 371 bytes Type: DirectKey Unhashed area: Here's the zlib header! ↓
1. Take the ciphertext of the last block, or when initializing the IV block 2. Encrypt (yes, encrypt) the result of 1. with the key 3. XOR the current ciphertext with the result of 2.
Said "trampoline" does the following: So what we insert via XORing is:
This sets us up so our PGP packet stream does not get corrupted.
GnuPG violates this in the following ways:
- "it SHOULD NOT attempt to parse nor release decrypted data to the user":
$ gpg key.gpg gpg: WARNING: no command supplied. Trying to guess what you mean ... pub ed25519 2025-12-21 [C] [expires: 2028-12-17] 7C996D1BA8E1D4082719424AE80EBABCC54F0335 uid Mallory <exfil () gpg fail> sub ed25519 2025-12-21 [S] [expires: 2028-12-17] sub cv25519 2025-12-21 [E] [expires: 2028-12-17] Item 5: Memory Corruption in ASCII-Armor Parsing This is a serious memory-safety error in GPG. Item 6: Trusted comment injection (minisign)
Agreed. This can and should be fixed.
Item 10: Cleartext Signature Forgery in GnuPG Agreed. This can and should be fixed.
Item 11: Radix64 Line-Truncation Enabling Polyglot Attacks Agreed. This can and should be fixed.
Item 13: GnuPG Trust Packet Parsing Enables Adding Arbitrary Subkeys Keyrings are trusted stores, so this is more of a documentation problem. What should be highlighted especially here are the manual page entries:
--keyring file $GNUPGHOME is used). fied keyring alone, use --keyring along with --no-default-keyring.
--import-options restore overridden. Item 14: Trusted comment Injection (minisign)
Best, Lexi Groves (49016)
Stephan Verbücheln <stephan () buecheln ch> wrote: The RCE bug was actually fixed as they already state in their slides.
https://github.com/gpg/gnupg/commit/ad0c6c33c3d6fe7ff7cc8c2e73d02ead5788e5b3 This commit seems to be related to #3 https://gpg.fail/filename while the RCE is #5 https://gpg.fail/memcpy aka CVE-2025-68973, isn't it?
cu Andreas
On Sun, Dec 28, 2025 at 9:51 PM Demi Marie Obenour <demiobenour () gmail com> wrote: On 12/28/25 05:00, Sam James wrote: Demi Marie Obenour <demiobenour () gmail com> writes: https://gpg.fail lists many vulnerabilities in GnuPG, one of which allows remote code execution.
All are zero-days to the best of my knowledge. In 2.5.14: Fedora isn't running 2.5.14 even in Rawhide. It's a zero-day for Fedora users at least.
Upstream GnuPG is increasingly unwilling to collaborate with other OpenPGP implementations, and distros are having to patch GnuPG just to restore interoperability. If possible, it would be best for distros to either outright fork the project and create a new upstream, or stop packaging GnuPG entirely in favor of Sequoia's compatibility layer. The Fedora Linux family of distributions already doesn't use GnuPG in the critical path anymore. RPM and DNF have been switched to SequoiaPGP for quite some time. That change was inherited by Red Hat Enterprise Linux 10 as well.
This is why we have PQC support in our PGP stuff.
-- 真実はいつも一つ!/ Always, there's only one truth!