sign_ok · refuse_double_vote
The slashing firewall
for PoS validators.
nklave is a policy firewall that sits between your validator client and your signing keys. It enforces EIP-3076 slashing-prevention rules and configurable policies before any signature is produced — so slashable signing is impossible by construction, even if the host is compromised. As restaking multiplies the surfaces a key can be slashed on, that boundary stops being a nice-to-have.
Untrusted
Validator client
Lighthouse, Teku, Prysm, Lodestar. Speaks the Web3Signer HTTP signing protocol.
POST /api/v1/eth2/sign/:pubkey
Trust boundary
nklave
Policy engine evaluates the request. Slashing-protection DB is consulted. Decision is logged. Only then is the key touched.
policy.evaluate(ctx) → Allow | Refuse
Custody
Signing keys
Local keystore, YubiHSM 2, AWS CloudHSM, GCP KMS. Refused requests never reach the HSM.
BLS (ETH2) · Ed25519 (Cosmos)
Why this matters in 2026
Restaking multiplies your slashing surface.
For most of proof-of-stake's history, a validator key faced exactly one slashing surface: the consensus layer of the chain it validated. Restaking changed that. As EigenLayer-style restaking and Actively Validated Services (AVS) go mainstream, the same staked capital — and increasingly the same keys — are opted into multiple independent slashing regimes at once. Each AVS defines its own slashing conditions. Each one is a new way to lose stake, governed by code you did not write.
The shift
One key, many slashing regimes
Restaking turns a single key into an attack surface for every AVS it opts into. The boundary between "what asked for a signature" and "what actually gets signed" becomes the most valuable control point you have.
The control point
A firewall in front of the keys
nklave refuses anything that violates a rule before the key is touched, and logs every decision. Enforcement lives outside the process that signs, so it holds even when the validator host is fully compromised.
Honest scope
Protocol-level today; extensible by design
nklave enforces protocol-level slashing prevention (EIP-3076 and equivalents) — the rules behind the overwhelming majority of real slashing incidents. AVS-specific conditions are per-service and not built in, but the policy layer is the place operators express additional guardrails.
What the trust boundary enforces
Four built-in policies. All evaluate before the key is consulted.
Each refusal is deterministic, has a reason code, and is committed to the append-only log atomically with the slashing-protection DB update.
slashing-protection-attestation
Double-vote & surround-vote
Refuses any attestation whose target_epoch matches a previously-signed one, or whose (source, target) would surround / be surrounded by a prior signature.
tracked: min/max source · min/max target epoch · per pubkey
slashing-protection-block
Double block proposal
Refuses a beacon-block proposal if a block has already been signed for the same slot. For Cosmos / CometBFT validators, the equivalent rule applies on (height, round).
tracked: min/max proposal slot · last height/round
fork-allowlist
Allowlisted fork versions
Refuses any signing root whose fork version is not in the operator's allowlist — a defense against accidentally signing on testnet or an unintended fork.
allowed_forks = ["0x05000000", "0x06000000"]
rate-limit
Per-validator rate cap
Refuses signing requests when the validator's signing rate exceeds max_signs_per_hour. A backstop against runaway validator clients.
max_signs_per_hour = 240 # default ~4/min
Policy is a first-class layer, not a config afterthought. Every request resolves to an explicit Allow or Refuse(code) decision in nklave-core::policy before the key is consulted — the extension point that matters as restaking pushes more, and more heterogeneous, signing constraints onto the same keys.
Integrations
Keep your validator client. Keep your HSM. Drop nklave in between.
Validator clients
nklave speaks the Web3Signer HTTP signing protocol. Anything that supports a remote signer URL works.
- · Lighthouse — --use-remote-signer
- · Teku — validators-external-signer-url
- · Prysm — --web3signer-url
- · Lodestar
Key custody backends
Signing keys live in dedicated custody. nklave only requests signatures — and only for requests the policy chain allowed.
- · Local keystore — dev / single-host
- · YubiHSM 2
- · AWS CloudHSM
- · GCP KMS
Slashing-protection DB
Embedded or shared. The HA pattern is two nklave instances sharing a Postgres DB serialized by row-level locks.
- · RocksDB — default, single host
- · Postgres — leader/follower HA
- · EIP-3076 import/export
Threat model — v1
What nklave defends against. And what it doesn't.
We publish the threat model in full because the security properties of a signer are only as good as the assumptions behind them. Summary below; the authoritative version is in the docs.
v1 security goals
- guaranteed Signing keys are not readable by the host.
- guaranteed Slashable requests are refused, even from compromised software.
- guaranteed Safety state is monotonic — cannot be rolled back by host tampering.
- guaranteed Every decision is logged with a deterministic reason code.
Out of scope (v1)
- not_covered Physical access attacks (cold boot, DMA, evil maid).
- not_covered Advanced side-channel attacks on enclave execution.
- not_covered Compromise of the enclave implementation itself.
- not_covered Global anti-slash across multiple independent enclaves without explicit coordination.
Residual risks we name explicitly: a compromised host can still cause denial of service by blocking requests; strict enforcement can reduce availability if state is corrupted; supply-chain vulnerabilities in the build pipeline matter.
Append-only log
Every decision. Allow or refuse. Forever.
Every evaluation lands in a newline-delimited JSON log. Entries are sealed into Merkle-root checkpoints every 60 seconds and signed by a separate operator key. Tampering is detectable by re-walking the chain.
{"ts": 1742054400, "validator": "0xabc…", "type": "ATTESTATION", "decision": "allow", "signing_root": "0xdef…"}
{"ts": 1742054401, "validator": "0xabc…", "type": "ATTESTATION", "decision": "refuse",
"policy": "slashing-protection-attestation",
"reason": "double vote at target_epoch=12345"} verify chain
nklave log verify --from 0 --to latest re-walks every checkpoint, recomputes each Merkle root, and confirms the operator-key signatures. Non-zero exit means the log was edited.
operator key custody
Checkpoint-signing key is separate from any validator key. Lives in its own keystore, a YubiHSM slot, or an AWS KMS key — operator's choice.
retention
Logs rotate at 1 GB / 365 days by default. Older logs seal; the checkpoint chain remains verifiable across the boundary into cold storage.
Getting started
Five minutes from zero to validator signing through nklave.
1. Run nklave
docker run -d --name nklave \
-p 9000:9000 \
-v nklave-data:/var/lib/nklave \
-v $(pwd)/keystores:/keystores:ro \
ghcr.io/cryptuon/nklave:latest \
--keystore-dir /keystores \
--data-dir /var/lib/nklave Or cargo install nklave-server if you build from source.
2. Point your validator at nklave
# Lighthouse
lighthouse vc \
--beacon-nodes http://localhost:5052 \
--validators-dir /opt/lighthouse/validators \
--use-remote-signer http://localhost:9000
# Teku
validators-external-signer-url: http://localhost:9000 Prysm: --web3signer-url=http://localhost:9000
3. Import your slashing history
nklave import \
--interchange-file ./slashing-protection.json \
--keystore-dir ./keystores Standard EIP-3076 interchange. nklave will refuse anything that would duplicate what your previous client recorded.
4. Verify
curl http://localhost:9000/livez
curl http://localhost:9000/readyz
curl http://localhost:9000/health Then watch <data-dir>/log/ for signing decisions as they happen.
Explore
Go deeper into nklave.
Everything from the feature detail to the threat model, migration guides, and head-to-head comparisons.
Features
The enforce-before-the-key policy chain, EIP-3076 slashing protection, custom policies, tamper-evident audit log, and Web3Signer compatibility.
/features →How it works
The full request lifecycle — policy chain, slashing-protection DB, audit log, and key custody, plus the Merkle-checkpoint chain.
/how-it-works →Use cases
Staking operators, Web3Signer migration, multi-chain (ETH + Cosmos) validators, and security / compliance teams.
/use-cases →Compare
Head-to-head comparisons of nklave against other remote signers — Web3Signer and Dirk — grounded in published documentation.
/compare →Blog
Technical deep-dives: policy as a first-class concept, EIP-3076 import/export during migration, and the append-only decision log.
/blog →FAQ
nklave vs built-in protection, Web3Signer drop-in, the policy chain, custom policies, custody, audit-log tamper detection, chains, and HA.
/faq →About
What nklave is, a summary of the security model, and the current project status.
/about →As slashing surfaces multiply, put a firewall in front of your keys.
nklave is MIT-licensed, written in Rust, and built to be the simplest correct thing between your validator client and your keys. Read the threat model. Run the import. Switch your signer URL.