Vai al contenuto
Capitolo 05 · 10 min

Endpoint esposti, API e webhook

La superficie di attacco della tua app è ogni richiesta a cui risponderà, non solo le schermate su cui puoi cliccare. Gli strumenti IA lasciano dietro di sé endpoint che avevi dimenticato di aver pubblicato, API che non chiedono credenziali e webhook che si fidano di chiunque faccia loro un POST. Questo capitolo riguarda la superficie che non vedi nella UI, e come chiuderla.

Rinnovare la vetrina ma lasciare la vecchia porta sul retro aperta, e fuori dalla planimetria.

must passthenA requestValidate +rate-limitHandle safely
Treat every endpoint as hostile: validate, rate-limit, and verify webhooks.

Gli endpoint che avevi dimenticato di aver pubblicato

Cambiare la UI non cancella l'API che ci sta dietro. Rimuovi un pulsante, la schermata sembra pulita, e la route che quel pulsante chiamava è ancora attiva e risponde ancora. Nel corso delle iterazioni, un'app costruita con l'IA li accumula: vecchie versioni di endpoint, route di debug e test aggiunte "giusto per controllare una cosa", azioni admin mai protette. Sono invisibili nell'app e pienamente raggiungibili da chiunque conosca, o indovini, l'URL.

Il cambio di prospettiva: il tuo confine di sicurezza è l'insieme delle route a cui il tuo server risponde, non l'insieme dei link nella tua interfaccia. Un attaccante legge il tuo bundle JavaScript per enumerare le route, ignora del tutto la tua UI e le chiama direttamente. Rimosso-dallo-schermo non è rimosso-dal-server.

Webhook: chiunque può fare quel POST

Un webhook è un URL pubblico sul tuo server che un provider (Stripe, GitHub, un servizio email) chiama per dirti che è successo qualcosa. Il problema: l'URL è pubblico, quindi chiunque può chiamarlo, incluso un attaccante che invia un falso "pagamento riuscito" o "abbonamento aggiornato" per sbloccare gratis funzionalità a pagamento. Il provider firma ogni chiamata reale con un segreto condiviso; se non verifichi quella firma, ti stai fidando di ciò che gli sconosciuti raccontano sul tuo stesso business.

tsCopia il prompt
// Verify the signature BEFORE trusting anything in the payload.
const sig = req.headers.get("stripe-signature");
let event;
try {
  event = stripe.webhooks.constructEvent(rawBody, sig, process.env.STRIPE_WEBHOOK_SECRET);
} catch {
  return new Response("bad signature", { status: 400 }); // forged or tampered
}
// Only now is it safe to act on event.type

CORS e rate limit

Due impostazioni che gli strumenti IA sbagliano perché la versione permissiva fa sparire gli errori. Il CORS controlla quali script di altri siti possono chiamare la tua API da un browser; uno strumento bloccato su un errore cross-origin spesso lo imposterà per consentire tutto, il che, combinato con le credenziali, può permettere a qualsiasi sito di agire come il tuo utente. Restringilo alle tue origin. E il rate limiting: senza, login e registrazione sono aperti al brute force, gli endpoint costosi sono aperti ad abusi che gonfiano la bolletta, e i tuoi dati sono aperti allo scraping.

  • CORS: consenti solo le tue origin reali, mai '*' insieme alle credenziali.
  • Applica rate limit per utente e per IP, soprattutto su auth, registrazione, reset password e tutto ciò che costa denaro da eseguire.
  • Metti gli endpoint costosi o sensibili prima di tutto dietro autenticazione; il rate limiting è una rete di sicurezza, non la prima linea.

L'inventario che ti serve

Non puoi mettere in sicurezza una superficie che non hai mappato. Una volta, prima del lancio, enumerala:

  • Elenca ogni route che il server serve davvero, dal codice e dal bundle, non dal menu.
  • Per ciascuna: è pensata per essere pubblica? Se no, autentica e autorizza (capitolo 4)?
  • Cancella le route morte, di debug e delle vecchie versioni; la superficie più piccola è la più sicura.
  • Per ogni webhook in ingresso, conferma la verifica della firma, poi conferma che rifiuta una chiamata non firmata.

Questo inventario è anche l'input della checklist di lancio del prossimo capitolo. Non puoi spuntare "ogni endpoint è autorizzato" finché non sai qual è ogni endpoint.

Una riga per ciascuno

  • La tua superficie di attacco è ogni route a cui il server risponde, non ogni link nella UI; rimosso-dallo-schermo non è rimosso-dal-server.
  • Gli URL dei webhook sono pubblici; senza verifica della firma, chiunque può falsificare eventi come 'pagamento riuscito'.
  • CORS impostato su '*' e rate limit assenti sono i default permissivi a cui gli strumenti IA ricorrono per zittire gli errori; entrambi sono buchi.
  • Inventaria ogni endpoint prima del lancio: è pensato per essere pubblico, è autorizzato, le route morte si possono cancellare, i webhook sono verificati?
Endpoint esposti, API e webhook · Cours d'IA · SDEN