Every CVE Search/ Get API key

CVE-2026-87732

An issue was discovered in the mirage-crypto package before 2.2.0 for OCaml. The AES.GCM...

6.2 MediumFix available

An issue was discovered in the mirage-crypto package before 2.2.0 for OCaml. The AES.GCM.authenticate_decrypt_into and Chacha20.authenticate_decrypt_into functions write the decrypted plaintext into a caller-provided buffer and only then compares the tag. On a forged tag, the functions returns false, but the destination buffer already holds the full plaintext.

Attack profile

How easy it is to exploit

Attack vector
Local
Complexity
Low
Privileges needed
None
User interaction
None

What an attacker can affect

Confidentiality
None
Integrity
High
Availability
None

Exploit likelihood

0.11%Unchanged since Sep 9, 2026
90%50%10%1%

What each source reports

CVE List Score used 6.2

An issue was discovered in the mirage-crypto package before 2.2.0 for OCaml. The AES.GCM.authenticate_decrypt_into and Chacha20.authenticate_decrypt_into functions write the decrypted plaintext into a caller-provided buffer and only then compares the tag. On a forged tag, the functions returns false, but the destination buffer already holds the full plaintext.

Record
CVE-2026-87732
CVSS 3.1
6.2 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N
Weakness
CWE-347
Updated
2026-11-02
EUVDEUVD-2026-74618 6.2

An issue was discovered in the mirage-crypto package before 2.2.0 for OCaml. The AES.GCM.authenticate_decrypt_into and Chacha20.authenticate_decrypt_into functions write the decrypted plaintext into a caller-provided buffer and only then compares the tag. On a forged tag, the functions returns false, but the destination buffer already holds the full plaintext.

Record
EUVD-2026-74618
CVSS 3.1
6.2 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-vqxm-cgmv-2pcr 6.2

An issue was discovered in the mirage-crypto package before 2.2.0 for OCaml. The AES.GCM...

An issue was discovered in the mirage-crypto package before 2.2.0 for OCaml. The AES.GCM.authenticate_decrypt_into and Chacha20.authenticate_decrypt_into functions write the decrypted plaintext into a caller-provided buffer and only then compares the tag. On a forged tag, the functions returns false, but the destination buffer already holds the full plaintext.

Record
GHSA-vqxm-cgmv-2pcr
CVSS 3.1
6.2 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N
Weakness
CWE-347
Updated
2026-11-02
NVD 6.2

An issue was discovered in the mirage-crypto package before 2.2.0 for OCaml. The AES.GCM.authenticate_decrypt_into and Chacha20.authenticate_decrypt_into functions write the decrypted plaintext into a caller-provided buffer and only then compares the tag. On a forged tag, the functions returns false, but the destination buffer already holds the full plaintext.

Record
CVE-2026-87732
CVSS 3.1
6.2 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N
Weakness
CWE-347
Updated
2026-11-02
OSVDEBIAN-CVE-2026-87732 6.2

An issue was discovered in the mirage-crypto package before 2.2.0 for OCaml. The AES.GCM.authenticate_decrypt_into and Chacha20.authenticate_decrypt_into functions write the decrypted plaintext into a caller-provided buffer and only then compares the tag. On a forged tag, the functions returns false, but the destination buffer already holds the full plaintext.

Record
DEBIAN-CVE-2026-87732
CVSS 3.1
6.2 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N
Updated
2026-11-02
OSVOSEC-2026-12 6.2

AEAD `decrypt_into` functions writes plaintext before checking the tag

On the generic GCM path, AES.GCM.authenticate_decrypt_into (as well as Chacha20.authenticate_decrypt_into and AES.CCM16.authenticate_decrypt_into) writes the decrypted plaintext into the caller's destination buffer and only then compares the tag. On a forged tag the function returns false, but the destination buffer already holds the full plaintext. AEAD decryption is meant to be all-or-nothing: no plaintext should be released until the tag verifies. This is a release of unverified plaintext, and a caller that reads the buffer without first checking the return value sees forged-but-decrypted data. RustCrypto's aes-gcm fixed the same defect in CVE-2023-42811 (rated medium) by re-encrypting the buffer on tag failure.

Solution

The tag is validated first, and only if the tag is valid, the decryption into the provided buffer is done. In the CCM code, the tag is computed over the plaintext - if the tag validation fails, the provided buffer is zeroed.

Reproduction

