Post-Quantum SSH Warning: What It Means, How to Fix (2026)

The post quantum SSH warning explained: check which key exchange your session uses, fix the server or the client, and silence it safely per host.

Post-Quantum SSH Warning: What It Means, How to Fix (2026)

Since OpenSSH 10.1, ssh prints a three-line warning when a connection falls back to a key exchange that a future quantum computer could break. If you just saw it for the first time, nothing is broken and nobody is attacking you. The post quantum ssh warning means one thing: this session’s encryption keys were agreed with classical cryptography only, so someone who records the traffic today could, in principle, decrypt it years from now.

This guide shows what the warning means, how to check which key exchange your sessions actually use, and how to fix it on the server, on the client, or both. Every command below was run against a local OpenSSH 9.6 server and against github.com, gitlab.com and bitbucket.org on October 26, 2026.

Quick Summary: What You’ll Learn

  • What “connection is not using a post-quantum key exchange algorithm” means and why OpenSSH added it.
  • One command that shows which key exchange a session negotiated, and one that shows what the server offers.
  • Why the fix is sometimes on your laptop, not the server (GitLab and Bitbucket are a live example).
  • How to fix KexAlgorithms on a server without locking yourself out.
  • How to silence the warning for one host without breaking older ssh clients.

What does “connection is not using a post-quantum key exchange algorithm” mean?

This is the exact warning, as published by the OpenSSH project:

bash
** WARNING: connection is not using a post-quantum key exchange algorithm.
** This session may be vulnerable to "store now, decrypt later" attacks.
** The server may need to be upgraded. See https://openssh.com/pq.html

It means your client and the server could not agree on either of the two post-quantum key exchange algorithms OpenSSH supports, mlkem768x25519-sha256 or sntrup761x25519-sha512, and fell back to a classical one such as curve25519-sha256 or an ecdh-sha2-nistp* curve.

The connection still works, and it’s still encrypted with strong ciphers. What changes is the threat model. The key exchange decides the session keys, and if an attacker can break the key exchange, they can decrypt the whole recorded session. Classical Diffie-Hellman and elliptic-curve exchanges are the kind of math a large enough quantum computer is expected to solve. Nobody has built one that can do it yet, but traffic captured now can be stored and decrypted later. That’s the “store now, decrypt later” attack the warning names.

The warning exists to push the long tail of servers to upgrade. OpenSSH has offered a post-quantum key exchange by default since 9.0 (April 2022) and switched the default to mlkem768x25519-sha256 in 10.0 (April 2025). Most current OpenSSH pairs already negotiate a post-quantum algorithm without anyone touching a config file.

Which OpenSSH versions support post-quantum key exchange?

The timeline, from the OpenSSH release notes:

  • OpenSSH 9.0 (2022): [email protected] (Streamlined NTRU Prime + X25519) becomes the default key exchange.
  • OpenSSH 9.9 (2024): adds mlkem768x25519-sha256 (ML-KEM, standardized by NIST as FIPS 203, + X25519) and the unsuffixed name sntrup761x25519-sha512.
  • OpenSSH 10.0 (April 2025): mlkem768x25519-sha256 becomes the default.
  • OpenSSH 10.1 (October 2025): the client warns on non-post-quantum key exchange. A new WarnWeakCrypto option in ssh_config controls it.
  • OpenSSH 10.6 (October 2026): sshd_config gets WarnWeakCrypto too, on by default, so servers log clients that use a non-post-quantum key exchange.

Both algorithms are hybrids. Each combines a post-quantum scheme with X25519, so even if the post-quantum half turned out to be broken, the session is no weaker than plain curve25519-sha256. That’s why there’s no real downside to preferring them.

One detail that matters in practice: a client and a server both need to support the same post-quantum algorithm. An OpenSSH 9.6 client, for example, only knows [email protected]. That’s the version on Ubuntu 24.04, which is what we tested from:

bash
$ ssh -V
OpenSSH_9.6p1 Ubuntu-3ubuntu13.20, OpenSSL 3.0.13 30 Jan 2024
$ ssh -Q kex | grep -E 'mlkem|sntrup'
[email protected]

How do you check which key exchange an SSH session uses?

Run the connection in verbose mode and grep for the negotiated algorithm. This is the same check GitHub gives in its announcement:

bash
ssh -v [email protected] exit 2>&1 | grep 'kex: algorithm:'

The output looks like this:

yaml
debug1: kex: algorithm: [email protected]

If you see mlkem768x25519-sha256 or sntrup761x25519-sha512 (with or without @openssh.com), the session is post-quantum. If you see curve25519-sha256, any ecdh-sha2-* or any diffie-hellman-*, it isn’t.

To see what the server is willing to offer, which is what you need when deciding who has to change, go one level more verbose and read the server’s proposal:

bash
ssh -vvv user@host exit 2>&1 | grep -A2 'peer server KEXINIT' | grep 'KEX algorithms'

