Skip to main content
For full production verification, follow Phala’s official application verification instructions and complete chain-of-trust checklist. These are the authoritative references for Phala/dstack verification; this guide adds Chipotle-specific context and diagnostic examples, not a complete production verifier. You are responsible for implementing and enforcing attestation verification correctly for your integration. The implementation depends on your setup and where and how your client connects to the Chipotle server, including proxies, gateways, and TLS termination points. Define the workload and security policy you accept, and enforce the verified identity on the connection carrying application traffic before sending secrets. Following Phala’s instructions does not automatically choose your application policy or integrate those checks into your client. The commands below are diagnostic building blocks. In particular, observe the authentication prerequisites and limitations in Step 3; a passing checksum comparison is not authenticated attestation.
New to TEE verification? Work through the layers in order. Individual checksum matches are not proof of attestation; the TLS evidence checks require the signature, measurement and connection-binding prerequisites described in Step 3.
Prerequisites: python3 (3.8+), docker, openssl, dig, and optionally cosign and cast (from Foundry).

1. Verify the TDX attestation quote (Platform)

What this checks: Is the server running on real Intel TDX hardware? The TDX attestation quote is like a hardware-signed certificate of authenticity — Intel’s chips sign a statement about what software is running, and this step verifies that signature is genuine. Fetch the attestation from the live API and run the official dstack verifier. This validates the Intel TDX quote signature (proving genuine hardware), replays the RTMR3 event log (proving no events were tampered with), and checks OS measurements. Save the Python script below as fix-attestation-event-log.py, then run the verification commands.
The dstack guest-agent strips digests from RTMR3 runtime events to reduce response size. The fix script recomputes them as SHA384(event_type || ":" || event || ":" || payload). The Docker verifier’s parser rejects empty digests, so this preprocessing step is necessary.
If you prefer not to run the Docker verifier locally, you can verify the TDX quote signature via the Phala Cloud API:
Why are there two TDX quotes? This guide verifies two separate TDX quotes from the same CVM:
  • /attestation (Step 1) returns a fresh TDX quote for validating RTMR measurements and the software stack. Its reportData is unused (all zeros).
  • /evidences/quote.json (Step 3) returns a separate TDX quote generated by dstack-ingress, where reportData contains SHA-256(sha256sum.txt) — binding the TLS certificate checksums to the TEE hardware.
Both quotes come from the same CVM and share the same RTMR values, but serve different verification purposes.

2. Verify the application code (Application)

What this checks: Is the TEE running the exact code you expect, with no modifications? This step verifies the Docker images and their configuration match what was built in CI from the public GitHub repository.
Verify image provenance with Sigstore — Each image is signed with cosign (keyless, GitHub OIDC) during CI. This proves the image was built by GitHub Actions from the LIT-Protocol/chipotle repo:
The dstack-ingress image is a third-party dependency from the dstack project. It is Sigstore-signed from the dstack GitHub org, not from Lit’s. To verify it, use --certificate-identity-regexp "https://github.com/Dstack-TEE/dstack/.*" with the same OIDC issuer. See the dstack documentation for details on their signing and release process.

3. Verify TLS terminates in the TEE (Network)

The commands below are not a standalone TLS attestation verifier. Before trusting this chain, independently verify the signature of the dstack-ingress evidence quote and validate its measurements and workload identity against approved policy. Use reportData extracted from that verified quote, not an unauthenticated JSON field. Verifying the separate /attestation quote in Step 1 does not authenticate this evidence quote.The checksum comparison below reads report_data from JSON; it does not perform those prerequisite checks. You must also verify that the certificate file is covered by the authenticated sha256sum.txt and enforce the verified certificate on the TLS connection used for application traffic. A matching PEM from the same origin, or a separate openssl connection, is not sufficient to authenticate a later connection.
Verification goal: Establish that the certificate belongs to the approved TEE workload and is enforced on your application connection. The comparisons below alone do not establish this. Lit Chipotle uses dstack-ingress for custom-domain TLS. Unlike the default dstack gateway (which embeds cert hashes directly in the CVM’s boot-time TDX quote via reportData), dstack-ingress runs as an application container and generates a separate TDX evidence quote after obtaining the Let’s Encrypt certificate. This evidence quote binds the certificate to TDX hardware through a checksum chain:
  1. dstack-ingress obtains a Let’s Encrypt cert via DNS-01 inside the TEE
  2. It computes SHA-256 of each evidence file (cert PEM, ACME account) → sha256sum.txt
  3. It computes SHA-256(sha256sum.txt) and requests a TDX quote with this hash as reportData
  4. The evidence files and quote are served at /evidences/ on the custom domain
The CAA records on the gateway domain restrict certificate issuance to specific ACME account URIs. Verify that the ACME account URI from /evidences/acme-account.json matches one of the accounturi= values in the CAA records. If they don’t match, it means this CVM’s ACME account is not authorized by the DNS policy to obtain certificates for this domain.

4. Verify on-chain governance (Governance)

What this checks: Was the code running in the TEE authorized through on-chain governance? The compose-hash (a fingerprint of the entire application configuration) must be registered in a smart contract on Base before the CVM will accept it. This means deploying new code requires an on-chain transaction — you can audit the full history on Basescan. The compose-hash must be registered in the DstackApp smart contract on Base before the CVM will accept it. A separate Phala KMS contract whitelists allowed OS images and KMS instances. You can inspect both on Basescan. Finding the DstackApp contract address: The DstackApp contract is the on-chain governance contract that authorizes what code the CVM can run. To find the correct address for a given CVM:
  1. Go to the Phala Cloud dashboard and look up the application by its app_id (available from GET /info). The dashboard shows the associated DstackApp contract address.
  2. Verify the contract is the one your CVM is attached to by checking the app_id in the /info response matches the app registered in the contract on Basescan.
For Lit Chipotle production, the DstackApp contract is 0x3F91Deaf16FF7C823eE65081d6bAFA1cEea05FfC (matches the app_id returned by GET /info). The Phala KMS contract is 0x2f83172A49584C017F2B256F0FB2Dca14126Ba9C.
Governance via Safe multisig: Lit’s on-chain governance actions are controlled by a Safe multisig (0xF688411c0FFc300cAb33EB1dA651DBb3E6891098) on Base. This Safe administers: The Phala KMS contract (0x2f83172A49584C017F2B256F0FB2Dca14126Ba9C) — which whitelists allowed OS images and KMS instances — is not administered by the Lit Safe. It is a shared Phala-operated contract whose owner() is a separate Phala-controlled Safe (0x3926658a072F82BAEa5e5a15e1Fed8a776F4a663, 2-of-3). Verify with cast call 0x2f83172A49584C017F2B256F0FB2Dca14126Ba9C "owner()(address)" --rpc-url https://mainnet.base.org. Any Lit governance action (e.g., whitelisting a new compose-hash or upgrading the AccountConfig Diamond) requires Lit Safe signer approval. Production deployments use a two-phase workflow: CI proposes the transaction to the Safe, and signers approve it through the Safe UI before the deployment can proceed.