---
title: "Padroneggiare l'Arte della Sicurezza delle Progressive Web App"
---

# Padroneggiare l'Arte della Sicurezza delle Progressive Web App

Le Progressive Web App (PWA) sono diventate lo standard de‑facto per offrire esperienze simili a quelle delle app sul web aperto. I loro punti di forza — capacità offline, notifiche push e installabilità — introducono anche nuove superfici d’attacco che i siti web tradizionali raramente affrontano. Questo articolo approfondisce il **ciclo di vita della sicurezza di una PWA**, combinando indurimento a livello di rete, protezioni a runtime e migliori pratiche operative. Alla fine avrai una checklist applicabile a qualsiasi progetto, sia esso un semplice lettore di notizie o una complessa piattaforma e‑commerce.

> **TL;DR**: Metti al sicuro la tua PWA con HTTPS, applica una CSP rigorosa, isola i service worker, convalida tutti gli input e adotta una routine di monitoraggio continuo.

---

## 1. Livello di Trasporto – Prima Linea di Difesa

### 1.1 Imporre HTTPS Ovunque

Tutti i browser moderni richiedono **HTTPS** per la registrazione dei service worker. Tuttavia, alcune risorse (ad es. analytics di terze parti) possono ancora essere caricate via HTTP, generando avvisi di contenuto misto e aprendo la porta ad attacchi man‑in‑the‑middle (MITM).

**Passaggi chiave:**

1. Ottieni un certificato TLS affidabile (Let’s Encrypt, Cloudflare, ecc.).
2. Reindirizza tutte le richieste `http://` verso `https://` tramite la configurazione del server.
3. Abilita **HSTS** (HTTP Strict Transport Security) per forzare i browser a usare HTTPS per un periodo predefinito.

```nginx
# Esempio di snippet NGINX
server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}
server {
    listen 443 ssl http2;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    # Impostazioni TLS ...
}
```

> **Nota**: HSTS elimina gli attacchi di downgrade, ma richiede una pianificazione attenta perché, una volta impostato, i browser rifiuteranno connessioni HTTP per tutta la durata specificata.

### 1.2 Pinning del Certificato (Opzionale)

Per le PWA altamente sensibili — banking, cartelle cliniche — considera il **certificate pinning** tramite la **Public Key Pinning Extension for HTTP (HPKP)**. Sebbene HPKP sia in fase di deprecazione per i rischi di deployment, è possibile ottenere una sicurezza simile con gli header **Expect‑CT** che impongono la Certificate Transparency.

```http
Expect-CT: max-age=86400, enforce, report-uri="https://example.com/report"
```

---

## 2. Indurimento del Service Worker

I service worker costituiscono il cuore delle capacità offline di una PWA. Operano in un thread di background con privilegi elevati, diventando un bersaglio primario per l’exploit.

### 2.1 Limitazione dello Scope

Definisci lo `scope` più piccolo possibile al momento della registrazione del service worker. Questo impedisce al worker di intercettare richieste al di fuori dell’area prevista.

```javascript
navigator.serviceWorker.register('/sw.js', { scope: '/app/' })
  .then(reg => console.log('SW registrato con scope:', reg.scope));
```

### 2.2 Verifica dell’Integrità con Subresource Integrity (SRI)

Se carichi lo script del service worker da un CDN, proteggilo con **SRI** per assicurarti che il codice recuperato corrisponda a un hash previsto.

```html
<script src="https://cdn.example.com/sw.js"
        integrity="sha384-abc123..."
        crossorigin="anonymous"></script>
```

### 2.3 Content Security Policy per i Service Worker

Una CSP rigorosa può impedire al worker di caricare script malevoli o di connettersi a origini non volute.

```http
Content-Security-Policy: script-src 'self' https://trusted.cdn.com; 
                         connect-src 'self' https://api.example.com;
```

> **Suggerimento**: Usa la direttiva `worker-src` (supportata nei browser più recenti) per includere esplicitamente le origini consentite per gli script dei worker.

### 2.4 Gestione dello Stato e Validazione della Cache

Non fidarti mai ciecamente delle voci della cache. Valida sempre la freschezza delle risposte cache, soprattutto per token di autenticazione o dati personali.

```javascript
self.addEventListener('fetch', event => {
  const url = new URL(event.request.url);
  if (url.pathname.startsWith('/api/')) {
    // Bypass della cache per dati dinamici
    event.respondWith(fetch(event.request));
    return;
  }
  // Strategia cache‑first predefinita per risorse statiche
  event.respondWith(
    caches.match(event.request).then(cached => cached || fetch(event.request))
  );
});
```

---

## 3. Protezioni a Runtime – CSP, Permessi e Sandbox

