メインコンテンツへスキップ
Vercel 本番運用
Vercel
Next.js
セキュリティ
脆弱性診断
インフラ

Vercel セキュリティ設定チェックリスト:環境変数・Deployment Protection・Git連携・Next.jsの境界まで

Vercel で Next.js を運用するチーム向けの設定監査チェックリスト。Config/Secret 型の環境変数、Deployment Protection の既定値、Git Fork Protection、Server Actions の認可、キャッシュ、Cron を2026年10月時点の公式情報で確認。

公開日
読了時間
20分
著者
友田 陽大
シェア

Vercel に Next.js を載せると、デプロイも TLS も DDoS 緩和も「何もしなくても動く」状態から始まります。そのせいで、利用者側で決めるべき設定が既定値のまま残りがちです。Preview に本番の鍵が入っている、本番ドメインが誰にでも開ける、個人ごとのレスポンスが CDN に載る。どれもダッシュボードとリポジトリを見比べれば見つかります。

この記事は、スタートアップで Next.js を Vercel に載せているテックリード向けの設定監査チェックリストです。各項目について「何を確認するか」「どこで設定するか」「既定値」「なぜ重要か」を並べます。機能名・既定値・プランの差は、2026年10月時点の Vercel と Next.js の公式ドキュメントで確かめたものです。Vercel は 2026年8〜9月にいくつかの機能の名前と料金体系を変えているので、古い記事の情報とは食い違う箇所があります。

環境変数と Firewall にはそれぞれ詳しい記事があるので、この記事では要点だけ書いてリンクします。


まず責任分界:Vercel が守るもの、あなたが決めるもの

結論:Vercel が責任を持つのは基盤(インフラ・ネットワーク・保存時の暗号化)です。環境変数の扱い、アプリの認証、ログの長期保管、どの機能を使うかの選択は利用者の責任です。

Vercel の Shared Responsibility Model は、利用者側の責任を具体的に挙げています。

領域Vercel利用者
インフラ・ネットワーク・コンピュートの分離責任を持つ—
通信中と保存時の暗号化(Vercel が管理するサービス)責任を持つ連携するサードパーティ側の安全確保
コードと環境変数—環境変数の露出を含むコード管理、APIキーなど秘密情報の適切な取り扱い
認証プラットフォームの認証と Deployment Protection を提供アプリの認証
ログ短期のランタイムログを提供長期保管・監査のための Drains の設定
インシデント対応Vercel が管理する基盤自分のコード・設定・連携

つまり「Vercel を使っているから安全」ではなく、Vercel が用意した仕組みをどう設定したかが利用者側の安全性を決めます。以下のチェックリストはその設定の棚卸しです。自分たちで見る時間が取れない場合は、Vercel 設定と Next.js のデプロイ境界のレビューで同じ観点を確認しています。


Vercel の設定、最後に棚卸ししたのはいつですか?

Vercel の設定と Next.js のデプロイ境界をレビューします

1. 環境変数と環境の分離

結論:鍵・トークン・パスワードは Secret 型で保存し、Preview と Production で値を分けます。NEXT_PUBLIC_ を付けた値はブラウザに配られるので、秘密を入れません。

確認すること場所既定値なぜ重要か
秘密値が Secret 型かProject Settings → Environment Variables(各変数の Type)種類を選んで保存するSecret は保存後に読み出せない(書き込み専用)。Config は権限のあるメンバーが後から読める
Separate Production Secret ValuesTeam Settings → Security(owner が有効化)任意のポリシー有効にすると、Production の Secret は Preview・Development・カスタム環境と同じ値にできない
Preview に本番の値がないか各変数の対象環境変数ごとに選ぶPreview には未レビューのブランチも載る。本番の鍵が入っていれば、そこが本番への入口になる
ブランチ別の Preview 変数変数の対象に特定ブランチを指定全非本番ブランチブランチ指定の値は、同名の Preview 変数を上書きする
NEXT_PUBLIC_ の中身コードと変数一覧—ビルド時に JS バンドルへインライン化され、ブラウザに届く
長期の鍵の代わりに OIDCProject Settings → Security / 接続先クラウド—AWS・GCP・Azure と短命トークンで接続でき、長期の資格情報を環境変数に置かずに済む

