FixVibe

// docs / baas security / supabase service role exposure

Сервизният ключ на Supabase, разкрит в JavaScript: какво означава и как да го намерите

Сервизният ключ на Supabase е главният ключ за вашата база данни. Всеки, който го притежава, заобикаля Row-Level Security, може да чете всяка колона от всяка таблица и може да пише или изтрива каквото си поиска. Той е проектиран да живее изключително в сървърен код — никога в браузъра. Когато AI инструмент за кодиране го изпрати в JavaScript bundle-а, базата ви данни на практика е публична. Тази статия обяснява формата на JWT, която идентифицира изтекъл ключ, трите модела на AI инструменти, които произвеждат изтичането, какво да правите в първия час след откриване и как да сканирате за него автоматично, преди потребителите да го направят.

Какво представлява сервизният ключ

Supabase издава два различни ключа за всеки проект: anon ключ (наричан също публикуем ключ в по-нови проекти) и service_role ключ. И двата са JSON Web Token-и, подписани с JWT секрета на проекта ви. Разликата е claim-ът role, вграден в payload-а на JWT — anon за публичния ключ, service_role за главния ключ. PostgREST, Supabase Storage и Supabase Auth превключват в режим на пълно заобикаляне, когато видят claim service_role.

Декодирайте всеки Supabase ключ на jwt.io и погледнете payload-а. Формата на service-role JWT е неподражаема:

Декодиран payload на service-role JWT (показан като syntax-highlighted блок по-долу).

json
{
  "iss": "supabase",
  "ref": "[project-ref]",
  "role": "service_role",
  "iat": 1700000000,
  "exp": 2000000000
}

По-новите Supabase проекти издават ключове в стил secret с префикс sb_secret_ вместо JWT. Поведението е идентично — всичко, носещо sb_secret_ в публичен bundle, е също толкова катастрофално.

Как AI инструментите за кодиране изтичат сервизния ключ

Видяли сме същите три модела в хиляди vibe-кодирани приложения. Всеки започва с разработчик, който моли AI инструмент за помощ, и завършва със сервизния ключ, вграден в bundle.

Модел 1: Единичен .env файл с префикс NEXT_PUBLIC_

Разработчикът моли AI инструмента да "настрои Supabase" и приема единичен .env с двата ключа. AI инструментът — обучен върху корпус, в който повечето променливи на средата са изложени чрез NEXT_PUBLIC_* — поставя префикс NEXT_PUBLIC_ и на двата. Next.js вгражда всичко, съответстващо на този префикс, в клиентския bundle по време на build. Изпратете към Vercel и сервизният ключ е в main.[hash].js.

Модел 2: Грешен ключ в извикването на createClient

Разработчикът поставя двата ключа във файл config.ts, генериран от AI, и AI попълва извикването на createClient() на страната на браузъра с process.env.SUPABASE_SERVICE_ROLE_KEY по грешка. Build-ът внася променливата и JWT попада в bundle-а.

Модел 3: Service-role ключ, hardcoded в seed скриптове

Разработчикът моли AI инструмента да напише скрипт, който инициализира базата данни. AI hardcode-ва service-role ключа директно във файла (вместо да чете от средата), commit-ва файла в repo-то и публичното GitHub repo или маршрутът /scripts/seed.js на внедреното приложение вече сервира ключа.

Как сканирането на bundle на FixVibe открива изтичането

Проверката bundle-secrets на FixVibe изтегля всеки JavaScript файл, посочен от внедреното приложение — entry chunks, lazy-loaded chunks, web workers, service workers — и ги прокарва през детектор, който декодира всичко, съответстващо на формата на JWT (eyJ[base64-header].eyJ[base64-payload].[signature]). Ако декодираният payload съдържа "role": "service_role", сканирането докладва това като критично откритие с пътя до файла и точния ред, където се появява ключът. Същата проверка също съответства на по-новия модел sb_secret_* по префикс.

Сканирането никога не се автентикира с откритият ключ. Идентифицира формата и докладва изтичането — използването на ключа за доказване на експлоатируемостта би било неоторизиран достъп до вашата база данни. Доказателството е в самия JWT payload.

Открито — какво да направите в първия час

Изтекъл сервизен ключ е runtime спешен случай. Приемете, че ключът е изкопиран — нападателите наблюдават публични bundle-и в реално време. Третирайте базата данни като компрометирана, докато не ротирате ключа и не одитирате скорошната активност.

  1. Ротирайте ключа незабавно. В Supabase Dashboard отидете на Project Settings → API → Service role key → Reset. Старият ключ се анулира за секунди. Всеки сървърен код, използващ ключа, трябва да бъде актуализиран и преинсталиран преди ротацията да влезе в сила.
  2. Одитирайте скорошната активност в базата данни. Отворете Database → Logs в dashboard-а. Филтрирайте по последните 7 дни. Търсете необичайни SELECT * заявки срещу таблици с PII, големи UPDATE или DELETE изрази и заявки от IP адреси извън известната ви инфраструктура. Supabase логва заглавката x-real-ip на всяка заявка.
  3. Проверете обектите в хранилището. Посетете Storage → Logs и прегледайте скорошните изтегляния на файлове. Изтекъл service-role ключ дава пълен достъп и до частни bucket-и.
  4. Премахнете ключа от source control. Дори след ротация, оставянето на JWT в git историята означава, че е откриваем в публичното repo. Използвайте git filter-repo или BFG Repo-Cleaner, за да го изтриете от историята, след това force-push (предупредете сътрудниците първо).
  5. Сканирайте отново след поправката. Изпълнете ново FixVibe сканиране срещу преинсталираното приложение. Откритието bundle-secrets трябва да изчезне. Потвърдете, че няма останал service_role JWT и никакъв sb_secret_* низ в който и да е chunk.

