Five Critical CVEs for a Bug They Fixed in July: Privasys Files Against Its Own RA-TLS Stack

Between 21:17Z and 22:17Z on 9 October 2026, NVD ingested five new critical records — CVE-2026-108265, -108266, -108267, -108268 and -108269 — each scored 9.1 under CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N, each tagged CWE-346 (Origin Validation Error), each describing the same defect in a different layer of the same vendor’s stack. The vendor is Privasys, a confidential-computing platform. The defect is that its attested-TLS certificates proved which key was in the enclave without proving which connection you were on.

The part worth your attention is not the bug. It is the filing. The commits that fix all five landed on 9–10 July 2026; the fixed releases went out on 10 and 14 July. The CVEs were published three months later, by the vendor, against its own code, for a flaw that had already been patched before any identifier existed. That is the inverse of the pattern we keep documenting — advisories naming fixed versions that were never published, or records naming no fixed version at all. Here the remediation is real, installable and months old, and the paperwork is the thing that arrived late.

The flaw: the quote vouched for a key, not for a connection

RA-TLS embeds a hardware attestation quote inside the TLS certificate. The quote’s ReportData field commits to the certificate’s public key, so a client can confirm the key it is speaking to was generated inside a genuine, correctly measured enclave. Privasys additionally ran a challenge mode in which the client supplies a fresh nonce that the enclave folds in, defeating replay of old quotes.

Per the five GitHub advisories, the pre-fix construction was:

ReportData = SHA-512( SHA-256(SPKI_DER) || nonce )

Freshness: proved. Key provenance: proved. Connection identity: never mentioned. The attack the advisories describe is a relay, and the nonce does not stop it. An adversary holding the enclave’s extracted TLS private key accepts the victim’s connection, opens a second connection to the genuine enclave, forwards the victim’s own fresh challenge, and receives a brand-new valid quote signed by hardware for exactly that challenge. The quote commits to the public key the attacker is presenting — the stolen one — so every check the victim performs succeeds while the attacker sits in the middle. Borrowing the client’s challenge is free, because the challenge said nothing about the channel.

The precondition is heavy and the vendor says so plainly: the attacker must first extract an enclave TLS private key, which in this architecture means defeating TEE memory isolation on measured code. That is what holds AC:H/AT:P in the vector and keeps 9.1 below 10.0. It is also, as we note below, the exact point the original researchers dispute.

The fix, read at the commits

All five advisories prescribe the same construction, folding a 32-byte binder derived from the live TLS 1.3 key schedule into the signed quote:

ReportData = SHA-512( SHA-256(SPKI_DER) || nonce || binder )
binder     = HKDF-Expand-Label(client_handshake_traffic_secret,
                               "privasys-ratls-binder-v1",
                               Hash(ClientHello..ServerHello), 32)

Two connections cannot share that value, so the relayed quote no longer matches what the victim recomputes. We pulled the referenced commits from the GitHub API rather than trusting the prose. In the Go fork, src/crypto/tls/handshake_server_tls13.go captures client_handshake_traffic_secret and the ClientHello…ServerHello transcript hash at ServerHello time, then re-mints the leaf certificate at the Certificate-emit seam — the certificate is normally produced before the session secret exists, which is precisely why this is awkward. The commit comment states the transcript anchor “matches the rustls fork’s anchor so binders are byte-identical across forks,” and the re-mint fires either through an explicit RATLSBindCertificate hook or through a second GetCertificate call that only triggers for clients which sent the RA-TLS challenge extension, leaving ordinary handshakes untouched.

On the verifying side, go/ratls/client.go in ra-tls-clients gains VerifyRaTlsCertBound, and the challenge branch of verifyReportData stops using the bare nonce. The in-code comment is unambiguous about the intended failure mode: “Channel binding is mandatory in challenge mode… Recompute WITH the binder so a relayed or co-located quote — one that cannot commit to this TLS session — fails closed.” Deterministic mode, the cached-quote tier, carries no binder by design and is explicitly out of scope.

Five repositories, one defect, verified ranges

