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.
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_datafile 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-filestores 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.txtsudo chmod 600 /var/lib/ethereum/validator/wallet-password.txticacls <PATH_TO>\wallet-password.txt /inheritance:r /grant:r "${env:USERNAME}:R" -
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 mnemonic | Derive every key, and if you never set a withdrawal address (0x00 validator), take your stake. |
| A validator key | Get that validator slashed, or exit it. The balance still goes to your withdrawal address. |
| Your withdrawal address key | Exit 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-doppelgangerwhen 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.
| Port | Served by | What it is | Why it must stay private |
|---|---|---|---|
| 3500 | Beacon node | Beacon API | No authentication. Anyone can submit to your node and change the fee recipient it uses. |
| 4000 | Beacon node | gRPC API | No authentication. Anyone can act as a validator client against your node. |
| 8080 | Beacon node | Metrics | Reveal details about your node, such as its peers and sync status. |
| 7500 | Validator client | Keymanager API (with --rpc or --web) | With the token, a caller can import and delete keys, change your fee recipient, and sign exits. |
| 8081 | Validator client | Metrics | Reveal your validator public keys and balances. |
| 8551 | Execution client | Engine API | Controls your execution client. Keep it on localhost or a private network. |
| 8545 | Execution client | JSON-RPC API | Anyone 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.0on 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:3500forwards port 3500 on your laptop to127.0.0.1:3500on the node, through the encrypted SSH connection. The pattern is<LAPTOP_PORT>:<HOST_AS_SEEN_FROM_THE_NODE>:<NODE_PORT>.-Nopens the tunnel only, without starting a shell on the node.
While the tunnel runs,
http://127.0.0.1:3500on 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 withCtrl+C. -
With Docker, publish API ports on localhost only (
127.0.0.1:3500:3500), or not at all. Docker's published ports bypassufw. -
Keep
jwt.hexreadable only by the execution client and beacon node. -
Treat the Keymanager token file (
auth-tokenin the wallet directory) like a key.
Check what listens where:
sudo ss -tlnp | grep -E ':(3500|4000|7500|8080|8081|8551|8545)\b'
Get-NetTCPConnection -State Listen | Where-Object LocalPort -in 3500,4000,7500,8080,8081,8551,8545 | Select-Object LocalAddress,LocalPort,OwningProcess
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.confPasswordAuthentication noKbdInteractiveAuthentication noPermitRootLogin noApply with:
sudo sshd -t && sudo systemctl reload sshIf you don't use SSH, don't install the OpenSSH Server feature. If you do, set:
C:\ProgramData\ssh\sshd_configPasswordAuthentication noKbdInteractiveAuthentication noApply with, in an administrator PowerShell:
sshd -t; if ($?) { Restart-Service sshd } -
Turn on a default-deny firewall and allow only SSH and the P2P ports:
sudo ufw default deny incomingsudo ufw default allow outgoingsudo ufw allow 22/tcpsudo ufw allow 13000/tcpsudo ufw allow 13000/udpsudo ufw allow 12000/udpsudo ufw allow 30303 # execution client P2P; check your client's portsudo ufw enableIn an administrator PowerShell:
Set-NetFirewallProfile -All -Enabled True -DefaultInboundAction Block -DefaultOutboundAction AllowNew-NetFirewallRule -DisplayName "Prysm P2P TCP" -Direction Inbound -Action Allow -Protocol TCP -LocalPort 13000New-NetFirewallRule -DisplayName "Prysm P2P UDP" -Direction Inbound -Action Allow -Protocol UDP -LocalPort 12000,13000# Execution client P2P; check your client's portNew-NetFirewallRule -DisplayName "Execution P2P TCP" -Direction Inbound -Action Allow -Protocol TCP -LocalPort 30303New-NetFirewallRule -DisplayName "Execution P2P UDP" -Direction Inbound -Action Allow -Protocol UDP -LocalPort 30303The OpenSSH Server feature adds its own rule for port 22.
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-upgradessudo dpkg-reconfigure --priority=low unattended-upgradesThen make sure your services start on boot (add
mev-boostif you run it):sudo systemctl enable execution beacon validatorKeep Windows Update on, in Settings > Windows Update. It restarts the machine to install updates, so make sure the execution client, beacon node, and validator client start again after a restart.
-
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.
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.