押さえておく変更点があります。2026年8月24日に、環境変数の「Sensitive」の切り替えは Config / Secret の2種類に置き換わりました。既存の Sensitive 変数は自動で Secret として扱われます。チームポリシーの「Enforce Sensitive Environment Variables」は非推奨になり、代わりに上の Separate Production Secret Values が用意されました。以前は Sensitive を Development に使えませんでしたが、Secret は Development でも使えます。

CLI では vercel env add に --type secret を付けます(--visibility は非推奨の別名)。

# 本番用の Secret を追加(値は対話入力)
vercel env add STRIPE_SECRET_KEY production --type secret

ビルドログには保護があり、32文字以上の Secret の値がビルドログに出ると [REDACTED] に置き換わります。ただし対象はビルドログだけです。ランタイムログでの置き換えはドキュメントに書かれていません(9章)。

カスタム環境(staging など)は Pro と Enterprise で作れます。NEXT_PUBLIC_ の落とし穴と型安全な env の境界は Vercel 環境変数・シークレット管理ガイド、秘密がクライアントに混ざる経路と検出方法は Next.js の環境変数から秘密が漏れる経路と防ぎ方で詳しく扱っています。


2. Deployment Protection:既定では本番ドメインは守られない

結論:新規プロジェクトの既定は Standard Protection で、Preview は守られますが本番ドメインは対象外です。本番も隠したいなら All Deployments を選びます。2026年9月9日以降、Vercel Authentication で All Deployments を守る設定は全プランで追加費用なしです。

確認すること場所既定値なぜ重要か
保護の範囲Project → Security → Deployment ProtectionStandard Protection(本番ドメイン以外を保護)本番カスタムドメインは Standard では守られない
All Deployments が要るか同上—社内ツールや公開前のサイトは、本番 URL も含めて閉じる
保護の方式同上—Vercel Authentication が推奨の方式。無効にすると既存のデプロイがすべて保護されない状態になる
Password Protection同上—Pro では有料のオプション(2026年9月9日からプロジェクト単位で購入)、Enterprise は込み。Hobby では使えない
Trusted IPs同上—Enterprise のみ。IPv4 アドレスと IPv4 CIDR
チームの既定値Team Settings—新規プロジェクトに適用する既定の保護レベルと方式を決められる

Standard Protection の範囲に注意してください。 公式の説明は「本番ドメイン以外のすべてのドメインを保護する」です。*.vercel.app のデプロイ固有 URL は保護されますが、example.com のような本番ドメインは誰でも開けます。

Vercel Authentication で保護されたデプロイを見られるのは、プロジェクトにアクセスできるチームメンバー、アクセスを許可された Vercel ユーザー、Shareable Link を受け取った人、後述のバイパス用ヘッダーを送るツールです。

例外の穴を点検する

保護を有効にしたら、次は例外として開けた穴を確認します。

  • Protection Bypass for Automation(全プラン):x-vercel-protection-bypass ヘッダー(またはクエリパラメータ)に秘密を付けると保護を通過できます。秘密はプロジェクトのすべてのデプロイに効き、取り消すまで有効です。CI・E2E テストなど用途ごとに複数作れるので、用途別に発行して不要になったものは消します。ヘッダーを付けられない Webhook 送信元にはクエリパラメータで渡せますが、その場合は秘密が相手側の設定画面に残ります。
  • Shareable Links(全プラン):特定ブランチのデプロイに、クエリパラメータ付きの URL で外部アクセスを許可します。配った先と取り消しを管理します。
  • OPTIONS Allowlist(全プラン):CORS のプリフライト用に、登録したパスで始まる OPTIONS リクエストの保護を外します。/api を登録すれば /api/v1/users も対象です。前方一致なので、必要最小限のパスにとどめます。

