Skip to main content
GrN.dk

Main navigation

  • Articles
  • Cases
  • Contact
  • Your Digital Project Manager
  • About Greg Nowak
  • Services
  • Portfolio
  • Container
    • Excel Freelancer
    • Kubuntu - tips and tricks
    • Linux Apache MySQL and PHP
    • News
    • Image Gallery
User account menu
  • Log in

Breadcrumb

  1. Home

WordPress 6.8 Password Hashing: The Hidden Risk in Legacy Login Bridges

By Greg Nowak. Last updated 2026-07-15.

WordPress 6.8 made password storage stronger without asking users to reset their passwords. For an ordinary site using the standard WordPress login, the change is deliberately uneventful. The operational risk sits elsewhere: old plugins, member portals, mobile APIs, migration tools, and support scripts that treat WordPress database fields as a stable authentication interface.

Those integrations may work for months after an upgrade. Then one user logs in through WordPress, their old password hash is replaced, and a separate login bridge stops recognising the account. That delayed failure is why this deserves an audit rather than a quick admin-login check.

What WordPress 6.8 actually changed

Since WordPress 6.8, wp_hash_password() uses bcrypt by default. WordPress first processes the password with SHA-384 to avoid bcrypt’s 72-byte input limit, then stores the resulting hash with a WordPress-specific prefix—normally $wp$2y$.

Existing phpass hashes, usually identified by $P$, remain valid. During the standard username-and-password authentication flow, WordPress checks whether a successful login needs rehashing and saves a new hash when necessary. Users are not migrated in one database operation, so old and new formats can coexist indefinitely on a site with infrequent users.

WordPress also introduced wp_fast_hash() for randomly generated, high-entropy secrets. Application passwords, password-reset keys, personal-data request keys, and recovery-mode keys can consequently appear with a $generic$ prefix. This fast BLAKE2b-based mechanism is not intended for user-chosen passwords.

The problem is the contract, not the prefix

A common patch is to teach an integration about $wp$2y$ and $generic$. That may restore service today, but it preserves the underlying design problem: an internal storage format has become an undocumented contract between systems.

WordPress already knows how to handle its current format, legacy phpass and MD5 values, compatible hashes created by plugins, and deliberately selected alternatives such as Argon2. Custom code should call the relevant WordPress authentication API instead of reproducing that decision tree.

Authentication path Warning sign Preferred boundary Minimum test
Browser or member login Reading user_pass directly wp_authenticate() Login before and after rehashing
Custom password check Calling PHP password_verify() on WordPress data wp_check_password() Legacy and current hashes
Application integration Inspecting _application_passwords REST authentication or WP_Application_Passwords::check_password() Old and newly issued credentials
Password reset Reimplementing user_activation_key checks check_password_reset_key() Issue, validate, expire, and reuse attempts
SSO or social login Fallback code touches stored hashes The provider callback and WordPress user APIs Success, denial, logout, and fallback
A practical decision matrix for reviewing authentication code after the WordPress 6.8 hashing change.

Search the codebase before tracing individual bugs

Start with custom plugins, must-use plugins, theme code, deployment utilities, and integration packages. These searches are intentionally broad; a match is a review prompt, not proof of a vulnerability.

rg -n '\$P\$|\$wp\$2y\$|\$generic\$|user_pass|user_activation_key|_application_passwords|PasswordHash' wp-content/
rg -n 'md5\(|password_verify\(|password_hash\(|wp_hash_password|wp_check_password|wp_verify_fast_hash' wp-content/

Also search repositories outside the WordPress installation. A Node, Java, .NET, or older PHP service that receives a copy of wp_users is often the real source of the failure. Database exports, reporting replicas, and migration code deserve attention too.

Use the highest-level supported API available

For a conventional username-and-password flow, let WordPress run the authentication pipeline:

$user = wp_authenticate( $username, $password );

if ( is_wp_error( $user ) ) {
    return $user;
}

// Authentication succeeded.

If custom code already has a user object and genuinely needs a password comparison, use wp_check_password(). Remember that this function only checks the value; it does not itself save a replacement hash. The standard wp_authenticate_username_password() flow performs the rehash after a valid check. A custom flow that bypasses it must deliberately handle that lifecycle, including the session implications of updating a password.

For application passwords, prefer WordPress’s REST authentication rather than reading user metadata. If verification inside WordPress is unavoidable, WP_Application_Passwords::check_password() handles both current and pre-6.8 application-password hashes. Use wp_verify_fast_hash() directly only for an appropriate high-entropy secret hashed through the matching WordPress mechanism—not as a generic password checker.

If another service needs to authenticate WordPress users, exporting password hashes is the fragile option. A small authenticated endpoint, an established identity provider, or a proper SSO boundary keeps the hashing implementation inside the system that owns it.

A staging test that reflects production

Create a test matrix around user journeys, not only functions. Include an account with a legacy hash and confirm its first standard login succeeds. Capture only the hash prefix—not credentials or full hashes—then confirm that the stored format changes and a second login still works.

