ドキュメント

モニタリングと変更アラート

AppSafeは確認済みサイトの各スキャンを前回のスキャンと比較し、何が変わったかをお知らせします。定期スキャンやデプロイ時の再スキャンと組み合わせれば、メール、Slack、Discord、または署名付きWebhookによるアラート付きの継続的なモニタリングになります。

変更アラートはPro、Agency、Teamプランに含まれています。定期スキャンはProとAgencyでは毎日または毎週、Teamでは毎時実行されます。

AppSafeが比較する項目

アラートは定期スキャンとデプロイ時のスキャンで、問題ごとに1回送信されます。変わらず残っている問題は、次回のスキャンで再びアラートされません。問題が解消された後に再発した場合は、再度アラートされます。

アラートを設定する

ダッシュボードで確認済みサイトを開き、「モニタリングとアラート」でチャネルを追加します。各チャネルには最低重大度と「テストアラートを送信」ボタンがあります。

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.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は各アラートを1回だけ送信し、再試行しません。8秒以内に2xxステータスで応答してください。ダッシュボードにはチャネルの前回の配信エラーが表示されます。

アラートに決して含まれないもの

アラートのペイロードには、変更の種類、重大度、指摘のタイトル、ヘッダー名、スクリプトとサブドメインのホスト名、レポートへのリンクが含まれます。指摘の詳細、シークレット(マスク済みのものも含む)、個人データは決して含まれません。