Two more checks that don’t need a connection:

  • ssh -Q kex lists every key exchange your client binary supports.
  • ssh -G host | grep -i kexalgorithms prints the list your client will actually offer to that host after reading ~/.ssh/config.
  • On the server, sudo sshd -T | grep -i kexalgorithms prints the effective server list after all includes and Match blocks.

Why do some Git hosts still negotiate classical key exchange?

Here’s what we got on October 26, 2026, connecting from the OpenSSH 9.6 client above:

  • github.com offers mlkem768x25519-sha256, sntrup761x25519-sha512 and the @openssh.com name. Negotiated: [email protected]. Post-quantum.
  • gitlab.com offers mlkem768x25519-sha256 but no sntrup761. Negotiated: curve25519-sha256. Classical.
  • bitbucket.org offers mlkem768x25519-sha256 but no sntrup761. Negotiated: curve25519-sha256. Classical.

GitLab and Bitbucket aren’t the problem here. Both offer ML-KEM. Our 9.6 client doesn’t speak ML-KEM, so the only overlap left is classical. A client on OpenSSH 9.9 or newer would get a post-quantum key exchange with all three, and 10.0 or newer prefers mlkem768x25519-sha256.

This is the part the warning text can mislead you on. It says “the server may need to be upgraded”, and it’s printed by a client that is new enough to know ML-KEM, so for that client the server usually is the gap. But if you have older clients around (CI runners on an LTS image, a jump host nobody has upgraded, a vendor appliance), they will quietly negotiate classical key exchange with servers that are fully post-quantum ready, and they’ll never warn you, because the warning only exists from 10.1 on.

GitHub’s own announcement has one more exception worth knowing: GitHub Enterprise Cloud with data residency in the US region doesn’t offer sntrup761, because only FIPS-approved cryptography may be used there and that algorithm isn’t FIPS-approved. If you’re in a FIPS environment, expect your options to differ.

How do you fix the warning on a server you control?

There are two causes, and they need different fixes.

1. The server’s OpenSSH is too old. Anything before 9.0 has no post-quantum key exchange at all. Check the version from the outside with ssh -v user@host 2>&1 | grep 'remote software version', or on the box with sshd -V (OpenSSH 9.2 and later) or your package manager. Distribution packages often carry an older upstream version number with security fixes backported, so read the number as “which features exist”, not “is it vulnerable”. If the version is below 9.0, the fix is a distribution upgrade or a newer OpenSSH package, not a config change.

2. The server is new enough, but KexAlgorithms strips the post-quantum algorithms. This is common on servers hardened with an older guide that pinned an explicit list. We reproduced it on OpenSSH 9.6 with one line:

bash
KexAlgorithms curve25519-sha256,[email protected]

With that line, every client negotiates curve25519-sha256, even ones that support post-quantum algorithms. Find it:

bash
sudo sshd -T | grep -i kexalgorithms
sudo grep -rni kexalgorithms /etc/ssh/sshd_config /etc/ssh/sshd_config.d/

The cleanest fix is to delete the pinned line and let the OpenSSH default apply, which already puts the post-quantum algorithms first. If you must keep an explicit list, put a post-quantum algorithm in it. On 9.6 that means:

bash
KexAlgorithms [email protected],curve25519-sha256,[email protected]

On 9.9 or newer, add mlkem768x25519-sha256 (and sntrup761x25519-sha512) as well. Only list algorithms your ssh -Q kex output on the server shows; an unknown name is a config error.

Then apply it the safe way. Test the config, reload, and keep your current session open while you check from a second terminal:

bash
sudo sshd -t && sudo systemctl reload ssh   # the unit is "sshd" on RHEL-family systems
# from a NEW terminal, keep the old session open:
ssh -v user@host exit 2>&1 | grep 'kex: algorithm:'

sshd -t matters more than usual here. If a config line is wrong, a restart can leave sshd not running, and the open session you kept is your way back in.

If your server sits behind a bastion, remember each hop is its own SSH connection with its own key exchange. With ProxyJump, check both the jump host and the target; our bastion host and ProxyJump guide covers how the hops connect.

How do you fix it from the client side?

Upgrade the client. If your client is older than 9.9, you can’t negotiate ML-KEM, and some servers (like GitLab and Bitbucket in our test) only offer ML-KEM as their post-quantum option. On a laptop that usually means a newer OS release or a newer OpenSSH package. On CI runners, it means a newer base image.

Check your own ~/.ssh/config. A pinned KexAlgorithms line on the client has the same effect as one on the server. ssh -G host | grep -i kexalgorithms shows what you’ll offer.

Require post-quantum for hosts that matter. You can make the client refuse classical key exchange for a specific host, instead of just warning about it:

bash
Host git.internal.example.com
    KexAlgorithms mlkem768x25519-sha256,sntrup761x25519-sha512,[email protected]

Use only names your ssh -Q kex knows (on 9.6, only the @openssh.com sntrup name). If the server can’t match, the connection fails instead of falling back. This is the error we got from a 9.6 client forcing sntrup against a server limited to curve25519:

bash
Unable to negotiate with 127.0.0.1 port 2299: no matching key exchange method found. Their offer: curve25519-sha256,[email protected],ext-info-s,[email protected]

That’s a loud failure by design. Use it for hosts where you’ve confirmed post-quantum support, not as a global default. If you keep a large config, our ssh config organization guide shows how to group these per-host rules so they don’t sprawl.

How do you silence the post-quantum warning safely?

Sometimes you can’t fix the other end: a network switch, an embedded device, a vendor appliance with its own SSH server. OpenSSH recommends turning the warning off selectively, not globally:

bash
Match host unsafe.example.com
    WarnWeakCrypto no-pq-kex

no-pq-kex disables only the post-quantum warning. WarnWeakCrypto no disables all of these warnings, including any OpenSSH adds later, so avoid it.

There’s a trap here if you share one ~/.ssh/config across machines, or check it into a dotfiles repo. Clients older than 10.1 don’t know WarnWeakCrypto and refuse to run. On OpenSSH 9.6:

yaml
config: line 2: Bad configuration option: warnweakcrypto
config: terminating, 1 bad configuration options

That breaks every ssh command on that machine, not just the one host. Put this at the very top of the file, before any Host or Match block:

bash
IgnoreUnknown WarnWeakCrypto

IgnoreUnknown only applies to options that appear after it, which is why it has to come first.

The same trap exists on servers, with no IgnoreUnknown escape hatch. WarnWeakCrypto in sshd_config is new in 10.6. On our 9.6 server, sshd -t rejected it with Bad configuration option: WarnWeakCrypto. Don’t push it to a fleet of mixed versions through one shared config template.

Do you also need post-quantum SSH keys?

Not urgently. The key exchange protects the secrecy of the traffic, and that’s what “store now, decrypt later” targets. Your SSH keys (user keys and host keys) are used for signatures, which prove who you are at connection time. A future quantum computer could forge signatures for keys that are still trusted then, but it can’t use that to decrypt sessions you recorded in the past.

OpenSSH has started on post-quantum signatures anyway. OpenSSH 10.6 enabled the hybrid ssh-mldsa44-ed25519 algorithm, and keys generated with the earlier experimental version have to be regenerated. Server and client support is still thin, so for most people the right move today is to keep using Ed25519 and plan to rotate when your servers and Git hosts accept the new type. Our ssh-keygen best practices guide covers where mldsa44-ed25519 stands and what to generate now.

Order of work, if you’re auditing a fleet: key exchange first (it protects traffic recorded today), signatures later.

Where does termique fit?

A GUI SSH client uses its own SSH library, so your ~/.ssh/config KexAlgorithms and WarnWeakCrypto lines don’t apply to it. That’s true for termique too. termique’s docs don’t currently list which key exchange algorithms its connections negotiate, so for a connection where post-quantum key exchange is a requirement, verify it with ssh -v from a terminal against the same host.

What termique does handle is the part around the session. It saves each host’s key on first connect and blocks the connection, before sending any credential, if a host later presents a different key, showing the new key’s SHA256: fingerprint so you can compare it with the server. Our host key verification guide explains why that check matters. Your SSH passwords and private keys are end-to-end encrypted before they sync between devices, so the sync server only stores ciphertext; host names, groups and snippets sync as plain metadata. The details are on our security page.

For the wider checklist (key types, password auth, hardening, auditing), see the SSH security best practices guide.

FAQ

Is the post-quantum SSH warning an attack?

No. It means your session negotiated a classical key exchange. The connection is still encrypted and authenticated. The risk is long term: recorded traffic could be decrypted once a large enough quantum computer exists.

How do I check if my SSH connection is post-quantum?

Run ssh -v user@host exit 2>&1 | grep 'kex: algorithm:'. If it shows mlkem768x25519-sha256 or sntrup761x25519-sha512, it’s post-quantum. Anything else is classical.

Does GitHub support post-quantum SSH?

Yes. GitHub added sntrup761x25519-sha512 on September 17, 2025, and in our October 2026 test github.com also offered mlkem768x25519-sha256. GitHub Enterprise Cloud with US data residency is the exception, because only FIPS-approved algorithms are used there.

How do I turn off the post-quantum warning for one server?

Add Match host that.server.example with WarnWeakCrypto no-pq-kex under it, and put IgnoreUnknown WarnWeakCrypto at the top of your config so clients older than 10.1 don’t fail on the unknown option.

Which is better, mlkem768x25519-sha256 or sntrup761x25519-sha512?

Both are hybrids with X25519 and both protect against “store now, decrypt later”. OpenSSH made mlkem768x25519-sha256 the default in 10.0; it’s NIST-standardized and faster. Use whichever both ends support; with a recent OpenSSH you don’t have to choose.

If you juggle more servers than you can track by hand, try termique free: hosts in one place, host keys checked before credentials are sent, and credentials encrypted before they sync.

All articles