### 3.1 CSP Completa

Una CSP ben costruita riduce il rischio di **Cross‑Site Scripting (XSS)** e **Data Injection**. Di seguito un esempio di policy ottimizzata per una tipica PWA:

```http
Content-Security-Policy:
  default-src 'self';
  script-src 'self' 'sha256-XYZ' https://analytics.example.com;
  style-src 'self' 'unsafe-inline';
  img-src 'self' data:;
  font-src 'self' https://fonts.gstatic.com;
  connect-src 'self' https://api.example.com wss://socket.example.com;
  frame-ancestors 'none';
  base-uri 'self';
  form-action 'self';
```

- `script-src` include un hash per gli script inline, evitando `unsafe-inline`.
- `frame-ancestors 'none'` disabilita il clickjacking.
- `connect-src` whitelist le API e gli endpoint WebSocket.

### 3.2 Permissions Policy (ex Feature‑Policy)

Limita le potenti funzionalità del browser che le PWA potrebbero ereditare involontariamente.

```http
Permissions-Policy: geolocation=(), microphone=(), camera=(), payment=()
```

### 3.3 Attributo Sandbox per i Contenuti Incorporati

Se la tua PWA incorpora iframe di terze parti, sandboxali per impedire l’esecuzione di script e la navigazione.

```html
<iframe src="https://maps.example.com"
        sandbox="allow-scripts allow-same-origin"
        loading="lazy"></iframe>
```

---

## 4. Autenticazione & Autorizzazione

### 4.1 Autenticazione Basata su Token con JWT

Utilizza **JSON Web Tokens (JWT)** per l’autenticazione senza stato, ma non conservarli in `localStorage` — usa **cookie Secure, HttpOnly** per mitigare il furto via XSS.

```http
Set-Cookie: token=eyJhbGciOi...; HttpOnly; Secure; SameSite=Strict; Path=/; Max-Age=3600
```

### 4.2 Rotazione del Refresh Token

Implementa refresh token rotanti per limitare i danni in caso di token compromesso.

1. Il client invia il refresh token.
2. Il server lo valida e rilascia un nuovo access token **e** un nuovo refresh token.
3. Il vecchio refresh token viene invalidato nel database.

### 4.3 Mitigazione CSRF

Anche con cookie SameSite, utilizza **token anti‑CSRF** per le richieste POST che modificano lo stato.

```html
<input type="hidden" name="csrf_token" value="{{ .CSRFToken }}">
```

Sul server, verifica che il token corrisponda alla sessione.

---

## 5. Memorizzazione Sicura dei Dati

Le PWA possono archiviare dati tramite **IndexedDB**, **Cache API** e **Web Storage**. Ognuno ha proprie considerazioni di sicurezza.

| Memorizzazione | Idoneità | Consigli di Sicurezza |
|----------------|----------|-----------------------|
| **Cache API** | Risorse statiche, fallback offline | Cache solo risorse immutabili. Usa nomi di cache versionati per eliminare dati obsoleti. |
| **IndexedDB** | Dati strutturati, preferenze utente | Cifra i campi sensibili lato client con Web Crypto API. |
| **LocalStorage / SessionStorage** | Dati piccoli, non sensibili | Evita di memorizzare segreti. I dati sono accessibili a qualsiasi script nella pagina. |

### 5.1 Esempio: Cifrare Dati in IndexedDB

```javascript
async function encryptAndStore(key, value) {
  const cryptoKey = await crypto.subtle.generateKey(
    { name: "AES-GCM", length: 256 },
    true,
    ["encrypt", "decrypt"]
  );
  const iv = crypto.getRandomValues(new Uint8Array(12));
  const encoded = new TextEncoder().encode(value);
  const ciphertext = await crypto.subtle.encrypt(
    { name: "AES-GCM", iv },
    cryptoKey,
    encoded
  );
  const db = await openDB('secure-store', 1, {
    upgrade(db) { db.createObjectStore('secrets'); }
  });
  await db.put('secrets', { iv, ciphertext }, key);
}
```

---

## 6. Monitoraggio, Audit e Risposta agli Incidenti

La sicurezza non è una configurazione una tantum; è un ciclo continuo.

### 6.1 Scansioni Automatizzate

- Usa **OWASP ZAP** o **Burp Suite** per rilevare XSS, CSRF e intestazioni insicure.
- Integra le verifiche **Lighthouse** nelle pipeline CI/CD per imporre la conformità PWA.

### 6.2 Logging a Runtime

Cattura gli errori del service worker e inoltrali a un endpoint sicuro per l’analisi.

```javascript
self.addEventListener('error', event => {
  fetch('https://logs.example.com/collect', {
    method: 'POST',
    body: JSON.stringify({ message: event.message, stack: event.error.stack })
  });
});
```

