背景
POST /feedback は誰からでも・どこからでも受け付ける。公開デプロイすると spam / ゴミデータ / 悪意ある payload の投入が可能になり、受け取り側にもリスクがある(後述の SVG の件など)。widget と receiver の間に「ペア認証」的な仕組みが欲しい。
前提の整理
公開デモページに埋める widget はブラウザで動くため、埋め込んだキーは閲覧者全員に見える。したがってここでの ingest key は「秘密による認証」ではなく、(a) プロジェクト識別、(b) 無差別 spam の抑止、(c) キーのローテーションによる失効、を目的とした軽量な仕組みになる。本気のレビュアー認証はデモ側にログインがある前提で署名付き token を発行する形(将来スコープ)。
スコープ
ペア認証(ingest key)
- widget init に
ingestKey(プロジェクトごとの公開キー)を追加し、payload またはヘッダーで送る
- receiver 側 config に許可キーのリストを持ち、不一致は 401/403 で拒否
- キーごとに projectId を紐付けてもよい(payload の projectId 詐称対策)
受信データの安全な取り扱い
- screenshot SVG の stored XSS 対策(重要): 保存した SVG は
<script> や onload を含み得る。inbox の <img> 表示では実行されないが、GET /screenshots/:file を直接開くと receiver オリジンで実行される。対策候補:
- 配信時に
Content-Security-Policy: sandbox / script-src 'none' を付ける(最小・推奨)
- もしくは
Content-Disposition: attachment
- もしくは保存時に SVG をサニタイズ(script / イベント属性 / foreignObject 内の危険要素除去は難しいので CSP 推奨)
- Origin / Referer の allowlist チェック(CORS とは別にサーバー側でも検証)
- rate limit(IP ごと / キーごと)と保存件数・ディスク使用量の上限
- 既存の防御の維持: payload shape validation / MAX_BODY_BYTES / SCREENSHOT_MAX_BYTES / mime type 制限 / inbox の HTML escape
受け入れ条件
- ingest key を設定した receiver は、キーなし・不正キーの
POST /feedback を拒否する
- ローカル開発(キーなし運用)は引き続き動く
- screenshot を直接開いても script が実行されない
- README に設定方法が記載されている
関連
- 管理面(inbox 閲覧・操作)の認証は別 issue(公開デプロイ時のハードニング)
背景
POST /feedbackは誰からでも・どこからでも受け付ける。公開デプロイすると spam / ゴミデータ / 悪意ある payload の投入が可能になり、受け取り側にもリスクがある(後述の SVG の件など)。widget と receiver の間に「ペア認証」的な仕組みが欲しい。前提の整理
公開デモページに埋める widget はブラウザで動くため、埋め込んだキーは閲覧者全員に見える。したがってここでの ingest key は「秘密による認証」ではなく、(a) プロジェクト識別、(b) 無差別 spam の抑止、(c) キーのローテーションによる失効、を目的とした軽量な仕組みになる。本気のレビュアー認証はデモ側にログインがある前提で署名付き token を発行する形(将来スコープ)。
スコープ
ペア認証(ingest key)
ingestKey(プロジェクトごとの公開キー)を追加し、payload またはヘッダーで送る受信データの安全な取り扱い
<script>やonloadを含み得る。inbox の<img>表示では実行されないが、GET /screenshots/:fileを直接開くと receiver オリジンで実行される。対策候補:Content-Security-Policy: sandbox/script-src 'none'を付ける(最小・推奨)Content-Disposition: attachment受け入れ条件
POST /feedbackを拒否する関連