Security

Security and assurance

What an integrator needs to know before routing funds through Valtu, and how to check it yourself instead of taking our word for it. Each item says plainly whether it exists today.

ItemStatus
Enclave attestationAvailable: verify the running image with AWS's signature
Reproducible builds and measurementsAvailable. A second independent build is still owed.
Production keysCreated in an offline key ceremony (13 October 2026); public keys published below
External security auditNot done yet: required before significant funds. An internal security review is done.
Supported chains, finality and reorganizationsAvailable
Webhook delivery guaranteesAvailable
Recovery proceduresDocumented; restart, rollback and host failover drilled; full disaster recovery not yet drilled
AvailabilityTwo enclave hosts in two zones, public status page. No uptime commitment yet.
SDK checksumsAvailable: reproducible package, published SHA-256
Reporting a vulnerabilitysecurity@valtu.io

Enclave attestation

Keys are generated, held and used only inside AWS Nitro Enclaves. You can check which image is running, at any moment, without trusting Valtu:

  1. Pick a random nonce (8 to 64 bytes) and call GET /v1/attestation?nonce=<hex>. No API key is needed.
  2. Each returned document is signed by AWS (COSE_Sign1, ES384) with a certificate that chains to the AWS Nitro Enclaves root. It carries the image measurements (PCR0/1/2), your nonce, so it was made just now for you, and the enclave's statement of the public keys it holds.
  3. Compare PCR0 with the published measurements, and the keys with the published public keys. Rulings, notarizations and signatures come from those keys, so they come from that image. Production runs two enclave hosts: you get one document per host, and every one must pass.
import { randomBytes } from "node:crypto";
import { verifyAttestation } from "@valtu/wallet-kit";

const nonce = randomBytes(32).toString("hex");
const { attestations } = await valtu.attestation(nonce);
for (const a of attestations) {
  const v = verifyAttestation(a.document, { nonce, expectedPcr0: PUBLISHED_PCR0 });
  console.log(v.pcrs[0], v.statement?.keys);   // throws AttestationError if anything doesn't hold
}
GET /v1/attestation?nonce=9f2c…e1

200 OK
{"nonce": "9f2c…e1", "format": "aws-nitro-cose-sign1",
 "attestations": [{"document": "hEShATgioFkRX…", "statement": {"v": 1, "service": "valtu-enclave", "role": "all",
   "keys": {"policy": "02…", "signer": "03…", "notary": "02…", "quorum": "…"}}}]}

verifyAttestation has no dependencies, so you can read it in full. It checks the certificate chain up to AWS's root (pinned by its published SHA-256), each certificate's validity, the ES384 signature, the nonce and PCR0. Any COSE and X.509 library can do the same.

Reproducible builds and published measurements

The enclave image is built reproducibly. Everything that affects PCR0 is pinned: the Rust image, a Debian snapshot, timestamps, the Amazon Linux image and the nitro-cli version. Anyone with the source at the release commit gets the same measurements. KMS releases the keys' secrets only to an attestation whose image hash is the published PCR0.

ReleaseMeasurements
Production, since 15 October 2026
c3bdf5ecd389
PCR0 3dc42f070f94fc08fda5d8e4beb9251321fbd1d2bf360f0d6c34b33c5c844e7ee712c1e05aa4bcaef920088b51523c30
PCR1 4b4d5b3661b3efc12920900c80e126e4ce783c522de6c02a2a5bf7af3a2b9327b86776f188e4be1c1c404a129dbda493
PCR2 8b61f0b81fbf6a146d0b275cbf2c8065a5842e2cffe6a787c186c19146ff637ecce715c28f442d0dea5e33e94428dd6f
Anchors file SHA-256 769069031898576240b4189357a73eb728a78ee41728723216ac1ec03a4ee286
Previous, 14–15 October 2026
b1a851982639
PCR0 2f05574996f4a721ac86766860287a842f7424c41a1d80795bbbb0226a32d624ca0b64b665b89473eb5eacfefb7196d1
PCR1 4b4d5b3661b3efc12920900c80e126e4ce783c522de6c02a2a5bf7af3a2b9327b86776f188e4be1c1c404a129dbda493
PCR2 32d5c2fd1b2c6d046391153f6e4307dea9bf69811ad60dcd602f92883aee021794c97db8f8c49b4895094b3302bc6773
Anchors file SHA-256 769069031898576240b4189357a73eb728a78ee41728723216ac1ec03a4ee286

This release was built twice from scratch with identical results. A second build by an independent person, on their own machine, is still owed before real funds. Source access for auditors and partners is available on request.

Production keys

The enclaves' keys were created on 13 October 2026 in an offline key ceremony, on a machine never connected to a network. Their public keys are compiled into the image (the anchors file above), so the measurement covers them, and every enclave reports them in its attestation. Signed results from Valtu verify against these keys:

Quorum (seals wallet seeds)3697da95fcd2aa08a3a4499a8d1feb5938dfd23c91492068c905afdcddc91138
Policy (rules on every request)0322b364e672d8158565a19cf299fbf8b8c580129e4e018827a6de1731412c5469
Signer (signs transactions)0370f63d286dd7468e19448aa9ec912cc7965c45efe2b53e429cca5429034b1a43
Notary (signs organization state)039e94af4524592494852ec55c64b7fab17613e4c20b1cd0aecf3d460d4ac201bf

A backup of the secrets is split with Shamir secret sharing and held offline; recovering it needs a threshold of holders together (see the whitepaper). Wallets created before 14 October 2026 used keys from a test ceremony; production moved to these keys that day, and those wallets were given new addresses.

