Security property
The client establishes three linked facts before it sends private content:- A genuine supported AMD platform produced the report. The browser verifies the AMD SEV-SNP report signature and the ARK → ASK → chip-specific VCEK certificate chain.
- The enclave is running an expected release. The browser verifies a Sigstore DSSE bundle issued through GitHub Actions for a tagged release of the expected repository, checks Rekor consistency, and compares the signed release measurement with the measurement in the hardware report.
- The encryption key belongs to that enclave. The report data contains the enclave’s HPKE public key. Certificate verification binds the expected domain, HPKE key, and attestation-document hash together.
securityVerified becomes true only when every verification stage succeeds. getbased additionally requires a non-empty attested HPKE public key before creating the private transport.
Verification flow
- The app creates a Tinfoil
SecureClientwithtransport: 'ehbp'. - The client fetches an attestation bundle containing the SEV-SNP report, VCEK certificate, signed release data, enclave certificate, and routing domain.
- The verifier checks the AMD certificate chain, report signature, firmware and TCB minimums, production guest policy, and that debug and migration-agent modes are disabled.
- The verifier validates the Sigstore identity, tagged workflow reference, release digest, and signed code measurement for the expected repository.
- It compares the signed measurement with the live enclave measurement.
- It verifies that the enclave certificate matches the domain and embeds both the attested HPKE key and the attestation-document hash.
- getbased accepts the returned key only when
securityVerifiedis true and then binds the secure fetch implementation to the verified proxy and enclave origins.
/private attestation bundle and private chat endpoint.
Key model
Private TEE mode does not use a long-lived private key owned only by the user.- Browser: EHBP creates ephemeral HPKE sender material and retains the per-request context in browser memory.
- Enclave: The enclave holds the private key corresponding to the HPKE public key embedded in its signed hardware report.
- Proxy: The PPQ or Routstr proxy receives the encrypted request and routing headers but has neither endpoint’s body-decryption material.
Ehbp-Encapsulated-Key header. The encrypted response keys are derived from the request exporter secret, encapsulated key, and a fresh response nonce.
Request and response handling
getbased builds the normal OpenAI-compatible request before the secure fetch layer encrypts its body. For Routstr, the encrypted JSON uses the enclave model ID without thetinfoil- prefix, while the full advertised model ID remains in X-Routstr-Model for routing and billing.
The proxy must be able to read operational headers. Depending on the provider, visible information includes:
- API or session bearer credentials
- Selected private model and query-source headers
- Destination, IP address, timing, and approximate payload size
- Balance, reservation, and billing metadata
- A plaintext proxy error such as authentication, insufficient balance, or rate limiting can pass through unchanged because it was generated before enclave processing.
- A successful response must include
Ehbp-Response-Nonce. The browser rejects a plaintext success response and decrypts only a nonce-bound EHBP stream.
Failure and rotation behavior
Private selections fail closed. They never fall through to the provider’s standard plaintext request path.- Missing or failed attestation stops setup.
- An unverified or missing HPKE key stops setup.
- Requests to origins outside the verified proxy/enclave set are rejected locally.
- A successful response without the EHBP nonce is rejected.
- An EHBP key-configuration mismatch resets the client, performs one fresh attestation, and retries once.
- Changing the Routstr node clears node-scoped models and cached attestation clients.
Trust assumptions and non-guarantees
Remote attestation identifies the running enclave and binds its encryption key. It is not a general proof that the software is safe. The design still trusts:- The getbased JavaScript delivered to the browser and the locked Tinfoil/EHBP dependencies
- The browser, operating system, and extensions before encryption and after decryption
- AMD SEV-SNP hardware, firmware, root certificates, and the verifier’s policy
- The expected GitHub repository, its tagged Sigstore release workflow, and the audited behavior of the measured release
- The absence of exploitable TEE implementation bugs and relevant side channels
Implementation references
js/tinfoil-secure-fetch.js— shared verified EHBP transport and fail-closed response handlingjs/api-routstr.js— Routstr private model routing and metadata boundaryjs/api-ppq.js— PPQ private endpoint integrationjs/chat-attestation.js— user-visible verification statustests/tinfoil-secure-fetch.test.js— transport security regression coverage