Host key verification failed
Every guide opens with ssh-keygen -R. That silences the warning whether or not it was right — and in the case the warning exists to catch, silencing it is the attacker's goal.
Before the fix, the question. Nearly every page about this
error opens with ssh-keygen -R. That command silences the warning
whether or not the warning was right. SSH is telling you the server's identity
changed; the useful first step is establishing why, because in the
case the warning exists to catch, deleting the entry is precisely what an
attacker needs you to do.
What is a host key, and what changed?
Every SSH server has its own key pair, separate from any user's. On your
first connection your client records the server's public host key in
~/.ssh/known_hosts, and on every connection after that it checks
the server still presents the same one. This is what stops someone who controls
the network between you and the server from impersonating it: they can redirect
your traffic, but they cannot produce the server's private host key. When the
key you are shown does not match the key you recorded, SSH refuses to continue
and prints this error. The refusal is the feature working, not a malfunction.
Whether it indicates an attack or an administrative change is the thing you now
have to determine, and SSH cannot determine it for you.
Which of the two messages did you get?
They mean different things and are worth separating.
| Message | Situation | Risk |
|---|---|---|
Host key verification failed. alone, with no prior record |
Often StrictHostKeyChecking set to yes on a host
you have never connected to, or a known_hosts file that cannot be
read or written. |
Low. Nothing contradicts anything. |
WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! |
You have a recorded key for this host and the server presented a different one. | This is the one to think about. |
Is there a legitimate reason for the key to have changed?
Usually yes, and here are the ones that account for almost all real cases. The server was rebuilt or reinstalled, which generates fresh host keys. A cloud instance was destroyed and a new one took the same IP address — extremely common with dynamic addressing, and the reason connecting by IP produces this error far more often than connecting by hostname. The administrator rotated host keys deliberately. The host is behind a load balancer and you reached a different backend than last time, each with its own key. Or you are connecting through a port forward that now points somewhere else. Every one of these is mundane. What they have in common is that you can confirm them independently, and that is the test.
How to confirm the new key out of band
The verification has to come from somewhere other than the connection you are suspicious of, or it proves nothing. Practical options, in rough order of strength: read the fingerprint from the provider's web console or serial console for that machine; ask the administrator through a channel that is not this SSH session; check the cloud provider's instance metadata or launch log, which many record automatically; or compare against a fingerprint your organisation publishes. Once you have the expected fingerprint from one of those, compare it to what your client is showing you. If they match, the change is real and you can clear the old entry with confidence. If you cannot verify it by any independent means, do not connect — and specifically do not type your password or unlock your key, because that is the material an impersonating server is there to collect.
ssh-keyscan -t ed25519 server.example.com | ssh-keygen -lf -
The command above prints the fingerprint the server is currently offering. It is useful for comparing against a fingerprint you obtained elsewhere. It is not itself verification: it travels the same network path as the connection you are questioning, so it will happily report an impostor's key.
Clearing the entry, once you have decided it is safe
ssh-keygen -R server.example.com
ssh-keygen -R 192.0.2.10
Run it for both the hostname and the IP address if you have connected using
both, because they are recorded as separate entries and clearing one leaves the
other to fail next time. The command rewrites known_hosts and
leaves the previous version alongside it as known_hosts.old, which
is a small safety net worth knowing about. Your next connection will show the
new fingerprint and ask you to accept it. Read that fingerprint against the one
you verified rather than typing "yes" reflexively — this is the moment the
whole exercise was for.
Why you cannot find the line in the file
If you open known_hosts and see lines beginning with
|1| followed by base64, the hostnames are hashed and searching for
your server's name will find nothing. This is a privacy feature: it stops
someone who obtains the file from reading off a list of every machine you
connect to. Use ssh-keygen -F to look up an entry and
ssh-keygen -R to remove one, both of which understand the hashed
format. Editing the file by hand is possible but unnecessary, and it is how
people accidentally delete the wrong line.
ssh-keygen -F server.example.com
What not to do
Do not set StrictHostKeyChecking no globally, and be suspicious
of any guide that suggests it. That setting tells your client to accept
whatever key it is handed, on every host, permanently — it does not fix the
error so much as remove your ability to ever see it again, including the one
time it would have mattered. The same applies to deleting
known_hosts wholesale to make a single warning go away: you
discard the recorded identity of every server you have ever connected to, and
your client will then silently trust the next thing that answers on any of
those addresses. If you need to skip verification for a genuinely disposable
host, scope it to that host and use
UserKnownHostsFile /dev/null alongside it so nothing is
recorded.
The same error from a mounting app
An app that mounts a server as a Finder volume performs the same host key
check, and should — but it may show you a dialog instead of a terminal message,
and it may consult a different known_hosts than your shell does.
If a mount fails while the command line connects fine, or the reverse, the two
are looking at different records. The reasoning on this page is unchanged: the
question is still whether the key legitimately changed, and the answer still
has to come from outside the connection.
Disclosure. Published by OnePasswordManager Ltd, developers
of SSHMount for macOS. Everything here uses ssh-keygen, which
ships with your Mac. About this site.
Sources
Every technical claim above is checked against one of these. Where a manual page is quoted, it is the copy shipped by the vendor named, not a third-party summary of it.
- ssh-keygen(1), the manual page shipped with macOS — -R, -F and known_hosts handling — https://keith.github.io/xcode-man-pages/ssh-keygen.1.html
- ssh_config(5), the manual page shipped with macOS — StrictHostKeyChecking, UserKnownHostsFile — https://keith.github.io/xcode-man-pages/ssh_config.5.html
- ssh(1), the manual page shipped with macOS — host key verification — https://keith.github.io/xcode-man-pages/ssh.1.html