anonrouterdocs

TEE verification and encrypted inference

Verify enclave evidence and per-request receipts, understand verification levels, and use opaque NEAR or Chutes E2EE.

AnonRouter exposes provider-neutral enclave attestation and request-signature services. Provider evidence is fetched by a credential-isolated worker, verified fail-closed, and returned to you so your client can independently repeat the verification.

TEE is not automatically hardware-verified

A route's privacy modality and its verification level are separate claims. This API never turns a provider boolean, model suffix, or confidential-compute flag into silicon proof. No provider route (hop 2) currently reaches hardware-verified: several run GPU enclaves whose NVIDIA chain is not available to verify, and chaining only the CPU quote would claim more than was checked.

Hop 1 — AnonRouter's own routing plane — is different, and is reachable at hardware_verified with a DCAP engine. See Verify AnonRouter itself.

Building an E2EE client?

Follow the dedicated E2EE client guide for the ticket sequence, provider wire formats, required headers, retry rules, and production checklist. This page remains the attestation and receipt reference.

Two hops, verified separately

A request passes through two parties, and verifying one tells you nothing about the other.

Question it answersHow to check it
Hop 1 — AnonRouter's own routing planeIs the router I am talking to the exact reviewed build, running inside an Intel TDX confidential VM, bound to my nonce and my origin?GET /v1/gateway/attestation — credential-free
Hop 2 — the downstream provider routeDid the model provider terminate my request inside a verified enclave running measurements I pinned?the provider attestation and receipt APIs below

A verified hop 2 says nothing about who routed the request there. A verified hop 1 says nothing about where inference actually ran. Most of this page is about hop 2; the section immediately below is hop 1.

Verify AnonRouter itself (hop 1)

AnonRouter's content plane runs inside an Intel TDX confidential VM. The relay, the compatibility broker, and every provider worker run inside that TD, and TLS terminates in-enclave rather than at a platform gateway in front of it.

This is why the privacy properties on the privacy page are not just policy. Prompts do not reach ordinary AnonRouter infrastructure, and no operator can read them off a running host — and you do not have to take that on trust, because the plane will attest to itself on demand.

The endpoint

NONCE=$(openssl rand -hex 32)
curl -s "https://api.anonrouter.ai/v1/gateway/attestation?nonce=$NONCE"

GET /v1/gateway/attestation is credential-free — a client should be able to check the plane before trusting it with anything, including before it has an account. The nonce is required and must be exactly 64 hex characters (32 bytes); a request without one is a 400.

The response is a JSON document of roughly 95 KB:

FieldWhat it carries
bindingthe claims being attested: your nonce, app_id, instance_id, compose_hash, release_id, origin, the plane's public_key, transport, and tls_spki_sha256
binding_hashthe digest committed into the quote's report_data
quotethe raw Intel TDX quote
event_logthe boot event log, which replays to the quote's RTMRs
app_compose, vm_configthe measured deployment definition
issued_at_msfreshness

What a verdict establishes

Verifying that document is what turns "AnonRouter says it runs in an enclave" into something you checked:

  • the quote is fresh and yours — your nonce appears inside the quote's report_data, as the digest of the canonical binding, so a recorded response cannot be replayed at you;
  • TLS terminates inside the TD — binding.transport is in-tee-tls, not gateway-tls. There is no platform proxy in front of the enclave holding your plaintext;
  • the certificate belongs to the attested TD — the leaf SPKI you observed on your own connection equals binding.tls_spki_sha256. This is the check that turns "somebody named a certificate" into "the enclave holds the key for this connection";
  • the build is the reviewed one — compose_hash, app_id, release_id and the platform measurements match pins you hold locally, not values the server chose;
  • the event log is consistent — it replays to the quote's RTMRs.

The pins must not come from the server being checked

A server that could hand you the list of builds you accept could always name itself. Hold the plane to measurements you obtained independently. The SDK ships reviewed pins inside the package for exactly this reason, and fails rather than falling back to whatever the origin claims.

Checking it without writing a verifier

Both SDK packages install anonrouter-verify, which does the whole document and exits nonzero unless the assurance you asked for held:

anonrouter-verify gateway --origin https://api.anonrouter.ai \
  --dcap --require hardware_verified
echo $?   # 0 met, 1 not met, 2 the command was wrong

Hop 1 is the one place a hardware_verified result is reachable, and only with a DCAP engine that actually chained the quote's ECDSA signature to Intel's roots with an accepted TCB status. Without an engine the honest ceiling is cryptographically_checked, and a policy demanding hardware verification fails closed rather than quietly settling for less. See the SDK verification guide and the command reference.

