💡 Tips

個人開発のシークレット管理と漏洩対策【TypeScript × Workers Secrets 実装手順】

結論:シークレットは「入口・実行時・出口」の3層で守る

個人開発で環境変数の漏洩を防ぐなら、次の3層をそろえる。どれか1つだけでは穴が残る。

層やること主な道具
入口リポジトリに入れない.gitignore / gitleaks / pre-commit
実行時コードに埋め込まず注入するWorkers Secrets / .dev.vars
出口漏れた前提で捨てるローテーション手順書

理由は単純だ。漏洩の大半は高度な攻撃ではなく、うっかりコミットと使い回したまま放置から起きる。個人開発はレビュアーがいないぶん、機械的なガードを自分で仕込むしかない。

入口:誤コミットを機械で止める

.gitignore は例外だけ許可する形にする

.env
.env.*
.dev.vars
.dev.vars.*
!.env.example
!.dev.vars.example

追跡するのは .env.example だけにして、キー名のみ共有する。値は空文字にしておく。

pre-commit で gitleaks を走らせる

#!/bin/sh
# .git/hooks/pre-commit (chmod +x を忘れずに)
gitleaks protect --staged --redact --no-banner || {
  echo 'シークレットらしき文字列を検出した。commit を中止する。'
  exit 1
}

Husky や lefthook を使っているなら、そのフック定義に同じコマンドを置けばよい。CI 側にも gitleaks detect のジョブを足しておくと、フックを入れ忘れた別マシンからの push を拾える。

ただし gitleaks はパターンマッチなので万能ではない。自作の短いトークンや、config.ts にベタ書きした ID は検出されないことがある。「検出ゼロ=安全」とは考えないほうがよい。

実行時:TypeScript で型と検証をまとめる

Cloudflare Workers なら値は wrangler secret に保存し、コードからは Env 経由で読む。

npx wrangler secret put STRIPE_SECRET_KEY
npx wrangler secret list

注意点として、wrangler.toml の [vars] は平文でリポジトリに入る。ここに置いてよいのは公開しても困らない設定値だけだ。API キーやトークンは必ず secret put 側に置く。

型は手書きせず、バリデーションと一緒に定義すると保守が楽になる。

import { z } from 'zod';

const EnvSchema = z.object({
  STRIPE_SECRET_KEY: z.string().startsWith('sk_'),
  AUTH_SECRET: z.string().min(32),
  PUBLIC_SITE_URL: z.string().url(),
});

export type AppEnv = z.infer<typeof EnvSchema>;

export function loadEnv(env: unknown): AppEnv {
  const parsed = EnvSchema.safeParse(env);
  if (!parsed.success) {
    // 値そのものは出力しない。キー名だけ出す
    const keys = parsed.error.issues.map((i) => i.path.join('.'));
    throw new Error(`環境変数が不正: ${keys.join(', ')}`);
  }
  return parsed.data;
}

肝は、エラー時に値をログへ出さないこと。設定ミスの調査で console.log(env) を書き、それがログ収集サービスに流れて漏れる事故は実際にある。

ローカル開発では .dev.vars を使う。wrangler dev が自動で読み込み、本番の Secrets とは分離される。ここに本番キーを書かず、テスト用キーを使うこと。決済系はテストキーと本番キーの取り違えがそのまま実害になる。

認証系の値を Workers に載せるときの詰まりどころはAuth.js (NextAuth v5) をCloudflare Workersで動かすときのtrustHost設定にまとめてある。

出口:ローテーション手順を先に書いておく

漏洩時にいちばん時間を食うのは「どこに何のキーがあったか思い出す作業」だ。平常時に台帳を作る。

<!-- docs/secrets.md -->
| キー名 | 発行元 | 使用箇所 | 再発行ページ | 最終更新 |
|---|---|---|---|---|
| STRIPE_SECRET_KEY | Stripe | Worker: checkout | ダッシュボード内APIキー画面 | 2026-06-01 |

ローテーションの手順は「新旧を併用できるか」で変わる。

A. 複数キーを同時に持てるサービス

  1. 新キーを発行する
  2. wrangler secret put で上書きし、デプロイする
  3. 実際のリクエストで動作確認する
  4. 旧キーを失効させる

B. キーを1つしか持てないサービス

再発行した瞬間に旧キーが死ぬ。デプロイ完了までの短いダウンタイムを見込み、アクセスの少ない時間帯に実施する。

3〜6か月に1回の棚卸しをカレンダーに登録しておくと、現実的に回る。なお各サービスのキー発行仕様や無料枠の条件は変わりやすいので、実施前に公式の最新情報を確認してほしい。

公開サイトを運用しているなら、キー管理と並行して改ざん監視も検討したい。

のような外部サービスは、自分では気づきにくいスクリプト混入の検知手段になる。

漏洩に気づいたときの初動

  1. まずキーを失効させる。履歴の削除は後回しでよい
  2. 発行元のダッシュボードで不正利用の有無を確認する
  3. git filter-repo や BFG で履歴から除去する(force push が必要で、fork されていれば完全には消えない)
  4. GitHub のシークレットスキャン通知メールを無視しない

順番が重要だ。履歴を書き換えても、すでに取得された値は無効化されない。

正直に書いておく注意点

  • gitleaks も Secrets も運用が前提。フックを --no-verify で素通りさせれば意味がない
  • Workers Secrets は保存後に値を再表示できない。控えは別途パスワードマネージャーに置く
  • 個人開発だと台帳の更新が形骸化しやすい。項目は最小限にして続けられる形にする

背景の原則を体系的に押さえたいなら

体系的に学ぶ 安全なWebアプリケーションの作り方 第2版[固定版] 脆弱性が生まれる原理と対策の実践
📚 おすすめ書籍

体系的に学ぶ 安全なWebアプリケーションの作り方 第2版[固定版] 脆弱性が生まれる原理と対策の実践

参考価格¥3,080(税込)

いわゆる徳丸本。秘密情報の扱いと攻撃経路の基礎が一冊でそろう

Amazonで最新価格をチェック

が定番だ。あわせて

Yubico セキュリティキー YubiKey 5 NFC ログイン/U2F/FIDO2/USB-A ポート/2段階認証/高耐久性/耐衝撃性/防水
📚 おすすめ書籍

Yubico セキュリティキー YubiKey 5 NFC ログイン/U2F/FIDO2/USB-A ポート/2段階認証/高耐久性/耐衝撃性/防水

参考価格¥10,200(税込)

GitHubの2要素認証をハード鍵にすると、アカウント乗っ取り経路を1つ潰せる

Amazonで最新価格をチェック

も検討に値する。

まとめ

入口で機械的に止め、実行時は型と検証付きで注入し、出口のローテーション手順を先に用意する。この3層は半日あれば導入でき、一度入れれば以後は自動で効き続ける。個人開発こそ、判断を人間の注意力に任せない設計が有効だ。