Skip to content
11 / 12

Security and threat model

Who could hurt you, how, and what stops them. Read this before relying on any part of Hushd, and remember it runs on testnet with development keys and no audit.

Network
Testnet only
Proving keys
Development, one contributor
Audit
None yet

What Hushd protects

  • Custody. Only the holder of a note's spending key can spend it. No account, Hushd's included, can move pooled funds: the pool has no admin withdraw.
  • Atomicity. Both legs of a spot deal are applied in one call, or neither is.
  • Privacy inside the pool. Amounts and parties of transfers and settlements, as set out in the privacy model.
  • Privacy of the request. Your limit and your words, up to the trust you place in the matcher enclave and the intake model.

Your keys and notes

Your seed comes from a NEAR wallet's signature of one fixed message, or from a passkey. Anyone who gets it can spend your private balance. Malware on your device, or a tampered copy of the app, could take it. The app at hushd.net is open source; you can build and run it yourself instead.

Agents

An agent's private balance is guarded by the spending limits in its local MCP server, which runs beside the agent with its seed. The relayer sends whatever was proved and does not know those limits. Anything that can read the seed, the agent itself included when it has shell or file access, can spend the whole balance without asking the server. A policy wallet guards the agent's NEAR account in a TEE, not its private balance, so keep in that balance only what the agent may lose. See spending limits.

The relayer

The relayer sends proven actions from its own account. Before it sends one it checks the proof against the exact inputs the contract will rebuild, that the root is known and that every note is unspent. It sends only to an allowlist of contracts and methods, with a rate limit per client and a daily gas budget.

  • It can refuse or delay an action, and see when it arrived and from where.
  • It cannot change what you proved. A cash out's recipient, the fee, the relayer, the refund note and the memo are bound into the proof, and each leg of a swap is bound to its deal and to all four outputs. A changed action fails the contract's check.

The matcher enclave

The matcher is a WASI module run as an OutLayer project inside Intel TDX. Its key is generated inside the TEE, and the desk learned it through an OutLayer call, so it comes from that code. The desk accepts a match only from OutLayer's callback or with that key's signature, and trusts OutLayer to resume only with results from attested workers running the pinned matcher.

If the TEE, or that trust, failed, whoever broke it could:

  • read requests, limits and quotes, and
  • match you with a quote other than the best. A match below your limit, in another token or for another package is refused by your own client before it proves anything, so the deal just expires.

They could not invent a maker's consent (the desk checks each maker's quote key), and could not move your notes: settlement still needs your own proof, and your client checks the note it receives opens to the agreed terms before it proves.

The intake model

The API verifies the model's TDX and NVIDIA GPU attestation and gives your browser its signing key; your browser encrypts your words to that key and checks the TEE's signature on the answer. It accepts only a signature by that same key, whatever signer the API names, so an API that swapped in a key of its own for the answer gets a draft marked not verified. The browser does not check the attestation itself: it relies on the API's check of the Intel TDX quote and the NVIDIA GPU evidence, and shows beside each answer what the API returned (the model, its signing key, the TDX status and when it was verified), so you can check the same model and key yourself at cloud.near.ai/verify. Whatever the model answers is only a draft in a form you check.

The API, the matcher client and the keeper

Hushd runs these services itself, next to the relayer. Their health is on Transparency.

  • The API stores the sealed requests, quotes and deal-room messages and hands them on. It cannot open them, but it sees the network side of everything that passes through it: IP addresses, timing and deal-room traffic. It can refuse, delay or drop a message. In a deal room it sees which deal each message is for, its size and time, and the key it is sealed to: the maker's own, or a key the trader's wallet made for that deal alone, which leads to no hushd1… address. It deletes a room once its deal settles or closes on the desk, and any message after a day.
  • The matcher client builds each batch for the enclave from the quotes in the API's database. It cannot read them or forge a match, but it could leave a quote out, and the enclave could not tell: the best quote the enclave sees may not be the best one sent. It can also hold a batch back until the match is too late for the desk.
  • The keeper submits each hedge order to Hyperliquid and alone reports whether it filled. The desk releases or slashes the maker's bond on that report, so a false fill would keep a missed hedge's bond from you, and a false miss would take an honest maker's bond. If the keeper reports nothing, anyone may slash an overdue hedge (slash_overdue) and expire an unsettled deal (expire).

Makers

  • A maker can decline to quote, quote badly, or fail to settle. An unsettled deal expires, and nothing moves.
  • A maker has a last look. You prove your leg first and hand it over, and the maker submits both legs, so it can wait out the settlement window and settle only if the price still suits it. It loses no bond for that: a spot deal has none, and a hedged deal's bond is released too when a deal expires unsettled. The lapse is public, though: the deal's receipt says failed and names the maker, and a request from the app, the SDK or the MCP server skips a maker that let more than 25% of its last 20 ended deals lapse (once 5 have ended). The desk cannot tell which side let a deal expire, so a trader that walks away from deals can push a maker toward that line. See last look.
  • A maker that misses a hedge, as the keeper reports it, loses its bond to the trader. The hedge itself trades for the maker's own Hyperliquid account: it does not hedge the trader (see packages).
  • A bond is public, so the desk takes it only in fixed steps of its minimum (1, 2, 5, 10, 20, 50 and so on times it): the bond says which step a trade falls in, not its size. A hedge order is public on Hyperliquid, so a hedged deal's size is not private.
  • A maker sees the pair, the side and the size of every ask sealed to it, and could act on that elsewhere.
  • The winning maker pays your note to an address your wallet made for that deal alone, never your hushd1… address, so it cannot link two of its deals to one trader by the address. Each deal's pair, size and timing can still hint at it.

The contracts

  • Pool rule changes (listing a token, its deposit limits, the desk it trusts, its owner) wait out a public timelock, and anyone can apply them after. The owner can pause new deposits at once, never cash outs.
  • The desk's pool, bond token and Chain Signatures signer are fixed when it is created. Its other settings (the keeper, the matcher project, the minimum bond) change only after a public one-day timelock, and never touch notes in the pool.
  • A cash out the token refuses comes back as a refund note, and a failed swap applies nothing. Failed bond moves are credited back.

Proving keys

The transcript is in circuits/KEYS.md, and the browser's copies of the keys are listed with their sha256 in /circuits/manifest.json.

Not audited

The contracts, circuits and services have unit, circuit and sandbox tests. No external audit has been done.

Not covered

  • Sanctions screening beyond its list: it checks public addresses against a dated OFAC snapshot, so it misses an address listed later or one that is not listed at all. Transfers inside the pool are private and are not screened.
  • Network privacy: your IP address, as seen by the API, the relayer and NEAR RPC nodes.
  • A compromised device or browser.
  • Real value: there is none on testnet, by design.

Reporting a problem

Open an issue on GitHub. If the problem could put someone at risk, say only that you found one and ask for a private way to share it, without details. Test against testnet, or a local sandbox. See also security.