How attestation works
Hosted inference is fast and cheap. The catch is the trust posture: your prompts run on someone else's hardware, and the standard ask is that you trust them not to read or log it. BaseVault replaces that ask with a chain of cryptographic checks that ground out in silicon and in public transparency logs — something you can verify without having to trust anyone in particular.
This page is the long version. If you want the short version, see the Trust model section on the home page. If you want the full design record, that lives in issue #135.
That's the property. Concretely, before a single byte of your prompt leaves your laptop, BaseVault confirms three things, by cryptography, against public roots of trust:
Each is a separate cryptographic system. They compose into one transitive guarantee. The rest of this page walks each piece in turn, ends with a worked example you can verify yourself, and is honest about what's still trust.
Modern AMD EPYC and Intel Xeon CPUs ship with on-die secure processors that can produce a signed attestation report. The report is a binary blob that says, in cryptographic terms: "I am this chip, my firmware is at this version, and the code currently loaded into this isolated VM hashes to this 48‑byte value." The signature roots in the chip vendor's certificate authority — AMD's VCEK chain or Intel's PCK chain.
The 48‑byte hash is called the measurement
(or M for short).
It captures everything about the initial state of the
enclave: the kernel image, the initial RAM disk, the
kernel command line, the CPU and memory configuration,
and (transitively) every file inside the root filesystem
via dm-verity. Change a byte anywhere in that chain and
you get a different measurement.
The hardware also signs an extra 64‑byte field
called report_data.
Tinfoil's enclave fills this field with the SHA-256 of
its TLS public key (in the first 32 bytes). This is the
bridge between "what code is running" and "which
connection you're talking to" — we'll come back to it
in section 3.
The hardware quote tells you some code is running and gives you its hash. It doesn't tell you that hash is the right one. Sigstore is how you know.
Sigstore is a Linux Foundation project that lets developers sign artifacts using short-lived certificates tied to an OIDC identity, and records every signing event in a public append-only transparency log. Three components:
The pitch is "keyless" signing. No developer holds a long-lived signing key. CI generates an ephemeral keypair, gets a 10-minute Fulcio cert tied to its OIDC identity, signs, logs to Rekor, throws away the keypair. The signature is verifiable later from public information alone — the cert encodes which workflow signed what, and the Rekor proof confirms the signature was logged at signing time.
For Tinfoil's enclave releases, every per-model
deployment ships a tinfoil-deployment.json
file that contains the expected hardware measurement.
That file is signed via Sigstore at GitHub Actions build
time. The Sigstore cert's extensions encode the workflow
identity (e.g., tinfoilsh/confidential-kimi-k2-6/.github/workflows/build.yml@refs/tags/v0.0.2),
the runner type (must be GitHub-hosted, not self-hosted),
and the source-code commit SHA.
The first two pieces give you "this enclave is running this code." They don't say anything about the connection. For that we use TLS pubkey pinning rooted in the same hardware quote.
When the enclave boots, it generates a fresh TLS keypair
inside the encrypted memory region. The private
key never leaves the enclave (memory encryption keeps
even the host operator out). The enclave then asks the
hardware for a quote whose report_data[0:32]
field equals SHA-256 of its newly-generated TLS public
key — specifically, the SHA-256 of the DER-encoded
SubjectPublicKeyInfo,
which is the standard X.509 way to wrap "what kind of
key plus the key bytes." This 32-byte hash is called the
SPKI fingerprint.
The hardware signs the quote, sealing the binding
between the measurement M
and the fingerprint fp
into one cryptographic statement: "the enclave running
code with measurement M generated a TLS keypair whose
SPKI hashes to fp."
BaseVault's SDK does two things with this. First, it
verifies the quote and extracts fp.
Second, it installs a custom verifier in the TLS layer
that rejects every connection where the server cert's
SPKI doesn't hash to fp.
Because the TLS handshake's transcript signature
cryptographically proves the server holds the matching
private key, and the private key is sealed in the
enclave, every successful handshake transitively proves
you're talking to that specific enclave running that
specific code.
A copy-cat proxy serving a stolen quote would fail because it doesn't have the matching private key. A load balancer terminating TLS upstream would fail because its key wouldn't match the quote's fingerprint. The pin enforces that TLS terminates inside the enclave, on the same keypair the hardware attested.
Each link is a separate cryptographic check. The whole chain runs at TinfoilAI() construction in the SDK BaseVault uses, plus per-request TLS pin enforcement on every subsequent call.
Source. Per-model deployment config lives in tinfoilsh/confidential-<model> on GitHub. Public repository.
e.g., github.com/tinfoilsh/confidential-kimi-k2-6
Build. A pinned-by-SHA GitHub Actions workflow runs tinfoilsh/measure-image-action. The action computes the expected hardware measurement deterministically from the kernel, initrd, OVMF firmware, command line, and config. Outputs tinfoil-deployment.json.
AMD measurement is reproducible bit-for-bit via IBM's open-source sevsnpmeasure-py; see the gaps section for the TDX side.
Sign. Sigstore signs tinfoil-deployment.json via Fulcio (10-minute cert tied to the workflow's GitHub Actions OIDC identity) and logs the signing event to Rekor. The cert's extensions encode workflow path, commit SHA, runner type.
The bundle is published as a GitHub release attestation, e.g., github.com/tinfoilsh/confidential-kimi-k2-6/attestations/...
Deploy. Tinfoil boots the enclave on AMD SEV-SNP or Intel TDX silicon. Hardware measures the load and produces a signed quote. Inside, the enclave generates a fresh TLS keypair and binds its SPKI fingerprint into the quote's report_data.
Live attestation endpoints: /.well-known/tinfoil-attestation on each enclave host.
Verify. When BaseVault's SDK initializes, it (a) fetches the live quote, (b) verifies the chip-vendor signature against AMD/Intel roots, (c) extracts the measurement, (d) fetches the matching Sigstore bundle from GitHub, (e) verifies Fulcio + Rekor + the in-toto signature, (f) asserts the live measurement equals the Sigstore-signed expected value, (g) extracts the TLS pubkey fingerprint from report_data[0:32], and (h) installs that fingerprint as the TLS pin for every subsequent request.
Run. Each chat completion opens TLS to the pinned endpoint. The handshake fails if the cert SPKI doesn't hash to the pinned fingerprint, before any prompt bytes leave the laptop. If the handshake succeeds, the connection terminates inside an enclave whose code measurement was already verified.
For per-model enclaves (the boxes that actually run
kimi-k2-6,
gpt-oss-120b, etc.), the
same chain runs once more, this time with Tinfoil's
open-source router (tinfoilsh/confidential-model-router,
AGPL-3.0) playing the verifier role. The router's own
attestation is checked by BaseVault's SDK; the router then
attests every model enclave the same way before routing
traffic to it. Two layers of attestation, both auditable from
public source.
These are the actual values produced by the live system at the time of writing. Hardware-extracted measurement on the left, Sigstore-signed expected on the right, equality at the bottom. Reproduce them yourself with the recipes in the next section.
live extraction
From kimi-k2-6-inf10.tinfoil.containers.tinfoil.dev/.well-known/tinfoil-attestation
Decoded TDX QuoteV4 (base64 + gzip envelope, then parsed at byte offsets per Intel DCAP spec):
rtmr1 : 4f7be53273f4ed3114e7578574f98eec
533d5a18484e4e8a5feef1672b4a94e1
7646e7ab9e1f3c722faea496bac4dc8d
rtmr2 : 1d161bb053cad2ab012b05a6b89cb6da
913b5ab11f9ed35eda24caaa32ff4b08
537f7626b3ec14bf34329ee343987923
tls_key_fp: 33eb805dd932812a03a7a97c6626abd7
6cfa8e58d9aace2787a87f0e08e212fd
All three fields are signed by Intel's chip-vendor PCK chain. Tampering with the bytes invalidates the signature.
Sigstore-signed expected
From tinfoilsh/confidential-kimi-k2-6@v0.0.2/tinfoil-deployment.json, signed by GitHub Actions workflow at build time:
"tdx_measurement": {
"rtmr1": "4f7be53273f4ed3114e7578574f98eec
533d5a18484e4e8a5feef1672b4a94e1
7646e7ab9e1f3c722faea496bac4dc8d",
"rtmr2": "1d161bb053cad2ab012b05a6b89cb6da
913b5ab11f9ed35eda24caaa32ff4b08
537f7626b3ec14bf34329ee343987923"
}
In-toto Statement signed via DSSE. The Fulcio cert encodes tinfoilsh/confidential-kimi-k2-6/.github/workflows/build.yml@refs/tags/v0.0.2 — only that specific workflow can produce a valid signature for this digest.
equality — the boundary
rtmr1, rtmr2:
byte-identical between the live hardware quote and the
Sigstore-signed manifest. Two cryptographic systems,
independently rooted (Intel chip vendor, Linux Foundation
transparency log), converge on the same hash.
What that proves, in plain terms: the running enclave is
bit-for-bit the code described by tag v0.0.2 of the public
tinfoilsh/confidential-kimi-k2-6 repo. You can read
the source. You can read the workflow that built it. You
can rebuild from public inputs and confirm the hash.
There's nowhere for malicious code to hide that wouldn't
change those 96 hex characters.
You don't have to take BaseVault's word for any of this. Each step of the chain is publicly verifiable with off-the-shelf tools. The recipes below run against the live system at the time of reading; outputs will reflect whatever release Tinfoil is currently running.
curl -s https://kimi-k2-6-inf10.tinfoil.containers.tinfoil.dev/.well-known/tinfoil-attestation \
| python3 -c "
import sys, json, base64, gzip
doc = json.load(sys.stdin)
raw = gzip.decompress(base64.b64decode(doc['body']))
b = 48 # skip 48-byte quote header
print('format :', doc['format'])
print('rtmr1 :', raw[b+376 :b+424].hex())
print('rtmr2 :', raw[b+424 :b+472].hex())
print('tls_key_fp :', raw[b+520 :b+552].hex())
"
For the router itself, swap the URL to inference.tinfoil.sh/.well-known/tinfoil-attestation. The router runs on SEV-SNP, so the layout is slightly different (single 48-byte measurement at offset 0x90, fingerprint at 0x50).
gh release download v0.0.2 \
-R tinfoilsh/confidential-kimi-k2-6 \
-p 'tinfoil-deployment.json'
jq '.tdx_measurement' tinfoil-deployment.json
Compare the bytes printed by [A] to the bytes printed by [B]. If they match (they will), the live enclave is the code described by the public release.
gh attestation verify tinfoil-deployment.json \
-R tinfoilsh/confidential-kimi-k2-6 \
--predicate-type https://tinfoil.sh/predicate/snp-tdx-multiplatform/v1 \
--deny-self-hosted-runners
gh attestation verify walks the Sigstore bundle: validates the Fulcio cert chain, checks the Rekor inclusion proof, verifies the DSSE signature over the artifact digest, and confirms the cert's identity matches the GitHub Actions workflow you specified. --deny-self-hosted-runners additionally refuses any signature produced on a self-hosted runner.
For the router, the same recipe with -R tinfoilsh/confidential-model-router and the matching release tag.
The most subtle check — that the host serving the quote is the enclave the quote describes (not a copy-cat proxy serving a stolen quote) — is a single openssl invocation:
openssl s_client -connect inference.tinfoil.sh:443 \
-servername inference.tinfoil.sh \
-showcerts < /dev/null 2>/dev/null \
| openssl x509 -noout -pubkey \
| openssl pkey -pubin -outform DER \
| openssl dgst -sha256
That hash should equal tls_key_fp extracted by [A] (run against the router's attestation endpoint). If the bytes match, the host on the other end of your TCP connection holds the private key that the hardware quote committed to. Since the private key is sealed inside the enclave, "holds the key" means "is the enclave."
The terminal recipes above are exactly what BaseVault runs under the hood — just wrapped in a UI so you don't have to type them yourself. The verification chain runs once on app mount (and again whenever your TEE settings change or you click Recheck), and the results are visible whenever you want to look.
BaseVault has multiple inference modes (Local, Cloud TEE, etc.). When you're in Cloud (TEE) mode, the top-right of the title bar carries a small badge that reflects the current attestation state. While the chain is verified, it sits green:
← click the badge to open the chain
The badge only goes green after the full chain passes end-to-end: the SDK constructs successfully against the router (which verifies the hardware quote against the AMD or Intel root, validates the matching Sigstore bundle for the running release, and installs the TLS pin), a tiny authenticated probe confirms the API key works, and every backend's live measurement is fetched and compared byte-for-byte against the matching public deployment manifest. If any link fails — cert fingerprint mismatch, missing/expired Rekor proof, GitHub unreachable, a backend whose live measurement no longer matches the published one — the badge flips red and starting a new Cloud-mode run is refused before any prompt bytes can leave the laptop.
Clicking the badge opens the TEE attestation modal. One row per backend the session uses: the router on top, then each model enclave behind it. For every row, the live hardware measurement is compared byte-for-byte against the Sigstore-signed expected measurement from the matching GitHub release, with a green “Measurements match” check when they agree.
Each row also surfaces the URLs that produced both
halves of the comparison: the live
/.well-known/tinfoil-attestation
endpoint that returned the quote, and the
github.com/tinfoilsh/confidential-<model>/releases/tag/v…
page that published the manifest. Clickable copy
affordances next to each so the values can be lifted out
into a terminal and re-verified independently.
The (details) link on any row opens a deeper modal that walks the byte-level extraction. Same logic as the recipes above — fetch the gzipped + base64'd quote body, decompress, pull the canonical fields at the offsets defined in the SDK's SEV-SNP report layout (or TDX layout for Intel-backed enclaves) — rendered with copy buttons at every step so anyone curious can replicate the work on their own machine:
The bottom of the modal ships a single Python script that reproduces the extraction on stock macOS Python 3 (no extra installs). Paste-it-and-run; it should print the same Measurement, TLS pubkey fingerprint, and HPKE pubkey the modal extracted — byte-for-byte. The same fingerprint the SDK pinned for this session's TLS transport.
The modal's Recheck button forces a fresh verification run — useful after a long-running session, after Tinfoil pushes a new release, or just to confirm the chain is still healthy. While the re-check is in flight, the title-bar indicator switches from the green “Attested” state to a neutral “Checking…” state:
→
Starting a new Cloud-mode run is gated on the badge sitting green and not currently in-flight — the Run button is disabled while the re-check is happening, so a run can't start against a chain that's about to flip ok→fail. The window is usually a few seconds (SDK handshake + Sigstore-bundle verification + per-backend live-quote pulls); once it lands green again, the Run button re-enables. Already-running pipelines aren't interrupted; the gate sits in front of starting work, not in the middle of it.
If the re-check fails — a backend's live measurement no longer matches the published manifest, or Tinfoil pushed a release whose hash BaseVault hasn't verified against — the badge flips red, the attestation modal auto-opens to show which row failed, and Cloud-mode runs stay blocked until either another Recheck (or an app restart) lands green, or you switch to Local mode and run on your own hardware instead.
The cryptographic guarantee only tells you "this code matches this hash." For that to mean anything, you need to be able to read the code. The chain BaseVault relies on is auditable end-to-end:
BaseVault's own source code will be public on launch. Until then, the trust posture for the laptop-side .dmg is Apple Developer ID notarization plus the SHA-256 published on the download page. See the "And the app itself?" note on the home page for the verification recipe today.
No system reduces to "verify everything from first principles." Trust always grounds out somewhere — in a chip vendor, in a transparency log operator, in a registry. What an honest threat model can do is make the residual trust as narrow and as observable as possible. Where the chain still requires trust:
The whole chain roots in AMD's VCEK chain or Intel's PCK chain. If the chip vendor's signing infrastructure is compromised, attackers could forge quotes. This is the standard TEE threat model assumption; mitigated by the vendor's own key-management discipline. Nothing BaseVault can do about it; same constraint as any TEE-based system.
Linux Foundation operated. Mitigated by the transparency log being append-only and globally consistent (any retroactive tampering is detectable by anyone monitoring the log against expected workflow identities). Trust roots are TUF-distributed so they can rotate without baked-in keys.
The AMD-side measurement is reproducible bit-for-bit via IBM's open-source sevsnpmeasure-py. The Intel-TDX-side uses a precompiled tdx-measure binary inside measure-image-action's Docker image. The image is pinned by SHA so we know exactly which binary ran, but the binary's source isn't in the public repo. A residual gap for the TDX path.
cvmimage is built via mkosi from upstream Linux distro packages. End-to-end bit-identical reproducibility from public source isn't yet validated — it's a non-trivial commitment. Until then, you trust the GitHub Actions runner produced the kernel/initrd hashes that ended up in the Sigstore-signed manifest.
Trusting the source code of confidential-model-router means trusting its dependencies, which means trusting Go's module proxy, which transitively means trusting the registries that publish those modules. Hash-pinned lockfiles bound the exposure; a compromised registry replacing artifacts would still produce a hash mismatch. But the top-level trust roots eventually end at PyPI / npm / GHCR and at Sigstore + AMD/Intel as ultimate anchors.
These aren't hidden caveats — they're the actual frontier of where TEE-based attestation currently sits. The deliberate posture is: shrink the trust surface as far as cryptography reaches today, then be explicit about what's still trust so anyone reading can decide whether the tradeoff fits their threat model.
In-app trust dashboard. When you launch BaseVault, the live measurements for the router and every model your session uses are visible in the trust panel, with timestamps and an independent-verify recipe per row. Same data as this page, scoped to your actual session.
Design record. The full architectural walk-through — including the deeper code reading, the audit findings, and the rationale for what BaseVault verifies vs. delegates to the SDK — lives in issue #135.
Tinfoil's supply-chain writeup. Part 1 of their two-part series on supply-chain hygiene at the build/CI layer. Part 2 will cover the enclave-image side directly.
Open issues. Trust-loop closure work (open-sourcing BaseVault, supply-chain hardening of BaseVault's own CI, periodic Sigstore monitoring) is tracked in issue #202.