The pin SDK v0.1.0 ships is older than the running plane

A shipped pin is a snapshot of a reviewed release, and the content plane has been released since v0.1.0 was tagged. The pin in that version names the previous build, so the command above fails closed against production today on compose_hash_pinned and release_pinned rather than passing. That is the design working — the alternative would be an SDK that accepts whatever the origin currently claims — but until a refreshed pin ships, gate on a policy you reviewed yourself with --policy. Check the running build's compose_hash and release_id against the release you reviewed.

What hop 1 does not cover

  • It says nothing about the provider. That is hop 2, below.
  • It does not make a TEE route end-to-end encrypted. Inside the enclave, the relay handles your plaintext to route and meter it. What that buys you is that a build changed to exfiltrate it would change the measurements and stop verifying — cheating is detectable, not impossible. Only an E2EE route keeps content opaque to AnonRouter's build whatever code it is running.
  • It says nothing about what the provider does with the prompt. On an ordinary route the worker forwards plaintext to the upstream provider, which sees it under that provider's own policy. Check the privacy label on the route.
  • Attestation names the build; it does not review it. Reading the source behind a pinned compose hash is a separate act.

Support matrix

ProviderMaximum verificationAnonRouter modalityPer-request receipt
Chutes confidential textprovider-attestedNon-streaming ML-KEM whole-body e2eeNot exposed by the provider; returns tee_signature_not_supported
Tinfoilsdk-verifiedtee over TLS/JSONNot exposed by the provider; returns tee_signature_not_supported
Veniceprovider-attestede2eeEIP-191 enclave receipt for completed non-stream and streaming requests
NEAR AI directprovider-attestedOpaque e2ee, version 2EIP-191 receipt with exact AnonRouter wire-hash binding for completed non-stream requests
NEAR AI attested-3pNo direct model-enclave attestationteeNo receipt through the direct flow

NEAR AI has no callable route in the current catalog

The NEAR verifier and the version 2 opaque protocol below are implemented and documented, but the live catalog publishes no callable NEAR AI route. Every NEAR example on this page is therefore a protocol reference rather than a request you can run today. Read GET /v1/catalog/models for what is actually callable before pinning a provider.

The confidential routes the catalog publishes as callable today are Tinfoil tee, Venice e2ee, and Chutes e2ee. Chutes' callable routes are text-only; the one callable embedding route is Tinfoil's nomic-ai/nomic-embed-text, which is tee rather than e2ee.

Tinfoil documents EHBP/HPKE transport, but its model selector is encrypted and the documented outer headers do not bind that model to an AnonRouter ticket or reservation. AnonRouter fails closed rather than expose a proxy through which a caller could ticket one model and encrypt a request for another. Tinfoil routes are therefore not advertised as E2EE.

Verification levels

LevelWhat the result proves
hardware-verifiedQuote signatures, certificate and revocation chains, acceptable TCB, GPU evidence, nonce and key bindings, debug state, and pinned measurements all passed to silicon-vendor trust roots. No provider route reaches this level; AnonRouter's own plane (hop 1) does, with a DCAP engine.
sdk-verifiedThe official provider SDK completed its required cryptographic verification and the result matched AnonRouter's pinned release policy.
provider-attestedRequired structure, freshness, nonce/key, route, certificate-possession, and pinned-measurement checks passed, but the complete silicon-vendor chain was not independently established.
unverifiedA required check, policy value, or evidence item was absent or failed.
unsupportedThe selected provider or route does not expose the requested capability.

The Intel/NVIDIA chain port remains intentionally unwired. The currently available path does not provide all collateral, trust-root, revocation, and TCB handling needed to make the stronger claim. Incomplete evidence fails closed at provider-attested or unverified.

Fetch fresh attestation evidence

Both public TEE endpoints require an API key with the inference scope. Use a fresh random nonce containing 32 to 64 bytes, encoded as hexadecimal:

curl "https://control.anonrouter.ai/v1/tee/attestation?model=openai/gpt-oss-120b&provider=tinfoil&nonce=$NONCE" \
  -H "Authorization: Bearer $ANONROUTER_API_KEY"

The same evidence is available from the confidential origin without presenting a key to it, using an attestation ticket instead.

The response identifies the exact provider route and privacy modality and contains:

  • verification_level and every individual check;
  • normalized measurements and public signing identities;
  • the measurement-policy version and expiry;
  • the exact raw provider evidence for independent client verification.

