Documentazione
Monitoraggio e avvisi sulle modifiche
AppSafe confronta ogni scansione di un sito verificato con la precedente e ti dice cosa è cambiato. Con le scansioni programmate o la ri-scansione al deploy, questo diventa un monitoraggio continuo con avvisi via email, Slack, Discord o un webhook firmato.
Gli avvisi sulle modifiche sono inclusi nei piani Pro, Agency e Team. Le scansioni programmate sono giornaliere o settimanali su Pro e Agency, e ogni ora su Team.
Cosa confronta AppSafe
- Problemi nuovi e risolti.
- Header di sicurezza aggiunti, rimossi o indeboliti (per esempio un Content-Security-Policy rimosso o un max-age HSTS più breve).
- Sostituzioni del certificato TLS e avvisi di scadenza 14 e 3 giorni prima che il certificato scada.
- Nuovi domini di script di terze parti e script esterni senza Subresource Integrity (SRI).
- Nuovi sottodomini del tuo dominio nei log di Certificate Transparency (crt.sh) e sottodomini il cui CNAME punta a una risorsa eliminata su un servizio di hosting. Vengono usate solo query DNS passive.
- Modifiche ai record SPF, DMARC, CAA e MX.
Gli avvisi vengono inviati per le scansioni programmate e per quelle al deploy, una sola volta per problema: un problema che resta invariato non genera un nuovo avviso alla scansione successiva. Se scompare e poi ricompare, riceverai di nuovo un avviso.
Configura gli avvisi
Apri un sito verificato nella tua dashboard e aggiungi i canali in Monitoraggio e avvisi. Ogni canale ha una gravità minima e un pulsante Invia avviso di prova.
- Email: Qualsiasi indirizzo email. Gli avvisi sono scritti nella lingua del tuo account.
- Slack: L’URL di un incoming webhook di un’app Slack (https://hooks.slack.com/services/…).
- Discord: L’URL del webhook di un canale (Impostazioni server → Integrazioni → Webhook).
- Webhook: Qualsiasi endpoint https. AppSafe invia in POST il payload JSON qui sotto, firmato con un secret mostrato una sola volta quando crei il canale.
Payload del webhook
I webhook generici ricevono questo JSON (Content-Type: application/json). Gli avvisi di prova usano l’evento monitoring.test e hanno scan impostato a null.
{
"event": "monitoring.changes",
"deliveryId": "5f2c9a0e41b7d3a8c6e1f0b2",
"createdAt": "2026-10-26T12:00:00.000Z",
"site": {
"domain": "myapp.com"
},
"scan": {
"id": "3f1c2b9e-1111-4222-8333-944455556666",
"grade": "C",
"score": 67,
"reportUrl": "https://appsafe.dev/report/…"
},
"summary": "2 changes on myapp.com",
"changes": [
{
"type": "header_removed",
"severity": "high",
"subject": "content-security-policy",
"message": "content-security-policy header removed"
},
{
"type": "finding_new",
"severity": "critical",
"subject": "baas-supabase-table-readable",
"title": "Supabase tables readable without logging in",
"message": "New issue: Supabase tables readable without logging in"
}
]
}Tipi di modifica: finding_new, finding_resolved, header_added, header_removed, header_weakened, header_changed, tls_changed, tls_expiring (con days), script_domain_new, sri_missing, subdomain_new, subdomain_dangling, dns_changed. Gravità: low, medium, high, critical. Gli avvisi includono solo le regressioni, quindi finding_resolved e header_added compaiono nella dashboard e nel report ma da soli non generano avvisi.
Verifica la firma
Ogni richiesta webhook ha un header X-AppSafe-Signature. Calcola un HMAC-SHA256 con il secret del canale su timestamp, un punto e il body grezzo della richiesta, e confrontalo con v1 in tempo costante. Rifiuta le richieste il cui timestamp è più vecchio di 5 minuti.
X-AppSafe-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of "<t>.<raw body>">
X-AppSafe-Event: monitoring.changes | monitoring.testimport { createHmac, timingSafeEqual } from "node:crypto";
// header: the X-AppSafe-Signature value, e.g. "t=1761480000,v1=5d41…"
// body: the raw request body (string), before JSON.parse
export function verifyAppSafeSignature(secret, header, body) {
const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
const timestamp = Number(parts.t);
if (!parts.v1 || Math.abs(Date.now() / 1000 - timestamp) > 300) return false;
const expected = createHmac("sha256", secret).update(`${timestamp}.${body}`).digest();
const given = Buffer.from(parts.v1, "hex");
return given.length === expected.length && timingSafeEqual(given, expected);
}AppSafe invia ogni avviso una sola volta e non riprova. Rispondi con uno stato 2xx entro 8 secondi. La dashboard mostra l’ultimo errore di consegna del canale.
Cosa non contengono mai gli avvisi
I payload degli avvisi contengono tipi di modifica, gravità, titoli dei problemi, nomi degli header, hostname di script e sottodomini e un link al report. Non contengono mai i dettagli dei problemi, secret (nemmeno oscurati) o dati personali.