### 6.3 Playbook di Incident Response

1. **Rilevare**: Allarme attivato da traffico anomalo o segnalazioni di violazione CSP.
2. **Contenere**: Revoca dei JWT compromessi, rotazione delle chiavi API.
3. **Eradicare**: Correzione del codice vulnerabile, aggiornamento della cache del service worker.
4. **Ripristinare**: Deploy della nuova versione, monitoraggio per recidiva.
5. **Post‑mortem**: Documentare la causa radice, aggiornare la checklist di sicurezza.

---

## 7. Panoramica Visiva – Strati di Sicurezza in una PWA

```mermaid
flowchart TB
    subgraph "Livello di Trasporto"
        H["\"HTTPS\""]
        S["\"HSTS\""]
    end
    subgraph "Service Worker"
        SW["\"Scope Limitation\""]
        CS["\"Cache Validation\""]
    end
    subgraph "Runtime"
        CSP["\"Content Security Policy\""]
        PP["\"Permissions Policy\""]
        SAN["\"Sandboxed iFrames\""]
    end
    subgraph "Auth & Data"
        JWT["\"Secure Cookies\""]
        REF["\"Refresh Rotation\""]
        ENC["\"IndexedDB Encryption\""]
    end
    subgraph "Monitoring"
        SCAN["\"OWASP ZAP\""]
        LOG["\"Runtime Logging\""]
    end

    H --> SW --> CSP --> JWT --> SCAN
    S --> SW
    CS --> PP
    PP --> ENC
    LOG --> SCAN
```

Il diagramma illustra come ogni controllo di sicurezza si sovrapponga al precedente, formando un’architettura a difesa in profondità.

---

## 8. Checklist – Riferimento Rapido per una PWA Sicura

- [ ] Servire tutto il contenuto via HTTPS con HSTS attivo.
- [ ] Registrare i service worker con lo scope più ristretto possibile.
- [ ] Applicare Subresource Integrity per gli script caricati da remoto.
- [ ] Applicare una CSP rigorosa, includendo `worker-src` e hash per gli script.
- [ ] Utilizzare Permissions‑Policy per disabilitare le funzionalità del browser non necessarie.
- [ ] Conservare i token di autenticazione in cookie Secure, HttpOnly; mai in localStorage.
- [ ] Ruotare i refresh token e validare i token anti‑CSRF per le richieste che modificano lo stato.
- [ ] Cifrare i dati sensibili in IndexedDB.
- [ ] Eseguire scansioni OWASP ZAP automatizzate ad ogni pull request.
- [ ] Configurare logging in tempo reale degli errori del service worker.
- [ ] Mantenere un playbook di risposta agli incidenti.

---

## 9. Domande Frequenti

**D1: Le PWA hanno bisogno di un Service Worker per la sicurezza?**  
No. Misure come HTTPS, CSP e cookie sicuri funzionano indipendentemente. Tuttavia, il Service Worker è dove la maggior parte degli attacchi a runtime si manifestano, quindi richiede un indurimento aggiuntivo.

**D2: Posso usare `unsafe-inline` nella CSP per gli stili?**  
È preferibile evitarlo. Usa invece hash o nonce per gli stili inline, oppure spostali in file CSS esterni.

**D3: Con quale frequenza devo ruotare i certificati TLS?**  
Let’s Encrypt rilascia certificati da 90 giorni; automatizza il rinnovo. Per certificati auto‑firmati o commerciali, punta a una validità massima di 1 anno.

---

## 10. Conclusioni

Le Progressive Web App sfumano il confine tra esperienze native e web, offrendo potenti capacità che ampliano anche la superficie di attacco. Sovrapponendo la sicurezza del trasporto, limitando gli scope dei service worker, imponendo una rigorosa Content Security Policy e adottando pratiche di autenticazione robuste, puoi proteggere la tua PWA senza sacrificare le performance.

Ricorda: la sicurezza è un viaggio, non una destinazione. Mantieni le dipendenze aggiornate, effettua audit regolari del codice e resta informato sulle nuove minacce. Con le pratiche descritte in questo documento, la tua PWA sarà pronta a resistere agli attacchi web più comuni.

---

## <span class='highlight-content'>Vedi</span> Anche

- [MDN Web Docs – Service Workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API)
- [OWASP Top Ten Project](https://owasp.org/www-project-top-ten/)
- [Mozilla – Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP)
- [Web.dev – HTTPS and HSTS](https://web.dev/transport-layer-security/)
- [RFC 6797 – HTTP Strict Transport Security (HSTS)](https://tools.ietf.org/html/rfc6797)