Dokumentasi
Pemantauan dan peringatan perubahan
AppSafe membandingkan setiap pemindaian situs terverifikasi dengan pemindaian sebelumnya dan memberi tahu apa yang berubah. Dengan pemindaian terjadwal atau pindai ulang saat deploy, ini menjadi pemantauan berkelanjutan dengan peringatan lewat email, Slack, Discord, atau webhook bertanda tangan.
Peringatan perubahan sudah termasuk dalam paket Pro, Agency, dan Team. Pemindaian terjadwal berjalan harian atau mingguan di Pro dan Agency, dan per jam di Team.
Apa yang dibandingkan AppSafe
- Temuan baru dan yang sudah teratasi.
- Header keamanan yang ditambahkan, dihapus, atau dilemahkan (misalnya Content-Security-Policy yang dihapus atau max-age HSTS yang lebih pendek).
- Penggantian sertifikat TLS, serta peringatan kedaluwarsa 14 dan 3 hari sebelum sertifikat kedaluwarsa.
- Domain skrip pihak ketiga baru, dan skrip eksternal tanpa Subresource Integrity (SRI).
- Subdomain baru dari domainmu di log Certificate Transparency (crt.sh), dan subdomain yang CNAME-nya mengarah ke resource yang sudah dihapus di layanan hosting. Pemeriksaan ini hanya memakai lookup DNS pasif.
- Perubahan record SPF, DMARC, CAA, dan MX.
Peringatan dikirim untuk pemindaian terjadwal dan pemindaian saat deploy, sekali per temuan: temuan yang tetap sama tidak akan memicu peringatan lagi di pemindaian berikutnya. Jika temuan itu hilang lalu muncul kembali, kamu akan mendapat peringatan lagi.
Atur peringatan
Buka situs terverifikasi di dashboard-mu dan tambahkan saluran di bagian Pemantauan & peringatan. Setiap saluran punya tingkat keparahan minimum dan tombol Kirim peringatan uji.
- Email: Alamat email apa pun. Peringatan ditulis dalam bahasa akunmu.
- Slack: URL incoming webhook dari aplikasi Slack (https://hooks.slack.com/services/…).
- Discord: URL webhook channel (Pengaturan Server → Integrasi → Webhook).
- Webhook: Endpoint https apa pun. AppSafe mengirim POST berisi payload JSON di bawah, ditandatangani dengan secret yang ditampilkan sekali saat kamu membuat saluran.
Payload webhook
Webhook generik menerima JSON ini (Content-Type: application/json). Peringatan uji memakai event monitoring.test dan scan bernilai 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"
}
]
}Jenis perubahan: finding_new, finding_resolved, header_added, header_removed, header_weakened, header_changed, tls_changed, tls_expiring (dengan days), script_domain_new, sri_missing, subdomain_new, subdomain_dangling, dns_changed. Tingkat keparahan: low, medium, high, critical. Peringatan hanya mencakup regresi, jadi finding_resolved dan header_added muncul di dashboard dan laporan tetapi tidak memicu peringatan dengan sendirinya.
Verifikasi tanda tangan
Setiap permintaan webhook memiliki header X-AppSafe-Signature. Hitung HMAC-SHA256 dengan secret salurannya atas timestamp, sebuah titik, dan body permintaan mentah, lalu bandingkan dengan v1 dalam waktu konstan. Tolak permintaan yang timestamp-nya lebih lama dari 5 menit.
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 mengirim setiap peringatan sekali dan tidak mencoba ulang. Balas dengan status 2xx dalam 8 detik. Dashboard menampilkan error pengiriman terakhir saluran tersebut.
Yang tidak pernah ada di peringatan
Payload peringatan berisi jenis perubahan, tingkat keparahan, judul temuan, nama header, hostname skrip dan subdomain, serta link ke laporan. Payload tidak pernah berisi detail temuan, secret (bahkan yang sudah disamarkan), atau data pribadi.