WordPress 6.8 changed a part of the stack most sites never think about until it causes trouble: password hashing and related verification logic. From a security standpoint, this is a sensible upgrade. Core user passwords move from portable phpass hashing to bcrypt, and several other security-sensitive values now use WordPress’s fast-hash path with BLAKE2b via Sodium. The problem is not the change itself. The problem is older custom code that assumed WordPress hash formats were stable enough to inspect, pattern-match, or verify outside the supported APIs.
That matters because WordPress 6.8 is not some short-lived release you can wait out. The 6.8 field guide lists bcrypt as a shipped security change for developers, and WordPress 6.8.5 was released publicly on March 10, 2026. This is live production behaviour now.
The good news is that core handled backwards compatibility carefully. Existing password hashes still work. Logged-in users stay logged in after the upgrade. A password is only rehashed when the user next logs in successfully or changes it. In practice, that means many sites will not see an obvious issue on upgrade day. The trouble often appears later, when a custom bridge that used to cope with old $P$ hashes starts seeing newer values instead.
What changed in 6.8
For user passwords, WordPress 6.8 updates wp_hash_password() and wp_check_password() to use PHP’s native password functions with bcrypt, plus SHA-384 pre-hashing to avoid bcrypt’s 72-byte limit. Core marks these hashes with a $wp prefix so they are distinguishable from plain bcrypt hashes a plugin might generate directly. In other words, the default new prefix becomes $wp$2y$.
Several other values changed as well. Application passwords, user password reset keys, personal data request keys, and the recovery mode key now use a fast generic hash with BLAKE2b via Sodium. In WordPress, those values are verified through wp_verify_fast_hash(), which understands the new $generic$ format and still falls back to phpass handling for older values created before 6.8. Unlike user passwords, these values are not automatically rehashed. Older hashes remain valid if they were generated before 6.8 and used before expiry.
There are two details worth keeping straight. First, older phpass password hashes are still accepted, so legacy user records do not suddenly become invalid. Second, post passwords have not moved yet; the 6.8 developer note says they still use phpass for now. That is why broad, assumption-heavy rewrites can be just as risky as ignoring the change.
Where the real breakage tends to show up
Core is clear on one point: code that already relies on wp_hash_password() and wp_check_password() should continue to work. The risk is in code that stepped outside those functions and treated stored hashes as part of a stable internal contract. The developer note calls out the usual suspects directly: code that assumes a $P$ prefix, code that validates hashed values itself, code that reads application passwords or security keys as raw stored values, and plugins that override WordPress’s pluggable password functions.
That is where this becomes a paid troubleshooting problem. A custom bridge might have been written years ago to inspect wp_users.user_pass, recognise a WordPress password by prefix, and pass control to another system. An integration may read the _application_passwords user meta and expect phpass-style verification. A password reset helper may depend on the old behaviour of what is stored in wp_users.user_activation_key. Those shortcuts can sit quietly in production for a long time, right up until a core change makes the underlying assumption false.
The range of valid formats is also wider than many one-off integrations expect. WordPress’s own developer note says modern installs may now contain $wp$2y$ for the default pre-hashed bcrypt format, plain $2y$ from plugins using bcrypt directly, $generic$ for fast hashes, $argon2 if a site opts into Argon2, older $P$ phpass hashes that are still common, and even legacy plain MD5 on older data. If a bridge only recognises one prefix and rejects the rest, it is fragile by design.
There is one nuance here. WordPress says alternative authentication methods such as SSO, social login, one-time login, MFA, and 2FA are unlikely to be affected by the hashing change itself. That is reasonable as a core statement. It is not the same as saying every implementation is safe. If the code around those systems still performs its own hash or security-key handling, it needs review.
What a proper fix looks like
The fix is usually not to teach every custom component about every possible WordPress hash prefix forever. The practical fix is to stop handling WordPress hashes directly unless you are operating at the same abstraction level as core. For user passwords, verification should go through wp_check_password(). For application passwords and related security keys, verification should go through wp_verify_fast_hash(). That is where WordPress keeps its compatibility logic.
WordPress 6.8 also introduced wp_password_needs_rehash() as the supported way to decide when a stored password hash should be refreshed. That matters because sites may still contain phpass hashes, and future PHP or WordPress changes to default cost or algorithm can make older hashes outdated again. The implementation is explicit about the new prefix behaviour too: under the default bcrypt path, an unprefixed bcrypt hash needs rehashing, while a $wp-prefixed value can be checked correctly after removing that prefix for the underlying PHP function. For plugin and integration authors, that is the safe decision point instead of custom migration logic.
If a plugin overrides the pluggable password functions only to preserve older behaviour, the 6.8 developer note says that override may now need to go. That is another reason a real audit has to reach beyond the visible login form and into the code paths that quietly alter how core works.
If you maintain custom PHP or a Python service that touches WordPress authentication, the immediate question is simple: are you reading, comparing, parsing, or validating any stored WordPress hash yourself? If the answer is yes, that path deserves review.
What to test before users do it for you
A sensible staging test needs to cover the handover from old data to new behaviour. Test a user who still has a legacy password hash. Confirm the first successful login after the upgrade works. Then confirm later logins still work after WordPress rehashes that password. Password changes should be tested as well, because core also rehashes on password change.
Then test the flows tied to fast hashes. The WordPress code reference shows wp_verify_fast_hash() being used in application password checks, recovery mode key validation, user request key validation, and password reset key checks. If your site customises, proxies, or bridges any of those flows, you want evidence that both pre-6.8 data and 6.8-generated hashes behave correctly.
It is also worth testing the places developers commonly cut corners: direct reads from wp_users.user_pass, logic tied to the _application_passwords user meta structure, anything that touches wp_users.user_activation_key, and plugins that override the pluggable password functions. Those are the paths most likely to survive untouched for years and then fail only when a core upgrade changes the assumptions underneath them.
Why this is worth fixing properly
Authentication faults are expensive because they are awkward to reproduce, easy to miss in casual testing, and highly visible once they hit production. WordPress 6.8 made a sensible security improvement, and core preserved compatibility for existing credentials. Ironically, that compatibility is part of what makes the risk easy to miss: weak custom code may appear fine until the wrong account happens to trigger the new format.
For GrN, the useful commercial response is not a dramatic rewrite. It is a targeted audit. Greg can review plugins and custom PHP or Python auth code, replace raw hash handling with supported WordPress functions, test rehash behaviour on staging, and verify password-reset and application-password flows before users get locked out of important paths. On sites with legacy login bridges, that is usually a cheaper conversation than emergency diagnosis after the first incident.
Need help with this kind of work?
Discuss a WordPress auth audit Get in touch with Greg.