"Sicurezza in Lovable" sono due cose che conviene tenere separate. La prima è il progetto Lovable in sé: cosa incolli nella chat, dove conserva i segreti, chi può vedere il tuo progetto e dove finisce pubblicata l'app. La seconda è il codice che Lovable genera, una SPA in React su Supabase che porta sempre gli stessi cinque o sei difetti. Questa guida copre entrambe, con un blocco di istruzioni per la sezione Knowledge del tuo progetto, un prompt di revisione prima di pubblicare e il modo di verificare il risultato dall'esterno.
Parte 1: proteggere il tuo progetto Lovable
Quello che incolli nella chat resta lì
La chat del progetto è la storia della tua app: ogni prompt, ogni chiave che hai incollato "per farlo funzionare" e ogni risposta. Se una chiave segreta entra dalla chat, il modello tende a scriverla direttamente nel codice del frontend, e da lì viaggia nel bundle verso tutti i visitatori. La regola è semplice: le chiavi non entrano mai dalla chat. Quando Lovable ti chiede un segreto per collegare un servizio, usa il riquadro dei segreti che ti offre; così lo salva come variabile delle Edge Functions di Supabase, lato server, e il codice generato lo legge con Deno.env.get.
Segreti: server sì, browser no
Lovable sa fare due cose con un'integrazione: chiamarla dal browser o da una Edge Function. La prima è corretta per le chiavi pubbliche (la anon di Supabase, la publishable di Stripe, l'ID di un progetto). La seconda è l'unica opzione per le chiavi segrete (OpenAI, Resend, la secret di Stripe, la service_role). Se chiedi una funzionalità e il risultato la chiama da un componente React con la chiave dentro, chiedigli esplicitamente di spostarla in una Edge Function. Di più in segreti che la tua app fa trapelare nel browser.
Visibilità del progetto e del codice
Un progetto pubblico su Lovable espone il codice e la cronologia dei prompt a chiunque abbia il link, inclusa qualsiasi chiave che hai incollato una volta. Controlla la visibilità nelle impostazioni del progetto e, se hai attivato la sincronizzazione con GitHub, che il repository sia privato. Se una chiave è stata in un progetto o repository pubblico, considerala compromessa e ruotala.
Dove vive l'app pubblicata
Lovable pubblica su un sottodominio .lovable.app o sul tuo dominio. Quell'hosting non ti permette di configurare header di sicurezza né redirect personalizzati. Per molte app basta; se ti servono Content-Security-Policy, HSTS o regole di cache, esporta su GitHub e fai il deploy su Vercel o Netlify con il loro file di configurazione. Tieni presente anche che l'URL di anteprima di ogni versione è raggiungibile da chiunque lo abbia.
Supabase è tuo, non di Lovable
Quando colleghi Supabase (o usi il backend gestito di Lovable, che sotto è Supabase), Lovable crea tabelle, policy e funzioni per te. Ma RLS, bucket e impostazioni di Auth restano responsabilità tua. Lovable ha aggiunto una revisione di sicurezza prima della pubblicazione dopo la CVE-2025-48757; prendila come un primo filtro, non come garanzia, e ripassa la guida alla sicurezza per Supabase, che ha tre query SQL per fare l'audit del progetto in un minuto.
Parte 2: i difetti che Lovable mette nel tuo codice
- Tabelle senza RLS o con policy
using (true). L'origine della CVE e il difetto più grave. Chiunque abbia la chiave anon legge e scrive i tuoi dati. - Controlli dei permessi solo nel frontend. Una rotta
/adminche si limita a nascondere il pulsante se l'utente non è amministratore. Il server (RLS o la Edge Function) deve controllarlo anche lui, perché l'API si può chiamare senza passare dall'interfaccia. - Edge Functions senza autenticazione né limiti. Il template risponde a chiunque, con
Access-Control-Allow-Origin: *, e se chiama OpenAI o invia email, chiunque può consumare la tua quota. Richiedi il JWT dell'utente, limita l'origine e metti un tetto di richieste per utente. - Bucket pubblici per i file degli utenti. Lovable crea il bucket pubblico perché così le immagini "si vedono". Per i documenti privati, bucket privato e URL firmati.
- Invisibile all'IA e ai motori di ricerca. L'app è una SPA di Vite: l'HTML arriva vuoto e i bot di ChatGPT o Perplexity non vedono nulla. Se la landing e il blog contano, separali dall'app. Dettaglio in perché le app create con l'IA sono invisibili all'IA.
- Senza header di sicurezza né metadati. Né CSP, né HSTS, né X-Frame-Options, e il titolo è quello del template. Il primo richiede un deploy fuori da lovable.app; il secondo si sistema con un prompt.
- Validazione solo nel form. Il campo ha
maxLengthma la Edge Function o la tabella accettano quello che arriva. Valida anche sul server e nei vincoli del database.
Un blocco per la sezione Knowledge del tuo progetto
Nelle impostazioni del progetto, Lovable ha una sezione di conoscenza che il modello legge a ogni richiesta. Incolla questo perché le regole si applichino dal primo prompt:
Regole di sicurezza di questo progetto:
- Ogni tabella nuova ha RLS attivo e una policy esplicita per operazione. Non usare mai using (true) né with check (true) se non su tabelle di contenuto pubblico in sola lettura, e dimmelo quando lo fai.
- Non mettere mai chiavi segrete nel codice del frontend. Le integrazioni con chiavi segrete vanno in una Edge Function che legge il segreto con Deno.env.get.
- Ogni Edge Function verifica il JWT dell'utente salvo mia indicazione contraria, limita Access-Control-Allow-Origin al nostro dominio e valida l'input.
- I permessi di amministratore si controllano in RLS o sul server, mai solo nel frontend.
- I file caricati dagli utenti vanno in bucket privati con policy e URL firmati.
- Le colonne role, is_admin, plan e credits non sono modificabili dall'utente.
- Metti titolo, meta description e tag Open Graph reali in index.html.
Un prompt di revisione prima di pubblicare
Rivedi la sicurezza di questo progetto e non cambiare ancora nulla. Rispondi con una lista:
1. Tabelle senza RLS e policy con using (true) o with check (true).
2. Chiavi o token presenti nel codice del frontend, con file e riga.
3. Edge Functions che non verificano il JWT, che rispondono con Access-Control-Allow-Origin: * o che non validano l'input.
4. Rotte o azioni di amministratore protette solo nel frontend.
5. Bucket pubblici con file degli utenti.
6. Colonne di privilegio che un utente può modificare.
7. Metadati di index.html ancora quelli del template.
Per ogni punto, proponi la modifica esatta e aspetta la mia conferma.
Verifica il risultato dall'esterno
Apri la tua app pubblicata in una finestra in incognito, tasto destro, "Visualizza sorgente", e cerca service_role, sk_live, sk- e Bearer nei file JavaScript che carica. Poi prova l'API di Supabase senza sessione:
curl -s "https://TUO_PROGETTO.supabase.co/rest/v1/profiles?select=*" -H "apikey: TUA_CHIAVE_ANON" -H "Authorization: Bearer TUA_CHIAVE_ANON"
Se restituisce righe, quella tabella è aperta. Scanaris fa questo e una quarantina di altri controlli in 30 secondi: rileva che l'app è fatta con Lovable, prova le tabelle di Supabase senza sessione, cerca segreti nel bundle, controlla header, cookie, CORS e file esposti, e verifica se il tuo contenuto è leggibile senza JavaScript. Per ogni errore ti dà un fix prompt da incollare nella chat di Lovable con la modifica esatta, e può riscansionare ogni giorno, perché una rigenerazione del codice può riportare un difetto che avevi già sistemato.
Domande frequenti
Lovable ha già risolto il problema dell'RLS?
Lovable ha aggiunto una revisione di sicurezza prima della pubblicazione e migliorato i template, ma il modello continua a generare policy aperte quando una query fallisce. La responsabilità dell'RLS è tua: usa le query della guida a Supabase.
Posso impostare header di sicurezza su un'app ospitata su lovable.app?
Non da Lovable. Se ti servono, sincronizza con GitHub e fai il deploy su Vercel o Netlify, dove si configurano con un file. L'app continua a essere modificata in Lovable.
Cosa faccio se ho incollato una chiave segreta nella chat?
Ruotala nel servizio di origine anche se non è più nel codice: la cronologia della chat e i bundle precedenti la conservano. Poi aggiungila dal riquadro dei segreti e chiedi al modello di spostare l'integrazione in una Edge Function.