Docs
Surveillance et alertes de changement
AppSafe compare chaque scan d’un site vérifié au précédent et vous indique ce qui a changé. Avec les scans planifiés ou le re-scan au déploiement, cela devient une surveillance continue avec des alertes par e-mail, Slack, Discord ou webhook signé.
Les alertes de changement sont incluses dans les plans Pro, Agency et Team. Les scans planifiés s’exécutent chaque jour ou chaque semaine sur Pro et Agency, et toutes les heures sur Team.
Ce qu’AppSafe compare
- Les problèmes nouveaux et résolus.
- Les en-têtes de sécurité ajoutés, supprimés ou affaiblis (par exemple une Content-Security-Policy supprimée ou un max-age HSTS plus court).
- Les remplacements de certificat TLS, et des avertissements 14 et 3 jours avant l’expiration du certificat.
- Les nouveaux domaines de scripts tiers, et les scripts externes sans Subresource Integrity.
- Les nouveaux sous-domaines de votre domaine dans les journaux Certificate Transparency (crt.sh), et les sous-domaines dont le CNAME pointe vers une ressource supprimée chez un hébergeur. Seules des requêtes DNS passives sont utilisées.
- Les changements des enregistrements SPF, DMARC, CAA et MX.
Les alertes sont envoyées pour les scans planifiés et les scans au déploiement, une seule fois par problème : un problème qui reste identique ne déclenche pas de nouvelle alerte au scan suivant. S’il disparaît puis revient, vous serez de nouveau alerté.
Configurer les alertes
Ouvrez un site vérifié dans votre tableau de bord et ajoutez des canaux dans Surveillance et alertes. Chaque canal a une gravité minimale et un bouton Envoyer une alerte de test.
- E-mail: N’importe quelle adresse e-mail. Les alertes sont rédigées dans la langue de votre compte.
- Slack: Une URL d’incoming webhook d’une app Slack (https://hooks.slack.com/services/…).
- Discord: Une URL de webhook de salon (Paramètres du serveur → Intégrations → Webhooks).
- Webhook: N’importe quel endpoint https. AppSafe envoie en POST le payload JSON ci-dessous, signé avec un secret affiché une seule fois à la création du canal.
Payload du webhook
Les webhooks génériques reçoivent ce JSON (Content-Type: application/json). Les alertes de test utilisent l’événement monitoring.test et ont scan à 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"
}
]
}Types de changement : finding_new, finding_resolved, header_added, header_removed, header_weakened, header_changed, tls_changed, tls_expiring (avec days), script_domain_new, sri_missing, subdomain_new, subdomain_dangling, dns_changed. Gravités : low, medium, high, critical. Les alertes ne contiennent que les régressions : finding_resolved et header_added apparaissent dans le tableau de bord et le rapport, mais ne déclenchent pas d’alerte à eux seuls.
Vérifier la signature
Chaque requête webhook comporte un en-tête X-AppSafe-Signature. Calculez un HMAC-SHA256 avec le secret de votre canal sur le timestamp, un point et le corps brut de la requête, puis comparez-le à v1 en temps constant. Rejetez les requêtes dont le timestamp date de plus de 5 minutes.
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 envoie chaque alerte une seule fois, sans nouvelle tentative. Répondez avec un statut 2xx en moins de 8 secondes. Le tableau de bord affiche la dernière erreur d’envoi du canal.
Ce que les alertes ne contiennent jamais
Les payloads d’alerte contiennent les types de changement, les gravités, les titres des problèmes, les noms d’en-têtes, les noms d’hôte des scripts et sous-domaines, et un lien vers le rapport. Ils ne contiennent jamais le détail des problèmes, de secrets (même masqués) ni de données personnelles.