Предотвратяване на изтичането на първо място

Структурната поправка е дисциплина в именуването плюс предпазни механизми на ниво инструменти:

  • Никога не поставяйте префикс NEXT_PUBLIC_*, VITE_* или какъвто и да е друг префикс за вграждане в bundle на сервизния ключ. Конвенцията за именуване е границата — всяка рамка я зачита.
  • Дръжте сервизния ключ напълно извън .env на машината на разработчика. Прочитайте го от мениджър на тайни (Doppler, Infisical, Vercel криптирани env vars) при deploy, никога не го commit-вайте локално.
  • <strong>Mark every Supabase client construction with explicit context.</strong> Files named <code>supabase/browser.ts</code> use the anon key; files named <code>supabase/server.ts</code> use the service-role key with <code>import 'server-only'</code> at the top. The <code>server-only</code> import causes a build error if a client component tries to consume the module.
  • <strong>Add a pre-commit hook that greps for JWT-shaped strings.</strong> <code>git diff --staged | grep -E 'eyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+'</code> catches both anon and service tokens before they leave your machine.
  • Добавете CI gate, който сканира build output-а. След next build правете grep на изхода .next/static/chunks/ за низа service_role. Прекратете build-а, ако нещо съвпадне.
bash
# Pre-commit hook: refuse any staged JWT-shaped string.
git diff --staged \
  | grep -E 'eyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+' \
  && echo "JWT detected in staged changes — refusing commit" \
  && exit 1

# CI gate: fail the build if "service_role" shipped to the static bundle.
grep -RE 'service_role|sb_secret_' .next/static/chunks/ \
  && echo "Service-role credential leaked into bundle" \
  && exit 1

Често задавани въпроси

Колко бързо нападателите наистина намират изтекли Supabase service-role ключове?

Скенери на публични bundle-и обхождат нови деплои в рамките на минути. Изследователи са документирали работещи експлойти срещу нови Supabase проекти за по-малко от час от първото деплойване. Третирайте всяко излагане на service-role като 60-минутен прозорец, а не 60-дневен.

Достатъчно ли е ротирането на ключа, или трябва да приема ексфилтрация на данни?

Ротацията анулира изтеклия ключ, но не отменя вече извлечените данни. Ако таблиците ви съдържат PII, платежни данни или каквито и да е регулирани данни, може да имате задължение за уведомяване по GDPR (72 часа), CCPA или HIPAA. Одитирайте логовете и се консултирайте с правен съветник, ако одитът покаже подозрителен достъп.

Може ли RLS да ме защити, ако сервизният ключ изтече?

Не. Сигурността на ниво ред е напълно заобиколена от claim service_role. Това е по дизайн — ключът съществува точно за да позволи на backend кода да пропуска RLS за admin операции. Смекчаването е да се уверите, че ключът никога не достига контекст, в който нападател може да го прочете.

Прилага ли се това към новия модел на Supabase с публикуем / секретен ключ (<code>sb_publishable_</code> / <code>sb_secret_</code>)?

Да — идентичен клас риск. Ключът sb_secret_* е новият формат на секретния ключ, който замества service-role JWT за по-нови проекти. Всичко, носещо sb_secret_* в bundle, е също толкова катастрофално, колкото изтекъл service-role JWT. Детекторът bundle-secrets на FixVibe съответства на двете форми.

Какво ще кажете за anon / публикуемия ключ — безопасен ли е в bundle-а?

Да, по дизайн. Anon ключът е предназначен да живее в браузъра и е това, което използва всеки Supabase web клиент. Безопасността му зависи изцяло от това дали RLS е правилно конфигуриран на всяка публична таблица. Вижте статията Сканер за Supabase RLS за това какво да проверите.

Следващи стъпки

Изпълнете FixVibe сканиране срещу production URL — проверката bundle-secrets е безплатна, без регистрация и докладва излагане на service_role за по-малко от минута. Сдвоете това със статията Сканер за Supabase RLS, за да проверите дали RLS слоят си върши работата, и Контролен списък за сигурност на storage bucket на Supabase, за да заключите достъпа до файлове. За фон относно това защо AI инструментите генерират този клас изтичане толкова надеждно, прочетете Защо AI инструментите за кодиране оставят пропуски в сигурността.

// сканирайте вашата baas повърхност

Намерете отворената таблица, преди някой друг да го направи.

Въведете production URL. FixVibe изброява доставчиците на BaaS, с които комуникира приложението ви, снема отпечатъци от публичните им крайни точки и докладва какво може да прочете или запише неавтентикиран клиент. Безплатно, без инсталация, без карта.

  • Безплатен план — 3 сканирания / месец, без карта при регистрация.
  • Пасивен отпечатък на BaaS — не се изисква проверка на домейн.
  • Supabase, Firebase, Clerk, Auth0, Appwrite и още.
  • AI промптове за поправка на всяко откритие — поставете обратно в Cursor / Claude Code.
Стартирайте безплатно BaaS сканиране

не се изисква регистрация

Сервизният ключ на Supabase, разкрит в JavaScript: какво означава и как да го намерите — Docs · FixVibe