Audit, reserves and records

  • External security audit: not done yet. The enclave applications, the coordinator, the deployment and these procedures still need review by an independent firm. It's required before the service holds significant customer funds.
  • Internal security review: done (October 2026), by the team with automated review tools. Its findings were fixed. The last, released on 15 October, makes the enclave take its time from the hardware's signed attestation rather than the host's clock. It doesn't replace the external audit.
  • Reserves. GET /v1/balances and every wallet address can be checked on-chain. Signed liability attestations aren't offered yet.
  • Records. The workspace audit log is append-only, enforced by the database, and exports to CSV. Enclave organization state is versioned append-only and notarized every 12 hours.

Supported chains, finality and reorganizations

Default confirmation depths for every network Valtu supports. Which networks are live, and the values in force, are what GET /v1/networks reports; the tokens per workspace are at GET /v1/assets. Live today: Ethereum, BNB Chain, Polygon, Base, Lisk, TRON and Bitcoin. Solana is paused.

NetworkNativeA deposit is final atNotes
EthereumETH12 blocks
BNB ChainBNB15 blocks
PolygonPOL64 blocks
BaseETH12 blocks
Arbitrum OneETH20 blocksNot live yet
OP MainnetETH20 blocksNot live yet
Avalanche C-ChainAVAX12 blocksNot live yet
LiskETH12 blocks
TRONTRXsolidified blockWithdrawals final at 19 blocks. Fees can be paid with rented energy, using your own energy provider key (Gas station).
SolanaSOLfinalized commitmentPaused. Payments that wait for an approval use a durable nonce.
BitcoinBTC3 blocksA payment unconfirmed for 30 minutes is replaced with a higher fee (replace-by-fee). No CPFP.

Deposits are recorded PENDING when seen and become CONFIRMED only once they're deep enough and still on the canonical chain. That's the only state to credit on. Each block is checked to link to the one before it. A deposit dropped by a reorganization before then becomes ORPHANED. One dropped after confirmation becomes NEEDS_REVIEW, which means the depth was too shallow for that chain. Each status has its own webhook.

Withdrawals are CONFIRMED at the same depth. The same externalId always returns the same transfer, so a retry never pays twice. A withdrawal that can't be sent within 30 minutes (no funds or gas, signer unavailable, rejected by nodes) is CANCELLED. That happens only from states where the network never acknowledged the transaction. A broadcast transaction that's never accepted becomes NEEDS_REVIEW.

Known gaps:

  • EVM deposits made by contract-internal transfers aren't detected without a tracing node.
  • TRON, Solana and Bitcoin workspace transfers have run end to end only on test networks. Use capped amounts on them first.

Webhook delivery guarantees

DeliveryAt least once. De-duplicate on the event id.
OrderingNot guaranteed. Act on the state in the event, not on arrival order.
SignaturesEd25519 (X-Valtu-Signature-Ed25519, key at GET /v1/webhooks/public-key) and HMAC-SHA256 (X-Valtu-Signature), both over "<t>.<raw body>". Reject anything signed more than 5 minutes ago.
SuccessAny 2xx within 10 seconds.
RetriesAfter failure n, the next attempt waits min(2n s, 1 h): 15 attempts over about 4 hours. Then the delivery is marked failed, and you can resend it from the dashboard. Attempts are kept for 30 days.
Catch-upWebhooks are a notification, not the record. Reconcile with GET /v1/deposits?after= and GET /v1/transfers?after=.

Recovery procedures

EventWhat happens and how it's recoveredDrilled
Enclave restartSigning pauses. Deposits keep being recorded, and waiting withdrawals resume. The host fetches the published image, and KMS releases the secrets only to that measured image. About 1–2 minutes.Yes
Bad releaseThe previous image is re-bound and restarted in about 2 minutes. Workspaces already using team signing move forward with a fixed release instead.Yes, on staging
Enclave host downThe second host, in another zone, takes every request; the failed one rejoins after a health check. Requests in flight are retried on the other host.Yes (13 October 2026)
Host lossA replacement host boots the same image and is provisioned from KMS.Not yet timed
Cloud keys or account lostThreshold key holders recover the secrets on an air-gapped machine and re-encrypt them to new keys.Not yet
DatabaseMulti-AZ, encrypted, 30 days of point-in-time backups, deletion protection. Signed organization state is append-only. A rollback window of up to 24 hours remains open until a monotonic counter is added.Restore not yet drilled

Availability

Production runs two enclave hosts and two API instances, each pair spread over two availability zones, with a Multi-AZ database. A monitor in a separate AWS region checks the website, the dashboard, the API, signing and each network's deposits every minute and publishes the results at status.valtu.io, with 90 days of history. The same summary is at GET /v1/status (no API key needed).

There's no uptime commitment yet.

SDK checksums

The wallet kit package is reproducible: the copy served here and a local build from the same commit are byte-for-byte identical. Checksums for the current release are at /site/downloads/SHA256SUMS.txt.

curl -sSLO https://valtu.io/site/downloads/valtu-wallet-kit-0.8.2.tgz
curl -sSL https://valtu.io/site/downloads/SHA256SUMS.txt | grep 0.8.2 | shasum -a 256 -c -

Pin the exact version and its integrity hash in your lockfile; don't install -latest in production.

Reporting a vulnerability

Email security@valtu.io with the details and how to reproduce them, and please give us reasonable time to fix the issue before you disclose it. Don't access other customers' data or move funds beyond what you need to show the issue. Contact details are also at /.well-known/security.txt.