We confirmed every fixed tag exists and is a published, non-draft release:

  • CVE-2026-108267 — Privasys/go (fork of Go, RA-TLS in crypto/tls). Affected ≤ privasys-v0.3.0-go1.26.5; fixed privasys-v0.5.1-go1.26.5, released 10 July 13:40:31Z. This is the layer that derives the binder.
  • CVE-2026-108266 — Privasys/rustls (fork adding the RA-TLS CertificateRequest extension 0xFFBB). Affected ≤ privasys-v0.2.0; fixed privasys-v0.8.1, 10 July 12:27:12Z. The advisory notes the affected release is deliberately left in place, marked do-not-use, so enclave measurements built from it stay reproducible — an unusual and, in a measured-boot world, correct choice.
  • CVE-2026-108265 — Privasys/enclave-os-mini, the SGX runtime. Affected ≤ wasm-v0.39.0; fixed wasm-v0.40.0, 10 July 13:39:14Z.
  • CVE-2026-108268 — Privasys/enclave-os-virtual, the TDX/GPU confidential-VM runtime. Affected ≤ tdx-v0.2.35 and ≤ tdx-gpu-v0.6.26-dev; fixed tdx-v0.2.43 and tdx-gpu-v0.6.27, both 14 July. The whole fix here is 25 added lines in one file, caddy/ratls/ra-tls.go, because the hard work lives in the Go fork underneath.
  • CVE-2026-108269 — Privasys/ra-tls-clients, the Rust and Go verifiers. Affected ≤ v0.4.9; fixed v0.5.0, 10 July 01:24:33Z.

Splitting one defect across five records is the right call and under-practised. A verifier that accepts an unbound quote and an issuer that emits one are different bugs with different owners, different version ranges and different upgrade paths; a single CVE spanning all five would have been unactionable for anyone consuming only the client library. Note also the live-ecosystem gap: the GitHub advisories were all published 3 September and only updated into CVEs on 9 October, and as of writing all five return 404 from OSV while the ecosystem field on every record is other — these are Git-tag ranges, not package-manager ranges, so go get-style scanners will not see them at all. If you consume the Privasys forks, the version check is a manual one.

The part the vendor and the researchers still disagree about

The flaw class is not Privasys-specific. It comes from formal work by Muhammad Usama Sardar (TU Dresden), Viacheslav Dubeyko (IBM) and Jean-Marie Jacquet (University of Namur), whose paper Intra-handshake.fail (CVE-2026-33697) was accepted at ESORICS 2026 and used ProVerif to show that intra-handshake attested-TLS designs do not bind evidence to the session. All five Privasys advisories credit that team plus Songbo Bu (Stevens Institute of Technology), explicitly naming ProVerif.

The reference victim is instructive. CVE-2026-33697 was filed in March 2026 against CoCoS AI, Ultraviolet’s confidential-computing system for AI workloads, covering v0.4.0–v0.8.2 across both AMD SEV-SNP and Intel TDX. Its advisory is blunt: the aTLS implementation was “fully redesigned in v0.7.0, but the redesign does not address this vulnerability… The relay attack weakness is architectural.” NVD scores it 6.3; GitHub 7.5. CoCoS shipped v0.9.0 on 27 March 2026 with post-handshake aTLS binding; the GitHub advisory text, as served today, still reads “There is currently no patch available” while its structured metadata lists v0.9.0 as patched — a record that contradicts itself depending on which field you read.

Where vendor and researchers part company is the precondition. Privasys’s engineering post argues the attack “begins where confidential computing’s core guarantee has already failed,” and that a high CVSS score “reflects the severity if the precondition holds; it does not describe how often it holds.” Sardar’s reply, in a public pull-request thread on the researchers’ own repository, calls that “a common misunderstanding,” pointing at section 7.1.4 of the paper and in particular to the case where the enclave key “may be extracted on a different machine than the desired one” — same measured code, different box, no isolation break on the target at all. That is a materially different threat model from “your specific enclave was cracked,” and it is unresolved in public. We take no position on which reading the CVSS vector should encode; we note that AC:H/AT:P bakes the vendor’s reading into the number.