Attestation results are cached for five minutes without prompts, responses, private keys, or raw request bodies. A hostname or model name alone never earns a verification level.

Retrieve a request receipt

After a supported completion, use the provider's request ID returned with that completion:

curl "https://control.anonrouter.ai/v1/tee/signature/$PROVIDER_REQUEST_ID?model=z-ai/glm-5.2&provider=venice" \
  -H "Authorization: Bearer $ANONROUTER_API_KEY"

Optional request_hash and response_hash query parameters are additional client cross-checks. They never replace the content-free hashes calculated and stored by AnonRouter.

NEAR exact-wire receipts

For a non-stream request, the credential worker hashes the exact JSON sent to the direct enclave and the exact raw response before parsing. Receipt lookup requires an unexpired route binding, a fresh matching attestation, exact hash equality, and successful EIP-191 recovery to the attested signing address.

For a verified NEAR receipt, hash_binding_checked: true means the signed request and response hashes equal the exact bytes observed by AnonRouter. NEAR streaming does not yet provide the completed-response binding needed for this claim and fails with tee_signature_binding_unavailable.

Venice enclave receipts

Venice receipts are recovered with EIP-191 against the secp256k1 key committed to the earlier TDX attestation. The signed statement, completion ID, model, and request.received/response.returned event hashes must agree.

Venice signs an enclave-internal ingress/egress representation rather than the exact public API wire bytes. A valid receipt therefore normally returns verified: true, verification_level: "provider-attested", and hash_binding_checked: false. The response exposes both bound_* provider hashes and gateway_* wire hashes instead of claiming equality Venice did not sign.

Completed Venice streams are supported. Receipt metadata crosses the worker boundary in a private sideband that is never emitted as a customer SSE event. Aborted or incomplete streams produce no signature binding.

Unsupported is not a broken TEE route

Chutes and Tinfoil inference and public attestation work normally. They do not expose a compatible per-completion receipt, so signature lookup returns the structured 501 tee_signature_not_supported response. AnonRouter never fabricates a substitute gateway signature.

NEAR v2 opaque E2EE

NEAR direct routes expose the provider-neutral v2 field-encryption modality. Request a nonce-bound attestation ticket for the exact direct route, then send ciphertext with this validated header set:

X-AnonRouter-E2EE-Provider: near-ai
X-Signing-Algo: ed25519
X-Client-Pub-Key: <32-byte Ed25519 public key as 64 lowercase hex chars>
X-Encryption-Version: 2

Do not send X-Model-Pub-Key. That field belongs to NEAR's cloud gateway; AnonRouter obtains the model key from the direct enclave's attestation.

For every encrypted field, the client uses ephemeral X25519 ECDH and HKDF-SHA256 with info = "ed25519_encryption", then encodes this lowercase-hex wire value:

[ephemeral X25519 public key: 32 bytes]
[XChaCha20-Poly1305 nonce: 24 bytes]
[ciphertext + authentication tag]

Encryption and decryption stay client-side. AnonRouter forwards only the validated headers and opaque ciphertext, does not parse message fields as plaintext, and never receives either private key.

Endpoint discovery must exactly match the reviewed direct enclave domain. Missing or mismatched discovery fails with e2ee_enclave_endpoint_unavailable; an E2EE request never falls back to the cloud gateway, a plaintext route, or another provider.

Chutes ML-KEM whole-body E2EE

Confidential Chutes text routes are ciphertext-only through AnonRouter. First, use the normal model-bound attestation-ticket flow. The returned raw evidence contains e2e_instances: instance UUIDs, ML-KEM-768 public keys, and short-lived single-use nonces. Accept a key only after verifying the response and its SHA256(caller nonce || ML-KEM key) TDX report-data commitment.

Encrypt with Chutes' official transport format, then submit the exact bytes:

curl "https://api.anonrouter.ai/v1/e2ee/chat/completions" \
  -X POST \
  -H "Content-Type: application/octet-stream" \
  -H "X-AnonRouter-Ticket: $INFERENCE_TICKET" \
  -H "X-AnonRouter-E2EE-Provider: chutes" \
  -H "X-Chutes-Instance-Id: $ATTESTED_INSTANCE_ID" \
  -H "X-Chutes-E2E-Nonce: $SINGLE_USE_NONCE" \
  --data-binary @encrypted-request.bin \
  --output encrypted-response.bin

