Live on npm · Open source (MIT)

Your AI agent can't leak the API key it never had.

Blindfold seals your key inside an Intel TDX hardware enclave on Terminal 3. Your agent only ever sees a placeholder — the real key is substituted inside the enclave. A prompt injection has nothing to steal.

npm i -g @fiscalmindset/blindfold
npm license tdx
zsh — you@mac
Built on Terminal 3Confidential compute · Intel TDX Open source · MITOne-line adoptionSelf-serve in ~30s
What is Blindfold?

A vault your agent can use but never read

To do real work, AI agents need API keys. The moment a key sits in the agent's memory, a single prompt injection can talk it into leaking it. Blindfold removes the target entirely: the real key lives inside a hardware-isolated enclave, and your agent only ever holds a harmless placeholder — __BLINDFOLD__. The substitution happens inside the enclave, at the last moment, so the plaintext key is never on your machine or in the agent's context.

🔒 EnclaveA region of RAM inside an Intel TDX chip that nobody — not the OS, not root, not the cloud host — can read.
🎭 SentinelThe literal string __BLINDFOLD__. Your agent sends it thinking it's a key. It's just a placeholder.
🔁 In-enclave swapThe contract swaps the sentinel for the real key inside TDX RAM, calls the API, and returns only the response.
📄 Canonical copyThe one authoritative key lives only in the enclave. Every other copy on disk or in .env gets deleted.
How sealing works

Follow the key — from your terminal to the API

You touch the plaintext exactly once, at seal time. After that it lives in the enclave, and even you only ever get results, not the key.

You
🔑

1 · Seal it

Run register; type the key with input hidden (no echo, no shell history). Or seal straight from an env var.

blindfold register --name openai_api_key
Enclave
🔒

2 · It lives in TDX

The value goes straight into the enclave's secrets map. Your machine drops it — nothing on disk. Confirm it's sealed:

blindfold status
Agent
🎭

3 · Use the placeholder

Your agent sends __BLINDFOLD__ via the proxy, or you inject the key into one command.

blindfold use --name openai_api_key -- cmd
Enclave

4 · Swap & call

Inside TDX, the sentinel becomes the real key, the API is called, and only the result comes back. Verify the code first:

blindfold attest

The plaintext key exists on your machine for one moment (step 1) and inside the enclave for one call (step 4). Never in the agent, never in a log.

The full command set — tap any command to copy

🚀 Onboard & check

🔑 Seal & manage

🔀 Use it

📜 Verify & help

Architecture

The real stack — nested, not flat

Your machine is untrusted. The key lives inside an enclave, inside an Intel TDX trust domain, inside the Terminal 3 network. Each boundary is real hardware/crypto isolation.

🔑
🚨 Your machine — untrusted for secrets
🤖 AI Agent
holds only __BLINDFOLD__
🔀 Blindfold proxy / CLI
routes by URL, forwards the sentinel — never sees the key
▼ agent → Blindfold proxy → sentinel over the tenant-authenticated session ▼
☁️ Terminal 3 — confidential-compute network
🪪 Tenant
your DID + eth key (secp256k1) — authenticates every call
📇 Contract registry
blindfold-proxy v0.5.6, published to your tenant
🚧 Egress allowlist
agent-auth-update — server-side, deny-by-default host ACL
💳 Token ledger
metered credits per enclave op (~20 tokens each)
🔐 Intel TDX — hardware trust domain
🧊 Confidential VM
memory-encrypted RAM — opaque to the host, OS, and root
📏 RTMR3 measurement
runtime hash of the contract code — pin it with attest
🧾 TDX quote
signed attestation; chains to the Intel SGX root CA
🧩 WASM runtime
runs the wasm32-wasip2 contract inside the enclave
🔒 Enclave — blindfold-proxy contract (Rust → WASM)
⚙️ forward()
swaps sentinel → real key, calls the API from inside TDX
🗝️ release-to-tenant()
returns plaintext to the authenticated tenant, for one call
📦 secrets map
z:<tenant>:secrets — the ONLY copy of your real key
▼ real key substituted in-enclave — outbound HTTPS ▼
✅ Upstream API
OpenAI · Stripe · GitHub · Google · …
authenticates the real key; only the response flows back — the key never returns

Deny-by-default at two gates: the proxy 404s any unmapped API, and the enclave refuses any host not on your egress allowlist. Verify the enclave runs your exact code with blindfold attest (RTMR3 pin → Intel root CA).  ·  Full system design →

