ドキュメント
モニタリングと変更アラート
AppSafeは確認済みサイトの各スキャンを前回のスキャンと比較し、何が変わったかをお知らせします。定期スキャンやデプロイ時の再スキャンと組み合わせれば、メール、Slack、Discord、または署名付きWebhookによるアラート付きの継続的なモニタリングになります。
変更アラートはPro、Agency、Teamプランに含まれています。定期スキャンはProとAgencyでは毎日または毎週、Teamでは毎時実行されます。
AppSafeが比較する項目
- 新しい指摘と解決済みの指摘。
- 追加、削除、または弱められたセキュリティヘッダー(例:削除されたContent-Security-Policyや、短くなったHSTSのmax-age)。
- TLS証明書の置き換えと、証明書の有効期限の14日前と3日前の警告。
- 新しいサードパーティスクリプトのドメインと、Subresource Integrity(SRI)のない外部スクリプト。
- Certificate Transparencyログ(crt.sh)に現れたドメインの新しいサブドメインと、CNAMEがホスティングサービス上の削除済みリソースを指しているサブドメイン。これらはパッシブなDNSルックアップのみを使用します。
- SPF、DMARC、CAA、MXレコードの変更。
アラートは定期スキャンとデプロイ時のスキャンで、問題ごとに1回送信されます。変わらず残っている問題は、次回のスキャンで再びアラートされません。問題が解消された後に再発した場合は、再度アラートされます。
アラートを設定する
ダッシュボードで確認済みサイトを開き、「モニタリングとアラート」でチャネルを追加します。各チャネルには最低重大度と「テストアラートを送信」ボタンがあります。
- メール: 任意のメールアドレス。アラートはアカウントの言語で書かれます。
- Slack: SlackアプリのIncoming Webhook URL(https://hooks.slack.com/services/…)。
- Discord: チャンネルのWebhook URL(サーバー設定 → 連携サービス → ウェブフック)。
- Webhook: 任意のhttpsエンドポイント。AppSafeは下記のJSONペイロードをPOSTします。ペイロードは、チャネル作成時に一度だけ表示されるシークレットで署名されます。
Webhookのペイロード
汎用WebhookはこのJSONを受け取ります(Content-Type: application/json)。テストアラートはイベント monitoring.test を使用し、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"
}
]
}変更の種類:finding_new、finding_resolved、header_added、header_removed、header_weakened、header_changed、tls_changed、tls_expiring(days付き)、script_domain_new、sri_missing、subdomain_new、subdomain_dangling、dns_changed。重大度:low、medium、high、critical。アラートには悪化した変更のみが含まれるため、finding_resolved と header_added はダッシュボードとレポートには表示されますが、それだけではアラートは送信されません。
署名を検証する
すべてのWebhookリクエストにはX-AppSafe-Signatureヘッダーが付きます。タイムスタンプ、ドット、生のリクエストボディを連結したものに対して、チャネルのシークレットでHMAC-SHA256を計算し、v1と定数時間で比較してください。タイムスタンプが5分より古いリクエストは拒否してください。
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は各アラートを1回だけ送信し、再試行しません。8秒以内に2xxステータスで応答してください。ダッシュボードにはチャネルの前回の配信エラーが表示されます。
アラートに決して含まれないもの
アラートのペイロードには、変更の種類、重大度、指摘のタイトル、ヘッダー名、スクリプトとサブドメインのホスト名、レポートへのリンクが含まれます。指摘の詳細、シークレット(マスク済みのものも含む)、個人データは決して含まれません。