RUSTSEC-2026-0199 Panic in `bcrypt::verify` on non-ASCII hash input

Not scored Published

Attackers can crash Rust applications by supplying non-ASCII bcrypt hashes, causing a panic in the verification logic.

Exploited in the wild
Not known
Login needed
Not needed
Attackable
Over the internet
Victim action needed
Not needed
Fix
Available

What is RUSTSEC-2026-0199?

RUSTSEC-2026-0199 is a denial of service vulnerability in bcrypt, published on 20 Jun 2026. An attacker can exploit it over the internet without logging in, with no action from the victim.

Official description

bcrypt::verify(password, hash) and HashParts::from_str(hash) panic in str::slice_error_fail when given a 60-byte &str containing a multi-byte UTF-8 character at certain byte positions.

Impact

Any Rust code that calls bcrypt::verify (or HashParts::from_str) with an attacker-controlled hash string will panic. The bcrypt crate is #![forbid(unsafe_code)], so this is limited to a denial-of-service and cannot lead to memory corruption.

Realistic attack contexts include:

  • Rust authentication services reading hashes from a database that was previously compromised via, e.g., SQL injection. The attacker can then crash the service on every login attempt against the tampered account.
  • CLI tools accepting hashes from stdin or command-line arguments.
  • Password managers or vault services loading hashes from untrusted configuration sources.

Root cause

split_hash performed five &str slicing operations on the input hash: &hash[1..3], &hash[4..6], &hash[7..], &salt_and_hash[..22], and &salt_and_hash[22..]. None of these were char-boundary-checked. Any input where a multi-byte UTF-8 character spanned one of those byte positions caused a panic.

This is a regression of the fix originally shipped in 2021 for issue #62 (commit 0833509). The regression was introduced in the parser rewrite in PR #95 (commit e9a8394, released as 0.19.0).

The pre-existing regression test does_no_error_on_char_boundary_splitting was not removed, but was silently rendered ineffective by the new bytes[0] != b'$' guard, which rejected its input earlier and prevented it from reaching the buggy slices — leaving CI green through the regression.

Fix

split_hash now rejects any hash string containing non-ASCII bytes up front. A valid bcrypt hash is always exactly 60 ASCII bytes, so this closes the entire class of byte-boundary panics rather than guarding each slice individually.

The fix was merged in PR #103 and released as bcrypt 0.19.2 on 2026-06-20.

Downstream impact

pyca/bcrypt (which depended on bcrypt 0.19.1) is not affected. Its Python-side wrapper performs its own byte-level salt parsing before invoking bcrypt::hash_with_salt, and never reaches the buggy code path in split_hash or verify.

Which versions are affected by RUSTSEC-2026-0199?

1 open source package ship an affected version, including bcrypt.

PackageAffectedFixed in
bcrypt crates.ioFrom 0.19.00.19.2

How do I fix RUSTSEC-2026-0199?

Upgrade bcrypt to 0.19.2 or later.

Upgrade, then put limits on request size, rate and nesting depth so one client cannot exhaust the service. More about Denial of service.

Is RUSTSEC-2026-0199 being exploited?

There is no known exploitation of RUSTSEC-2026-0199 in the wild and no public exploit code.

Sources

Is RUSTSEC-2026-0199 in your software?

Upload an SBOM and sbomify checks it against every vulnerability here, every day.

Check your SBOMs for free