Breach research, Product updates

516 Breaches Leaked Passwords. 56% Stored Them Badly.

September 7, 2026
A login field with the password readable in plain text and a red stored-as-is tag: 516 breaches leaked passwords, 56 percent stored them badly

Use a strong password. Every guide says it, and it’s still good advice.

Here’s what it can’t do: stop the company on the other end from storing that password badly. And in our data, that happens more than half the time.

XposedOrNot is a free breach-notification service. The catalog behind it lists every public breach we’ve loaded, and anyone can read it through an open, keyless API. This is the first post in a series where I take that catalog apart in public. (Numbered #1, though the second one went out first. Long story.) Numbers first, receipts at the end. Every figure below comes from the API, and the exact commands to reproduce it are in the appendix.

The short version

  • 516 of the 783 breaches in our catalog leaked passwords (as of 7 September 2026).
  • 83 of those stored them in plaintext. 206 used hashing weak enough to crack on ordinary hardware. 153 did it properly. 74 we can’t classify.
  • So 289 of 516, or 56%, were recoverable. That’s the floor. Among the ones we can actually classify, it’s 65%.
  • Plaintext isn’t ancient history. Nineteen of the 83 plaintext breaches happened this decade. One is from 2026.

How I counted

Our catalog held 783 breaches and 11.62 billion records when I ran this. Each entry records, where we know it, how the breached company stored passwords: plaintext, weakly hashed (crackable in hours to days with commodity hardware), or strongly hashed. I filtered to the breaches that list passwords among the exposed data, and I counted.

(If you’d rather see the headline number in context with the rest of our catalog stats, it’s on the data breach statistics page too, pulled in August when the catalog stood at 772. This post is the working behind it.)

The numbers

StorageBreaches (of 516 that leaked passwords)Share
Plaintext8316%
Weak hashing20640%
Strong hashing15330%
Not classified7414%

Plaintext plus weak: 289. Fifty-six percent of the breaches that lost your password barely slowed the attacker down.

And 56% is generous. It treats all 74 unclassified breaches as if they’d stored passwords well, which nobody believes. Drop those and the recoverable rate among classifiable breaches is 65%. The truth sits somewhere between the two, and neither end is flattering.

Stacked bar of the 516 password-leaking breaches: 83 plaintext, 206 weak hashing, 153 strong hashing, 74 not classified, with the callout that 289 of 516 is 56 percent and that is the floor

Catalog-wide, for the pedants (me included): 84 entries carry a plaintext label, 210 weak, 156 strong, 333 unknown. The gap is eight entries that carry a storage label but no “Passwords” tag in their exposed-data field. Metadata rough edges, and the script counts it either way. Combolists count as breaches here too, which is one reason the three-leak taxonomy matters when you read counts like these.

Is it getting better?

Slowly, and not nearly enough.

Take the 83 plaintext breaches by the year they happened. Sixty-four of them predate 2020. Nineteen don’t. And one is dated March 2026.

Somewhere, this year, a company was still keeping customer passwords in a form you could open and read, two decades after hashing them properly became standard guidance. It isn’t exotic, and it isn’t expensive, which is the part that stings. The companies behind those 289 breaches either didn’t do it or did it badly enough that it didn’t matter.

Bar chart of the share of password-leaking breaches that used strong hashing, by breach year 2015 to 2022, rising from 11 percent in 2015 to 47 percent in 2020

The direction is right, though. The strong-hashing column climbs year on year. In 2015, 6 of the 54 password-leaking breaches had hashed properly. By 2020 it was 29 of 62. Progress. Glacial, but progress.

What this changes for you

Not “don’t bother with strong passwords”, because please do keep bothering.

It changes to this: a strong password is necessary and not sufficient, because you can’t audit how anyone stores it and you’ll never see their database. Two things you do control:

  1. A different password everywhere. Then one bad storage decision costs you one account, not seven. A password manager makes that the default rather than a chore. (The reuse maths gets its own post; it’s uglier than this one.)
  2. Hearing about it early. You can’t stop a company mishandling your password. You can find out before someone uses it. That’s a free alert, no paid plan, ever.

Curious what’s already out there with your address on it? Check now. Ten seconds, no signup. And if you want to know whether a specific password has already appeared in a breach, the password checker tells you without ever seeing the password itself.

What this data can’t tell you

Honesty section. A number without its limits is marketing.

  • “Unknown” is big. 333 of the 783 entries carry no storage classification at all, 74 of them among the password leakers. The 56% headline treats those 74 as safely stored. That’s the generous reading, and I’ve said so.
  • Metadata has rough edges. Eight entries carry a storage label without listing passwords in their exposed-data field. Strict and lenient counting differ by a handful. None of it moves the headline, and the script lets you count it your way.
  • Our catalog isn’t the universe. It’s 783 public breaches. The ones never disclosed, or never surfaced, aren’t in anyone’s denominator.
  • Old breaches dominate the plaintext count partly because old breaches dominate, full stop. Read the year-by-year line, not the raw total. It’s fairer.

Frequently asked questions

What does “weak hashing” mean here? Weak, in this post, means an attacker with a gaming PC gets most of the passwords back in hours to days. Unsalted MD5. SHA-1. Or a decent algorithm run with far too few rounds. Strong means bcrypt, scrypt, Argon2 or PBKDF2 set up sensibly, where cracking at scale just isn’t worth anyone’s time.

Does XposedOrNot store the passwords from these breaches? No. We store exposure facts: which breach, which data types, how the passwords were stored. Password checks run against one-way hashes, never the passwords themselves.

Can I reproduce the 56% figure? Yes, from the free public API, no key required. The script is in the appendix. The counts will grow with the catalog and the percentage may move either way; that’s the point of a live receipt.

Appendix: sources and references

  • All figures: api.xposedornot.com/v1/breaches, computed 7 September 2026, script below.
  • Headline stat in context: blog.xposedornot.com/data-breaches-statistics/, August 2026.
  • Next in the series: breach-to-surfacing lag, already published as The Breach You Heard About Today Happened More Than Four Years Ago.
  • Password storage guidance: OWASP Password Storage Cheat Sheet, cheatsheetseries.owasp.org.

Reproduce it yourself

Don’t take my word for any of this. The catalog is a free, keyless, public API.

curl -s -A "Mozilla/5.0" "https://api.xposedornot.com/v1/breaches" > breaches.json
import json, collections
d = json.load(open("breaches.json"))["exposedBreaches"]
print("total:", len(d))
pw = [x for x in d if "Passwords" in x["exposedData"]]
print("password-leaking:", len(pw))
print("storage among them:", collections.Counter(x["passwordRisk"] for x in pw))
bad = sum(x["passwordRisk"] in ("plaintext", "easytocrack") for x in pw)
print("recoverable:", bad, f"{bad/len(pw):.0%}")
cls = len(pw) - collections.Counter(x["passwordRisk"] for x in pw)["unknown"]
print("classified rate:", f"{bad/cls:.0%}")
print("catalog-wide:", collections.Counter(x["passwordRisk"] for x in d))
pt = [x for x in pw if x["passwordRisk"] == "plaintext"]
print("plaintext pre-2020:", sum(int(x["breachedDate"][:4]) < 2020 for x in pt))
print("plaintext 2020s:", sum(int(x["breachedDate"][:4]) >= 2020 for x in pt))
for y in ("2015", "2020"):
    yy = [x for x in pw if x["breachedDate"].startswith(y)]
    print(y, len(yy), sum(x["passwordRisk"] == "hardtocrack" for x in yy), "strong")

Output on 7 September 2026: total 783, password-leaking 516, plaintext 83, easytocrack 206, hardtocrack 153, unknown 74, recoverable 289 (56%), classified rate 65%, catalog-wide 84/210/156/333, plaintext pre-2020 64, 2020s 19, 2015 54 with 6 strong, 2020 62 with 29 strong.

If analysis-with-receipts is the kind of security content you want more of, drop us a star on GitHub. It helps others find the project, and honestly, it makes our day.

—

Get alerted when your email shows up in a new breach. Set up free breach alerts, it takes two minutes.


Check out some of our posts for you.

Discover more from Data Breach Insights

Subscribe now to keep reading and get access to the full archive.

Continue reading