FixVibe

// docs / baas security / supabase service role exposure

Service role key του Supabase εκτεθειμένο σε JavaScript: τι σημαίνει και πώς να το βρεις

Το service role key του Supabase είναι το master key προς τη βάση δεδομένων σου. Όποιος το κατέχει παρακάμπτει το Row-Level Security, μπορεί να διαβάσει κάθε στήλη κάθε πίνακα και μπορεί να γράψει ή να διαγράψει οτιδήποτε επιλέξει. Είναι σχεδιασμένο να ζει αποκλειστικά σε κώδικα από την πλευρά του server — ποτέ στον browser. Όταν ένα εργαλείο κωδικοποίησης με ΤΝ το αποστέλλει στο JavaScript bundle, η βάση δεδομένων σου είναι ουσιαστικά δημόσια. Αυτό το άρθρο εξηγεί τη μορφή JWT που ταυτοποιεί ένα διαρρεόμενο key, τα τρία μοτίβα εργαλείων ΤΝ που παράγουν τη διαρροή, τι να κάνεις στην πρώτη ώρα μετά την ανίχνευση και πώς να σαρώνεις για αυτό αυτόματα πριν το κάνουν οι χρήστες.

Τι είναι το service role key

Το Supabase εκδίδει δύο διακριτά keys για κάθε project: το anon key (που ονομάζεται επίσης publishable key σε νεότερα project) και το service_role key. Και τα δύο είναι JSON Web Tokens υπογεγραμμένα από το JWT secret του project σου. Η διαφορά είναι το claim role που είναι ψημένο στο payload JWT — anon για το δημόσιο key, service_role για το master key. Τα PostgREST, Supabase Storage και Supabase Auth μεταβαίνουν όλα σε λειτουργία παράκαμψης-όλων όταν δουν το claim service_role.

Αποκωδικοποίησε οποιοδήποτε Supabase key στο jwt.io και κοίταξε το payload. Η μορφή ενός JWT service-role είναι αλάνθαστη:

Αποκωδικοποιημένο payload ενός JWT service-role (εμφανίζεται ως μπλοκ με syntax highlighting παρακάτω).

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

Νεότερα Supabase project εκδίδουν keys σε στυλ secret με το πρόθεμα sb_secret_ αντί για JWT. Η συμπεριφορά είναι ταυτόσημη — οτιδήποτε φέρει sb_secret_ σε ένα δημόσιο bundle είναι εξίσου καταστροφικό.

Πώς τα εργαλεία κωδικοποίησης με ΤΝ διαρρέουν το service role key

Έχουμε δει τα ίδια τρία μοτίβα σε χιλιάδες vibe-coded εφαρμογές. Καθένα ξεκινά με έναν προγραμματιστή που ζητά βοήθεια από ένα εργαλείο ΤΝ και τελειώνει με το service key ενσωματωμένο σε ένα bundle.

Μοτίβο 1: Ενιαίο αρχείο .env με πρόθεμα NEXT_PUBLIC_

Ο προγραμματιστής ζητά από το εργαλείο ΤΝ να «ρυθμίσει το Supabase» και αποδέχεται ένα μοναδικό .env με αμφότερα τα keys. Το εργαλείο ΤΝ — εκπαιδευμένο σε corpus όπου οι περισσότερες μεταβλητές περιβάλλοντος εκτίθενται μέσω NEXT_PUBLIC_* — προσθέτει πρόθεμα NEXT_PUBLIC_ και στα δύο. Το Next.js ενσωματώνει inline οτιδήποτε ταιριάζει σε αυτό το πρόθεμα στο client bundle κατά τον χρόνο build. Κάνε deploy στο Vercel και το service key βρίσκεται στο main.[hash].js.

Μοτίβο 2: Λάθος key στην κλήση createClient

Ο προγραμματιστής επικολλά και τα δύο keys σε ένα αρχείο config.ts που δημιούργησε η ΤΝ, και η ΤΝ συμπληρώνει την κλήση createClient() στην πλευρά του browser με process.env.SUPABASE_SERVICE_ROLE_KEY κατά λάθος. Το build τραβά τη μεταβλητή μέσα και το JWT προσγειώνεται στο bundle.

Μοτίβο 3: Service-role key hardcoded σε scripts seed

Ο προγραμματιστής ζητά από το εργαλείο ΤΝ να γράψει ένα script που γεμίζει τη βάση δεδομένων. Η ΤΝ κωδικοποιεί το service-role key απευθείας μέσα στο αρχείο (αντί να το διαβάζει από το περιβάλλον), commitάρει το αρχείο στο αποθετήριο, και το δημόσιο repo GitHub ή η διαδρομή /scripts/seed.js της deployed εφαρμογής σερβίρει τώρα το key.

Πώς η σάρωση bundle του FixVibe ανιχνεύει τη διαρροή

