Per i team di sicurezza e chi valuta le app

La sicurezza in Peel

In breve: il contenuto delle bacheche viene cifrato nel browser con una chiave che vive nel frammento del link, quindi i nostri server salvano e inoltrano testo cifrato che non possono leggere. Ecco esattamente come funziona, e dove sono i limiti.

Riepilogo

  • Testo delle schede, nomi, titoli delle bacheche, voti e sticker sono cifrati con AES-256-GCM tramite una chiave della bacheca generata nel browser. La chiave viaggia nel frammento dell’URL (#k=) e non viene mai inviata a un server.
  • Le azioni del facilitatore, l’intestazione della bacheca e gli snapshot sono firmati con la chiave Ed25519 del facilitatore. L’ID della bacheca deriva da quella chiave, quindi i client si accorgono di una sostituzione della chiave.
  • Le schede nascoste sono sigillate per il facilitatore (sealed box X25519) fino alla rivelazione, e vincolate da commitment con salt perché il testo svelato non possa essere sostituito.
  • Anonimo di default: le operazioni non contengono alcun ID dell’autore; voti e reazioni usano un ID casuale per bacheca.
  • I partecipanti non si autenticano mai. Niente SDK di analytics, niente pubblicità, niente script di terze parti tranne Paddle.js nella pagina di checkout.
  • Solo Cloudflare. Le bacheche non rivendicate vengono eliminate 60 giorni dopo l’ultima visita.

Come scorrono i dati

Il frammento di un URL (tutto ciò che segue il #) è gestito dal browser e non fa parte della richiesta HTTP. È lì che Peel mette la chiave della bacheca.

Flusso dei dati: la chiave viene letta localmente dal link; in rete passano solo testo cifrato e metadati minimi.

Modello delle minacce

Progettiamo in modo che un server completamente compromesso o curioso, noi compresi, venga a sapere il meno possibile di ciò che dice un team.

Cosa proteggiamo

  • Il testo delle schede, le GIF scelte e, in modalità con nome, il nome dell’autore.
  • Nomi e avatar dei partecipanti, il nome della bacheca e i titoli dei modelli personalizzati.
  • Chi ha votato o reagito a cosa, e chi ha scritto quale scheda.
  • L’integrità della retro: fasi, rivelazioni e decisioni del facilitatore non si possono falsificare.

Gli avversari che consideriamo

  • I nostri stessi server, un insider malintenzionato o chi viola il nostro storage: ottengono testo cifrato e metadati.
  • Un attaccante sulla rete: TLS ovunque; la chiave non attraversa mai la rete.
  • Un server che sostituisce le chiavi: l’ID della bacheca deriva dalla chiave pubblica del facilitatore e i client verificano l’intestazione firmata.
  • Un partecipante che vuole sbirciare o falsificare: le schede nascoste sono sigillate per il facilitatore; le operazioni del facilitatore richiedono la sua firma; modificare una scheda richiede la chiave di quella scheda.
  • Un facilitatore che ripubblica per un autore offline: i commitment gli impediscono di cambiare il testo.

Fuori ambito, onestamente

  • Chiunque abbia il link da partecipante può leggere la bacheca. Il link è il controllo d’accesso. Va condiviso con la stessa cura della bacheca stessa.
  • Un dispositivo compromesso, un’estensione del browser malevola o qualcuno che ti guarda alle spalle.
  • L’analisi del traffico: il server vede tempi, dimensioni e conteggi (vedi la mappa dei dati).
  • Il denial of service da parte del server: può scartare o ritardare i messaggi, ma non leggerli né falsificarli.

Crittografia

Tutte le primitive vengono dall’API WebCrypto del browser. Niente crittografia fatta in casa, niente librerie crittografiche di terze parti.

ChiaveAlgoritmoUsata per
K_boardAES-256-GCM, IV casuale a 96 bitCifra ogni operazione, snapshot e aggiornamento di presenza. I dati aggiuntivi vincolano ID della bacheca, tipo di operazione e ID dell’operazione, così il testo cifrato non può essere riproposto in un’altra bacheca o posizione. Vive solo nel frammento del link #k=.
K_ownerEd25519L’autorità del facilitatore. Firma le operazioni del facilitatore (fase, timer, riflettore, modello, impostazioni, apertura dei voti, occultamento di una scheda), l’intestazione della bacheca e gli snapshot. Un contatore strettamente crescente blocca i replay. Solo nel link del facilitatore (&o=).
ID della bachecaSHA-256, primi 80 bit, base32Deriva dalla chiave pubblica del facilitatore, quindi l’ID stesso dimostra quale chiave possiede la bacheca. I client rifiutano un’intestazione la cui chiave non corrisponde all’hash dell’ID.
K_facSealed box X25519: X25519 effimera + HKDF-SHA256 + AES-256-GCMLe schede nascoste vengono sigillate con la chiave pubblica del facilitatore mentre le persone scrivono. Solo il link del facilitatore (&f=) può aprirle.
Chiavi delle schedeEd25519, una chiave per schedaLa possiede solo l’autore. Modifiche e rivelazione vengono firmate con essa: autenticità senza identità.
CommitmentHMAC-SHA256 con salt casuale a 128 bitUna scheda nascosta pubblica un commitment sul proprio contenuto. Alla rivelazione vengono pubblicati contenuto e salt, e ogni client li verifica: nessuno può sostituire il testo.
PresenzaAES-256-GCM con K_boardNomi, avatar e indicatori di scrittura sono cifrati come tutto il resto.
Pacchetto di chiaviHKDF-SHA256 dal PRF della passkey o dal codice di recupero, AES-256-GCMI facilitatori che hanno effettuato l’accesso possono sincronizzare le chiavi delle bacheche tra dispositivi. Il pacchetto viene cifrato sul dispositivo; il server salva solo testo cifrato e chiavi incapsulate.

I messaggi firmati sono separati per dominio (per esempio peel/sig/v1, peel/header/v1, peel/snap/v1), così una firma fatta per uno scopo non può essere riutilizzata per un altro.

Le schede nascoste e la rivelazione

  1. Durante la scrittura, il browser dell’autore sigilla la scheda con la chiave X25519 del facilitatore e pubblica un commitment con salt. Il testo in chiaro resta sul dispositivo dell’autore.
  2. Gli altri partecipanti vedono una scheda nascosta: non possono decifrarla, e il server nemmeno.
  3. Il browser del facilitatore può aprire le schede sigillate (l’anteprima “👁 solo tu”).
  4. Alla rivelazione, ogni autore ripubblica la propria scheda cifrata con K_board, firmata con la chiave della scheda, insieme al salt.
  5. Se un autore è offline, il facilitatore ripubblica al suo posto. Ogni client verifica il commitment, quindi il testo deve corrispondere a ciò che l’autore ha scritto.

Poiché il facilitatore tecnicamente può vedere in anteprima, ogni bacheca mostra a tutti l’etichetta “il facilitatore può vedere in anteprima” finché ci sono schede nascoste. Non è un’impostazione che si possa nascondere.

Anonimato

  • Le operazioni non contengono alcun ID dell’autore. Il server non può collegare una scheda a una persona e, di default, nemmeno il facilitatore.
  • Voti e reazioni sono associati a un ID casuale per bacheca, non collegato ad alcun nome.
  • Gli indicatori di scrittura mostrano che qualcuno sta scrivendo, mai cosa.
  • La modalità con nome è un’impostazione esplicita della bacheca; il nome dell’autore viaggia allora dentro la scheda cifrata.
  • I partecipanti non accedono mai, quindi non c’è nessun account da incrociare.

Mappa dei dati

Tutto ciò che conserviamo, dove si trova, chi può leggerlo e per quanto tempo resta.

DatiDoveLeggibili daConservazione
Schede, voti, reazioni, sticker, azioni, nome della bacheca, titoli dei modelli personalizzatiStorage del Durable Object, come testo cifratoChi ha il link della bachecaFinché la bacheca non viene eliminata
Busta dell’operazione: tipo, sequenza e ora del server, dimensione, contatore del facilitatoreStorage del Durable ObjectPeelFinché la bacheca non viene eliminata
Nomi e avatar dei partecipanti, scrittura in corsoInoltrati come testo cifrato; in memoria durante la connessioneChi ha il link della bachecaDurante la connessione
Stato della bacheca: fase, numero di partecipanti e di schede, ID del modello di catalogo, flag di blocco, date di creazione e scadenzaDurable Object, D1; messaggi Slack/Teams se installatoPeel; il vostro canale Slack/TeamsDurata della bacheca
Account del facilitatore: ID del provider, nome, email se condivisa, provider collegati, data di creazione, sessioneD1PeelFinché non elimini l’account
Pacchetto di chiavi e chiavi incapsulateD1, come testo cifratoSolo tu (passkey o codice di recupero)Finché non elimini l’account
Piano, stato dell’abbonamento, ID cliente e abbonamento PaddleD1; PaddlePeel, PaddleCome richiesto dalla normativa fiscale
ID di workspace, canale e messaggio Slack/Teams; token del bot (cifrato con AES-GCM)D1PeelFino alla disinstallazione
Indirizzo IPEdge di Cloudflare, in modo transitorio (consegna, limiti di frequenza)Cloudflare, il rate limiter di PeelNon salvato nei nostri database
Contatori giornalieri (bacheche create, fasi raggiunte)D1PeelSolo aggregati, senza identificativi

Cosa può e non può fare il nostro server

Può

  • Vedere tipi di operazione, dimensioni, tempi, la fase, il numero di partecipanti e di schede, l’ID del modello di catalogo e il flag di blocco.
  • Scartare, ritardare o rifiutarsi di consegnare operazioni (denial of service).
  • Vedere gli indirizzi IP al bordo della rete.
  • Contare bacheche e fasi raggiunte, in forma aggregata.
  • Eliminare una bacheca (scadenza, segnalazioni di abuso).

Non può

  • Leggere il testo delle schede, nomi, titoli delle bacheche, titoli dei modelli personalizzati, voti o sticker.
  • Leggere le schede nascoste prima della rivelazione (e nemmeno dopo).
  • Falsificare azioni del facilitatore: richiedono la sua firma.
  • Infilare chiavi proprie: l’ID della bacheca lo tradirebbe.
  • Cambiare il testo svelato di una scheda: commitment e firme delle schede lo tradirebbero.
  • Sapere chi ha scritto quale scheda.

Come per qualsiasi web app, ti fidi del codice che serviamo. Teniamo questa superficie ridotta: una Content Security Policy rigorosa, script-src limitato alla nostra origine, nessuno script di terze parti, e il protocollo è aperto alla revisione su richiesta.

Slack e Microsoft Teams

  • I messaggi contengono il link della bacheca e metadati (titolo, fase, conteggi). Il testo delle schede viene inviato solo quando il facilitatore pubblica un riepilogo e lo conferma.
  • La scheda per entrare contiene il link da partecipante, che include la chiave. Chiunque possa leggere quel canale può entrare, proprio come se il link fosse stato incollato lì.
  • Le anteprime dei link mostrano solo fase e conteggi, mai il contenuto.
  • Scope di Slack: commands, chat:write, links:read, links:write; users:read solo quando un team attiva le menzioni.
  • I token dei bot sono cifrati a riposo (AES-GCM, chiave conservata come secret del Worker). Le firme delle richieste Slack e i token di Bot Framework vengono verificati a ogni richiesta.
  • Disinstallare l’app interrompe ogni pubblicazione ed elimina i suoi token.

Web e infrastruttura

  • Solo Cloudflare: Pages, Workers, Durable Objects, D1, R2 e KV sull’account di 1801 Labs. Nessun altro server.
  • TLS ovunque, HSTS e una Content Security Policy rigorosa.
  • Niente SDK di analytics, niente pubblicità, niente script di terze parti. L’unica eccezione è Paddle.js, caricato solo nella pagina di checkout.
  • Un solo cookie, solo per i facilitatori che hanno effettuato l’accesso: peel_session, httpOnly, Secure, SameSite=Lax.
  • La ricerca di GIF e i contenuti multimediali passano dalla nostra API, quindi gli indirizzi IP dei partecipanti non arrivano mai a GIPHY.
  • Font e risorse ospitati da noi. Niente font da CDN, niente pixel di tracciamento.
  • Limiti di frequenza per IP e per bacheca; segnalazioni di abuso e blocco da parte del facilitatore.

Account e conservazione

  • I partecipanti non si autenticano mai. I facilitatori accedono con Google (o Entra ID tramite Teams) solo per conservare le bacheche o usare le funzioni a pagamento.
  • Un account conserva un ID, il nome e l’email forniti dal provider e un pacchetto di chiavi cifrato, sbloccato da una passkey (WebAuthn PRF) o da un codice di recupero. L’accesso dà la proprietà, non l’accesso ai contenuti.
  • Rivendicare una bacheca dimostra la proprietà con una firma del facilitatore. Le chiavi delle bacheche non vengono mai inviate.
  • Le bacheche senza account vengono eliminate 60 giorni dopo l’ultima visita; ogni visita fa ripartire il conteggio. Gli allarmi dei Durable Object cancellano lo storage.
  • Eliminando l’account vengono cancellati sessioni, pacchetto di chiavi e libreria, e le bacheche tornano alla scadenza di 60 giorni.

Divulgazione responsabile

Hai trovato qualcosa? Diccelo prima a noi e lavoreremo insieme. Confermiamo la ricezione delle segnalazioni entro tre giorni lavorativi.

[email protected]

  • Concedici un tempo ragionevole (puntiamo a 90 giorni) per correggere prima di rendere pubblico il problema.
  • Fai i test con bacheche e account tuoi. Non accedere ai dati di altre persone e non degradare il servizio.
  • Non intraprenderemo azioni legali contro ricerche condotte in buona fede nel rispetto di queste regole.
  • Contatto leggibile dalle macchine: /.well-known/security.txt.

I clienti del piano Azienda ricevono un pacchetto per la valutazione di sicurezza (risposte ai questionari, sub-responsabili, flussi di dati). DPA · Privacy