Documentación

Monitorización y alertas de cambios

AppSafe compara cada escaneo de un sitio verificado con el anterior y te dice qué cambió. Con los escaneos programados o el reescaneo al desplegar, eso se convierte en una monitorización continua con alertas por email, Slack, Discord o un webhook firmado.

Las alertas de cambios están incluidas en los planes Pro, Agency y Team. Los escaneos programados se ejecutan a diario o cada semana en Pro y Agency, y cada hora en Team.

Qué compara AppSafe

Las alertas se envían en los escaneos programados y al desplegar, una vez por problema: un problema que sigue igual no volverá a generar una alerta en el siguiente escaneo. Si desaparece y vuelve, recibirás una nueva alerta.

Configura las alertas

Abre un sitio verificado en tu panel y añade canales en Monitorización y alertas. Cada canal tiene una severidad mínima y un botón Enviar alerta de prueba.

Payload del webhook

Los webhooks genéricos reciben este JSON (Content-Type: application/json). Las alertas de prueba usan el evento monitoring.test y tienen scan con valor 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"
    }
  ]
}

Tipos de cambio: 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. Severidades: low, medium, high, critical. Las alertas solo incluyen regresiones, así que finding_resolved y header_added aparecen en el panel y en el informe, pero no generan alertas por sí solos.

Verifica la firma

Cada solicitud de webhook lleva un encabezado X-AppSafe-Signature. Calcula un HMAC-SHA256 con el secreto de tu canal sobre el timestamp, un punto y el cuerpo sin procesar de la solicitud, y compáralo con v1 en tiempo constante. Rechaza las solicitudes cuyo timestamp tenga más de 5 minutos.

X-AppSafe-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of "<t>.<raw body>">
X-AppSafe-Event: monitoring.changes | monitoring.test
import { 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 envía cada alerta una sola vez y no reintenta. Responde con un estado 2xx en menos de 8 segundos. El panel muestra el último error de envío del canal.

Lo que las alertas nunca contienen

Los payloads de las alertas contienen tipos de cambio, severidades, títulos de hallazgos, nombres de encabezados, hostnames de scripts y subdominios, y un enlace al informe. Nunca contienen detalles de los hallazgos, secretos (ni siquiera ocultos) ni datos personales.