Caution is backed by Y Combinator. Learn more.

All posts

STEVE: Attesting the session, not just the enclave

TL;DR

STEVE keeps application plaintext and session traffic keys away from the host by establishing an encrypted channel that terminates inside a confidential computing enclave, even when ordinary TLS does not. This release binds fresh attestation evidence directly to each session, so application data flows only after the client verifies that the attested enclave holds the session keys.

  1. What is STEVE?
  2. Why attestation must bind to the session
  3. When valid evidence protects the wrong channel
  4. How STEVE now binds evidence to the session
  5. What changes in practice
  6. What STEVE does not prove
  7. Conclusion: the right workload and the right session keys
  8. References

What is STEVE?

We first introduced STEVE on the Distrust engineering blog in February 2026. Short for Secure Transport Encryption Via Enclave, STEVE establishes an encrypted channel between a client and an application running inside a confidential computing enclave. This matters because ordinary TLS often terminates at infrastructure outside the enclave, allowing the host to see application plaintext even when the workload itself is isolated. STEVE keeps that plaintext and the session traffic keys away from the host.

STEVE keeps application plaintext and session traffic keys at the client and inside the attested enclave, even though the untrusted host carries every message.

The new release, STEVE v2, strengthens the protocol by binding attestation evidence to the exact session receiving the data.

Why attestation must bind to the session

The original STEVE design attested a process-lifetime Ed25519 public key. The enclave used the corresponding signing key to authenticate later ephemeral key exchanges, so clients trusted each session through that attested key.

STEVE v2 removes that intermediate authority. It obtains a new attestation for each session and binds the evidence directly to the session’s key exchange and a value derived from its shared secret. The client therefore verifies two things: that the evidence is valid, and that the attested endpoint holds the keys for this exact session.

Why the binding matters

Attestation tells the client which enclave measurements produced the evidence. A key exchange establishes session keys. Neither alone proves that the attested endpoint holds the keys for this session.

STEVE v2 connects them by binding fresh evidence to the session’s key exchange and shared secret, then confirming possession of the resulting traffic keys before application data flows.

When valid evidence protects the wrong channel

CVE-2026-33697 shows what happens when the evidence and the channel come apart. It is not a STEVE vulnerability and its construction differs from both STEVE versions. It is worth walking through because the failure mode does not depend on the construction.

The attack had a substantial precondition: the attacker first had to extract the private key associated with a per-connection TLS certificate, for example through a physical, side-channel or transient-execution attack. The affected design attested a hash of that certificate’s public key and a client nonce. The evidence could therefore be genuine, fresh and consistent with the client’s measurement policy.

But the certificate key was not the TLS application traffic secret. Once the private key had escaped, an attacker could use genuine evidence while authenticating a different TLS handshake whose traffic keys the attacker controlled. No attestation signature needed to be forged.

Valid evidence is not enough if it authenticates the wrong channel. The protocol must bind the evidence to the session’s key schedule and confirm possession of the resulting traffic keys.

How STEVE now binds evidence to the session

STEVE v2 keeps the same basic architecture. Ordinary TLS authenticates the public origin and carries the initial browser delivery and STEVE messages. Inside it, STEVE creates a separate encrypted channel between the client and the enclave. The host can terminate outer TLS and route inner records without learning application contents.

1. Pin the suite and construct the transcript. The client pins a key-exchange suite before connecting: X25519 by default, or the versioned XWING-DRAFT10 hybrid. The client creates new key material and a nonce; the enclave creates fresh server material and a random session identifier. Both sides construct the same transcript, committing to the selected suite, the nonce, both key-exchange messages, the session identifier and a client context.

For the browser, that context commits to the service worker’s origin. Native clients can include application-specific context. This prevents the context from being silently substituted inside the exchange. It is a client commitment, not server-side authorization of an origin or application.

2. Bind evidence to the session. The enclave asks for fresh evidence using the client’s nonce. The signed user data commits to the protocol, selected suite, session identifier, transcript hash and a binder derived from the shared secret. The client computes the same values locally, verifies the certificate chain and signature, checks freshness and its nonce, then compares every session-binding value.

The transcript hash identifies the exact exchange the enclave attested. The binder shows that the attested endpoint derived the same shared secret from that exchange. Moving the evidence to another exchange changes the client’s locally computed values and causes verification to fail.

3. Confirm possession of the traffic keys. The peers confirm possession before carrying application data. The client sends an encrypted sequence-zero confirmation under the new client-to-server key, and the enclave replies under a separate server-to-client key. Only then does the session become active.

4. Protect application traffic with directional keys. Subsequent requests and responses use directional AES-256-GCM keys and authenticated sequence numbers. Duplicate and stale records are rejected. The original HTTP method, path, selected headers and body travel inside protected STEVE records rather than as visible application requests at the host.

What changes in practice

Two changes come with v2 beyond the binding itself.

Fail closed by default. The server now rejects plaintext application requests unless an operator deliberately enables a migration mode. A narrow set of public resources remains available to bootstrap a browser client, but sensitive application traffic is expected to pass through a confirmed STEVE session. Exposing the enclave application through a separate port would still bypass that protection.

No silent downgrade. X-Wing combines ML-KEM-768 and X25519 and is designed to retain session secrecy if either component remains secure. It is an explicitly selected, versioned draft suite, not an unqualified claim that the whole system is post-quantum secure. A client pinned to X-Wing does not fall back to X25519 if initialization, attestation or confirmation fails.

What STEVE does not prove

Session binding does not solve every trust problem around confidential computing.

Availability and traffic metadata. The host still controls connectivity. It can drop, delay, reorder or flood records and deny service. It also observes metadata such as source addresses, the public origin and STEVE endpoint, session identifiers, ciphertext sizes, timing and traffic patterns. STEVE protects application content and integrity; it is not an availability or traffic-analysis system.

Workload identity and client policy. Fresh, genuine evidence also does not identify the workload a particular user intended to reach unless the client applies an independent workload policy. Caution’s native Rust client and Swift interface require such a policy. The browser now supports the same pinned-profile and TOFU choices, and reapplies configured policy on every rotation, but keeps PCR policy optional for backward compatibility. When omitted, it reports that PCR policy was not checked.

TOFU enrollment and continuity. TOFU enrollment happens only after the evidence, session binding and encrypted confirmation have succeeded. It provides continuity after enrollment; it does not independently establish that the first workload was correct. In the browser, TOFU survives service-worker restarts, but clearing or evicting same-origin storage reopens enrollment.

Browser bootstrap trust. The browser has a different boundary. Its service worker verifies the attestation chain, nonce, session transcript, binder, pinned suite and encrypted confirmation. When configured, it also enforces the expected PCR policy before application traffic. The initial page, worker, configuration and, for X-Wing, its WASM still arrive through the existing web origin. If that origin is already hostile, it can replace the verifier or policy before STEVE runs.

Under that bootstrap assumption, the browser can establish an attested, session-bound channel to a genuine enclave. Identifying it as a particular reviewed application additionally requires an independently trusted workload policy.

The full security claim depends on two independent checks: that the evidence describes the intended workload, and that it is bound to the exact session keys.

STEVE protects application contents and session keys, not delivery or traffic metadata. The host relays ciphertext but retains control over connectivity.

Conclusion: the right workload and the right session keys

Attestation reports the enclave’s measurements. Policy decides whether to accept them. STEVE binds the accepted evidence to the session keys. The accepted evidence must describe the intended workload and be bound to the exact keys carrying the data.

References

STEVE and Caution

Related security research