---
id: "CVE-2026-115408"
kind: "vulnerability"
aliases: ["CVE-2026-115408"]
title: "crypto11 Go library: ML-KEM key lookup can return the wrong public key"
severity: "medium"
cvss: 5.5
epss: null
exploited: false
status: "open"
category: "package"
products: []
ecosystems: []
tags: ["go", "ml-kem", "package", "pkcs11", "post-quantum"]
not_affected_if: ["authenticated-token-only", "no-ml-kem", "v1-module"]
published_at: "2026-10-27T12:17:07+00:00"
first_seen_at: "2026-10-27T12:31:37+00:00"
updated_at: "2026-10-27T12:32:11+00:00"
sources: [{"source": "nvd", "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-115408", "first_seen_at": "2026-10-27T12:31:37+00:00"}]
---

# crypto11 Go library: ML-KEM key lookup can return the wrong public key

The Go library github.com/eclipse-keypont/crypto11/v2 finds an ML-KEM public key by label or ID without checking it matches the private key, and falls back to returning the first ML-KEM public key on the token when no ID is set. An attacker who can plant a public ML-KEM object on the token can get shared secrets from encapsulations that were meant for the victim's key.

_Summary, check and fix written by a model from the sources; labelled as such._

## How to check

- Check the version of `github.com/eclipse-keypont/crypto11/v2` in `go.mod` (look for `require github.com/eclipse-keypont/crypto11/v2 v2.0.0-rc...`).
- Search the code for calls to `FindMLKEMKeyPair`, `FindMLKEMKeyPairs` or `FindMLKEMKeyPairsWithAttributes`.
- Confirm whether the module is the v2 path; v1 paths are not affected.

## Fix

- Upgrade `github.com/eclipse-keypont/crypto11/v2` to a version above `2.0.0-rc8` (the fixed version number is unknown from the sources).
- Until upgraded, avoid ML-KEM key lookup by label or ID on tokens that untrusted parties can open unauthenticated sessions on.

## Timeline

- 2026-10-27T12:31:37+00:00 nvd https://nvd.nist.gov/vuln/detail/CVE-2026-115408

## From the sources

In `github.com/eclipse-keypont/crypto11/v2` versions `>= 2.0.0-rc3, <= 2.0.0-rc8`, the ML-KEM key-pair lookup functions (`FindMLKEMKeyPair`, `FindMLKEMKeyPairs`, `FindMLKEMKeyPairsWithAttributes`) locate the public half of an ML-KEM key pair by `CKA_ID`/`CKA_LABEL` and never verify it against the private key. In addition, the "ID only" fallback search runs even when the private key has no `CKA_ID`, so the search template reduces to the public-key class and the ML-KEM key type and the first ML-KEM public key on the token is returned. `Encapsulate()` on the resulting key pair encrypts the fresh shared secret to that key, so its owner — not the holder of the private key the caller looked up — can recover the secret. An attacker who can open an unauthenticated session on the token and plant a public `CKK_ML_KEM` object carrying the victim's `CKA_ID`/`CKA_LABEL` receives the shared secrets for encapsulations performed through the substituted key pair, compromising the confidentiality of those secrets and of everything protected by keys derived from them. The v1 module paths have no ML-KEM support and are not affected.

---

_Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai_
