AI-coded apps

    Supabase JWT Secret Leaked (Immediate Remediation Steps)

    A Supabase JWT secret exposed in a repository, letting an attacker forge a service_role token.

    A leaked Supabase JWT secret is the worst-case Supabase exposure, because it is the master signing key. In the legacy model it signs every authentication token, and your anon and service_role keys are themselves tokens derived from it. Anyone with it can forge any token, impersonating any user or minting a service_role token that gives full, RLS-bypassing access to your database. Rotate the JWT secret immediately, which regenerates your API keys and invalidates every existing session, then migrate to asymmetric signing keys so a single shared secret cannot cause this again.

    Short answer

    The JWT secret signs everything, so a leak is total compromise. In Supabase's legacy model the JWT secret signs all auth tokens, and your anon and service_role keys are JWTs derived from it, per Supabase's API keys documentation. With it, an attacker can forge a token for any user or with the service_role claim, bypassing Row Level Security entirely. Rotate the JWT secret now, following Supabase's rotation guide; this regenerates the anon and service_role keys and invalidates all existing tokens and sessions. Update every client and server with the new keys, remove the secret from your code and Git history, and migrate to asymmetric signing keys for the long term.

    What the JWT secret is

    The JWT secret is the single symmetric key Supabase uses, in the legacy model, to sign and verify the JSON Web Tokens that represent every session and every API key. When a user logs in, Supabase issues a JWT signed with this secret; when a request arrives, Supabase verifies the signature with the same secret. Because it is symmetric, the same value both creates and validates tokens.

    This is what makes it the master secret. Your anon and service_role keys are not separate credentials in the legacy model; they are long-lived JWTs signed by this very secret, which is why rotating the JWT secret regenerates them. Anyone who holds the JWT secret can produce a token that Supabase will accept as genuine, which is the entire trust model of your backend in one value.

    What an attacker can do with it

    With the JWT secret, an attacker can forge any token they want, and Supabase will trust it. They can mint a token that claims to be any user, reading and writing that user's data, or a token carrying the service_role claim, which bypasses Row Level Security and grants full access to your entire database. There is no higher level of compromise; it is complete.

    The table below places the JWT secret against the other credentials, so the severity is clear.

    SecretWhat it doesIf leaked
    anon / publishable keyPublic client key, governed by RLSSafe if RLS is on
    service_role / secret keyBypasses RLS, admin accessFull database access; rotate
    JWT secret (legacy)Signs all tokens and derives both keysForge any token; rotate everything

    Unlike a leaked anon key, which is only dangerous without RLS, and even a leaked service_role key, which RLS at least frames, a leaked JWT secret defeats everything, because it lets the attacker forge the very tokens your access control trusts. That is why it is the one to treat as a full breach the moment you suspect it.

    Step 1: rotate the JWT secret immediately

    Rotating is the only action that neutralizes a leaked JWT secret, so do it first. In your Supabase project, roll the JWT secret from the API settings, which generates a new secret and re-signs your keys. This is the single most important step, because until the secret is changed, every forged token the attacker made remains valid.

    Do it before anything else, and accept the disruption. Rotating the JWT secret is intentionally heavy precisely because the secret is so central; that weight is the point, since it is what invalidates the attacker's forged tokens along with everyone else's. Treat the leaked secret as compromised even if you rotate within minutes, and review your logs for signs of forged-token access.

    What rotation invalidates

    Rotating the JWT secret invalidates every token signed with the old one, which has real, immediate effects you should expect. All existing user sessions become invalid, so every user is effectively signed out and must log in again. Any cached or stored tokens stop working, and any service using an old token fails until updated. This is not a bug; it is the mechanism that locks the attacker out.

    Because the anon and service_role keys are derived from the secret, they change too. Every place that used the old anon or service_role key, your web client, your mobile app, your Edge Functions, your CI, will stop working until you update it with the new key. Plan for this: the rotation that saves you also briefly breaks your own app, so line up the key updates to follow immediately.

    Update every client and server with the new keys

    After rotation, propagate the new keys everywhere the old ones lived. Update the anon key in your frontend and mobile app, update the service_role key in your backend and Edge Functions, and update any keys stored in CI secrets or configuration. Miss one and that part of your system stays broken, so treat this as a checklist of every place a Supabase key appears.

    This is also the moment to fix any exposure that caused the leak. If the JWT secret or a service_role key was in your client or repository, do not simply paste the new one into the same place; move secrets server-side and keep only the public anon key in the client. Otherwise you will rotate straight into a second leak.

    Migrate to asymmetric JWT signing keys

    The durable fix is to stop relying on a single shared symmetric secret at all. Supabase now offers asymmetric JWT signing keys, where a private key signs tokens and a public key verifies them, and the private key never leaves Supabase. Because verification uses only the public key, there is no shared secret for your code to leak, and you can rotate keys without the all-or-nothing disruption of the legacy secret.

    Migrating to signing keys is the way to make sure this incident cannot repeat in the same form. It removes the master symmetric secret from the picture, supports smoother rotation, and aligns with how modern token systems work. After you have contained the current leak, plan the migration as the structural improvement that prevents the next one.

    RLS does not save you here

    It is worth being clear that Row Level Security, which protects you from an exposed anon key, does not protect you from a leaked JWT secret. RLS enforces policies based on the identity in a token, but a JWT secret lets an attacker forge a token with any identity, including one that bypasses RLS entirely. The control assumes tokens are genuine, and the leaked secret breaks that assumption.

    This is why the JWT secret sits above RLS in severity. RLS remains essential as defense in depth, and you should have it enabled on every table regardless, but for this specific leak the fix is rotation and migration, not policy. Do not treat enabling RLS as a substitute for rotating the secret; it is a complement, not a cure.

    Verification checklist

    After you respond, verify each part rather than assuming. The checklist below confirms the leak is closed.

    StepActionWhat it confirms
    1Rotate the JWT secret in SupabaseOld signatures are invalid
    2Confirm old tokens and sessions are rejectedForged tokens no longer work
    3Update clients and servers with the new keysYour apps work again
    4Remove the secret from code and Git historyNo re-leak of the old secret
    5Enable RLS on every tableDefense in depth is in place
    6Plan migration to signing keysThe long-term fix is scheduled

    The verification that matters most is confirming that old tokens are rejected: try an old session or token and ensure Supabase refuses it. If forged and stale tokens no longer work, your new keys are in place, and the secret is out of your code and history, the immediate incident is contained, and the signing-key migration is what keeps it contained.

    Prevent the next leak: scan and secret hygiene

    Most JWT secret leaks are avoidable accidents, a secret committed to a repository or shipped in a build, so preventing the next one is about secret hygiene and checking what you ship. Keep the JWT secret and service_role key server-side only, never in client code or Git, enable GitHub secret scanning and push protection, and scan your build before release.

    A scanner like PTKD.com analyzes your mobile build and returns findings ordered by severity and mapped to OWASP MASVS, including embedded secrets, so a secret does not reach users in the first place. To be clear about the boundary: a build scanner checks the app you ship, not your Supabase project, so it does not rotate the secret or migrate you to signing keys. It catches the client-side exposure that starts many of these incidents; the server-side response is still yours to run.

    What to take away

    • The Supabase JWT secret is the master signing key; a leak lets an attacker forge any token, including service_role.
    • Rotate the JWT secret immediately, which regenerates your anon and service_role keys and invalidates all sessions.
    • Expect rotation to log every user out and break clients until you update them with the new keys.
    • RLS does not protect you from a forged token, so rotation, not policy, is the fix for this leak.
    • Migrate to asymmetric signing keys to remove the shared secret, and scan each build with PTKD.com to prevent the next leak.
    • #supabase
    • #jwt secret
    • #auth
    • #key rotation
    • #backend security

    Frequently asked questions

    What is the Supabase JWT secret?
    In Supabase's legacy model, the JWT secret is the single symmetric key used to sign and verify every authentication token. Your anon and service_role keys are themselves long-lived JWTs signed by this secret, which makes it the master credential: anyone who holds it can produce tokens that Supabase will accept as genuine.
    What happens if my JWT secret is leaked?
    It is a total compromise. An attacker can forge a token for any user, reading and writing that user's data, or a token with the service_role claim that bypasses Row Level Security and grants full access to your database. It is the most severe Supabase leak, because it defeats the token trust your access control depends on.
    How do I rotate the Supabase JWT secret?
    In your Supabase project's API settings, roll the JWT secret, which generates a new secret and re-signs your keys. This is the only action that neutralizes the leak, so do it first. Then update every client and server with the regenerated anon and service_role keys, and remove the old secret from your code and Git history.
    Does rotating the JWT secret log everyone out?
    Yes. Rotating invalidates every token signed with the old secret, so all existing sessions become invalid and users must log in again. Cached and stored tokens stop working too. This disruption is the mechanism that locks out the attacker's forged tokens, so it is expected, not a side effect to avoid.
    Do the anon and service_role keys change when I rotate the JWT secret?
    Yes, in the legacy model. Because those keys are JWTs derived from the JWT secret, rotating it regenerates them. Every place that used the old anon or service_role key, your frontend, mobile app, Edge Functions, and CI, must be updated with the new key, or that part of your system will stop working.
    How do I prevent the JWT secret from leaking again?
    Keep it and the service_role key server-side only, never in client code or Git, and enable GitHub secret scanning and push protection. Scan your build before release with a tool like PTKD.com (https://ptkd.com) to catch embedded secrets, and migrate to Supabase's asymmetric signing keys so there is no shared symmetric secret to leak.

    Keep reading

    Scan your app in minutes

    Upload an APK, AAB, or IPA. PTKD returns an OWASP-aligned report with copy-paste fixes.

    Try PTKD free