The token above travels the real path, on loop ↑
1 · Seal2 · Agent sends placeholder3 · Swap in-enclave4 · Result returns

Inside this step

    System design

    The complete picture — nothing hidden

    Every component, the exact request lifecycle, and the real contract interface. This is what actually runs — not a simplification.

    ▸ Request lifecycle — proxy path (an agent HTTP call)

    Your machine
    untrusted
    🤖
    AI Agentholds only the placeholder __BLINDFOLD__ — never a real key
    🔀
    Blindfold proxy · proxy.tsroutes by URL prefix → provider (host · secret · auth scheme). Unmapped host → 404
    Terminal 3
    ☁️
    Tenant session · t3-client.tseth-signed RPC → your contract blindfold-proxy v0.5.6. Egress allowlist checked · ≈20 tokens metered
    Intel TDX
    🔐
    Confidential VMmemory-encrypted RAM · RTMR3-measured · opaque to host, OS & root
    Enclave
    ⚙️
    forward() — Rust→WASM contractkv::get z:<tenant>:secrets → swap sentinel → apply auth (bearer/basic/sigv4/webhook) → http::call
    Upstream
    🌐
    Upstream API · OpenAI · Stripe · GitHub · …authenticates with the real key; only the response flows back — the key never returns
    request path — steps 1→7 response — step 8 · only the result returns, the key stays in the enclave

    🧩 Components

    proxy.tslocal router — sentinel enforcement, URL→provider mapping
    t3-client.tstenant-authenticated RPC to Terminal 3 (forward / release)
    forward()Rust→WASM contract fn — in-enclave swap + upstream call
    release-to-tenant()returns plaintext to the authenticated tenant, one call
    secrets mapz:<tenant>:secrets — the only copy of the real key
    egress ACLagent-auth-update — server-side host allowlist, deny-by-default
    sealed ledger~/.blindfold/sealed.jsonl — HMAC hash-chained metadata

    📐 Contract & trust

    runtimewasm32-wasip2 module, contract tail blindfold-proxy v0.5.6
    interfaceWIT — forward(req) · release-to-tenant(name)
    auth schemesbearer · basic · sigv4 · webhook
    identitytenant DID + secp256k1 eth key signs every call
    attestationRTMR3 measurement → TDX quote → Intel SGX root CA
    isolationmemory-encrypted VM — opaque to host, OS, and root
    metering≈20 tokens / op (1 token = 1,000,000 base units)

    Two deny-by-default gates: the proxy 404s any unmapped API, the enclave refuses any host off your allowlist.  ·  Full system_design.md — 11 diagrams →

    Three ways to use a sealed key

    One sealed key, three call styles

    All three keep the key out of your agent's memory. They differ in where the plaintext briefly appears: the proxy never lets it leave the enclave, release borrows it for one command, and register is the one-time seal.

    1

    Proxy / forward

    🔒 strongest

    Plaintext lives: only inside the enclave — never on your machine.

    Your agent sends the sentinel to the local proxy; the key-swap and the real API call happen inside Intel TDX. The best choice for autonomous agents that make HTTP calls.

    # 1 · run these once
    $ blindfold proxy
    $ blindfold grant --host api.openai.com
    
    # 2 · point your agent at the proxy — it sends
    #     the sentinel in place of the real key:
    base URL: http://127.0.0.1:8787/openai
    header:   Authorization: Bearer __BLINDFOLD__

    ✓ The real key never touches your machine — a prompt injection has nothing to steal.

    2

    Release for one command

    ⚡ flexible

    Plaintext lives: on your machine, for a single command.

    Blindfold pulls the real key from the enclave and injects it as an env var into just one command — then it's gone. Your shell and your agent never keep it. Use it for non-HTTP tools, CLIs and batch jobs the proxy can't front.

    # one command — run it, key is injected, then gone
    $ blindfold use --name openai_api_key --as OPENAI_API_KEY -- python app.py
    
    # --name  the sealed key to release
    # --as    the env var it becomes ($OPENAI_API_KEY)
    # --      your command — receives the key, nothing else does

    ⚠️ Unlike the proxy, the plaintext does briefly touch your local process. Keep your tenant key (T3N_API_KEY) out of the agent's reach so only you can release.

    3

    Register / seal

    🔑 one-time

    Plaintext lives: in your terminal, once — at seal time.

    The one unavoidable moment you hold the key: typed with input hidden (no echo, no shell history), sent straight to the enclave, then dropped. Rotate or delete anytime.

    # hidden prompt — no echo, no shell history
    $ blindfold register --name openai_api_key
    
    # …or seal straight from an env var
    $ blindfold register --name aws_secret --from-env AWS_SECRET
    
    # replace a value later, rollback-safe
    $ blindfold rotate --name openai_api_key
    Supported providers

    First-class integrations, not a generic passthrough

    Each provider is a real entry with its exact upstream host and the auth scheme the enclave applies. Add your own in one line.

    OpenAI
    api.openai.com
    bearer
    Anthropic
    api.anthropic.com
    bearer
    Google Gemini
    generativelanguage.googleapis.com
    x-goog-api-key
    Groq
    api.groq.com
    bearer
    xAI · Grok
    api.x.ai
    bearer
    Stripe
    api.stripe.com
    bearer
    GitHub
    api.github.com
    bearer
    SendGrid
    api.sendgrid.com
    bearer
    Slack
    slack.com/api
    bearer
    Twilio
    api.twilio.com
    basic
    AWS · SES / S3
    *.amazonaws.com
    sigv4
    Discord
    discord.com/api
    webhook

    Anything with a Bearer / Basic / SigV4 / webhook scheme works. Not listed? blindfold grant --host your.api.com plus a one-line provider entry — that's the whole change.

    Live proof

    An agent read a 2,000-row Google Sheet
    with a key it never actually saw

    The key was released only into the python subprocess, used once, and dropped. This is a real run — the numbers below are the actual output.

    zsh — blindfold (release path)
    $ blindfold use --name google_sheet_api_key --as GKEY -- \
        python3 read_sheet.py 1N5xuy8j8ny-…-HaX4o
    
    ✓ released "google_sheet_api_key" (39 B) → injecting $GKEY (never printed)
      · Terminal 3 → Intel TDX enclave → release-to-tenant (metered ~20 tokens)
    
    TITLE: raksha-farmer-query   (2003 rows × 14 cols)
    HEADERS: StateName | DistrictName | Sector | QueryType | QueryText | …
      KARNATAKA   | HUBBALLI | HORTICULTURE | Market | Sowing time of Onion?
      MAHARASHTRA | AKOLA    | HORTICULTURE | Market | Fertilizer doses for Citrus?
    
     agent's answer: 2,003 farmer queries · top sector HORTICULTURE · most-asked: sowing time & fertilizer doses
    ✓ the agent saw the data — never the key.
    2,003rows read
    14columns parsed
    39 Bkey size
    0times the agent saw the key
    ~20tokens metered
    How it compares

    Blindfold vs. every other option

    Vaults, managers and HSMs solve storage & rotation — but they all decrypt the key into the process that makes the call, so a prompt-injected agent can still leak it. Blindfold solves use: the agent calls the API without ever holding the key.

    Approach Plaintext at call time Agent holds the raw key? Prompt-injection can leak it? Enclave makes the API call? Hardware TEE for the key in use? Also does storage / rotation? Setup
    .env / env vars agent process memory Yes Yes — trivially No No No none
    Password manager / keychain
    1Password · Bitwarden · macOS Keychain
    agent process, after autofill/read Yes Yes No No* Yes vault app
    Secrets manager
    AWS / GCP Secrets Manager
    agent process, after fetch Yes Yes No No Yes SDK + IAM
    HashiCorp Vault agent process, after fetch Yes Yes No No Yes server + policies
    KMS / HSM
    AWS KMS · hardware key store
    process (decrypt); key material stays for crypto Partly Partly — not for API keys No Yes Yes keys + IAM
    🛡️ Blindfold
    proxy path
    only inside the TDX enclave No — never No — the key isn't there Yes Yes (Intel TDX) Complements a vault npm i -g + signup

    ← swipe the table to see all columns →

    * A keychain may hold its own master key in a secure element, but your API key is still decrypted into the app/process that uses it.  ·  Blindfold is the only row where the agent never holds the plaintext for its actual use — calling OpenAI, Stripe, GitHub, etc. Keep your vault for storage; put Blindfold in front of the agent.

    What it costs

    Free to start · metered by the token

    🎁

    Free on testnet

    blindfold signup mints a funded testnet tenant (~20,000 welcome tokens) — enough to seal and run thousands of ops before you pay anything.

    🪙

    ≈20 tokens per op

    Each enclave operation (seal, forward, release) meters about 20 tokens — measured live. 1 token = 1,000,000 base units on the Terminal 3 ledger.

    📊

    See it anytime

    Balance and reservations are always visible with blindfold credit. No seats, no invented subscription — you pay for enclave compute you actually use.

    Pricing

    Free on testnet today

    Blindfold runs on Terminal 3 enclave compute. Right now it's testnet — the real product, the real enclave, at zero cost. Paid plans arrive once Terminal 3 sets production pricing.

    Live on testnet · free

    ~1,000 enclave operations, on the house

    blindfold signup mints a funded testnet tenant automatically — no card, no waiting, no manual token.

    ~20,000welcome tokens
    ~1,000enclave operations
    $0cost on testnet
    I need operations → 20,000 tokens
    1 token = 1,000,000 base units · ~20 tokens per op (measured live). Ops = seal · proxy call · release.

    Production $/token is Terminal 3's to set — we won't quote a number we can't stand behind. Need more testnet credit? email with subject "More Credit Request".  · 

    What you get

    Everything to run agents safely

    🔀

    In-enclave proxy

    Agent sends the sentinel; the enclave swaps in the real key and makes the call. Deny-by-default routing + egress allowlist.

    🗝️

    Release broker

    Need the value locally? Release it for one command, injected as an env var — never back in your environment.

    📜

    Remote attestation

    Verify the enclave runs your exact code (RTMR3 pin → Intel root CA) before you trust it with a secret.

    🧾

    Tamper-evident ledger

    HMAC hash-chained record of what's sealed. audit reconciles it against the enclave — the source of truth.

    👥

    Team sharing

    Let a teammate's agent use your sealed key for a host — forward-only. They call, never see the key.

    Self-serve, one line

    npm i -g + signup and you're sealing keys in ~30s. Works with any stack.

    FAQ

    The questions everyone asks

    Can Blindfold — or you — see my key?
    No. At seal time the value goes straight from your terminal into the enclave's secrets map; it's never printed, logged, or written to disk. After that the plaintext only ever exists inside the TDX enclave during a single call. The proxy, the CLI, and the maintainer never see it.
    What actually stops a prompt injection?
    The agent's process only ever holds the placeholder __BLINDFOLD__. There's no real key in its memory or context to exfiltrate — convincing the agent to "print the key" prints the sentinel. The substitution happens inside the enclave, after the request has already left the agent.
    Is it production-ready?
    It's live on npm (@fiscalmindset/blindfold, MIT), runs on Terminal 3's Intel TDX, and is self-serve. It's early and open source. The strongest guarantee is the proxy path, where the key never leaves the enclave. The release path returns plaintext into your local process for one command, so keep your tenant key off the agent's reachable env.
    How do I know the enclave runs the real code?
    Remote attestation. blindfold attest pins the RTMR3 code measurement and verifies the TDX quote, which chains to the Intel SGX root CA. You confirm the enclave is running your exact contract before trusting it with a secret.
    What if Terminal 3 is unavailable?
    Calls that need the enclave (proxy/forward, release) fail closed — they error rather than fall back to an unprotected path. Your sealed keys stay in the enclave; nothing leaks. You retry when it's back.
    What does it cost?
    Free on testnet — signup mints ~20,000 tokens. Each enclave op meters about 20 tokens (1 token = 1,000,000 base units). Check anytime with blindfold credit. See the cost section.
    Which languages and stacks work?
    Any. The proxy is a plain local HTTP endpoint, so anything that makes an HTTP request — Node, Python, Go, curl, your agent framework — works by pointing at it and sending the sentinel. The release path wraps any command with an injected env var.
    See all questions →
    Get started

    Three commands to un-leakable keys

    1

    Create a tenant

    Self-serve — a funded Terminal 3 testnet tenant. No manual setup.

    blindfold signup --email you@x.com
    2

    Seal a key

    Hidden prompt. The value goes to the enclave and is dropped.

    blindfold register --name openai_api_key
    3

    Use it safely

    Point your agent at the proxy, or inject into one command.

    blindfold proxy

    Seal your first key in 30 seconds

    Free on testnet · Open source · No config files.

    npm i -g @fiscalmindset/blindfold && blindfold signup
    Who's building this
    FiscalMindset avatar
    Built by FiscalMindset

    Solo founder — building un-leakable secret infrastructure for AI agents on Terminal 3 (Intel TDX). Open source, published to npm, and shipped in the open. If your agents touch real keys, I'd love your feedback.