Repeat the test through every real entry point: member portal, mobile client, customer dashboard, support impersonation tool, SSO fallback, password reset, application password, and recovery flow. Test failure cases as well as success. An integration that accepts an expired reset key or sends useful credentials into logs is a more serious problem than a clean rejection.

Finally, review observability. Authentication logs should identify the route, integration, and error category without recording plaintext passwords, tokens, or complete stored hashes. That gives the operations team enough context to distinguish a proxy problem, disabled application-password feature, rejected SSO assertion, and incompatible legacy bridge.

When a targeted review is worth it

A standard WordPress site probably needs no special project. A site with custom authentication, shared user tables, an inherited membership plugin, or credentials checked by another service does. The useful deliverable is a map of authentication paths, evidence from staging, and a short remediation list—not a speculative rebuild.

If ownership of those paths is unclear, Greg can audit the WordPress and integration code, replace direct hash handling with supported boundaries, and build a focused test plan for your release process. Talk to Greg about a targeted WordPress authentication review.

Related on GrN.dk

  • CodeIgniter Tips and Tricks for Secure Login and Password Resets
  • NGINX 1.30 changed upstream connection reuse by default: what to check before you upgrade
  • When AI writes JSON, one bad field can break the workflow

Need help with this kind of work?

Ask Greg about a WordPress authentication audit Get in touch with Greg.

Sources

  • WordPress 6.8 will use bcrypt for password hashing
  • wp_check_password() – WordPress Developer Resources
  • wp_authenticate_username_password() – WordPress Developer Resources
  • wp_verify_fast_hash() – WordPress Developer Resources
  • WP_Application_Passwords::check_password() – WordPress Developer Resources
Last modified
2026-07-15

Tags

  • wordpress
  • authentication
  • php
  • Operations

Review Greg on Google

Greg Nowak Google Reviews

 

Illustrated infographic summarizing: Shorter TLS certificates expose every renewal you never automated
Shorter TLS certificates expose every renewal you never automated
2026-07-26

Shorter TLS lifetimes leave less room for manual handoffs and faulty deploy hooks. Build a renewal path that protects service availability.

Illustrated infographic summarizing: One Timeout, Two Orders: Make AI Actions Safe to Retry
One Timeout, Two Orders: Make AI Actions Safe to Retry
2026-07-25

A timed-out AI action may already have succeeded. Stable keys, durable ledgers, queues and stored results prevent a routine retry from duplicating real work.

Illustrated infographic summarizing: Your AI Visibility Dashboard Needs a Methodology, Not More Charts
Your AI Visibility Dashboard Needs a Methodology, Not More Charts
2026-07-24

A practical framework for measuring AI-search visibility with fixed prompts, repeated tests, separate metrics, retained evidence, and honest reporting.

Illustrated infographic summarizing: AI Admin APIs Are Here—But Your Directory Is Still the Source of Truth
AI Admin APIs Are Here—But Your Directory Is Still the Source of Truth
2026-07-23

New AI admin APIs can automate access and spend controls, but reliable governance still starts with authoritative directory data and clear ownership.

Illustrated infographic summarizing: OpenAI Presence Arrived—But Is Your Workflow Ready for an Agent?
OpenAI Presence Arrived—But Is Your Workflow Ready for an Agent?
2026-07-22

Before an AI agent can take on real work, its workflow needs clear scope, permissions, handoffs, evaluation cases, and production monitoring.

Illustrated infographic summarizing: Chatbot Transcripts Quietly Became a Retention and Redaction Problem
Chatbot Transcripts Quietly Became a Retention and Redaction Problem
2026-07-21

Chatbot transcripts spread across providers, logs and support tools. Here is how to map each copy, redact sensitive data and test deletion properly.

Illustrated infographic summarizing: Cloudflare Service Keys Stop in September: Find Every Caller
Cloudflare Service Keys Stop in September: Find Every Caller
2026-07-20

Cloudflare Service Keys stop working on September 30, 2026. Here is how to find every caller, move to scoped API tokens and avoid a late outage.

Illustrated infographic summarizing: Your AI Workflow Needs an Acceptance Test Before It Meets Customers
Your AI Workflow Needs an Acceptance Test Before It Meets Customers
2026-07-19

A practical way to test AI workflows using realistic scenarios, tool checks, human rubrics, regression suites, and clear release gates.

Three cover candidates for The Goats Were Load-Bearing fanned on a dark background: an ember-lit door, three slow knocks, and a founders' ledger
The Goats Were Load-Bearing: a fantasy where the bill always comes due
2026-07-19

A teaser for the upcoming darkly comic fantasy novel The Goats Were Load-Bearing — a village, a door that must stay poor, and the worst possible time to sell the herd. Readers pick the cover.

Vegan Power game: the yellow player catches falling fruit while a chicken and a cow look on
Vegan Power: The Little Game About Eating Fruit, Not Friends
2026-07-19

Vegan Power is a free browser game where you catch fruit, dodge the animals, protect seven hearts, and chase a better high score.

More articles
RSS feed

GrN.dk web platforms, web optimization, data analysis, data handling and logistics.