ベータ版(30-50人)リリース前の総点検で2件のセキュリティ問題を検出。 コードレビュー(code-reviewer エージェント)+ context7(Vonage API docs)+ 手動レビューの3重チェック結果。 どちらも小さな修正で防御を強化できる。
line_user_id チェック追加ファイル: src/index.ts 642-653行目
問題: action=cancel の Postback 処理で、リマインダーの所有者チェックがない。
SELECT/UPDATE ともに id だけで絞り込んでおり、line_user_id 条件がない。
リスク: LINE署名検証済みのため実際の悪用は極めて困難だが、defense-in-depth として必須。
修正:
// SELECT: AND line_user_id = ? を追加
const reminder = await c.env.DB.prepare(
"SELECT id, content FROM reminders WHERE id = ? AND line_user_id = ? AND status = 'pending'",
).bind(id, userId).first<{ id: number; content: string }>();
// UPDATE: AND line_user_id = ? を追加
await c.env.DB.prepare(
"UPDATE reminders SET status = 'cancelled' WHERE id = ? AND line_user_id = ?",
).bind(reminder.id, userId).run();
テスト: src/index.test.ts に「他ユーザーのリマインダーはキャンセルできない」テストを1件追加。
/vonage-events に共有シークレットトークン認証を追加ファイル: src/index.ts 1429-1461行目
問題: /vonage-events エンドポイントが完全に認証なし。
URL POST https://remindenwa.com/vonage-events は推測可能で、
外部から { uuid: "...", status: "completed" } を送り込めば通話ステータスを偽装できる。
調査結果: context7 で Vonage Voice API docs を確認。Vonage は webhook コールバックに署名ヘッダーを付与しない(LINEの HMAC-SHA256 とは異なる)。標準的な対策は 共有シークレットトークンをクエリパラメータで渡す方式。
修正:
app.post("/vonage-events", async (c) => {
const token = c.req.query("token");
if (!c.env.VONAGE_WEBHOOK_SECRET || token !== c.env.VONAGE_WEBHOOK_SECRET) {
return c.text("Unauthorized", 401);
}
// ...既存処理
});
設定変更:
worker-configuration.d.ts に VONAGE_WEBHOOK_SECRET: string を追加VONAGE_WEBHOOK_SECRET を設定: npx wrangler secret put VONAGE_WEBHOOK_SECREThttps://remindenwa.com/vonage-events?token=YOUR_SECRET に変更Note: caller.ts は per-call event_url を使っていない(アプリレベル設定のみ)。コード変更は不要。
テスト: src/vonage-events.test.ts に認証テストを追加(トークンなし→401、正しいトークン→200)。
| 項目 | 判定理由 |
|---|---|
| timing-safe署名比較 | todo.md記載済み。30-50人でタイミング攻撃は非現実的 |
| jwt.ts単体テスト | モック化済み。壊れればcron全体が失敗し即発覚 |
| 認証コードのハッシュ化 | 4桁+10分TTL+段階式クールダウン+10回BANの多層防御で十分 |
| wrangler.tomlのLINE User ID | 秘密情報ではない。リポジトリがprivateなら許容 |
各修正を RED → GREEN → REFACTOR の TDD サイクルで実装する。
line_user_id チェックAND line_user_id = ? を追加 → テスト通過/vonage-events のトークン認証YAGNI 判定した項目を以下に記録:
docs/PRODUCT-OVERVIEW.md — セクション8「将来の技術改善」に追記docs/todo.md — Phase 3 または調査セクションに追記tsc --noEmit — 型チェックpnpm test — 全テスト通過(新規テスト含む)