Ο έλεγχος bundle-secrets του FixVibe κατεβάζει κάθε αρχείο JavaScript που αναφέρεται από την deployed εφαρμογή — entry chunks, lazy-loaded chunks, web workers, service workers — και τα τρέχει μέσα από έναν ανιχνευτή που αποκωδικοποιεί οτιδήποτε ταιριάζει στη μορφή JWT (eyJ[base64-header].eyJ[base64-payload].[signature]). Εάν το αποκωδικοποιημένο payload περιέχει "role": "service_role", η σάρωση το αναφέρει ως κρίσιμο εύρημα με τη διαδρομή του αρχείου και την ακριβή γραμμή όπου εμφανίζεται το key. Ο ίδιος έλεγχος ταιριάζει επίσης το νεότερο μοτίβο sb_secret_* ανά πρόθεμα.

Η σάρωση δεν πιστοποιείται ποτέ με το ανακαλυφθέν key. Ταυτοποιεί τη μορφή και αναφέρει τη διαρροή — η χρήση του key για να αποδείξει την εκμεταλλευσιμότητα θα ήταν μη εξουσιοδοτημένη πρόσβαση στη βάση δεδομένων σου. Η απόδειξη βρίσκεται στο ίδιο το payload JWT.

Ανιχνεύτηκε — τι να κάνεις στην πρώτη ώρα

Ένα διαρρεόμενο service role key είναι έκτακτη ανάγκη runtime. Υπέθεσε ότι το key έχει αρπαχθεί — οι επιτιθέμενοι παρακολουθούν δημόσια bundles σε πραγματικό χρόνο. Αντιμετώπισε τη βάση δεδομένων ως παραβιασμένη μέχρι να ανανεώσεις το key και να ελέγξεις την πρόσφατη δραστηριότητα.

  1. Ανανέωσε το key αμέσως. Στο Supabase Dashboard, πήγαινε σε Project Settings → API → Service role key → Reset. Το παλιό key ακυρώνεται μέσα σε δευτερόλεπτα. Κάθε κώδικας στην πλευρά του service που χρησιμοποιεί το key πρέπει να ενημερωθεί και να γίνει redeploy πριν προσγειωθεί η ανανέωση.
  2. Έλεγξε την πρόσφατη δραστηριότητα της βάσης δεδομένων. Άνοιξε Database → Logs στο dashboard. Φίλτραρε στις τελευταίες 7 ημέρες. Ψάξε για ασυνήθιστα queries SELECT * εναντίον πινάκων με PII, μεγάλες δηλώσεις UPDATE ή DELETE και αιτήματα από IPs εκτός της γνωστής υποδομής σου. Το Supabase καταγράφει τον header x-real-ip σε κάθε αίτημα.
  3. Έλεγξε τα αντικείμενα storage. Επισκέψου το Storage → Logs και ελέγξε τα πρόσφατα downloads αρχείων. Ένα διαρρεόμενο service-role key δίνει πρόσβαση παράκαμψης-όλων και σε ιδιωτικά buckets.
  4. Αφαίρεσε το key από τον έλεγχο πηγαίου κώδικα. Ακόμα και μετά την ανανέωση, το να αφήσεις το JWT στην ιστορία του git σημαίνει ότι μπορεί να ανακαλυφθεί στο δημόσιο repo. Χρησιμοποίησε git filter-repo ή BFG Repo-Cleaner για να το καθαρίσεις από την ιστορία και μετά κάνε force-push (προειδοποίησε πρώτα τους συνεργάτες).
  5. Επανάλαβε τη σάρωση μετά τη διόρθωση. Τρέξε μια φρέσκια σάρωση FixVibe εναντίον της redeployed εφαρμογής. Το εύρημα bundle-secrets θα πρέπει να εξαφανιστεί. Επιβεβαίωσε ότι δεν παραμένει κανένα JWT service_role και καμία συμβολοσειρά sb_secret_* σε κανένα chunk.

Πρόληψη της διαρροής εξαρχής

Η δομική λύση είναι πειθαρχία ονοματοδοσίας συν προφυλάξεις στο επίπεδο των εργαλείων:

  • Ποτέ μην βάλεις πρόθεμα στο service key με NEXT_PUBLIC_*, VITE_* ή οποιοδήποτε άλλο πρόθεμα ενσωμάτωσης bundle. Η σύμβαση ονοματοδοσίας είναι το όριο — κάθε framework το σέβεται.
  • Κράτησε το service key εντελώς εκτός του .env στη μηχανή του προγραμματιστή. Διάβασέ το από έναν διαχειριστή secrets (Doppler, Infisical, κρυπτογραφημένες env vars Vercel) κατά το 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 που σαρώνει την έξοδο build. Μετά το 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

Συχνές ερωτήσεις

Πόσο γρήγορα βρίσκουν οι επιτιθέμενοι πραγματικά διαρρεόμενα service-role keys του Supabase;

