aws-samples / aws-samples/serverless-full-stack-webapp-starter-kit
security(webapp): 兄弟サブドメインからの CSRF を防ぐため Server Actions の allowedOrigins を厳格化する
- Vorherrschende Sprache
- TypeScript
- Sterne
- 229
- Forks
- 45
- Ø Merge
- 1 Min.
- Gemergte PRs (30 T.)
- 4
Beschreibung
executor 07(全コードベースのコードレビュー)が発見し、独立したセキュリティレビュー(サブエージェント, opus-4.7)で裏付けた。
## 問題
`apps/cdk/lib/constructs/webapp.ts` は Docker ビルド引数 `ALLOWED_ORIGIN_HOST` を、カスタムドメイン分岐では `*.${hostedZone.zoneName}` に(CloudFront デフォルト分岐では `*.cloudfront.net` に)設定している。その値は `apps/webapp/next.config.ts` に取り込まれ、`experimental.serverActions.allowedOrigins` に渡される。
`serverActions.allowedOrigins` は CORS リストではなく、Next.js のデフォルトの CSRF 保護(Origin/Host の一致)を抑制する許可リストである。ワイルドカードを追加すると、そのホストゾーンの任意の兄弟サブドメイン(アプリが所有していない、新規登録された、乗っ取られた、他テナントと共有されているサブドメインを含む)が同一アプリのオリジンとして扱われ、認証済みの Server Actions をアプリに対して送信できてしまう。兄弟サブドメインは same-site であるため、`SameSite=Lax` クッキーではこれを防げない。
`*.cloudfront.net` のフォールバックはさらに悪く、インターネット上の _すべての_ CloudFront ディストリビューションを信頼された CSRF オリジンにしてしまう。
一次情報: https://nextjs.org/docs/app/api-reference/config/next-config-js/serverActions (Server Actions allowedOrigins / 組み込みの CSRF 保護)。
## 根拠
- `apps/cdk/lib/constructs/webapp.ts:80` — `ALLOWED_ORIGIN_HOST: hostedZone ? \`_.${hostedZone.zoneName}\` : '_.cloudfront.net'`
- `apps/webapp/next.config.ts:3-18` — ビルド引数から `allowedOrigins` を構築。
## 対応の方向性(要議論)
- カスタムドメイン分岐: 具体的なホスト(`${subDomain}.${hostedZone.zoneName}`、現状は `web.${zone}`)を渡し、ブラウザの Origin と一致させる。
- CloudFront デフォルト分岐: ドメインはデプロイ時に判明し、Lambda ↔ CloudFront の循環依存を生む(コード内で既に文書化済み)ため、「正確なホストを渡すだけ」では不十分。検討する選択肢: (a) デフォルトの `same-origin` 挙動を受け入れ、ビルド引数を完全に削除する(同一ホストから送信される Server Actions は Origin/Host 一致で成功する); (b) `AMPLIFY_APP_ORIGIN_SOURCE_PARAMETER` を既に更新している既存の `AwsCustomResource` を通じて、実行時に `ALLOWED_ORIGIN_HOST` を更新する。
この修正はエンドツーエンド(Lambda Function URL のレスポンスストリーミング → Next.js Server Actions を通じた `x-forwarded-host` の伝播)で検証する必要があるため、盲目的にマージするのではなく議論用の issue として起票する。
## サンプルとしての教育的リスク
このサンプルは、`allowedOrigins` をあたかも寛容な CORS リストであるかのように設定することを新規ユーザーに教えてしまう。コピーしたアプリが `beta.${zone}` や実験的なサブドメインを追加すると、同一ホストゾーンの任意のサブドメインに対する暗黙の信頼を引き継ぐ。
## 関連
- executor 07 の発見まとめ: `.kiro/specs/v3-release-prep/review-full-report.md` (H2)
- #173 の重複ではない(あちらはセッションキャッシュに関するもので CSRF ではない)。
Beitragsleitfaden
Rechercherichtung
Lies apps/cdk/lib/constructs/webapp.ts und apps/webapp/next.config.ts, um nachzuverfolgen, wie ALLOWED_ORIGIN_HOST in serverActions.allowedOrigins übernommen wird; prüfe außerdem .kiro/specs/v3-release-prep/review-full-report.md. Entscheide über die Strategie für benutzerdefinierte Domains und CloudFront und validiere anschließend anhand des Response-Streamings von Lambda Function URL und der Next.js Server Actions, dass nur die vorgesehenen Origins akzeptiert werden.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Bewertung
- Tech-Stack
- aws, nextjs, typescript
- Bereich
- backend, infrastructure, security
- Issue-Typ
- Bug
- Schwierigkeit
- 5/5
- Geschätzter Aufwand
- Über eine Woche
- Aktivitätsstatus
- Ruhig
- Klarheit
- Größtenteils klar
- Anfängerfreundlichkeit
- 35/100