フレームワーク別
Next.jsのセキュリティ対策 — Server Actions・環境変数・依存CVEの守り方
Next.jsは既定が安全寄りですが、事故は『サーバーとクライアントの境界』で起きます。三大=環境変数の露出(サーバー専用の秘密をクライアントに)/Server Actions・Route Handlersの認可漏れ/依存パッケージの既知CVE(本体RCE含む)。境界を意識し秘密をサーバー限定に・所有者チェック・CVE監視で守る方法を、攻撃手順を伏せて解説します。
対象:Next.jsでアプリを運営している人。ここでは攻撃手順は扱わず、サーバーとクライアントの境界で起きる事故と、その塞ぎ方を解説します。全体像は フレームワーク別セキュリティの入口 も参照。
三大落とし穴(境界で起きる)
Next.jsのエスケープやルーティングは優秀ですが、次の3つは開発者が境界を意識して塞ぐ領域です。
① 環境変数の露出
NEXT_PUBLIC_ の誤用や、秘密をクライアントに渡す。バンドルに焼き込まれ閲覧者に見える。
② アクションの認可漏れ
Server Actions / Route Handlers に所有者チェック無し。ID差し替えで他人のデータを操作。
③ 依存の既知CVE
本体・依存の既知脆弱性(RCE含む)を放置。実稼働版で判定し即パッチ。
塞ぎ方(3ステップ)
秘密はサーバー限定にする
NEXT_PUBLIC_ を付け、APIキー・接続情報など秘密には付けない。秘密はサーバーコンポーネント/Server Actions/Route Handler の中だけで読み、propsやレスポンスに混ぜない。(→ .envと秘密情報)Server Actions / Route Handlers で認可を毎回確認
依存CVEを機械監視して即パッチ
やりがち(危険)
- 秘密に
NEXT_PUBLIC_を付けてクライアントに露出 - Server Actions を「ログインしていれば実行可」に
- 外部URL取得をサーバーで無防備に(SSRF)
- 依存の既知CVEを放置
正しい
- 秘密はサーバー限定・クライアントに渡さない
- アクションで所有者スコープの認可
- URL取得はSSRF対策(内部IP遮断・許可先限定)
- 依存CVEを機械監視+即パッチ
当サイトの視点:本体より『境界と依存』を管理する
当サイトはNext.jsで動いており、実際に守りの重心を置いているのは派手な設定ではなく「サーバー/クライアントの境界」と「依存の鮮度」です。秘密は必ずサーバー側に留め、公開入口(Server Actions / Route Handlers)には認可を必ず書き、依存は毎デプロイ前にCVE監査する。当サイトの出自も“放置CVEの自動悪用”という事故なので、依存の機械監視は最優先の習慣です。外部URLを取得する処理は自前のSSRF安全ゲートウェイを通し、内部IPやメタデータへ到達させません(→ SSRFとは)。
次に読む
- 入口:フレームワーク別セキュリティ(入口) / Laravelのセキュリティ対策
- 依存:CVEに後れを取らないしくみ / 脆弱性(CVE)対応の実務
- 用語:IDORとは / SSRFとは / .envと秘密情報
よくある質問
QNext.jsは安全なフレームワークですか?
Next.jsは出力エスケープなど安全な既定を備え、素の状態では比較的堅いです。ただし事故は本体の既定ではなく『サーバーとクライアントの境界』の扱いで起きます。サーバー専用のはずの秘密がクライアントに載ってしまう、Server Actions に認可を書き忘れる、依存パッケージの既知CVEを放置する——この3つが実運用での主な穴です。既定に頼りきらず、境界と依存を自分で管理する必要があります。
Q環境変数はどう扱えば安全ですか?
原則は『秘密はサーバーだけ』です。ブラウザに載せてよい値だけ NEXT_PUBLIC_ を付け、APIキーや接続情報など秘密には絶対に付けません(NEXT_PUBLIC_ はビルド時にクライアントバンドルへ焼き込まれ、閲覧者から見えます)。秘密はサーバーコンポーネント/Server Actions/Route Handler の中だけで読み、クライアントへ渡さない。誤ってpropsやレスポンスに混ぜない設計にします。
QServer Actions で気をつけることは?
Server Actions や Route Handlers は『公開されたサーバーの入口』です。呼び出せる=実行してよい、ではありません。ログイン(認証)に加えて、その操作対象が本当にそのユーザーのものかを毎回スコープする認可を書きます。認可を書き忘れると、IDを差し替えるだけで他人のデータを更新・削除できてしまいます(認証≠認可)。入力の検証と併せて、アクション側で必ず所有者チェックを行ってください。