自動化ツールから保護されたデプロイに入る方法としては、ほかに Trusted Sources(短命の OIDC トークンを x-vercel-trusted-oidc-idp-token ヘッダーで送る)もあります。


3. Git 連携:誰のコミットがデプロイされるか

結論:フォークからの PR は承認なしにデプロイさせず、ビルドログとソースの公開設定を既定のまま閉じておきます。

確認すること場所既定値なぜ重要か
Git Fork ProtectionProject Settings → Security有効(無効化もできる)フォークからの PR のデプロイに、あなたかチームメンバーの承認を求める。環境変数と OIDC トークンの漏えいを防ぐ
コミット作者の確認設定項目なし常に適用非公開リポジトリでは、コミット作者が Vercel のプロジェクトにアクセスできる場合だけデプロイされる(GitHub の organization など組織配下のリポジトリが対象)
Require Verified CommitsProject Settings → Git無効GitHub で検証済みのコミットだけをデプロイし、それ以外は自動でキャンセルする(GitHub のみ)
Build Logs and Source ProtectionProject Settings → Security有効/_src(ソースとビルド出力)と /_logs(ビルドログ)をチームメンバーだけに限る

Git Fork Protection を無効にすると、外部の人が出した PR のコードがあなたの Preview 環境変数を使ってビルドされることになります。ドキュメントも「環境変数を確認するまで無効にしないこと」と注意しています。

Build Logs and Source Protection は、CLI の --public オプションや vercel.json の public プロパティで上書きされます。リポジトリに "public": true が残っていないか確認してください。また、この設定を切り替えても既存のデプロイには反映されません。


4. Next.js の境界:Server Actions は公開エンドポイント

結論:Server Actions と Route Handlers は、UI を経由せず直接呼べる公開 API として扱います。認証と認可は Proxy(旧 middleware)ではなく、各関数の中で確かめます。

Next.js の Data Security ガイドによると、作成して export した Server Action は、アプリの UI からだけでなく直接の POST リクエストで呼べます。コードのどこからも import されていなくても外部から呼べる、と明記されています。暗号化されたアクション ID などの保護もありますが、ガイドは「それでも各アクションの中で認証と認可を確かめる」よう求めています。

// app/invoices/actions.ts
"use server";

import { z } from "zod";
import { verifySession } from "@/lib/dal"; // server-only のデータアクセス層
import { db } from "@/lib/db";

const DeleteInvoiceInput = z.object({ invoiceId: z.uuid() });

export async function deleteInvoice(formData: FormData): Promise<void> {
  // 1. 認証:Proxy を通っていても、ここで必ず確かめる
  const session = await verifySession();
  if (!session) throw new Error("Unauthorized");

  // 2. 入力検証:直接 POST されうるので、引数の型を信用しない
  const { invoiceId } = DeleteInvoiceInput.parse({
    invoiceId: formData.get("invoiceId"),
  });

  // 3. 認可:対象が本人のものであることを削除条件に含める
  await db.invoice.deleteMany({
    where: { id: invoiceId, ownerId: session.userId },
  });
}

