Guides / Leaked Password Protection Disabled

last checked oct 2026

Supabase "Leaked Password Protection Disabled" warning: what it means and how to fix it

You run the Security Advisor on your Supabase project and one of the warnings says Leaked Password Protection Disabled. It sounds like something already leaked. It hasn't. It means your project will happily accept a password that's already sitting in public breach lists, and the fix is a single setting, if your plan has it.

The short answer

This is an Auth setting, not a database problem. The advisor check is called auth_leaked_password_protection, and it fires when Supabase Auth isn't checking new passwords against the HaveIBeenPwned Pwned Passwords list.

How urgent is it? It only matters if users sign in with an email and password. If they do, it's worth fixing before launch. Supabase's docs put the risk plainly: there are hundreds of millions of known leaked passwords, and attackers use those lists to automate sign-in attempts (credential stuffing). Someone who reuses Summer2024! everywhere is the account that gets taken over. If your app only uses magic links or OAuth, this setting has nothing to check, so it's low priority.

What the setting actually does

When it's on, Supabase Auth checks a new password against the open-source HaveIBeenPwned Pwned Passwords API and rejects it if it shows up there. The Pwned Passwords API is built so the password itself doesn't have to be sent: it supports searching by the first 5 characters of the password's SHA-1 hash (HaveIBeenPwned calls this k-anonymity) and returns every breached hash with that prefix, so the match happens on the caller's side.

A rejected password comes back as a weak_password error. In supabase-js that's an AuthWeakPasswordError whose reasons array can include "length", "characters" or "pwned". That last one is the leaked-password case.

What about people who already have accounts? Supabase's password docs say existing users can still sign in with their current password, but if it falls short of the strengthened requirements they'll get a WeakPasswordError during signInWithPassword explaining why. Plan for that in your UI (more on it below).

How to check your project

Option 1: the dashboard

Open the Security Advisor in your project's dashboard. If you see Leaked Password Protection Disabled, it's off. You can also look at the Email provider settings directly and see whether the leaked password option is switched on.

Option 2: the Management API (no keys printed)

Create a personal access token in your Supabase account settings. Don't paste it into a chat with your AI tool. Read it into an environment variable so it never lands in your shell history or on screen:

# prompts for the token without echoing it
read -rs SUPABASE_ACCESS_TOKEN && export SUPABASE_ACCESS_TOKEN
PROJECT_REF=your-project-ref   # the 20-letter ID in your project URL, not a secret

Then ask for only the password settings. The jq filter keeps everything else in your auth config (which includes things like SMTP and provider settings) off your screen:

curl -s "https://api.supabase.com/v1/projects/$PROJECT_REF/config/auth" \
  -H "Authorization: Bearer $SUPABASE_ACCESS_TOKEN" \
  | jq '{password_hibp_enabled, password_min_length, password_required_characters}'

"password_hibp_enabled": false (or null) means leaked password protection is off. While you're there, check the other two: a password_min_length under 8 and an empty password_required_characters are the defaults worth tightening.

You can also pull the same findings the Security Advisor shows, filtered to the auth password checks:

curl -s "https://api.supabase.com/v1/projects/$PROJECT_REF/advisors/security" \
  -H "Authorization: Bearer $SUPABASE_ACCESS_TOKEN" \
  | jq '[.lints[] | select(.name | test("password")) | {name, level, title}]'

Look for auth_leaked_password_protection. The same endpoint can also report password_requirements_min_length if your minimum length is too short.

How to fix it

On Pro and above: turn it on

In the dashboard, open the Email provider settings, switch on the leaked password option and save. Or do it with the same token, setting the length and character rules at the same time:

curl -s -X PATCH "https://api.supabase.com/v1/projects/$PROJECT_REF/config/auth" \
  -H "Authorization: Bearer $SUPABASE_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "password_hibp_enabled": true,
    "password_min_length": 10,
    "password_required_characters": "abcdefghijklmnopqrstuvwxyz:ABCDEFGHIJKLMNOPQRSTUVWXYZ:0123456789"
  }' \
  | jq '{password_hibp_enabled, password_min_length, password_required_characters}'

The password_required_characters field only accepts a few fixed values, one per option in the dashboard. The value above means "lowercase, uppercase and digits". Supabase's docs recommend the strongest option, which also requires symbols. Copy its exact value from the API reference rather than typing it out, because the symbol list has to match character for character. Supabase also says anything under 8 characters isn't recommended for the minimum length.

Then re-run the Security Advisor. The warning should be gone.

On the Free plan: tighten what you can

You can't turn on the leaked password check without upgrading, but you can still:

A signup-form check isn't the same thing. You can call the Pwned Passwords range API from your own signup page to warn people, and that helps honest users. But anyone can call your project's Auth API directly with the public key and skip your form, so it doesn't enforce anything. Only the server-side setting does.

Handle the error in your app

Once the check is on, signups and password changes with a leaked password fail. Show people a useful message instead of a generic "something went wrong":

import { isAuthWeakPasswordError } from '@supabase/supabase-js'

const { error } = await supabase.auth.signUp({ email, password })

if (isAuthWeakPasswordError(error)) {
  if (error.reasons.includes('pwned')) {
    showError('That password has appeared in a data breach. Please choose a different one.')
  } else {
    showError(error.message) // too short, or missing required characters
  }
}

Do the same on your password change screen (supabase.auth.updateUser({ password })). If you use signInWithPassword, catch the same error there and send the user to change their password, since existing users can now hit it at sign-in.

Confirm it worked

Run the GET request above again and check that password_hibp_enabled is true. Then try signing up a test account with a password you know is in breach lists, like password123. It should fail with the pwned reason. Delete the test user afterwards if the signup somehow succeeds.

If the advisor flagged this, it's worth checking the database side too. Our Supabase Row Level Security guide covers the checks that matter most for apps built with Lovable, Bolt or Cursor.

next step

Check your live app for free

Our free Leak Checker looks at your deployed app the way any visitor's browser does and flags exposed secret keys, public source maps and missing security headers. It can't see your Supabase Auth settings, so it won't catch this warning, but it's a quick first pass on what your frontend gives away.

If you want the deeper look, the $99 Scan + Report covers your repo and live app, including database access rules, leaked keys and deploy settings.

Sources

Every product step above was checked against these official pages. Last checked Oct 2026. Products change; if a setting moved, the docs below are the source of truth.