---
title: "Supabase anon key vs service role key: co který otevře"
description: "Supabase anon key (publishable key) je v prohlížeči bezpečný jen za RLS; service role key (secret key) RLS obchází. Kam který patří, ověřeno na lokálním stacku."
url: "https://madsalt.tech/cs/blog/supabase-anon-key-vs-service-role-key/"
author: "Denys Zaichenko"
language: "cs"
published: 2026-10-25
---

# Supabase anon key vs service role key: co který otevře

TL;DR

Anon key, dnes nazývaný publishable key, je určen k tomu, aby byl veřejný: mapuje se na roli `anon` nebo `authenticated` a o tom, co uvidí, rozhodují vaše politiky RLS. Service role key, dnes secret key, se mapuje na `service_role`, která RLS obchází úplně. Na mé lokální testovací tabulce se zapnutým RLS a bez politiky dostal publishable key 0 řádků a secret key všechny 3. Publishable key patří do prohlížeče, secret key na server, a pokud kdy unikl, vyměňte ho.

Jsem Denys, full-stack a AI inženýr. Uniklý secret key je první věc, kterou hledám, když převezmu aplikaci na Supabase, protože s ním je každá další ochrana jen dekorace. Tento článek vysvětluje, co který klíč otevírá, s požadavky, které jsem pustil, abych to ověřil.

## Co je Supabase anon key?

Anon key identifikuje vaši aplikaci, ne vašeho uživatele. Nese ho každý požadavek z prohlížeče nebo mobilní aplikace, takže musí být veřejný: kdokoli si ho přečte ve zdroji stránky. Požadavek jen s tímto klíčem běží jako role Postgresu `anon`. Když se uživatel přihlásí přes Supabase Auth, stejný klíč cestuje s tokenem uživatele a požadavek běží jako `authenticated`. Vaše politiky RLS jsou psané pro tyto dvě role.

