technical

Blocca il clickjacking con frame-ancestors

MetricSpot cerca X-Frame-Options o CSP frame-ancestors. Questi header impediscono agli attaccanti di incorporare il tuo sito in un iframe nascosto per ingannare gli utenti.

Cosa controlla questo check

Ispeziona gli header della risposta per uno tra:

  • X-Frame-Options: DENY o X-Frame-Options: SAMEORIGIN
  • Content-Security-Policy: frame-ancestors 'none' o frame-ancestors 'self'

Il check fallisce quando nessuno dei due è presente e un attaccante potrebbe incorporare la tua pagina in un iframe nascosto su un sito malevolo.

Perché è importante

Il clickjacking è un attacco di UI-redress: l’attaccante carica il tuo sito in un iframe trasparente sovrapposto a un pulsante apparentemente innocuo (“iPad gratis! Clicca qui”). Il click dell’utente atterra in realtà su un vero pulsante nel tuo iframe — inviando un pagamento, cambiando una password, trasferendo fondi.

  • L’attacco funziona contro qualsiasi sessione loggata. Se un utente è loggato sul tuo sito in un’altra scheda, l’iframe eredita i cookie di sessione, quindi il click esegue come quell’utente.
  • È stato usato in natura contro siti bancari, social network e dashboard admin. Flussi OAuth e pagine di enrollment 2FA sono stati colpiti.
  • La fix è un singolo header. I browser rifiutano di renderizzare la tua pagina in un iframe quando l’header è presente — l’attacco smette di essere possibile.

La frame protection è la mitigazione più economica nella sicurezza web: un header di risposta per pagina, nessuna modifica al codice, nessun costo di prestazioni.

Come risolvere

Scegli uno dei due meccanismi. I browser moderni preferiscono CSP frame-ancestors; X-Frame-Options è l’header legacy che funziona anche nei browser più vecchi. Invia entrambi per la copertura massima — non sono in conflitto.

Negare tutto il framing (raccomandato per siti non pensati per essere incorporati):

Content-Security-Policy: frame-ancestors 'none'
X-Frame-Options: DENY

Permettere il framing solo dalla tua origin:

Content-Security-Policy: frame-ancestors 'self'
X-Frame-Options: SAMEORIGIN

Permettere il framing da origin specifiche e fidate (solo CSP supporta questo — X-Frame-Options non può elencare più domini):

Content-Security-Policy: frame-ancestors 'self' https://partner.example.com

nginx:

add_header Content-Security-Policy "frame-ancestors 'none'" always;
add_header X-Frame-Options "DENY" always;

Il flag always è critico — senza, nginx salta l’header sulle risposte di errore.

Apache:

Header always set Content-Security-Policy "frame-ancestors 'none'"
Header always set X-Frame-Options "DENY"

Caddy:

header {
  Content-Security-Policy "frame-ancestors 'none'"
  X-Frame-Options "DENY"
}

Cloudflare — Rules → Transform Rules → Modify Response Header, aggiungi entrambi gli header globalmente. Oppure usa il prodotto Page Shield se vuoi controllo a livello WAF.

Next.js (next.config.js):

module.exports = {
  async headers() {
    return [
      {
        source: "/(.*)",
        headers: [
          { key: "Content-Security-Policy", value: "frame-ancestors 'none'" },
          { key: "X-Frame-Options", value: "DENY" },
        ],
      },
    ];
  },
};

Express:

import helmet from "helmet";
app.use(helmet.frameguard({ action: "deny" }));
app.use(
  helmet.contentSecurityPolicy({
    directives: { frameAncestors: ["'none'"] },
  })
);

Testalo:

curl -sI https://yourdomain.com/ | grep -iE 'frame'

Aspettati entrambi gli header, o almeno frame-ancestors. Poi prova a incorporare in un iframe in locale per confermare che il browser rifiuta.

Domande frequenti

Dovrei negare tutto il framing o solo same-origin?

Default a frame-ancestors 'none' e rilassa solo se hai bisogno attivamente di incorporare le tue pagine. La maggior parte dei siti marketing, dashboard admin e app non dovrebbe mai essere inframmata — e i provider OAuth (Google, Apple, Stripe) che hanno genuinamente bisogno del framing hanno flussi di embed ben definiti che non richiedono di rilassare la tua CSP.

E X-Frame-Options: ALLOW-FROM?

Deprecato e non supportato in Chrome e Firefox. Usa Content-Security-Policy: frame-ancestors invece — accetta più origin e funziona in ogni browser moderno.

Questo rompe Google PageSpeed Insights o qualche tool?

No. Quei tool prendono la pagina direttamente, non in un iframe. L’header influisce solo sull’incorporamento in iframe.

Fonti

Ultimo aggiornamento 2026-05-11