Οι scanners δημόσιων bundle σαρώνουν νέα deployments μέσα σε λεπτά. Ερευνητές έχουν τεκμηριώσει λειτουργικά exploits εναντίον νέων Supabase project σε λιγότερο από μία ώρα από το πρώτο deploy. Αντιμετώπισε κάθε έκθεση service-role ως παράθυρο 60 λεπτών, όχι 60 ημερών.

Αρκεί η ανανέωση του key ή πρέπει να υποθέσω εκπομπή δεδομένων;

Η ανανέωση ακυρώνει το διαρρεόμενο key αλλά δεν αναιρεί δεδομένα που έχουν ήδη τραβηχτεί. Εάν οι πίνακές σου περιέχουν PII, δεδομένα πληρωμών ή οποιαδήποτε ρυθμιζόμενα δεδομένα, μπορεί να έχεις υποχρέωση ειδοποίησης βάσει GDPR (72 ώρες), CCPA ή HIPAA. Έλεγξε τα logs και συμβουλεύσου νομικό σύμβουλο εάν ο έλεγχος δείχνει ύποπτη πρόσβαση.

Μπορεί το RLS να με προστατέψει εάν διαρρεύσει το service-role key;

Όχι. Το Row-Level Security παρακάμπτεται εντελώς από το claim service_role. Αυτό είναι σχεδιαστικά — το key υπάρχει ακριβώς για να επιτρέπει στον κώδικα backend να παρακάμπτει το RLS για διαχειριστικές λειτουργίες. Η μετριασμός είναι να βεβαιωθείς ότι το key δεν φτάνει ποτέ σε ένα context όπου ένας επιτιθέμενος μπορεί να το διαβάσει.

Ισχύει αυτό για το νέο μοντέλο publishable / secret key του Supabase (<code>sb_publishable_</code> / <code>sb_secret_</code>);

Ναι — ταυτόσημη κατηγορία κινδύνου. Το key sb_secret_* είναι το νέο φορμά secret-key που αντικαθιστά το JWT service-role για νεότερα project. Οτιδήποτε φέρει sb_secret_* σε ένα bundle είναι εξίσου καταστροφικό με ένα διαρρεόμενο JWT service-role. Ο ανιχνευτής bundle-secrets του FixVibe ταιριάζει και τις δύο μορφές.

Τι γίνεται με το anon / publishable key — είναι ασφαλές στο bundle;

Ναι, σχεδιαστικά. Το anon key προορίζεται να ζει στον browser και είναι αυτό που χρησιμοποιεί κάθε web client του Supabase. Η ασφάλειά του εξαρτάται εντελώς από το ότι το RLS είναι σωστά ρυθμισμένο σε κάθε δημόσιο πίνακα. Δες το άρθρο Supabase RLS scanner για το τι να ελέγξεις.

Επόμενα βήματα

Τρέξε μια σάρωση FixVibe εναντίον του URL παραγωγής σου — ο έλεγχος bundle-secrets είναι δωρεάν, χωρίς εγγραφή, και αναφέρει έκθεση service_role σε λιγότερο από ένα λεπτό. Συνδύασε το με το άρθρο Supabase RLS scanner για να επαληθεύσεις ότι το επίπεδο RLS κάνει τη δουλειά του, και με τη Λίστα ελέγχου ασφάλειας bucket storage του Supabase για να κλειδώσεις την πρόσβαση σε αρχεία. Για το υπόβαθρο γιατί τα εργαλεία ΤΝ παράγουν αυτή την κατηγορία διαρροής τόσο αξιόπιστα, διάβασε Γιατί τα εργαλεία κωδικοποίησης με ΤΝ αφήνουν κενά ασφαλείας.

// σάρωσε την επιφάνεια baas σου

Βρες τον ανοιχτό πίνακα πριν τον βρει κάποιος άλλος.

Δώσε ένα URL παραγωγής. Το FixVibe απαριθμεί τους παρόχους BaaS με τους οποίους μιλάει η εφαρμογή σου, εντοπίζει τα δημόσια endpoints τους και αναφέρει τι μπορεί να διαβάσει ή να γράψει ένας μη πιστοποιημένος client. Δωρεάν, χωρίς εγκατάσταση, χωρίς κάρτα.

  • Δωρεάν επίπεδο — 3 σαρώσεις τον μήνα, χωρίς κάρτα στην εγγραφή.
  • Παθητικό fingerprinting BaaS — δεν απαιτείται επαλήθευση τομέα.
  • Supabase, Firebase, Clerk, Auth0, Appwrite και άλλα.
  • Prompts διόρθωσης με ΤΝ σε κάθε εύρημα — επικόλλησε τα ξανά στο Cursor / Claude Code.
Εκτέλεσε δωρεάν σάρωση BaaS

δεν απαιτείται εγγραφή

Service role key του Supabase εκτεθειμένο σε JavaScript: τι σημαίνει και πώς να το βρεις — Docs · FixVibe