Dokümanlar
İzleme ve değişiklik uyarıları
AppSafe, doğrulanmış bir sitenin her taramasını bir öncekiyle karşılaştırır ve neyin değiştiğini söyler. Zamanlanmış taramalar veya deploy'da yeniden tarama ile bu, e-posta, Slack, Discord veya imzalı bir webhook üzerinden uyarılarla sürekli izlemeye dönüşür.
Değişiklik uyarıları Pro, Agency ve Team planlarına dahildir. Zamanlanmış taramalar Pro ve Agency'de günlük veya haftalık, Team'de saatlik çalışır.
AppSafe neleri karşılaştırır
- Yeni ve çözülen bulgular.
- Eklenen, kaldırılan veya zayıflatılan güvenlik header'ları (örneğin kaldırılmış bir Content-Security-Policy veya kısaltılmış bir HSTS max-age).
- TLS sertifikası değişiklikleri ve sertifikanın süresi dolmadan 14 ve 3 gün önce gönderilen uyarılar.
- Yeni üçüncü taraf script alan adları ve Subresource Integrity (SRI) olmayan harici script'ler.
- Alan adının Certificate Transparency kayıtlarındaki (crt.sh) yeni alt alan adları ve CNAME kaydı bir hosting servisinde silinmiş bir kaynağa işaret eden alt alan adları. Bunlar yalnızca pasif DNS sorguları kullanır.
- SPF, DMARC, CAA ve MX kayıt değişiklikleri.
Uyarılar zamanlanmış ve deploy sonrası taramalar için, her sorun için bir kez gönderilir: aynı kalan bir sorun bir sonraki taramada yeniden uyarı oluşturmaz. Sorun ortadan kalkıp geri gelirse yeniden uyarılırsın.
Uyarıları kur
Panelinde doğrulanmış bir siteyi aç ve İzleme ve uyarılar bölümünden kanal ekle. Her kanalın bir minimum önem derecesi ve bir Test uyarısı gönder düğmesi vardır.
- E-posta: Herhangi bir e-posta adresi. Uyarılar hesabının dilinde yazılır.
- Slack: Bir Slack uygulamasından alınan incoming webhook URL'si (https://hooks.slack.com/services/…).
- Discord: Bir kanal webhook URL'si (Sunucu Ayarları → Entegrasyonlar → Webhook'lar).
- Webhook: Herhangi bir https endpoint'i. AppSafe aşağıdaki JSON payload'ını, kanalı oluşturduğunda bir kez gösterilen bir secret ile imzalayarak POST eder.
Webhook payload'ı
Genel webhook'lar bu JSON'u alır (Content-Type: application/json). Test uyarıları monitoring.test olayını kullanır ve scan değeri null olur.
{
"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"
}
]
}Değişiklik türleri: finding_new, finding_resolved, header_added, header_removed, header_weakened, header_changed, tls_changed, tls_expiring (days ile), script_domain_new, sri_missing, subdomain_new, subdomain_dangling, dns_changed. Önem dereceleri: low, medium, high, critical. Uyarılar yalnızca gerilemeleri içerir; bu yüzden finding_resolved ve header_added panelde ve raporda görünür ama tek başlarına uyarı tetiklemez.
İmzayı doğrula
Her webhook isteğinde bir X-AppSafe-Signature header'ı bulunur. Kanal secret'ınla zaman damgası, bir nokta ve ham istek gövdesi üzerinden HMAC-SHA256 hesapla ve sabit zamanlı olarak v1 ile karşılaştır. Zaman damgası 5 dakikadan eski olan istekleri reddet.
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 her uyarıyı bir kez gönderir ve yeniden denemez. 8 saniye içinde 2xx durum koduyla yanıt ver. Panel, kanalın son gönderim hatasını gösterir.
Uyarıların asla içermediği şeyler
Uyarı payload'ları değişiklik türlerini, önem derecelerini, bulgu başlıklarını, header adlarını, script ve alt alan adı hostname'lerini ve rapora bir bağlantıyı içerir. Bulgu ayrıntılarını, secret'ları (maskelenmiş olanları bile) veya kişisel verileri asla içermez.