Supabase klíče přejmenovává. [Průvodce API klíči](https://supabase.com/docs/guides/api/api-keys) nazývá nové publishable (`sb_publishable_…`) a secret (`sb_secret_…`) a starší klíče `anon` a `service_role` založené na JWT označuje za zastaralé do konce roku 2026. Role za nimi zůstávají stejné.

| Klíč                           | Starší název        | Role v Postgresu                                 | Platí RLS?              | Kam patří                                          |
| ------------------------------ | ------------------- | ------------------------------------------------ | ----------------------- | -------------------------------------------------- |
| Publishable `sb_publishable_…` | klíč `anon`         | `anon`, nebo `authenticated` s tokenem uživatele | Ano                     | Prohlížeč, mobilní aplikace, cokoli, co doručujete |
| Secret `sb_secret_…`           | klíč `service_role` | `service_role`                                   | Ne, role má `BYPASSRLS` | Jen server, Edge Function, cron úloha              |

## Je bezpečné odhalit Supabase anon key?

Ano, pokud je chráněná každá tabulka, view a funkce, kam dosáhne. Samotný klíč nedává nic zvláštního; o všem rozhodují granty a politiky ve vašem schématu. Ověřil jsem to na lokálním Supabase (CLI 2.109.1, Postgres 17.6) s jednou tabulkou o třech fiktivních objednávkách:

![Jakou rolí v Postgresu se každý klíč stane. A zda váš požadavek vidí politiky RLS. Publishable key, odhlášený: Publishable key → role anon → Politiky RLS platí; Publishable key, přihlášený: Publishable key + token uživatele → role authenticated → Politiky RLS platí; Secret key: Secret key → role service_role → RLS přeskočeno.](https://madsalt.tech/charts/cs/supabase-anon-key-vs-service-role-key.svg)

*Obrázek 1. Z průvodce API klíči Supabase, ověřeno na lokálním stacku, 23. října 2026.*

| Stav tabulky                         | Publishable key                                                   | Secret key      |
| ------------------------------------ | ----------------------------------------------------------------- | --------------- |
| RLS vypnuté                          | Všechny 3 řádky a vložení vrátilo `201 Created`                   | Všechny 3 řádky |
| RLS zapnuté, bez politiky            | `[]`                                                              | Všechny 3 řádky |
| RLS zapnuté, politika `using (true)` | Všechny 3 řádky                                                   | Všechny 3 řádky |
| Bez grantu pro `anon`                | `42501 permission denied` s nápovědou jmenující chybějící `GRANT` | Všechny 3 řádky |

Publishable key je tedy stejně bezpečný jako vaše nejslabší tabulka. Tabulku bez RLS nebo s politikou, která povoluje každý řádek, přečte každý, kdo otevře DevTools. To je díra za [CVE-2025-48757](https://mattpalmer.io/posts/2025/05/statement-on-CVE-2025-48757/), kde 170 z 1 645 ukázkových aplikací z Lovable vydávalo data veřejnému klíči.

## Co je service role key a proč je nebezpečný?

Secret key je hlavní klíč. Běží jako `service_role`, která má atribut `BYPASSRLS`, takže se na něj žádná vaše politika nikdy nevztahuje. V posledním sloupci tabulky výše přečetl všechny tři řádky v každém stavu. Průvodce Supabase uvádí, kam patří: servery, které provádějí vlastní kontroly autorizace, Edge Functions, úlohy na pozadí a administrátorské nástroje. Dva detaily z průvodce záleží v praxi:

- Nový secret key odmítá požadavky z prohlížeče: Supabase porovná `User-Agent` a vrátí `401`. Starší JWT `service_role` takovou kontrolu nemá, takže uniklý starší klíč funguje odkudkoli. Můj lokální stack, který takovou kontrolu na bráně nemá, odpověděl skriptu se secret key všemi 3 řádky.
- Secret key obchází RLS jen tehdy, když požadavek nenese token uživatele. S tokenem přihlášeného uživatele požadavek běží pod politikami toho uživatele.

Edge Function, která používá secret key, musí sama zkontrolovat, kdo volá, a filtrovat podle vlastníka nebo firmy, protože pod ní to neudělá nic.

## Kde klíče najdete?

V Dashboardu otevřete dialog Connect svého projektu pro URL a publishable key, nebo Settings → API Keys pro všechny klíče včetně starších. Lokálně `supabase start` a `supabase status` vypíšou publishable key a secret key. Držte je v proměnných prostředí: v Next.js smí předponu `NEXT_PUBLIC_` nést jen publishable key, protože bundler doručí do prohlížeče cokoli s touto předponou.

## Co dělat, když service role key unikl?

Berte ho jako kompromitovaný: každý řádek v každé tabulce mohl číst i zapisovat ten, kdo ho našel.

1. Vytvořte nový secret key, přepněte na něj své servery a uniklý smažte. Pokud unikl starší klíč `service_role`, cesta ven je přechod na nové klíče: vytvořte publishable a secret key, přepněte aplikaci a pak starší klíče vypněte v Settings → API Keys, kde jinak zůstávají platné.
2. Prohledejte sestavený JavaScript a historii Gitu na `sb_secret_` a `service_role`. Sken 5 600 aplikací z vibe codingu od Escape našel [více než 400 odhalených tajemství](https://escape.tech/blog/methodology-how-we-discovered-vulnerabilities-apps-built-with-vibe-coding/), většinu ve frontendových bundlech.
3. Zkontrolujte, co se změnilo, zatímco byl venku: noví uživatelé, změny rolí, smazané řádky.

Bezplatná [Kontrola zabezpečení Supabase](https://madsalt.tech/cs/tools/supabase-security-check/) váš frontend nečte, ale čte stranu databáze téhož problému: role, které obcházejí RLS, tabulky s vypnutým RLS, politiky, které povolují každý řádek, a sloupce, které vypadají citlivě a anonymní návštěvníci je mohou číst. Jak ověřit, kam váš veřejný klíč v praxi dosáhne, je v článku [bezpečnostní rizika vibe codingu](https://madsalt.tech/cs/blog/vibe-coding-security-risks/) a celý seznam, který na aplikaci spouštím, je v mém [checklistu zabezpečení Lovable aplikace](https://madsalt.tech/cs/blog/lovable-app-security-checklist/).

Nejste si jistí, který klíč vaše aplikace doručuje?

Rád se podívám a porovnám zkušenosti. Bez nabídky.

[Ozvěte se](https://madsalt.tech/cs/#contact)
