Back to Blog
securitysupabasepostgresfinancial-servicesrls

The Supabase Anon Key Security Trap That Leaked Hashes (Simply Explained)

A plain-language guide to supabase anon key security. No jargon, no tech speak, just what it means for your business.

By Mike Hodgen

Want the full technical deep dive? Read the detailed version

I Found Password Records Sitting in the Open

I was reviewing an app I had built for a financial advisory firm, the kind that manages serious money for serious people. Routine check. What I found was not routine.

The list of advisor logins, including their scrambled passwords, was readable by anyone who knew where to look. Not through a hidden admin door. Not with a stolen key. Through the same public address that loads when anyone visits the company website.

Think of it like this. Every website hands your browser a basic key when you visit. That key is supposed to be public. It is like the front door key to a store. Anyone can walk in during business hours. That is normal.

The problem was not the key. The problem was that the key opened a back room it should never have touched, the room holding the staff passwords.

If the wrong person had found this instead of me, it would not have been a bug report. It would have been a public breach, the kind regulators and lawyers get involved in.

I found it. I fixed it. The app is locked down now. But the fix had a trap in it that nearly fooled me, and that trap is the real reason I am writing this.

The Key Was Never the Secret

Here is the part most people get wrong, including a lot of developers.

That public key is not a password. It is meant to be visible. You can find it on almost any website in about ten seconds. Treating it like a secret is like putting a deadbolt on a door with no walls around it. Pointless.

Real security comes from a separate set of rules that decide what that public key is allowed to see. It is like a store where the front door is unlocked, but the safe, the back office, and the employee files are all behind locks the customer key cannot open.

The failure here was simple. The advisor information was all crammed into one big filing cabinet. Names, job titles, and the scrambled passwords were all in the same drawer. The website only ever needed the names and titles. But the public key could open the whole drawer.

So my first move was to split the cabinet. The website now only gets the safe stuff: names and roles. The passwords are sealed off entirely.

One thing worth saying plainly. People hear "scrambled password" and relax. Do not. A scrambled password is still dangerous if it leaks. A determined attacker can sit at their own computer, with all the time in the world, and grind away at unscrambling it. Weak passwords fall fast. "Scrambled" does not mean "safe to publish."

The Trap That Almost Got Me

The bigger problem was the password reset function. Anyone who knew the trick could reset an advisor's password without logging in as anyone. Bad.

So I did the obvious thing. I revoked permission from the public key. Two commands, two roles, done. The computer told me both commands succeeded.

Then I tested it the way an attacker would. I tried to reset a password using the public key.

It still worked.

I had just removed the permission, and the action went through anyway. That is the kind of moment that makes you stop and stare at the screen.

Here is what was actually going on. The system I was using has a hidden default. When you create one of these functions, it automatically gives permission to "everyone." Not "the public key." Everyone. Every role, including ones that do not even exist yet.

So when I revoked permission from "the public key," I was removing something it never actually held. The real permission was coming from the "everyone" setting. The public key was just one face in that crowd.

It is like firing one employee for leaving the back door unlocked, when the truth is the door was built without a lock in the first place. Firing the employee changes nothing. The door is still open.

The command said "success." It accomplished nothing. That is the dangerous part. It looks like you locked the door while you walk away.

The Real Fix

Once I understood where the permission actually lived, the fix was straightforward.

First, I revoked permission from "everyone," not from the public key. The second that ran, the public key could no longer touch the reset function. The thing it had been riding on was gone.

Second, the company's own server still needs to run resets when an advisor legitimately asks. So I gave permission back to one trusted helper only, the server itself. The server stays behind the counter. It never gets handed to a visitor's browser. So now the reset works for the business and nobody else.

Third, and this is the step almost everyone skips: I checked the actual permissions afterward to confirm only the trusted server remained. I did not trust that the command "worked" just because it said so. My first attempt also said it worked, and it did nothing.

Verification is the whole difference between thinking you are secure and knowing it.

Why This Hides So Well

Here is what should concern you if your business runs on an app that got built fast.

This kind of hole is completely invisible from the user's seat. The app works. Logins work. Resets work. Nothing looks broken because nothing is broken when you click around. You only find it by poking at the system the way an attacker would, on purpose.

Apps built quickly with AI tools are especially prone to this. Not because the AI is careless, but because it quietly accepts these hidden defaults. The "everyone has permission" setting is not written anywhere in the code. There is no line to spot in a review. It is an absence, and absences do not show up when you read through the work.

I will be honest. I run this exact stack. I know it cold. And these defaults still bit me on my own projects. Building fast is a real advantage and I would not give it up. But the same shortcuts that let you move quickly are the ones that quietly leave doors open. That is why I check for this on purpose instead of assuming it is fine. It usually is not.

For a business owner, the takeaway is simple. A working app is not the same as a secure app. Those are two different things, and the gap between them is a real review by someone who knows where these systems hide their defaults.

If an app built fast is holding your sensitive data right now, this is exactly the kind of check worth running before a customer or a regulator finds the problem for you.

Thinking about AI for your business?

If this hit home, let's talk. I do free 30-minute calls where we look at how your business actually runs and find the spots where AI could make a real difference.

Book a Discovery Call

Get AI insights for business leaders

Practical AI strategy from someone who built the systems — not just studied them. No spam, no fluff.

Ready to automate your growth?

Book a free 30-minute strategy call with Hodgen.AI.

Book a Strategy Call