The credential worker resolves the ticket-bound model to its live chute_id, requires confidential_compute: true, overwrites the chute, path, and streaming headers, and adds the Chutes credential. Only the two validated instance/nonce values cross from the client. Request and response bodies remain byte-for-byte opaque to AnonRouter, and there is no provider fallback.

This first endpoint is non-streaming. Chutes keeps its non-stream token usage inside the encrypted response, so the ticket must reserve the model's full output ceiling. AnonRouter reserves the full context at the most expensive token rate and conservatively captures it after success; it never estimates plaintext usage from compressed ciphertext length. The ticket-mint request must therefore set max_tokens to the model's published maximum.

The opt-in live suite performs a real ML-KEM-768 request/response round trip and decrypts only in the test client; the relay receives only the encrypted blobs.

What each provider check establishes

Chutes

AnonRouter checks every returned instance: TDX v4 structure and debug state, pinned MRTD/RTMR0-3 measurements, the nonce plus ML-KEM key commitment, the certificate SPKI commitment, RSA possession of the decoded attested body, inner/outer quote and GPU equality, certificate validity, and complete instance key discovery. The missing complete Intel/NVIDIA vendor chain keeps the result at provider-attested. For an e2ee result, the verified ML-KEM key commitment also has to pass; the route never claims hardware-verified.

Tinfoil

The credential worker runs the official tinfoil@1.2.1 verifier. An sdk-verified result requires securityVerified === true, all five SDK verification steps, the selected endpoint, and exact pinned release digest, code fingerprint, enclave fingerprint, and TLS key. A missing SDK or document never defaults to success.

NEAR direct

AnonRouter checks TDX v4 structure and debug state, NVIDIA evidence, the nonce/key/TLS commitment, exact model and direct endpoint, mr_config_id, the serialized app_compose hash, and pinned MRTD/RTMR0-3 measurements for that model. Current evidence does not independently prove the model-weight digest or complete silicon chain, so the maximum remains provider-attested.

Venice

AnonRouter checks TDX v4 structure and debug state, caller nonce and model, NVIDIA evidence, nested report-data equality, and a secp256k1 public key whose derived address matches the signer committed into TDX report data. Venice's own verified boolean is not accepted as proof.

Where a Venice E2EE route actually decrypts

E2EE guarantees that only the enclave you verified and encrypted to can read the prompt. On some Venice routes that enclave is a verified gateway rather than the machine running the model: it decrypts your request and forwards the plaintext onward inside Venice's own infrastructure. The attestation is real and AnonRouter still never sees plaintext, but "only the model host can read it" is a stronger claim than the evidence supports. The catalog states this per route in privacyNotes; read it before treating an E2EE label as a model-host guarantee.

Phala AI

Phala AI is classified private, not confidential, and appears in no two-hop count. It is an aggregator gateway that decrypts before forwarding, so it carries no route attestation and no receipt. Do not read the provider's name as a TEE claim; the route's own privacy label is the claim.

Service-level comparison

AnonRouter provides the core public operations documented by NanoGPT's TEE verification and signature APIs: fresh authenticated evidence, raw evidence for client verification, measurements and signing identities, and provider receipt lookup. AnonRouter also enforces explicit verification-strength levels, pinned measurement policies, route bindings, server-side EIP-191 recovery, and exact wire-hash checks where the provider signs those bytes.

The distinction is capability-specific: NEAR direct and Venice expose cryptographically verifiable request receipts, while Chutes and Tinfoil expose attestation without a compatible per-request receipt.

Trust boundaries

  • The relay, the compatibility broker and every provider worker run inside the Intel TDX confidential VM, which terminates TLS in-enclave. Prompts do not reach ordinary AnonRouter infrastructure, and the plane attests to that on demand (hop 1).
  • Provider credentials stay on their provider-specific worker.
  • Control receives only content-free metadata; it serves no request content at all, and answers 404 for /v1/chat/completions.
  • Raw prompts, responses, API keys, decrypted E2EE content, and unsafe upstream bodies are never written to verification caches or logs.
  • The dispatch fence still runs immediately before billable provider work.
  • Measurement-policy changes require reviewed immutable pins rather than trusting a live provider assertion in place.

See the E2EE client guide, models and privacy labels, intelligent routing, and the complete privacy architecture for how these capabilities affect route selection and the rest of the request lifecycle.

Or hand the whole thing to your agent

One prompt carries the entire setup. Give it to your agent, review what it configures, and you are done.

On this page