Un bug di HTML injection memorizzata nella bacheca di lavoro RamenHire ha permesso a chiunque di compilare un modulo pubblico, trasformando le email di notifica del team in una piattaforma di phishing.

Come si è insinuato il bug

RamenHire gira su Next.js e Supabase e consente alle startup di pubblicare offerte di lavoro senza effettuare l'accesso. Ogni invio attiva un'email al team di selezione interno. Il corpo dell'email viene costruito concatenando i campi grezzi del modulo — nome dell'azienda, descrizione del lavoro, nome del contatto — direttamente in una stringa HTML. Non avviene alcun escaping o sanificazione prima che la stringa raggiunga il servizio di posta.

Poiché il template tratta l'input dell'utente come HTML sicuro, un candidato malintenzionato può iniettare un falso link "clicca qui per verificare". Il payload viene memorizzato sul server come parte dell'annuncio di lavoro, quindi ogni email di notifica successiva trasporta il codice malevolo. Un attaccante può nascondere quel link accanto al vero pulsante "Visualizza Dashboard", ingannando un membro del team e spingendolo a rivelare le proprie credenziali o a visitare un sito di phishing.

Perché era importante

Le email vengono inviate al nucleo del team di selezione, persone che cliccano costantemente sui link per far avanzare i candidati nel processo di assunzione.

La lacuna tecnica

L'escaping dell'HTML non è un passaggio singolo. Due contesti necessitano di protezione:

  • Text nodes – il contenuto tra i tag. Convertire < in &lt; e > in &gt; blocca i tag, ma non impedisce a un attaccante di uscire dal valore di un attributo.
  • Attribute values – stringhe all'interno dei tag come href="…". Iniettare una virgoletta (" o ') consente a un attaccante di chiudere prematuramente l'attributo e inserire il proprio markup.

Il codice originale gestiva solo il testo semplice, lasciando l'iniezione di attributi completamente scoperta.

Risolvere il problema

Lo sviluppatore ha aggiunto una piccola funzione helper escapeHtml e l'ha applicata a ogni valore fornito dall'utente prima dell'interpolazione, sia che il valore finisca in un text node che in un attributo.

Passaggi di verifica

  • Local testing – Una suite di stringhe di iniezione è stata fornita alle funzioni del template. Ogni test ha mostrato solo caratteri in escaping, senza tag eseguibili.
  • Production testing – Dopo aver distribuito la patch, un payload è stato inviato tramite il sito live, superando il controllo bot di Cloudflare Turnstile. L'email risultante è arrivata nella casella di posta dello sviluppatore; il link malevolo e qualsiasi tag script sono apparsi come testo illeggibile, non come elementi cliccabili.

Una nota su Gmail: il servizio potrebbe comunque colorare un URL di blu e renderlo cliccabile, ma si tratta di una comodità lato client e non significa che l'iniezione HTML sia riuscita. La correzione impedisce all'iniezione di creare pulsanti reali o eseguire script.

A cosa devono prestare attenzione gli sviluppatori

  • Non fidarsi mai dei dati provenienti da moduli pubblici – Anche i moduli dall'aspetto innocuo possono produrre output memorizzati utilizzati altrove.
  • Effettuare l'escaping al punto di utilizzo – Applicare l'escaping consapevole del contesto (testo vs. attributo) subito prima del rendering, non prima nella pipeline.
  • Testare sia lato client che lato server – I test unitari rilevano i fallimenti ovvi; un test manuale end-to-end tramite l'interfaccia utente live conferma che le difese reggono sotto traffico reale.
  • Prestare attenzione alle stranezze dei client email – Alcuni client creano automaticamente link per gli URL, generando un falso senso di sicurezza. Verificare che l'HTML sottostante non contenga elementi attivi.

In sintesi

Una singola svista nella gestione dell'input dell'utente ha trasformato le normali email di notifica in un vettore di phishing. L'introduzione di una routine completa di escaping HTML e la validazione della correzione localmente e in produzione hanno ripristinato l'integrità della casella di posta. L'episodio sottolinea una lezione intramontabile per qualsiasi web app che generi HTML da dati non attendibili: una corretta sanificazione è imprescindibile, e ignorarla può aprire un canale diretto verso le caselle di posta dei propri utenti.