確認するポイントは次のとおりです。

  • Proxy だけで認可していないか。 Next.js 16 で middleware は非推奨になり、proxy に名前が変わりました。Proxy のドキュメントは、matcher の変更やリファクタで Server Function が別のルートに移ると Proxy の保護が黙って外れうるとして、「Proxy だけに頼らず各 Server Function の中で確かめる」よう書いています。認証ガイドも、Proxy では Cookie を読むだけの楽観的なチェックにとどめるよう勧めています。
  • CVE-2025-29927 の教訓。 2025年3月に公開されたこの脆弱性(深刻度 critical)は、認可チェックを middleware で行っている場合にそれを迂回できるというものでした。修正版は 15.2.3 / 14.2.25 / 13.5.9 / 12.3.5 です。アドバイザリには「Vercel でホストされた Next.js のデプロイは自動的に保護されている」と書かれており、Vercel 上のアプリが影響を受けたわけではありません。教訓は「middleware という1か所に認可を集めると、そこが外れたときに全部が外れる」という設計上の話です。
  • クロージャの暗号化に頼っていないか。 コンポーネント内で定義した Server Action が外側の変数を参照すると、その値はクライアントを往復します。Next.js は自動で暗号化しますが、ドキュメントは「暗号化だけに頼ることは勧めない」としています。秘密の値をクロージャに入れないようにします。
  • serverActions.allowedOrigins を広げすぎていないか。 Server Actions は POST でしか呼べず、Next.js は Origin ヘッダーと Host(または X-Forwarded-Host)を比べて CSRF を防ぎます。リバースプロキシの構成で必要なときだけ、allowedOrigins に許可するホストを足します。
  • process.env を読む場所を絞っているか。 Data Security ガイドは、import 'server-only' を付けたデータアクセス層だけが process.env を読む構成を勧めています。

5. 個人ごとのレスポンスをキャッシュさせない

結論:ユーザーごとに中身が変わるレスポンスには Cache-Control: private を付けます。Cookie で認証しているリクエストに s-maxage を返すと、CDN にキャッシュされる条件がそろうことがあります。

Vercel の CDN は、次のどれかに当てはまるレスポンスをキャッシュしません。

  • リクエストに Authorization ヘッダーがある
  • レスポンスに set-cookie ヘッダーがある
  • Cache-Control に private、no-cache、no-store のどれかがある
  • Vary: *、または Cookie のような値の種類が多いヘッダーを Vary に含む

Cache-Control の既定値は public, max-age=0, must-revalidate で、CDN にもブラウザにもキャッシュさせません。危ないのは、自分で s-maxage を付けたときです。Cookie ベースのセッションは Authorization ヘッダーを使わないので、上の除外条件に当たりません。ユーザー固有の JSON を返すルートに s-maxage を付け、set-cookie も返していなければ、そのレスポンスはキャッシュ対象になりえます。

// app/api/me/route.ts
import { verifySession } from "@/lib/dal";
import { getProfile } from "@/lib/profile";

export async function GET() {
  const session = await verifySession();
  if (!session) return new Response("Unauthorized", { status: 401 });

  const profile = await getProfile(session.userId);
  // 個人ごとのレスポンス:共有の CDN キャッシュに載せない
  return Response.json(profile, {
    headers: { "Cache-Control": "private, max-age=0" },
  });
}

2026年9月30日からは、Vary に Cookie を含むレスポンスを Vercel の CDN がキャッシュしなくなりました。これは安全側への変更ですが、Vercel は「Cookie に依存するレスポンスは Cache-Control: private を使う」よう案内しています。Vary: Cookie に頼らず、private を明示しておくのが確実です。キャッシュされなかったレスポンスは x-vercel-cache: MISS になり、ランタイムログに vary_key_denied:cookie が記録されます。


6. セキュリティヘッダー:既定は HSTS だけ

結論:Vercel のドキュメントで既定と明記されているセキュリティヘッダーは HSTS だけです。CSP などは自分で設定し、CSP は Report-Only から始めます。

ヘッダー既定対応
Strict-Transport-Securityあり(カスタムドメインは max-age=63072000、*.vercel.app は includeSubDomains; preload 付き)必要なら値を上書きする
Content-Security-PolicyなしReport-Only で観察してから強制する
X-Frame-Options / X-Content-Type-Options / Referrer-Policyドキュメントに既定の記載なし自分で設定する

設定場所は next.config.ts の headers()、vercel.json の headers、または vercel.ts です。vercel.ts と vercel.json はどちらか一方だけを使います。

// next.config.ts
import type { NextConfig } from "next";

// まずは Report-Only で違反を観察し、壊れないと確認してから
// キー名を Content-Security-Policy に切り替える
const csp = [
  "default-src 'self'",
  "script-src 'self'",
  "style-src 'self' 'unsafe-inline'",
  "img-src 'self' data: https:",
  "object-src 'none'",
  "base-uri 'self'",
  "frame-ancestors 'none'",
].join("; ");