Two further details from that exchange deserve recording, because they bear on how this kind of work should be read. The Privasys contributor disclosed, when asked directly, that the ProVerif edits, runs and text in the proposed models were “prepared with AI assistance (Anthropic’s Claude) under my direction and review” — disclosed on request rather than volunteered, and the PR was closed unmerged on the researchers’ repository. The models themselves are public in Privasys/security, with CI configured to re-run them. We have not executed those models, and nothing in this briefing rests on their results.

Level 2, deliberately

Privasys states it stopped at what the researchers call Level 2 — binding to the handshake traffic secret, the ceiling for anything emitted inside the handshake — and declined Level 3, which requires a post-handshake exchange keyed off the TLS exporter. The stated reason is compatibility: an enclave should stay reachable by an ordinary TLS client, curl included, without a bespoke second protocol. The vendor characterises the residual gap as “the difference between ‘bound to this key exchange’ and ‘bound to this exact completed connection’… a formal completeness property, not a new avenue of attack.” CoCoS, by contrast, went post-handshake. Both are defensible engineering; they are not the same guarantee, and a buyer comparing attestation claims across vendors should ask which rung is being sold. The IETF SEAT working group has chartered these correlation properties, which is where the question gets settled for everyone.

What to do

  • If you build on the Privasys forks, check tags manually. OSV has nothing, the ecosystem is other, and your SCA tooling will stay silent. Require privasys-v0.5.1-go1.26.5, privasys-v0.8.1, wasm-v0.40.0, tdx-v0.2.43/tdx-gpu-v0.6.27, and ra-tls-clients v0.5.0 or later.
  • Upgrade the verifier, not just the enclave. CVE-2026-108269 is a client-side bug. A patched enclave talking to an old verifier still accepts an unbound quote, because the verifier is what fails closed.
  • CoCoS operators: v0.9.0 or later. Everything from v0.4.0 to v0.8.2 is architecturally affected on both SEV-SNP and TDX, and the v0.7.0 redesign does not help. Treat the advisory’s “no patch available” sentence as stale against its own structured metadata and the v0.9.0 release notes.
  • Ask any attestation vendor which binding level they implement — nonce-only, handshake-secret (Level 2) or post-handshake exporter (Level 3). “We do RA-TLS” does not answer the question, and as these five records show, the answer can change between minor versions.
  • Do not treat a quote as a channel guarantee in your own designs. The generalisable lesson, well beyond this vendor: a signature over a public key proves provenance of the key. Proving you are talking to its holder right now is a separate property that must be constructed deliberately. The same reasoning applies to issuer binding in MCP OAuth clients, where credentials carried no issuer and upgrading alone changed nothing.

Verification note: all five CVE records were read from the NVD API (CVE-2026-108265 through -108269, status Received, published 9 October 2026 21:17:04Z–22:16:59Z, GitHub-supplied CVSS 4.0 9.1 and CWE-346 only; no independent NVD analysis at the time of writing). The five GitHub advisories were retrieved through the GitHub API, including their affected ranges, patched versions, credits and full descriptions, from which the two ReportData constructions are quoted verbatim. Fix commits were retrieved by SHA and the quoted code comments are verbatim from the diffs; every fixed tag and release date was confirmed against the releases and tags endpoints, and the absence of a privasys-v0.3.0-go1.26.5 release object (the tag exists) is a direct observation. OSV 404s for all five were checked directly. CVE-2026-33697 details, the CoCoS advisory text and the v0.9.0 release notes come from NVD, the GitHub advisory API and the release object. The vendor’s reasoning and the Level 2/Level 3 choice are quoted from the Privasys engineering post dated 9 July 2026; the researcher exchange, the AI-assistance disclosure and the PR’s closed-unmerged state are quoted from the public pull-request thread. ESORICS 2026 acceptance is per the symposium’s accepted-papers listing. We did not run ProVerif models, did not reproduce the relay, and have no evidence of exploitation of any of these issues.

Sources: