Skip to main content

Security checklist

Most staking losses come from a few causes: a leaked mnemonic, a wrong withdrawal address, the same key running in multiple places, and APIs left open to the internet. Work through this checklist before you go to mainnet, and again after any big change.

Operating system

Protect your keys​

  • Generate keys offline. Run the key generation tool on a machine that is disconnected from the network, and copy only the keystores and deposit_data file off it. See Create validator keys.

  • Keep the mnemonic on paper or metal, offline. No photos, cloud notes, password managers, or email. Never type it into a networked computer. Nobody legitimate ever asks for it, including Prysm maintainers.

  • Set a withdrawal address you control. Use an address from a hardware wallet or multisig, never an exchange deposit address, and set it when you create keys. After the deposit, check on a block explorer that the withdrawal credentials end with that address.

  • Use strong, unique keystore and wallet passwords. Anyone who copies a keystore can try passwords offline.

  • Lock down the password file. --wallet-password-file stores the wallet password in plain text. Make it readable only by the account that runs the validator client:

    sudo chown validator:validator /var/lib/ethereum/validator/wallet-password.txt
    sudo chmod 600 /var/lib/ethereum/validator/wallet-password.txt
  • Delete the original keystores from the node after import, and keep them only in your encrypted, offline backup. See Back up and restore.

If an attacker gets…They can
Your mnemonicDerive every key, and if you never set a withdrawal address (0x00 validator), take your stake.
A validator keyGet that validator slashed, or exit it. The balance still goes to your withdrawal address.
Your withdrawal address keyExit your validators and take everything paid to the address.

Never get slashed​

  • Run each key in exactly one validator client—no backup or failover copies.
  • When you move keys, stop the old validator, wait at least 2 epochs, and bring the slashing protection history along. See Move to a new machine.
  • Turn on doppelganger protection with --enable-doppelganger when you start a validator after a move.

See Avoid slashing.

Keep APIs private​

Every Prysm API listens on 127.0.0.1 by default. Keep it that way.

PortServed byWhat it isWhy it must stay private
3500Beacon nodeBeacon APINo authentication. Anyone can submit to your node and change the fee recipient it uses.
4000Beacon nodegRPC APINo authentication. Anyone can act as a validator client against your node.
8080Beacon nodeMetricsReveal details about your node, such as its peers and sync status.
7500Validator clientKeymanager API (with --rpc or --web)With the token, a caller can import and delete keys, change your fee recipient, and sign exits.
8081Validator clientMetricsReveal your validator public keys and balances.
8551Execution clientEngine APIControls your execution client. Keep it on localhost or a private network.
8545Execution clientJSON-RPC APIAnyone can use your execution client, and load it with requests.
  • Open only the P2P ports to the internet: TCP 13000, UDP 12000, and UDP 13000 for Prysm, and your execution client's P2P port. See Ports.

  • Reach APIs from another machine only through an SSH tunnel or a VPN. Never bind an API to 0.0.0.0 on a machine with a public IP. For example, to reach the Beacon API from your laptop, run on the laptop:

    ssh -N -L 3500:127.0.0.1:3500 <USER>@<NODE_HOST>
    • <USER>@<NODE_HOST> logs in to the node over SSH as <USER>.
    • -L 3500:127.0.0.1:3500 forwards port 3500 on your laptop to 127.0.0.1:3500 on the node, through the encrypted SSH connection. The pattern is <LAPTOP_PORT>:<HOST_AS_SEEN_FROM_THE_NODE>:<NODE_PORT>.
    • -N opens the tunnel only, without starting a shell on the node.

    While the tunnel runs, http://127.0.0.1:3500 on the laptop reaches the node's Beacon API. The API itself still listens only on the node's localhost, so nobody else can reach it. Stop the tunnel with Ctrl+C.

  • With Docker, publish API ports on localhost only (127.0.0.1:3500:3500), or not at all. Docker's published ports bypass ufw.

  • Keep jwt.hex readable only by the execution client and beacon node.

  • Treat the Keymanager token file (auth-token in the wallet directory) like a key.

Check what listens where:

sudo ss -tlnp | grep -E ':(3500|4000|7500|8080|8081|8551|8545)\b'

Every line must show 127.0.0.1, or ::1 (or a private IP), not 0.0.0.0, ::, or *.

Lock down the host​

  • Use a dedicated machine that runs only your node software—no browsing, email, or games.

  • Use SSH keys only. Disable password logins after confirming key login works in a second session:

    /etc/ssh/sshd_config.d/10-hardening.conf
    PasswordAuthentication no
    KbdInteractiveAuthentication no
    PermitRootLogin no

    Apply with:

    sudo sshd -t && sudo systemctl reload ssh
  • Turn on a default-deny firewall and allow only SSH and the P2P ports:

    sudo ufw default deny incoming
    sudo ufw default allow outgoing
    sudo ufw allow 22/tcp
    sudo ufw allow 13000/tcp
    sudo ufw allow 13000/udp
    sudo ufw allow 12000/udp
    sudo ufw allow 30303 # execution client P2P; check your client's port
    sudo ufw enable

    On a home network, forward only the P2P ports on your router, and don't use the router's DMZ.

  • Run each client as its own unprivileged user (execution, beacon, validator), never as root or an administrator. Refer to the Run with systemd page for more information.

  • Encrypt backups and store them off the machine. Don't sync the live validator directory to a cloud drive.

Install and update safely​

  • Verify every download against its signature or checksum. Read the How verification works page for more details. Do the same for the rest of your stack (execution client, MEV-Boost, remote signer, deposit CLI): download each from its official release page and follow that project's own verification steps.

  • Turn on automatic OS security updates, and make sure your node starts on boot.

    On Ubuntu and Debian, turn on automatic security updates:

    sudo apt install unattended-upgrades
    sudo dpkg-reconfigure --priority=low unattended-upgrades

    Then make sure your services start on boot (add mev-boost if you run it):

    sudo systemctl enable execution beacon validator
  • Update Prysm and your execution client promptly when a release is marked as a security or high-priority update. See Update and roll back.

  • Watch for problems. Set up dashboards and alerts, and rehearse migrations and restores on Hoodi.

Watch out for scams

Fake support staff in Discord DMs, fake launchpads, and "validator tools" that ask for your mnemonic are common. Prysm maintainers never contact you first by DM and never ask for your mnemonic or keys. Deposit only through the official launchpad.

Report a vulnerability​

If you find a security vulnerability in Prysm, don't open a public issue or post in Discord. Email security@prysmaticlabs.com. The Prysm security policy and security.txt list the PGP keys to encrypt your report. For bugs in the Ethereum protocol itself, use the Ethereum Foundation bug bounty.