MenuClose
If the host is compromised
You cannot check from outside how careful Nonceworks is, so this page assumes our host is compromised and works from the grant, which you can check.
In their hands
The credential you granted, scoped to kms:Sign and kms:GetPublicKey on one key, or the Google Cloud and Turnkey equivalents. The relayer's API key for your stack, and the webhook signing key, so they could send your receiver webhooks that pass verification. Your configuration, your RPC URLs and any API keys inside them, your webhook URLs, chat tokens and email (SMTP) credentials. Teams are separated by containers and networks, which does not survive a takeover of the host itself, so assume every team's credentials are in the same hands.
Possible
On AWS and Google Cloud, sign anything with your key until a revocation takes effect, on any EVM chain, because the relayer address is the same on all of them: a transaction to any recipient at any value and gas price, any message or typed data, and an EIP-7702 authorization that hands your address to code they control. AWS and Google Cloud KMS sign a 32-byte digest without knowing what it is, so a key policy there can limit who calls Sign but not what gets signed. On Turnkey, only what your policy allows.
The relayer's policies run on this host. They constrain the relayer process, not someone who holds the credential and can call your provider directly.
Revoking does not cancel what was already signed. Transactions signed for future nonces, EIP-7702 delegations and permits with late deadlines all stay valid, so after a suspected compromise treat the address as burned and follow the steps at the end of this page.
Limits on the damage
What the address holds and what it can authorize
Keep a few days of gas on it and nothing else, on every EVM chain. Give it no role beyond the transactions you send through it: not a Safe or smart-account owner or delegate, not a signer that a contract or forwarder trusts, and never an EIP-7702 delegation.
How fast you revoke, and at which level
Revoke the permission or the key. In a single test on a real AWS key on 2026-10-07, checking every 5 seconds, disabling the key stopped the relayer's signatures within 33 seconds, and removing the IAM policy took 3 minutes 38 seconds. So disable the key first when speed matters. Google Cloud says role changes can take seven minutes or more.
The options: on AWS, detach the policy or disable the key; on Google Cloud, remove the bindings on the key or disable the service account; on Turnkey, delete the user or its policy.
Deleting only the AWS access key, the Google service-account key or the Turnkey API key is not enough after a compromise, because session tokens minted from the access key, access tokens issued from the service-account key, and API keys the user added to itself keep working.
On AWS, CloudTrail's event history shows every kms:Sign call for 90 days with no setup, usually within about five minutes and without the digest; an alarm on them needs a trail that logs read management events, plus either an EventBridge rule in the ENABLED_ state (Sign is a read-only event) or a log metric filter. On Google Cloud, signing calls are logged once Data Access audit logs (DATA_READ) are on for Cloud KMS.
On Turnkey, a policy you own
Turnkey evaluates policies in its enclave, not on the Nonceworks host, and the relayer sends EVM transactions as ACTIVITY_, which a policy can read.
Grant a non-root user, preferably in a sub-organization of its own, one ALLOW on SIGN_TRANSACTION_V2 for this private key, pinned to eth.tx.chain_id, eth.tx.to and the functions the relayer calls (upload the contract ABI so eth.tx.function_name is filled in; pinning to alone allows any call to those contracts).
Allow one more shape as well: a zero-value transaction with empty data from the relayer address to itself, which is the no-op the relayer sends to cancel a transaction or fill a nonce gap; without it, cancels fail and a nonce gap blocks every later send.
Add explicit DENY rules for raw-payload signing of every kind and hash function, and for credential changes, since a Turnkey user can otherwise add API keys to itself. Value and gas caps apply per transaction, not per day.
The relayer's sign endpoints stop working under this policy, which a relayer that only sends transactions does not need. Of the three, this is the only one that can refuse a bad signature before it is made, and only Turnkey offers it.
Not possible
Extract the key from AWS or Google Cloud KMS: neither has a call that returns these private keys. Turnkey does have an export activity, which is one more reason the grant must be a non-root user with no policy allowing export. Sign with any other key in your account, because the grant names one key. Sign after a permission-level or key-level revocation has taken effect.
Without a compromise
In normal operation the relayer's policies bound what it sends, within these limits. whitelist_receivers checks the outer to only, so whitelisting a token contract allows any transfer of that token, and it always admits the zero address and the relayer's own address, so the native balance can still be sent to 0x0. gas_price_cap caps ordinary sends and replacements, but not the no-op and cancel transactions the relayer sends to clear a stuck nonce. Nothing caps value or the number of transactions, and min_balance is a floor checked one transaction at a time. None of this applies to the sign and sign-typed-data endpoints (read from the 1.8.0 source). One API key per relayer instance authorizes every call, including the one that changes the policies; we generate that key and hold it as well as you.
Secrets handling
- Secret values come encrypted to the age key, separately from the config. Once decrypted, credentials, keys and chat tokens are stored only in two environment files in your workspace on our host, one for the Monitor and one for the Relayer (directory mode 0700, files 0600), never in the workspace metadata, the Compose file or
config.json. - RPC URLs and the relayer's webhook URL are the exception: Relayer 1.8.0 accepts them only as plain strings in
config.json, so an API key inside an RPC URL sits there and, unencrypted, in the relayer's Redis store. Use RPC keys with origin or IP limits. - The Monitor container receives only the values its own configuration references. The Relayer container receives the values its
config.jsonreferences, your provider credentials and the keys generated for your workspace, and the secrets it copies into Redis are encrypted with the workspace's storage key. - Docker also keeps each container's environment, so anyone with root or Docker access on the host can read all of it, which is the case the first section of this page assumes.
- The control plane rejects a relayer config with a
localsigner or a plain-text value anywhere in a signer, and refuses variables that would point the relayer's AWS SDK at another endpoint. - One environment per team, so another team's containers cannot read yours. That separation is between containers and does not survive a compromise of the host.
- Webhooks are signed with your
WEBHOOK_SIGNING_KEY(32 characters minimum, enforced by 1.8.0). The signature covers the body only, with no timestamp, so a receiver should drop duplicates and check that events are fresh.
Binaries
We run the upstream images unmodified and pinned by digest, Redis included; the digests are on the operations page. If we ever need a patch to keep a stack running, it goes up as a public fork first. AGPL section 13 at least requires that you, as a user of the modified version, can get its source.
After a suspected compromise
- To stop new requests at once, PATCH the relayer with
{"paused": true}: it then refuses new sends, cancels and both sign endpoints. Transactions already queued or pending are still signed, sent and bumped, so cancel them before you pause. The pause lasts until someone with the API key unpauses it; revocation works either way. - Revoke at the permission or key level, as above.
- Stop using the address on every chain, and move its roles and funds to an address from a new key.
- On each chain you use, check
eth_getCodeon the address. A result that starts with0xef0100is an EIP-7702 delegation; clear it with an authorization to the zero address, signed through your own access to the key. - Revoke ERC-20 approvals and Permit2 allowances from the address (Permit2 has a
lockdowncall), and cancel open EIP-3009 authorizations where the token supportscancelAuthorization. - Rotate the relayer API key and any RPC keys, and ask us to rotate the webhook signing key; that needs a relayer reset start, so it happens once nothing is in flight.
Incidents
If an incident touches your stack you hear about it from us in writing within 24 hours of our finding it, with what happened and what changed. The limits of the service itself (no audit, no SLA, one engineer) are on the home page. Report a security problem in this service to security@nonceworks.com.