module GCM = Mirage_crypto.AES.GCM

let () =
  let key = GCM.of_secret (String.make 32 '\x00') in
  let nonce = String.make 12 '\x00' in
  let secret = "let password = 42" in
  let len = String.length secret in
  let blob = GCM.authenticate_encrypt ~key ~nonce secret in
  (* flip one bit of the 16-byte tag (at offset len); the ciphertext is untouched *)
  let forged = Bytes.of_string blob in
  Bytes.set forged len (Char.chr (Char.code (Bytes.get forged len) lxor 1));
  let forged = Bytes.unsafe_to_string forged in
  let dst = Bytes.make len '\x00' in
  let verified =
    GCM.authenticate_decrypt_into ~key ~nonce forged ~src_off:0 ~tag_off:len dst
      ~dst_off:0 len
  in
  Printf.printf "tag verified: %b (the message is rejected as forged)\n" verified;
  Printf.printf "secret left in the output buffer: %S\n" (Bytes.to_string dst)

Timeline

  • June 25th 2026: report to ocaml/security-advisories
  • June 29th: acknowledgement of issue with several questions for the reporter
  • July 6th: answers from reporter, including a patch
  • July 27th: release of mirage-crypto 2.2.0 and security advisory
Record
OSEC-2026-12
CVSS 3.1
6.2 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N
Updated
2026-11-02
OSVUBUNTU-CVE-2026-87732 6.2

An issue was discovered in the mirage-crypto package before 2.2.0 for OCaml. The AES.GCM.authenticate_decrypt_into and Chacha20.authenticate_decrypt_into functions write the decrypted plaintext into a caller-provided buffer and only then compares the tag. On a forged tag, the functions returns false, but the destination buffer already holds the full plaintext.

Record
UBUNTU-CVE-2026-87732
CVSS 3.1
6.2 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
ocaml-mirage-crypto
Debian:12
All versions, plus listed versions
0.10.7-10.11.1-10.11.1-20.11.1-30.11.2-1
Show 14 moreShow less
0.11.2-20.11.3-11.1.0-11.1.0-22.0.0-12.0.1-12.0.2-12.0.3-12.1.0-12.2.0-12.2.0-22.3.0-12.4.0-12.4.1-1
None known
ocaml-mirage-crypto
Debian:13
All versions, plus listed versions
2.0.0-12.0.1-12.0.2-12.0.3-12.1.0-1
Show 5 moreShow less
2.2.0-12.2.0-22.3.0-12.4.0-12.4.1-1
None known
ocaml-mirage-crypto
Debian:14
before 2.2.0-1, plus listed versions
2.0.0-12.0.1-12.0.2-12.0.3-12.1.0-1
2.2.0-1
mirage-crypto
opam
before 2.2.0, plus listed versions
0.6.00.6.10.6.20.7.00.8.0
Show 45 moreShow less
0.8.10.8.20.8.30.8.40.8.50.8.60.8.70.8.80.8.90.8.100.9.00.9.10.9.20.10.00.10.10.10.20.10.30.10.40.10.50.10.60.10.70.11.00.11.10.11.20.11.31.0.01.1.01.2.02.0.02.0.12.0.22.0.32.1.0v2.1.0v2.0.3v2.0.2v2.0.1v2.0.0v1.2.0v1.1.0v1.0.1v1.0.0v0.11.3v0.11.2v0.11.1
2.2.0
ocaml-mirage-crypto
Ubuntu:22.04:LTS
All versions, plus listed versions
0.10.5-40.10.5-4build2
None known
ocaml-mirage-crypto
Ubuntu:24.04:LTS
All versions, plus listed versions
0.11.1-30.11.2-10.11.2-1build10.11.2-2build3
None known
ocaml-mirage-crypto
Ubuntu:26.10
All versions, plus listed versions
2.0.2-1build52.4.0-1
None known
ocaml-mirage-crypto
Ubuntu:26.04:LTS
All versions, plus listed versions
2.0.1-1build12.0.2-1build12.0.2-1build22.0.2-1build32.0.2-1build5
None known

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-87732 is a medium vulnerability (CVSS 6.2) in Ocaml Mirage-crypto, published July 27, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.11%, the 1st percentile. Fixed in ocaml-mirage-crypto 2.2.0-1.

References

This page doesn't list everything

Left out here: 27 versions. The JSON record has them.

MoveEnter Open