const nextConfig: NextConfig = {
  async headers() {
    return [
      {
        source: "/:path*",
        headers: [
          { key: "Content-Security-Policy-Report-Only", value: csp },
          { key: "X-Content-Type-Options", value: "nosniff" },
          { key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
          { key: "X-Frame-Options", value: "DENY" },
        ],
      },
    ];
  },
};

export default nextConfig;

この設定のまま script-src 'self' を強制すると、Next.js の App Router がページに入れるインラインスクリプトは止まります。だからこの例は Report-Only で始め、違反レポートで確かめます。強制して動かせる方式は、Next.js の CSP ガイドが示す2つです。1つは nonce で、リクエストごとに nonce を作るので動的レンダリングが必須になります。もう1つはハッシュで、Subresource Integrity(SRI)によるハッシュベースの CSP は静的生成を保てますが、App Router 限定の実験的機能です。静的に配信しているページが多いアプリでは、この代償も含めて方式を選びます。


7. Firewall とレート制限

結論:カスタムルール、レート制限、Attack Mode、BotID の Basic はすべてのプランで使えます。ログイン・サインアップ・高コストな API には、少なくともレート制限を入れます。

機能プラン(2026年10月時点)確認すること
DDoS 緩和(L3・L4・L7)全プラン・自動設定不要
カスタムルール全プラン(Hobby 3 / Pro 40 / Enterprise 1000 まで)管理画面や管理 API へのアクセスを絞っているか
レート制限全プラン(Hobby はルール1つ)ログインや問い合わせフォームにかけているか。カウンタはリージョンごと
Attack Mode全プラン・無料攻撃時に誰が有効にするか決まっているか。自分の Functions と Cron は通過する
Bot Protection マネージドルールセット全プラン既定は無効
OWASP コアルールセットEnterprise のみPro では使えない前提で設計する
BotID(Basic)全プラン・無料サインアップや決済のような悪用されやすい操作に使うか

以前の「Attack Challenge Mode」は、現在のドキュメントでは Attack Mode という名前です。ルールの書き方や BotID の組み込み方は Vercel Firewall × WAF × BotID 実装ガイドにまとめています。入口の Firewall は多層防御の一層で、4章の認可の誤りは防げない点も忘れないでください。


8. Cron と Webhook:呼び出し元を確かめる

結論:Cron のエンドポイントは CRON_SECRET で認証し、未設定のときも拒否します。Webhook は送信元の署名を検証します。どちらも2回届いても壊れない処理にします。

Cron のエンドポイントは普通の HTTP ルートなので、そのままでは誰でも呼べます。プロジェクトに CRON_SECRET を設定すると、Vercel は Cron の実行時にその値を Authorization: Bearer <値> として送ります。Vercel は16文字以上のランダムな文字列を勧めています。

// app/api/cron/cleanup/route.ts
import { timingSafeEqual } from "node:crypto";
import { purgeExpiredSessions } from "@/lib/jobs";

function isAuthorizedCron(header: string | null, secret: string | undefined): boolean {
  // CRON_SECRET が未設定なら必ず拒否する(fail closed)
  if (!secret || !header) return false;
  const expected = Buffer.from(`Bearer ${secret}`);
  const actual = Buffer.from(header);
  return actual.length === expected.length && timingSafeEqual(actual, expected);
}

export async function GET(request: Request) {
  if (!isAuthorizedCron(request.headers.get("authorization"), process.env.CRON_SECRET)) {
    return new Response("Unauthorized", { status: 401 });
  }

  // 同じ実行が2回届いても結果が変わらない(冪等な)処理にする
  await purgeExpiredSessions();
  return Response.json({ ok: true });
}

公式のサンプルも !cronSecret || で始まる fail closed の形です。もし逆に if (process.env.CRON_SECRET && ...) と書くと、変数を入れ忘れた環境では誰でもジョブを実行できる状態になるので注意してください。

Cron の運用で押さえておく仕様は次のとおりです。

  • Vercel が呼ぶのは本番デプロイの URL です。
  • 同じスケジュールの実行が2回以上届くことがあるので、処理は冪等にします。
  • リダイレクトは追いません。3xx を返すとそこで終わります。
  • Hobby は1日1回まで(実行時刻のずれは ±59分)。Pro と Enterprise は1分ごとまで設定できます。

Webhook のエンドポイントでは、Stripe のように送信元が署名を付けるサービスなら、処理の前に必ず署名を検証します。Preview で Webhook を受けるために前述の Protection Bypass の秘密を URL に入れた場合は、その秘密の扱いも棚卸しの対象です。


9. ログとチームのアクセス権

結論:ランタイムログの保持期間はプランで決まり、長期保管は Drains で利用者が用意します。秘密値をログに書かないのはアプリ側の責任です。

項目プラン(2026年10月時点)
ランタイムログの保持Hobby 1時間 / Pro 1日 / Enterprise 3日(Observability Plus を付けると Pro・Enterprise とも30日)
DrainsPro・Enterprise
Audit Log DrainsEnterprise のみ
Audit Logs(CSV は最大90日分)Enterprise のみ
Developer ロールPro・Enterprise
Access Groups・プロジェクト単位のロールEnterprise のみ
SAML SSOEnterprise、Pro は有料アドオン
Directory SyncEnterprise のみ

ビルドログについては 1章で触れた置き換えがありますが、ランタイムログで秘密値が置き換えられるとはドキュメントに書かれていません。ここからは私たちの推論ですが、アプリが console.log でリクエストヘッダーやトークンを出力すれば、その値はランタイムログに残り、Drains を設定していれば転送先にも届くと考えるのが安全です。責任共有モデルでも、秘密情報の適切な取り扱いは利用者の責任とされています。

チームの権限では、Pro でも使える Developer ロールが役立ちます。Developer は Preview と Development の環境変数は扱えますが、本番の環境変数とチーム設定は変更できません。全員を Member にしている場合は、本番の鍵を触る必要がある人を絞れないか見直します。


一覧表:Vercel セキュリティ設定チェックリスト

項目既定値推奨プラン
秘密値の環境変数の型変数ごとに選ぶSecret全プラン
Separate Production Secret Values任意有効チームの Security 設定(owner)
Preview と Production の値変数ごとに選ぶ本番の鍵を Preview に入れない全プラン
NEXT_PUBLIC_—公開してよい値だけ—
外部クラウドの認証—OIDC Federation全プラン
Deployment Protection の範囲Standard(本番ドメインは対象外)本番を隠すなら All Deployments全プラン
保護の方式—Vercel Authentication全プラン
Password Protection—必要な場合だけPro は有料オプション、Enterprise は込み、Hobby 不可
Trusted IPs—社内ネットワーク限定にしたい場合Enterprise のみ
Protection Bypass の秘密—用途別に発行し、不要なら取り消す全プラン
OPTIONS Allowlist空最小限のパス(前方一致)全プラン
Git Fork Protection有効有効のまま全プラン
Require Verified Commits無効必要に応じて有効GitHub 連携のみ
Build Logs and Source Protection有効有効のまま(public の上書きに注意)全プラン
Server Actions の認可—各関数の中で認証・認可—
個人ごとのレスポンスpublic, max-age=0, must-revalidateprivate, max-age=0—
セキュリティヘッダーHSTS のみCSP(Report-Only から)ほか—
WAF カスタムルール・レート制限なしログインや高コスト API に設定全プラン(ルール数に差)
Attack Mode無効有効化の手順を決めておく全プラン
Cron の認証なしCRON_SECRET、fail closed全プラン
ランタイムログの保持1時間〜3日必要なら DrainsDrains は Pro・Enterprise
監査ログ—必要なら検討Enterprise のみ

まとめ

Vercel の既定値は「すぐ動く」ことを優先しています。本番ドメインは公開、環境変数の型は自分で選ぶ、セキュリティヘッダーは HSTS だけ、という状態から、チームの事情に合わせて締めていくのは利用者の仕事です。

優先順位を付けるなら、まず Preview に本番の鍵が入っていないかと Server Actions の中で認可しているかの2つです。どちらも、設定画面やコードを一度通して見るだけで確かめられます。設定とコードの両方をまとめて第三者に見てほしい場合は、Vercel 設定のセキュリティレビューで、このチェックリストと同じ観点を実際のプロジェクトに当てて確認します。

よくある質問

Vercel のプレビュー環境は、初期設定のままで外部から見えませんか?
新規プロジェクトの既定は Standard Protection で、Preview Deployment は保護されます。ただし本番ドメインは保護対象外です。社内ツールや公開前のサイトで本番も隠したい場合は、Deployment Protection を All Deployments にします。2026年9月9日以降、Vercel Authentication による All Deployments は全プランで追加費用なしで使えます。
Vercel の Sensitive 環境変数は今も使えますか?
2026年8月24日に、Sensitive の切り替えは Config と Secret の2種類に置き換わりました。既存の Sensitive 変数は自動的に Secret として扱われ、移行作業は不要です。Secret は保存後にメンバーが値を見られない書き込み専用で、パスワード・APIキー・トークン向けです。Config は保存後も読める設定値向けです。
Next.js の認証は Proxy(旧 middleware)で一括チェックすれば十分ですか?
十分ではありません。Next.js の公式ドキュメントは、Proxy だけに頼らず各 Server Function の中で認証と認可を確かめるよう求めています。Server Actions は UI を経由せず直接 POST で呼べるためです。Proxy では Cookie を読むだけの楽観的なチェックにとどめ、データに触る関数の中で必ず確認します。
Vercel Cron のエンドポイントは誰でも叩けてしまいませんか?
そのままでは誰でも呼べます。プロジェクトに CRON_SECRET という環境変数を置くと、Vercel は Cron 実行時にその値を Authorization ヘッダーに Bearer 付きで送ります。ハンドラ側で一致しないリクエストを 401 で拒否し、CRON_SECRET が未設定のときも拒否する(fail closed)書き方にします。同じ実行が2回届くことがあるので、処理は冪等にします。
Vercel はセキュリティヘッダーを自動で付けてくれますか?
公式ドキュメントで既定と明記されているのは HSTS(Strict-Transport-Security)だけです。CSP、X-Frame-Options、X-Content-Type-Options、Referrer-Policy は自分で設定します。CSP はいきなり強制せず、Content-Security-Policy-Report-Only で違反を観察してから強制に切り替えるよう、Vercel のドキュメントも勧めています。

参考文献

友田

友田 陽大

経済産業大臣賞 受賞プロダクト開発者。TypeScript + Python + AWS で、SaaS・業界DX・実用レベルの生成AI(RAG)を、要件定義からインフラ・運用まで一人で完遂します。

Vercel の設定、最後に棚卸ししたのはいつですか?

Vercel の設定と Next.js のデプロイ境界をレビューします

Preview に本番の鍵が入っていないか、プレビュー URL の保護範囲、Git 連携、Firewall、Cron、個人ごとのレスポンスのキャッシュ、Server Actions の認可まで、ダッシュボードの設定とリポジトリを突き合わせて確かめます。Vercel そのものではなく、あなたのプロジェクトの設定が対象です。

プロジェクト単位(請負)・技術顧問のどちらにも対応可能です。まずは30分の無料技術相談から。

最短ルート:カレンダーから直接予約

相談内容が固まっている方は、フォーム送信よりその場で日程を確定する方がスムーズです。下記から空き時間をお選びください。

  • 30分のオンライン無料相談
  • Google Meet / Zoom / Microsoft Teams
  • NDA 商談前締結可・無理な営業はいたしません
無料相談の空き枠を予約する

あわせて読みたい