[{"data":1,"prerenderedAt":810},["ShallowReactive",2],{"blog-it-supabase-security-checker":3,"blog-index-it":570},{"id":4,"title":5,"body":6,"category":522,"cover":523,"coverAlt":524,"description":525,"draft":526,"extension":527,"faq":528,"image":544,"keywords":545,"meta":558,"navigation":559,"ogTitle":560,"path":561,"published":562,"seo":563,"stem":564,"tldr":565,"updated":562,"__hash__":569},"blog_it\u002Fblog\u002Fsupabase-security-checker.md","Supabase security checker: i cinque controlli da fare da soli",{"type":7,"value":8,"toc":510},"minimark",[9,13,21,24,29,32,35,38,47,51,54,66,89,112,115,118,124,128,131,141,148,159,162,226,231,237,260,268,272,275,281,287,290,301,322,330,334,337,344,350,357,363,373,377,380,386,389,396,400,403,409,428,434,444,447,451,482,487,495,502],[10,11,12],"p",{},"Hai cercato un Supabase security checker e ne sono usciti nove. Uno vuole il tuo\nrepository. Uno vuole un'estensione del browser. Uno vuole accesso in lettura a\ntutto il tuo account Supabase, che assomiglia abbastanza alla cosa che ti\npreoccupava da farti esitare.",[10,14,15,16,20],{},"Ecco quello che nessuna di quelle pagine prodotto dice ad alta voce. ",[17,18,19],"strong",{},"I\ncontrolli sono cinque, e puoi farli tutti da solo",", senza account, senza\ninstallare niente e senza nessuna delle credenziali che sarebbe pericoloso\nconsegnare. Dieci minuti in un terminale coprono lo stesso terreno degli\nstrumenti.",[10,22,23],{},"I cinque qui sotto sono quelli che il nostro scanner esegue su un progetto\nSupabase, scritti come comandi. Se hai costruito con Lovable, Bolt, v0, Cursor,\nReplit, Windsurf o Base44 e la tua app salva qualcosa, il database dietro è\nmolto probabilmente Supabase, e queste sono le domande che gli farebbe uno\nsconosciuto.",[25,26,28],"h2",{"id":27},"che-cosa-controlla-davvero-un-supabase-security-checker","Che cosa controlla davvero un Supabase security checker?",[10,30,31],{},"La tua app pubblicata. Le impostazioni dentro il progetto sono il lavoro di un\naltro strumento, e Supabase quello strumento lo fornisce già.",[10,33,34],{},"Il Security Advisor nella tua dashboard legge il catalogo del progetto stesso:\nquali tabelle hanno la Row Level Security disattivata, quali funzioni hanno un\nsearch path troppo largo, quali estensioni stanno nello schema public. Legge\nquello che hai configurato.",[10,36,37],{},"Un checker legge quello che la tua app consegna a uno sconosciuto. Il bundle\nJavaScript che scaricano i visitatori, la risposta che una tabella dà a una\nrichiesta senza login, il contenuto di un bucket di storage, le intestazioni\ndelle tue pagine. Della tua configurazione non vede nulla, e non gli serve,\nperché sta guardando la conseguenza.",[10,39,40,41,46],{},"Le due metà si separano più spesso di quanto i nomi lascino intendere. Una\ntabella può passare l'Advisor con l'interruttore acceso e una policy scritta, e\nconsegnare comunque le sue righe a chiunque, perché la policy che è stata\nscritta fa entrare tutti. Vale una lettura a parte se è nuovo per te:\n",[42,43,45],"a",{"href":44},"\u002Fblog\u002Fsupabase-rls-on-but-table-still-public","l'interruttore non è la protezione",".",[25,48,50],{"id":49},"controllo-1-quale-chiave-supabase-consegna-la-tua-app","Controllo 1: quale chiave Supabase consegna la tua app?",[10,52,53],{},"Apri la tua app in un browser, premi F12 e guarda una sola richiesta.",[10,55,56,57,61,62,65],{},"Vai sulla scheda Rete, ricarica la pagina e scrivi ",[58,59,60],"code",{},"supabase"," nel filtro. La tua\napp farà almeno una richiesta a un indirizzo che finisce con ",[58,63,64],{},".supabase.co",".\nCliccaci sopra. Lì dentro ci sono le due cose che ti servono per il resto\ndell'articolo:",[67,68,69,80],"ul",{},[70,71,72,75,76,79],"li",{},[17,73,74],{},"L'indirizzo della richiesta"," inizia con l'URL del tuo progetto, qualcosa\ncome ",[58,77,78],{},"https:\u002F\u002Fabcdefghij.supabase.co",". I controlli 2 e 3 puntano lì.",[70,81,82,88],{},[17,83,84,85],{},"L'intestazione di richiesta ",[58,86,87],{},"apikey"," porta la chiave che la tua app\nconsegna a ogni visitatore.",[10,90,91,92,95,96,99,100,103,104,107,108,46],{},"Copia entrambe da qualche parte, poi leggi la chiave. Una che inizia con\n",[58,93,94],{},"sb_publishable_"," sta bene nella tua app e non c'è niente da sistemare. Una che\ninizia con ",[58,97,98],{},"sb_secret_"," non ci sta mai, e trovarla chiude la lista in anticipo:\nruotala oggi, prima di ogni altra cosa in questa pagina. I progetti più vecchi\nportano una coppia senza prefisso leggibile, ",[58,101,102],{},"anon"," e ",[58,105,106],{},"service_role",", e\ndistinguerle significa\n",[42,109,111],{"href":110},"\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend","leggere il ruolo dentro la chiave",[10,113,114],{},"Quest'ultimo caso è raro. Sulle 30.998 app dal vivo che abbiamo scansionato ad\nagosto 2026, una chiave segreta Supabase nel browser è comparsa tre volte.",[10,116,117],{},"Finché la scheda Rete è aperta, annota i nomi di tabella che vedi in quegli\nindirizzi. Il controllo successivo ne ha bisogno.",[119,120],"diagram",{"alt":121,"caption":122,"src":123},"Un pannello del bundle al centro che contiene una chiave e un indirizzo. Una freccia esce a sinistra verso una finestra del browser, contrassegnata con i numeri 4 e 5. Un'altra esce a destra verso un database e un bucket di storage etichettato .supabase.co, contrassegnata con 2 e 3.","Tutto quello che segue punta a uno di due indirizzi: quello della tua app e quello del tuo progetto. Il controllo 1 è ciò che ti procura il secondo.","\u002Fblog\u002Fsupabase-security-checker\u002Ftwo-addresses-1600x680.png",[25,125,127],{"id":126},"controllo-2-le-tue-tabelle-rispondono-a-uno-sconosciuto","Controllo 2: le tue tabelle rispondono a uno sconosciuto?",[10,129,130],{},"Chiedi al database quante righe darebbe a qualcuno senza login, e leggi il\nnumero nella risposta.",[132,133,139],"pre",{"className":134,"code":136,"language":137,"meta":138},[135],"language-bash","curl -s -i \\\n  -H \"apikey: LA_TUA_CHIAVE_PUBBLICABILE\" \\\n  -H \"Prefer: count=exact\" \\\n  -H \"Range: 0-0\" \\\n  \"https:\u002F\u002FIL_TUO_PROGETTO.supabase.co\u002Frest\u002Fv1\u002Fprofiles?select=count\" \\\n  | grep -i content-range\n","bash","",[58,140,136],{"__ignoreMap":138},[10,142,143,144,147],{},"Metti la chiave e l'indirizzo del progetto del controllo 1, e il tuo nome di\ntabella al posto di ",[58,145,146],{},"profiles",". curl è già installato su macOS, su Linux e su\nWindows recente, quindi non c'è nulla da scaricare prima.",[10,149,150,151,154,155,158],{},"Quella richiesta non preleva nessuna riga. ",[58,152,153],{},"select=count"," chiede un conteggio,\n",[58,156,157],{},"Range: 0-0"," non chiede nessuna delle righe, e l'intera risposta arriva in una\nsola intestazione. È la stessa richiesta che fa il nostro scanner, ed è per\nquesto che può girare sull'app dal vivo di qualcuno senza toccare i suoi dati.",[10,160,161],{},"Possono tornare quattro cose, e una sola è un riscontro:",[163,164,165,178],"table",{},[166,167,168],"thead",{},[169,170,171,175],"tr",{},[172,173,174],"th",{},"Cosa viene stampato",[172,176,177],{},"Che cosa significa",[179,180,181,192,202,216],"tbody",{},[169,182,183,189],{},[184,185,186],"td",{},[58,187,188],{},"content-range: *\u002F0",[184,190,191],{},"Niente di leggibile senza login. Quella tabella sta facendo il suo lavoro.",[169,193,194,199],{},[184,195,196],{},[58,197,198],{},"content-range: 0-0\u002F128",[184,200,201],{},"128 righe raggiungibili da chiunque abbia la chiave che viaggia nella tua pagina.",[169,203,204,213],{},[184,205,206,209,210],{},[58,207,208],{},"401"," o ",[58,211,212],{},"403",[184,214,215],{},"La chiave è stata respinta prima di arrivare alla tabella. Senza risposta, non pulito.",[169,217,218,223],{},[184,219,220],{},[58,221,222],{},"404",[184,224,225],{},"Nessuna tabella con quel nome. O hai tirato a indovinare, o si scrive altrimenti.",[119,227],{"alt":228,"caption":229,"src":230},"Due pannelli di risposta affiancati. Entrambi mostrano la stessa riga di stato 200. Quello a sinistra inquadra un'intestazione content-range che finisce con barra e zero, e prende un segno di spunta verde; quello a destra inquadra la stessa intestazione che finisce con 128, e prende una croce rossa.","Entrambe le richieste sono riuscite. Un'intestazione è tutta la differenza fra una tabella che fa il suo lavoro e una che consegna righe a chiunque le chieda.","\u002Fblog\u002Fsupabase-security-checker\u002Fthe-one-header-1600x700.png",[10,232,233,234,236],{},"Il rifiuto è la riga con cui stare attenti. Un ",[58,235,208],{}," dice che la richiesta si è\nfermata prima di arrivare alla tabella, il che non ti dice niente su quanto la\ntabella sia protetta, ed è la più facile delle quattro da arrotondare in un\nsegno di spunta.",[10,238,239,240,243,244,246,247,243,250,243,253,243,256,259],{},"Esegui il comando per ogni tabella che la tua app ha nominato al controllo 1,\npoi per quelle ordinarie che un'app di solito ha: ",[58,241,242],{},"users",", ",[58,245,146],{},",\n",[58,248,249],{},"customers",[58,251,252],{},"orders",[58,254,255],{},"messages",[58,257,258],{},"invoices",". In quelle sei stanno i dati di\naltre persone.",[10,261,262,263,267],{},"È il controllo che trova di più. Sulle 3.680 app con Supabase dove abbiamo\npotuto completarlo, 2.096 avevano almeno una tabella che rispondeva a una\nrichiesta senza login, e in 394 di esse la tabella aperta portava un nome di\npersone. La\n",[42,264,266],{"href":265},"\u002Fblog\u002Fcan-anyone-read-your-supabase-database","misurazione completa e di che cosa è una quota","\nè un articolo a parte.",[25,269,271],{"id":270},"controllo-3-un-bucket-di-storage-elenca-i-propri-file","Controllo 3: un bucket di storage elenca i propri file?",[10,273,274],{},"Chiedi a un bucket il suo contenuto e guarda se torna qualcosa.",[132,276,279],{"className":277,"code":278,"language":137,"meta":138},[135],"curl -s -X POST \\\n  -H \"apikey: LA_TUA_CHIAVE_PUBBLICABILE\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"prefix\":\"\",\"limit\":1}' \\\n  \"https:\u002F\u002FIL_TUO_PROGETTO.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Flist\u002Favatars\"\n",[58,280,278],{"__ignoreMap":138},[10,282,283,286],{},[17,284,285],{},"Manda il body."," Un POST a quell'indirizzo senza niente dentro risponde \"Body\ncannot be empty\" per ogni bucket di ogni progetto, comunque sia configurato. Lo\nsappiamo perché il nostro controllo sui bucket è uscito così e ha passato mesi a\nsegnalare allegramente che niente era elencabile.",[10,288,289],{},"Due forme di risposta:",[67,291,292,298],{},[70,293,294,297],{},[58,295,296],{},"[]"," significa che il bucket è chiuso, oppure che non esiste un bucket con\nquel nome. Da fuori non puoi sapere quale delle due, quindi un elenco vuoto\nnon prova nulla.",[70,299,300],{},"Un array con un file dentro significa che uno sconosciuto può chiedere al tuo\nprogetto un indice di quel bucket e ottenerlo.",[10,302,303,304,246,307,243,310,243,313,243,316,243,319,46],{},"Prova i nomi di bucket che ha usato la tua app, poi quelli comuni: ",[58,305,306],{},"avatars",[58,308,309],{},"public",[58,311,312],{},"uploads",[58,314,315],{},"files",[58,317,318],{},"images",[58,320,321],{},"documents",[10,323,324,325,329],{},"Elencabile e pubblico sono due impostazioni diverse tenute in due posti diversi,\ne ",[42,326,328],{"href":327},"\u002Fblog\u002Fsupabase-storage-bucket-public","la differenza decide quanto conta un bucket pubblico",".\nL'elenco è quello da chiudere, perché risparmia a uno sconosciuto la fatica di\nindovinare un nome di file. Sulle 27.269 app dove abbiamo potuto chiedere, 792\nhanno risposto con un elenco.",[25,331,333],{"id":332},"controllo-4-il-tuo-codice-sorgente-è-pubblicato-accanto-alla-tua-app","Controllo 4: il tuo codice sorgente è pubblicato accanto alla tua app?",[10,335,336],{},"Leggi l'ultima riga del tuo bundle JavaScript.",[10,338,339,340,343],{},"Torna nella scheda Rete del controllo 1, trova il file ",[58,341,342],{},".js"," più grande che la\ntua app ha caricato e copia il suo indirizzo. Poi:",[132,345,348],{"className":346,"code":347,"language":137,"meta":138},[135],"curl -s \"https:\u002F\u002Fla-tua-app.example\u002Fassets\u002Findex-abc123.js\" | tail -c 120\n",[58,349,347],{"__ignoreMap":138},[10,351,352,353,356],{},"Un'ultima riga che dice ",[58,354,355],{},"\u002F\u002F# sourceMappingURL=index-abc123.js.map"," significa che\nla tua build ha scritto una source map e ha detto ai browser dove si trova. Se\npoi l'abbia davvero pubblicata lo chiarisce una richiesta in più:",[132,358,361],{"className":359,"code":360,"language":137,"meta":138},[135],"curl -s -o \u002Fdev\u002Fnull -w \"%{http_code}\\n\" \\\n  \"https:\u002F\u002Fla-tua-app.example\u002Fassets\u002Findex-abc123.js.map\"\n",[58,362,360],{"__ignoreMap":138},[10,364,365,368,369,46],{},[58,366,367],{},"200"," significa che chiunque può scaricarla. Una source map riporta il\nJavaScript compresso ai tuoi file originali, con la tua struttura di cartelle, i\ntuoi commenti e la tua logica intatti. Quello che espone è il tuo codice, e\nqualunque chiave riveli stava già accanto nel bundle, che è di cosa parlava il\ncontrollo 1. 3.885 delle 30.987 app che abbiamo potuto esaminare pubblicano la\npropria, e su alcuni builder è un'impostazione predefinita della piattaforma e\nnon una decisione di qualcuno:\n",[42,370,372],{"href":371},"\u002Fblog\u002Fsource-maps-exposed-in-production","cosa mostra una source map pubblicata",[25,374,376],{"id":375},"controllo-5-cosa-manda-il-tuo-hosting-con-ogni-pagina","Controllo 5: cosa manda il tuo hosting con ogni pagina",[10,378,379],{},"Una richiesta all'indirizzo della tua app, leggendo cosa è tornato insieme.",[132,381,384],{"className":382,"code":383,"language":137,"meta":138},[135],"curl -s -i \"https:\u002F\u002Fla-tua-app.example\" | grep -i -E \\\n  \"content-security-policy|strict-transport-security|x-frame-options|x-content-type-options|referrer-policy\"\n",[58,385,383],{"__ignoreMap":138},[10,387,388],{},"Cinque intestazioni, e quelle che non vengono stampate sono quelle che ti\nmancano. Dicono a un browser di rifiutare la pagina se viene caricata dentro il\nsito di qualcun altro, di pretendere una connessione cifrata la volta\nsuccessiva, e di smettere di indovinare che tipo di file ha appena ricevuto.",[10,390,391,392,46],{},"Quasi tutte le app falliscono questo e quasi nessuno può farci qualcosa. A\n30.756 delle 30.981 app che abbiamo potuto esaminare ne mancava almeno una,\nperché le manda la piattaforma di hosting e chi ha l'app su un sottodominio di\nun builder non ha dove cambiarle. Lo contiamo e lo teniamo al massimo a medio:\n",[42,393,395],{"href":394},"\u002Fblog\u002Fmissing-security-headers","cosa prevedono e cosa no le intestazioni mancanti",[25,397,399],{"id":398},"come-leggere-quello-che-hai-trovato","Come leggere quello che hai trovato",[10,401,402],{},"Per gravità, che non è l'ordine in cui li hai eseguiti.",[10,404,405,408],{},[17,406,407],{},"Una chiave segreta nel bundle viene per prima."," Salta ogni regola che hai\nscritto su ogni tabella, quindi ruotala prima di guardare qualsiasi altra cosa\nqui.",[10,410,411,414,415,243,417,243,419,103,421,423,424,427],{},[17,412,413],{},"Una tabella piena di persone che risponde al controllo 2 viene dopo."," In\n",[58,416,242],{},[58,418,146],{},[58,420,252],{},[58,422,255],{}," stanno i dati di altra gente, e in\nquesto momento sono raggiungibili. Una tabella ",[58,425,426],{},"products"," che risponde allo\nstesso modo può essere del tutto corretta, e tu sei l'unica persona in grado di\ndistinguere le due.",[10,429,430,433],{},[17,431,432],{},"Poi un bucket elencabile, poi le map e le intestazioni",", che di solito sono i\nvalori predefiniti della tua piattaforma e non qualcosa che hai scelto.",[10,435,436,437,440,441,443],{},"Una cosa da portarsi via da tutti e cinque. ",[17,438,439],{},"Un controllo che non ha ottenuto\nrisposta non è passato."," Un ",[58,442,208],{},", una richiesta andata in timeout, una tabella\ndi cui hai sbagliato a indovinare il nome: ognuna di queste è una domanda ancora\naperta. Il nostro scanner scrive \"Non è stato possibile controllare\" su quelle\nrighe e lascia stare il voto, e farlo a mano significa tenere quella lista da\nsolo.",[10,445,446],{},"Tutto questo descrive inoltre l'app che era dal vivo nel momento in cui hai\nchiesto. La Row Level Security viene spenta per far caricare una pagina, un\nbucket viene aperto per un caricamento, una chiave viene incollata perché una\nfunzione esca stasera.",[25,448,450],{"id":449},"cosa-fare-questa-settimana","Cosa fare questa settimana",[452,453,454],"key-takeaways",{},[67,455,456,470,473,476,479],{},[70,457,458,459,243,461,243,463,243,465,103,467,469],{},"Esegui il controllo 2 su ogni tabella che la tua app nomina, poi su ",[58,460,242],{},[58,462,146],{},[58,464,249],{},[58,466,252],{},[58,468,255],{},". È lì che stanno i riscontri.",[70,471,472],{},"Se il controllo 1 ha tirato fuori una chiave segreta, ruotala per prima. Cancellarla dal codice lascia il vecchio valore funzionante per chi lo ha già.",[70,474,475],{},"Annota ogni sonda che ha ricevuto un rifiuto o nessuna risposta. Quelle restano senza risposta, e una domanda senza risposta non è un risultato pulito.",[70,477,478],{},"Lascia stare le tabelle che devono essere pubbliche. Un elenco di prodotti che risponde a uno sconosciuto è la tua app che funziona bene.",[70,480,481],{},"Riesegui tutti e cinque dopo un deploy e dopo che qualcuno ha cambiato una regola del database. Nessuno dei due si annuncia da solo.",[119,483],{"alt":484,"caption":485,"src":486},"Un referto di Reeve. Un grande riquadro ambra con la lettera C, sotto il numero 85 su 100, e nove righe a destra, ciascuna con l'icona di un controllo e una barra. Sette righe portano un segno di spunta verde, la riga dello storage porta una croce rossa, e la riga del database porta uno spazio tratteggiato vuoto al posto del segno.","Gli stessi cinque controlli, più altri quattro, restituiti come referto. Il punteggio è 85 e il voto è C, perché un riscontro alto limita la lettera qualunque cosa dica l'aritmetica. La riga tratteggiata è il database, che non ha mai risposto.","\u002Fblog\u002Fsupabase-security-checker\u002Fgrade-score-and-checks-1600x760.png",[10,488,489,490,494],{},"Il nostro ",[42,491,493],{"href":492},"\u002Fsecurity-scanner","scanner di sicurezza gratuito"," esegue questi\ncinque e altri quattro su qualsiasi URL dal vivo in una ventina di secondi,\nsenza account e senza credenziali da consegnare. Legge, non scrive mai, e dove\nnon ottiene risposta lo scrive sulla riga.",[10,496,497,498,46],{},"Tutti e cinque puoi farli oggi da solo. Quello che nessun passaggio singolo può\ndirti è se le risposte saranno le stesse il mese prossimo, ed è per questo che\nabbiamo costruito Reeve Care: riesegue questi controlli secondo un calendario,\nti scrive quando una risposta peggiora, e conserva backup verificati del tuo\ndatabase Supabase, più i file caricati dai tuoi utenti appena colleghi una\ncredenziale di storage. ",[42,499,501],{"href":500},"\u002F#pricing","Cosa sorveglia e quanto costa",[10,503,504,505,509],{},"Se un terminale non è dove vuoi stare, la guida in linguaggio semplice per le\n",[42,506,508],{"href":507},"\u002Fis-your-supabase-app-safe","app con Supabase"," spiega a cosa serve ognuna di\nqueste impostazioni e dove trovarla nella dashboard.",{"title":138,"searchDepth":511,"depth":511,"links":512},3,[513,515,516,517,518,519,520,521],{"id":27,"depth":514,"text":28},2,{"id":49,"depth":514,"text":50},{"id":126,"depth":514,"text":127},{"id":270,"depth":514,"text":271},{"id":332,"depth":514,"text":333},{"id":375,"depth":514,"text":376},{"id":398,"depth":514,"text":399},{"id":449,"depth":514,"text":450},"Basi della sicurezza","\u002Fblog\u002Fsupabase-security-checker\u002Fcover-1200x630.png","Una finestra di terminale vista di fronte, cinque comandi brevi sotto un prompt verde e un cursore che attende sulla sesta riga.","Un Supabase security checker legge la tua app pubblicata invece delle impostazioni del progetto. Ecco i cinque controlli che esegue e come farli da solo.",false,"md",[529,532,535,538,541],{"q":530,"a":531},"Il Security Advisor di Supabase trova tutto?","Trova tutto nella sua metà. L'Advisor legge la configurazione del tuo progetto e segnala le tabelle con la Row Level Security disattivata, le funzioni con un search path troppo largo e impostazioni simili che governi dalla dashboard. Quello che non può vedere è la tua app pubblicata: quale chiave è finita nel JavaScript che scaricano i tuoi visitatori, se una policy che hai scritto ferma davvero una richiesta anonima, o quali intestazioni manda il tuo hosting. Esegui l'Advisor e i cinque controlli di questo articolo, perché guardano cose diverse.",{"q":533,"a":534},"È sicuro eseguire questi controlli sul mio progetto?","Sì. Ogni comando qui legge e nessuno scrive. Il controllo sulle tabelle chiede al database un conteggio di righe e legge il numero da un'intestazione della risposta, quindi non viene mai prelevata una riga. Quello sui bucket chiede un elenco e si ferma lì, senza scaricare alcun file. Gli ultimi due sono una normale richiesta di pagina, del tipo che i tuoi visitatori fanno tutto il giorno. Eseguirli su un progetto che non è tuo è un'altra questione, e la risposta è chiedere prima a chi lo possiede.",{"q":536,"a":537},"La mia chiave anon è nel bundle. È un problema?","No. La chiave anon nei progetti più vecchi, e sb_publishable_ in quelli nuovi, è fatta per stare nel codice che scaricano i tuoi visitatori. Nomina il tuo progetto e da sola non concede nulla; è la Row Level Security a decidere quali righe torna indietro una richiesta. La chiave che non deve mai stare lì è quella segreta, chiamata service_role nei progetti vecchi e sb_secret_ in quelli nuovi, perché salta ogni regola che hai scritto.",{"q":539,"a":540},"Che cosa significa content-range: *\u002F0?","È il tuo database che dice che a questo chiamante darà zero righe da quella tabella. L'asterisco significa che la risposta non contiene alcuna riga, e il numero dopo la barra è il conteggio che il chiamante può vedere. Quindi *\u002F0 è la risposta che vuoi da una tabella con dati personali, e 0-0\u002F128 significa che 128 righe sono raggiungibili da chiunque abbia la chiave che viaggia nella tua app.",{"q":542,"a":543},"Mi serve la chiave service_role per provare tutto questo?","No, e un checker che te la chiede sta chiedendo la cosa sbagliata. Ogni controllo qui usa la chiave pubblicabile che è già dentro la tua app, perché è quella che avrebbe uno sconosciuto. Provare con una chiave segreta ti dice cosa raggiunge un amministratore, cosa che non è mai stata in dubbio. Non incollare una chiave service_role o sb_secret_ in nessuno scanner, incluso il nostro: niente di quello che facciamo ne ha bisogno.","\u002Fblog\u002Fsupabase-security-checker\u002Fcard-800x500.png",[546,547,548,549,550,551,552,553,554,555,556,557],"supabase security checker","controllare sicurezza supabase","supabase rls checker","scanner sicurezza supabase","audit sicurezza supabase","testare row level security supabase","supabase security advisor","tabelle esposte supabase","il mio database supabase è pubblico","chiave anon supabase esposta","controllare bucket pubblico supabase","scanner fughe di dati supabase",{},true,"Supabase security checker: i cinque controlli","\u002Fblog\u002Fsupabase-security-checker","2026-09-06",{"title":5,"description":525},"blog\u002Fsupabase-security-checker",[566,567,568],"Un Supabase security checker legge la tua app dal vivo come la legge uno sconosciuto: il bundle che consegna, le risposte delle tue tabelle, i tuoi bucket di storage, le tue intestazioni.","Il Security Advisor di Supabase legge l'altra metà, cioè la configurazione del tuo progetto. Nessuno dei due vede quello che vede l'altro.","Cinque controlli coprono la vista da fuori. Ognuno si lancia da un terminale, non chiede alcun account e insieme prendono una decina di minuti.","JnwcA_F4_6BempEUPobKbLLzV-1nDQYar8iXuCiQPIk",[571,578,584,590,596,602,608,614,620,626,632,638,644,650,656,662,668,674,675,681,686,692,698,704,710,716,722,728,734,740,746,752,757,763,769,774,778,784,790,795,800,806],{"path":572,"title":573,"description":574,"published":575,"category":576,"image":577,"draft":526},"\u002Fblog\u002Fsupabase-backup-auth-users","Perché nel tuo dump Supabase non ci sono utenti","Lancia supabase db dump da solo e ottieni la forma del tuo database e nessuna delle sue righe, senza lo schema auth in cui vivono i tuoi utenti.","2026-09-23","Backups","\u002Fblog\u002Fsupabase-backup-auth-users\u002Fcard-800x500.png",{"path":579,"title":580,"description":581,"published":582,"category":522,"image":583,"draft":526},"\u002Fblog\u002Fdomain-and-certificate-expiry","Dominio scaduto, sito offline: cosa succede adesso","Il tuo dominio è scaduto e il sito è offline. Il conto alla rovescia che parte, perché il certificato è il problema minore, e come controllarli entrambi.","2026-09-22","\u002Fblog\u002Fdomain-and-certificate-expiry\u002Fcard-800x500.png",{"path":585,"title":586,"description":587,"published":588,"category":522,"image":589,"draft":526},"\u002Fblog\u002Fis-lovable-safe","Lovable è sicuro? Cosa abbiamo trovato in 18.554 app Lovable","Lovable è sicuro? Abbiamo passato 18.554 app Lovable online per nove controlli. La piattaforma è risultata la più pulita di cinque. I rilievi stavano nelle app.","2026-09-21","\u002Fblog\u002Fis-lovable-safe\u002Fcard-800x500.png",{"path":591,"title":592,"description":593,"published":594,"category":522,"image":595,"draft":526},"\u002Fblog\u002Fvibe-coded-app-security-checklist","La checklist di sicurezza del vibe coding, in nove controlli","Una checklist di sicurezza del vibe coding in nove voci, ognuna verificabile dall’esterno sulla tua app dal vivo, e ognuna con un test di una riga.","2026-09-20","\u002Fblog\u002Fvibe-coded-app-security-checklist\u002Fcard-800x500.png",{"path":597,"title":598,"description":599,"published":600,"category":522,"image":601,"draft":526},"\u002Fblog\u002Fstripe-secret-key-in-frontend","Una chiave segreta Stripe nel frontend può muovere denaro","Una chiave segreta Stripe esposta nel tuo frontend può rimborsare, addebitare e leggere ogni scheda cliente che hai. La tua chiave pk_live_ ci sta bene.","2026-09-19","\u002Fblog\u002Fstripe-secret-key-in-frontend\u002Fcard-800x500.png",{"path":603,"title":604,"description":605,"published":606,"category":522,"image":607,"draft":526},"\u002Fblog\u002Fvite-and-next-public-env-vars","Variabili d’ambiente Vite esposte: il prefisso vuol dire pubblica","Variabili d’ambiente Vite esposte: la tua app ha fatto ciò che il prefisso chiedeva. VITE_ e NEXT_PUBLIC_ vogliono dire pubblica, e l’IA non sapeva il costo.","2026-09-18","\u002Fblog\u002Fvite-and-next-public-env-vars\u002Fcard-800x500.png",{"path":609,"title":610,"description":611,"published":612,"category":522,"image":613,"draft":526},"\u002Fblog\u002Fbase44-source-maps","Sicurezza Base44: cosa segnala uno scan e cosa tocca a te sistemare","Sicurezza Base44 su 5.438 app scansionate: tre segnalazioni su quasi tutte sono della piattaforma, la source map è il badge di Base44, la tua parte è corta.","2026-09-17","\u002Fblog\u002Fbase44-source-maps\u002Fcard-800x500.png",{"path":615,"title":616,"description":617,"published":618,"category":522,"image":619,"draft":526},"\u002Fblog\u002Fis-cursor-ai-safe","Cursor AI è sicuro? L’editor, il codice e l’app che hai pubblicato","Cursor AI è sicuro? Tre domande in una ricerca: cosa tiene Cursor, cosa sbaglia il codice che scrive, e se l’app che hai pubblicato è aperta.","2026-09-16","\u002Fblog\u002Fis-cursor-ai-safe\u002Fcard-800x500.png",{"path":621,"title":622,"description":623,"published":624,"category":522,"image":625,"draft":526},"\u002Fblog\u002Fis-replit-safe","Replit è sicuro? Cosa abbiamo trovato in 3.042 app Replit online","Replit è sicuro? Abbiamo passato 3.042 app Replit online per nove controlli esterni. I rilievi stavano nell’app pubblicata, non nell’host.","2026-09-15","\u002Fblog\u002Fis-replit-safe\u002Fcard-800x500.png",{"path":627,"title":628,"description":629,"published":630,"category":576,"image":631,"draft":526},"\u002Fblog\u002Fsupabase-storage-backup","Supabase storage backup: la copia del database non ha nessun file","Un Supabase storage backup è un lavoro a parte. I backup del database tengono la lista dei tuoi file e nessuno dei file, quindi ogni upload resta rotto.","2026-09-14","\u002Fblog\u002Fsupabase-storage-backup\u002Fcard-800x500.png",{"path":633,"title":634,"description":635,"published":636,"category":576,"image":637,"draft":526},"\u002Fblog\u002Fsupabase-point-in-time-recovery","Point-in-time recovery di Supabase: prezzo e limiti","Il point-in-time recovery di Supabase riavvolge il database a qualsiasi secondo della settimana scorsa. $100 al mese oltre a Pro, e copre solo il database.","2026-09-13","\u002Fblog\u002Fsupabase-point-in-time-recovery\u002Fcard-800x500.png",{"path":639,"title":640,"description":641,"published":642,"category":576,"image":643,"draft":526},"\u002Fblog\u002Fsupabase-project-paused-recover","Progetto Supabase in pausa? I tuoi dati sono ancora lì","Supabase ha messo in pausa il tuo progetto dopo una settimana senza attività. Non è cancellato niente, Ripristina è accanto al nome e hai un anno di tempo.","2026-09-12","\u002Fblog\u002Fsupabase-project-paused-recover\u002Fcard-800x500.png",{"path":645,"title":646,"description":647,"published":648,"category":522,"image":649,"draft":526},"\u002Fblog\u002Fsafest-ai-app-builder","Qual è il builder di app con IA più sicuro? 30.998 app testate","Qual è il builder di app con IA più sicuro? Abbiamo scansionato 30.998 app online di Lovable, Base44, Replit, v0 e Bolt. Non è il builder a decidere il voto.","2026-09-11","\u002Fblog\u002Fsafest-ai-app-builder\u002Fcard-800x500.png",{"path":651,"title":652,"description":653,"published":654,"category":522,"image":655,"draft":526},"\u002Fblog\u002Fenable-rls-on-every-supabase-table","Attiva Row Level Security su ogni tabella Supabase, poi verificalo","Attivare Row Level Security su Supabase senza una policy chiude del tutto la tabella. Una policy senza il flag non fa nulla. Ecco lo SQL, e la verifica.","2026-09-10","\u002Fblog\u002Fenable-rls-on-every-supabase-table\u002Fcard-800x500.png",{"path":657,"title":658,"description":659,"published":660,"category":522,"image":661,"draft":526},"\u002Fblog\u002Fsupabase-rls-disabled-in-public","Supabase \"RLS disabled in public\": cosa non vede l'avviso","Supabase segnala \"RLS disabled in public\" come errore. Non dice nulla della policy di lettura che lascia la tua tabella altrettanto aperta.","2026-09-09","\u002Fblog\u002Fsupabase-rls-disabled-in-public\u002Fcard-800x500.png",{"path":663,"title":664,"description":665,"published":666,"category":522,"image":667,"draft":526},"\u002Fblog\u002Frotate-supabase-service-role-key","Come ruotare una chiave service_role Supabase trapelata","Supabase dice di chiudere prima la falla. Altre guide dicono di ruotare subito. Quale sia giusto dipende da dove è finita la tua chiave service_role.","2026-09-08","\u002Fblog\u002Frotate-supabase-service-role-key\u002Fcard-800x500.png",{"path":669,"title":670,"description":671,"published":672,"category":522,"image":673,"draft":526},"\u002Fblog\u002Fvibe-coding-security-scanners-compared","Scanner di sicurezza per vibe coding a confronto, il nostro incluso","Il miglior scanner di sicurezza per vibe coding dipende da tre domande che nessun elenco di funzioni affronta. Dieci strumenti a confronto, con i prezzi.","2026-09-07","\u002Fblog\u002Fvibe-coding-security-scanners-compared\u002Fcard-800x500.png",{"path":561,"title":5,"description":525,"published":562,"category":522,"image":544,"draft":526},{"path":676,"title":677,"description":678,"published":679,"category":522,"image":680,"draft":526},"\u002Fblog\u002Fvibe-coding-security-scanner","Scanner di sicurezza per vibe coding: cosa si perde","Uno scanner di sicurezza per vibe coding legge la tua app dal vivo, da fuori. Cosa copre, le quattro cose che non può vedere e come leggere il risultato.","2026-09-05","\u002Fblog\u002Fvibe-coding-security-scanner\u002Fcard-800x500.png",{"path":394,"title":682,"description":683,"published":684,"category":522,"image":685,"draft":526},"Intestazioni di sicurezza mancanti: quando contano","Le intestazioni di sicurezza mancanti sono il rilievo che il nostro scanner stampa più spesso. Da cosa proteggono e quando sono la riga meno urgente.","2026-09-04","\u002Fblog\u002Fmissing-security-headers\u002Fcard-800x500.png",{"path":687,"title":688,"description":689,"published":690,"category":522,"image":691,"draft":526},"\u002Fblog\u002Fopenai-api-key-exposed-in-frontend","La tua chiave API OpenAI è esposta nel frontend. Ruotala.","Una chiave API OpenAI esposta nel frontend non si può legare a nessun dominio. Ruotala oggi, sposta la chiamata sul tuo server e metti un tetto di spesa.","2026-09-03","\u002Fblog\u002Fopenai-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":693,"title":694,"description":695,"published":696,"category":522,"image":697,"draft":526},"\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps","Chiave API esposta nel frontend: cosa spediscono 30.998 app","Una chiave API esposta nel tuo frontend è quasi sempre una chiave di Google Maps. Abbiamo scansionato 30.998 app vibe-coded e contato cosa esce davvero.","2026-09-02","\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps\u002Fcard-800x500.png",{"path":699,"title":700,"description":701,"published":702,"category":576,"image":703,"draft":526},"\u002Fblog\u002Fsupabase-backup-tools-compared","Strumenti di backup Supabase a confronto, il nostro incluso","Quattro tipi di strumento di backup Supabase, cosa copia davvero ognuno, e il caso in cui una GitHub Action gratuita batte il pagare chiunque, noi inclusi.","2026-09-01","\u002Fblog\u002Fsupabase-backup-tools-compared\u002Fcard-800x500.png",{"path":705,"title":706,"description":707,"published":708,"category":522,"image":709,"draft":526},"\u002Fblog\u002Freplit-secrets-explained","Come usare i secret su Replit, e cosa viene comunque pubblicato","Come usare i secret su Replit: aggiungerne uno, rileggerlo e risolvere le due cause dell'undefined. E le chiavi che lo strumento non riesce a proteggere.","2026-08-31","\u002Fblog\u002Freplit-secrets-explained\u002Fcard-800x500.png",{"path":711,"title":712,"description":713,"published":714,"category":576,"image":715,"draft":526},"\u002Fblog\u002Fback-up-supabase-free-tier","Backup del piano gratuito Supabase: farne uno senza terminale","Sul piano gratuito Supabase non esistono backup: la copia la fai tu. Come farne uno dalla dashboard e che cosa si lascia dietro la via del CSV.","2026-08-30","\u002Fblog\u002Fback-up-supabase-free-tier\u002Fcard-800x500.png",{"path":717,"title":718,"description":719,"published":720,"category":522,"image":721,"draft":526},"\u002Fblog\u002Fis-supabase-secure","Supabase è sicuro? Sì. Il tuo progetto è un'altra questione","Supabase è sicuro? La piattaforma è certificata, cifrata e sottoposta a pentest. La loro documentazione dice dove finisce quello e iniziano le tue impostazioni.","2026-08-29","\u002Fblog\u002Fis-supabase-secure\u002Fcard-800x500.png",{"path":723,"title":724,"description":725,"published":726,"category":522,"image":727,"draft":526},"\u002Fblog\u002Fwhere-to-find-supabase-api-keys","Dove trovare le chiavi API di Supabase: anon, service_role e URL","L'URL del progetto, la chiave anon e la chiave service_role stanno su una pagina della dashboard. Ecco dove si trova e quale dei quattro va nella tua app.","2026-08-28","\u002Fblog\u002Fwhere-to-find-supabase-api-keys\u002Fcard-800x500.png",{"path":729,"title":730,"description":731,"published":732,"category":522,"image":733,"draft":526},"\u002Fblog\u002Fnew-row-violates-row-level-security-policy","New row violates row-level security policy su Supabase. E adesso?","\"New row violates row-level security policy\" significa che Supabase ha rifiutato una scrittura. La soluzione veloce riapre la tabella a chiunque.","2026-08-27","\u002Fblog\u002Fnew-row-violates-row-level-security-policy\u002Fcard-800x500.png",{"path":735,"title":736,"description":737,"published":738,"category":522,"image":739,"draft":526},"\u002Fblog\u002Fcors-wildcard-security-risk","Un wildcard CORS è un rischio di sicurezza? Quasi mai.","Un wildcard CORS è un rischio di sicurezza? Di solito è il valore predefinito del tuo builder e non consegna nulla che il tuo server non desse già a chiunque.","2026-08-26","\u002Fblog\u002Fcors-wildcard-security-risk\u002Fcard-800x500.png",{"path":741,"title":742,"description":743,"published":744,"category":576,"image":745,"draft":526},"\u002Fblog\u002Fsupabase-branching-is-not-a-backup","Il branching di Supabase non è un backup. Va solo in avanti.","Perché il branching di Supabase non è un backup: un branch parte senza i tuoi dati e un merge sposta solo lo schema. A cosa serve davvero e cosa usare invece.","2026-08-25","\u002Fblog\u002Fsupabase-branching-is-not-a-backup\u002Fcard-800x500.png",{"path":747,"title":748,"description":749,"published":750,"category":576,"image":751,"draft":526},"\u002Fblog\u002Fhow-to-restore-a-supabase-backup","Come ripristinare un backup Supabase, e cosa si rompe dopo","Come ripristinare un backup Supabase dalla dashboard o da un file di dump, che cosa sostituisce il ripristino e perché la tua app può restare rotta lo stesso.","2026-08-24","\u002Fblog\u002Fhow-to-restore-a-supabase-backup\u002Fcard-800x500.png",{"path":327,"title":753,"description":754,"published":755,"category":522,"image":756,"draft":526},"Il tuo bucket Supabase Storage è pubblico. È un problema?","Un bucket Supabase Storage pubblico significa che chi ha l'URL di un file può aprirlo. Non significa che qualcuno possa elencare quello che c'è dentro.","2026-08-23","\u002Fblog\u002Fsupabase-storage-bucket-public\u002Fcard-800x500.png",{"path":758,"title":759,"description":760,"published":761,"category":522,"image":762,"draft":526},"\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend","Una chiave API Google nel frontend è un problema?","Una chiave API Google esposta nel frontend è la chiave che il nostro scanner trova più spesso, e di solito va bene così. Lo decide una impostazione gratuita.","2026-08-22","\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":764,"title":765,"description":766,"published":767,"category":576,"image":768,"draft":526},"\u002Fblog\u002Fai-agent-deleted-my-database","Un agente IA ha cancellato i miei dati Supabase. Cosa recupero?","Un agente IA ha cancellato dati dal tuo database. Quello che puoi recuperare era già deciso prima che partisse, e i prossimi minuti decidono il resto.","2026-08-21","\u002Fblog\u002Fai-agent-deleted-my-database\u002Fcard-800x500.png",{"path":265,"title":770,"description":771,"published":772,"category":522,"image":773,"draft":526},"Chiunque può leggere il tuo database Supabase? 3.680 app testate","Chiunque può leggere il tuo database Supabase senza fare login? Abbiamo scansionato 30.998 app online create con i builder IA e misurato quante rispondono sì.","2026-08-18","\u002Fblog\u002Fcan-anyone-read-your-supabase-database\u002Fcard-800x500.png",{"path":371,"title":775,"description":776,"published":772,"category":522,"image":777,"draft":526},"Source map esposte: la tua app sta pubblicando il codice originale","Una source map esposta permette a chiunque di leggere il codice originale della tua app, commenti inclusi. Il controllo da 30 secondi e cosa conta davvero.","\u002Fblog\u002Fsource-maps-exposed-in-production\u002Fcard-800x500.png",{"path":779,"title":780,"description":781,"published":782,"category":522,"image":783,"draft":526},"\u002Fblog\u002Fsupabase-new-api-keys","Le nuove chiavi API di Supabase: quale va nella tua app?","Supabase ha sostituito anon e service_role con chiavi pubblicabili e segrete. Quale sta bene nella tua app, e quale non deve starci mai?","2026-08-12","\u002Fblog\u002Fsupabase-new-api-keys\u002Fcard-800x500.png",{"path":785,"title":786,"description":787,"published":788,"category":576,"image":789,"draft":526},"\u002Fblog\u002Fdoes-supabase-back-up-my-database","Supabase fa il backup del mio database? Dipende dal tuo piano.","Supabase fa il backup del tuo database? Ogni giorno sui piani a pagamento, mai su quello gratuito. Come capire cosa hai e cosa quella copia non copre.","2026-08-11","\u002Fblog\u002Fdoes-supabase-back-up-my-database\u002Fcard-800x500.png",{"path":44,"title":791,"description":792,"published":793,"category":522,"image":794,"draft":526},"Supabase Row Level Security è attivo. La tabella resta pubblica.","Attivare Supabase Row Level Security non protegge una tabella. Lo fanno le policy, e quella che ha rimesso in piedi la tua app può far entrare chiunque.","2026-08-10","\u002Fblog\u002Fsupabase-rls-on-but-table-still-public\u002Fcard-800x500.png",{"path":796,"title":797,"description":798,"published":793,"category":576,"image":799,"draft":526},"\u002Fblog\u002Fversion-history-is-not-a-backup","La cronologia delle versioni non è un backup dei tuoi dati.","Lovable e Bolt tengono una cronologia delle versioni del codice. Il tuo database è un servizio a parte, e tornare indietro non ti restituisce i dati.","\u002Fblog\u002Fversion-history-is-not-a-backup\u002Fcard-800x500.png",{"path":801,"title":802,"description":803,"published":804,"category":576,"image":805,"draft":526},"\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database","Tre modi per fare il backup di un database Supabase, e cosa manca","Il pannello, pg_dump e un servizio gestito. Che cosa salva davvero ciascuno, cosa lascia fuori senza dirlo e quale sopravvive alla perdita dell'account.","2026-08-09","\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database\u002Fcard-800x500.png",{"path":110,"title":807,"description":808,"published":804,"category":522,"image":809,"draft":526},"Quali chiavi API sono sicure nel browser e quali no","La tua chiave anon di Supabase è fatta per essere pubblica. La chiave service_role no, e ignora ogni regola che imposti. Come distinguerle.","\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend\u002Fcard-800x500.png",1790150956074]