Skip to content

The session-signing security model

An autonomous agent needs to sign transactions when no human is present. The usual answer is a platform-held key; Crank's answer is a scoped, revocable credential the platform never holds. This page describes the security model behind unattended operation on Crank: what a session signer is allowed to do, what it is structurally prevented from doing, where TEE hardware isolation fits, and what happens when you pull the plug.

The baseline model — every value-bearing tool returns an unsigned transaction for the owner's own wallet to sign — is covered in How AI agents trade non-custodially. This page covers the layer on top: signing without the owner present.

The problem session signing solves

An agent that can only hand transactions back to a human for signature is supervised, not autonomous. The common shortcuts both concede custody or safety:

  • Raw key in the agent process. Simple, but the key can do anything the wallet can do — including transfer everything out — and every protection lives inside the same process the agent runs in.
  • Platform-managed TEE wallet. The key is generated and held inside the platform's own enclave infrastructure. The hardware isolation is real, but the platform operates the enclave and controls the signing path — the wallet is theirs to run, with your policy applied to it.

Crank's session-signing model keeps the hardware-isolation story and the non-custodial contract: the platform never generates, holds, or sees a signing key, and a session credential is structurally limited to trading.

Delegated session signers: scoped by construction

A session signer is a separate keypair, created and held by the user (or inside the user's own TEE sub-organization — see below). The user registers only its public key with Crank, authorizing it for one agent account with a limited capability set: swap, perp, lend, stake — trade-only.

That authorization is enforced server-side, per call, at two levels:

  1. Dispatch level. A tool call authorized by a session signer is checked against the signer's capability set before any transaction is constructed and before any fee. A swap-only signer calling a perps tool is refused.
  2. Instruction level. Every transaction constructed for a session-scoped call passes an instruction filter before it is returned. Under session scope, the base Solana programs may not move value out of, or change authority over, the wallet's own accounts:

  3. Denied outright: authority changes, account-owner reassignment, and token delegation (an approval is a deferred transfer).

  4. Denied when the destination is external: SOL and SPL token transfers, nonce withdrawals, and account closes whose recipient is outside the wallet's own account set.
  5. Fail-closed: a destination the filter cannot resolve offline (for example, hidden behind an address-lookup-table load) is treated as external and rejected.

Own-account flows — wrapping SOL into the wallet's own wSOL account and closing it back, venue routes through allowlisted programs — pass, because they are ordinary trade legs.

The practical consequence: a leaked or misbehaving session credential can trade inside the owner's guardrails. It cannot withdraw, cannot transfer out, cannot delegate authority, and cannot close accounts to an outside address. The blast radius of a compromised session key is bounded by construction, not by trust in the agent's code.

All of the owner's guardrails stack on top: max trade size, daily limits, token allow/deny lists, position limits, drawdown limits — the full policy gate runs on every session-scoped call, and a refused action is never billed.

Revocation: one action, effective on the next call

Revoking a session signer is a single control-plane action. The authorization is resolved fresh from the database on every call — no cache, no TTL, no propagation delay — so the very next call after revocation is refused. Credentials can also carry a hard expiry, past which they are inactive without any explicit revocation.

Revocation touches only Crank's authorization record. The keypair itself remains the user's property; what is revoked is what the platform will do for that public key.

TEE isolation without platform custody

For unattended operation, the signing key itself can live on TEE-isolated signing infrastructure: Crank provisions signing through Turnkey, whose signers run inside AWS Nitro Enclaves — hardware-isolated environments where the key is generated inside the enclave and is not exportable by design.

The custody distinction matters:

  • The key is generated inside a Turnkey sub-organization provisioned for that wallet — not in a platform wallet pool. Crank's code has no API that could receive the private key, and no code path transmits, persists, or logs one.
  • Session-signer capability sets are additionally provisioned into the enclave-side policy engine as a belt-and-braces layer: policies denying the same transfer, withdrawal, and authority-change instruction classes, and allowing venue programs only per the credential's capability set, are mapped per wallet at the signing infrastructure. Crank's own server-side gate is the authoritative check on every call — the enclave-side policy layer adds depth around it, never a substitute for it.
  • Non-exportability is a deliberate posture, not a limitation: the platform cannot extract the key even if asked.

So the comparison with platform-managed TEE wallets is not "TEE vs no TEE" — it is where authority lives. In a platform-managed model the platform generates and operates the wallet and applies your policy to it. In Crank's session-signer model the credential the agent operates under is trade-only by construction, the authoritative enforcement is the server-side gate on a wallet the owner controls, and what Crank holds is an authorization record about a public key — revocable in one action.

Kill switch and automated unwind

kill_wallet is the emergency stop for an agent account. It engages two independent layers, in order:

  1. The policy gate freeze lands first and is authoritative: every subsequent value-bearing action for that wallet is refused at the gate, before construction and before any fee. An outage anywhere else can never delay this.
  2. Signing-layer revocation follows for wallets on TEE-managed signing: session-signer credentials at the signing infrastructure are revoked and a deny-all policy recorded there as well — additional depth on top of the gate freeze, which alone is what stops the wallet; an outage on this layer is reported and retryable without ever delaying the freeze.

A killed wallet is not just frozen — it is unwound. The unwind sweep closes open perps positions and swaps residual non-USDC balances back to USDC. The sweep is idempotent and retry-safe: each run re-derives what is still outstanding rather than replaying a fixed plan, so a retried job can never double-close a position. During the unwind window, signing is narrowed to unwind actions only; once the sweep completes, credential removal closes the signing path entirely.

These protections are verified at two levels. The instruction filter's adversarial cases — external transfers, authority changes, delegation, external account closes, lookup-table-obfuscated destinations — are covered by the automated test suite, which asserts each one is refused. The full authorization loop — authorize a real delegated keypair, see a legitimate own-account transaction pass and an external-transfer transaction refused, revoke, and see the very next call refused — was additionally verified end-to-end against devnet (July 2026) as part of Crank's pre-mainnet verification work.

The layers, together

Layer What it bounds Who controls it
Capability set Which action classes a session credential may dispatch (trade-only) Owner, at authorization
Instruction filter What constructed transactions may do (no outward value movement, no authority changes) Enforced server-side, every session-scoped call
User-configured guardrails Size, volume, token, position, and drawdown limits Owner, changeable any time
Program allowlist + anti-drainer checks Which programs a transaction may touch Enforced server-side, every value-bearing call
TEE signing policy Enclave-side policies mirroring the same outward-value denials (defence in depth) Provisioned per wallet on TEE-managed signing
Revocation / expiry / kill switch Whether the credential works at all Owner (and the platform-wide emergency stop above it)

No single layer is the model. The model is that the server-side gate is always the authoritative check, the other layers add depth around it, and none of them requires the platform to hold the user's key.

Next