Skip to content

50_セキュリティ

本章では、filix-shadowwork-api におけるセキュリティ前提と、認証・署名・Secrets/PII の取り扱いを定義する。
ここで扱うのは「どのように安全性を確保するか」という設計上の前提であり、個別の実装詳細(ライブラリ呼び出し等)は対象外とする。


セキュリティ方針(前提)

  • 最小権限(Least Privilege)
    API の利用者・運用者・外部サービスに付与する権限は最小化する。

  • 入力はすべて不正である前提
    すべてのリクエスト入力を検証し、想定外のデータを拒否する。

  • 外部サービスとの境界は署名/トークンで保護する
    Webhook、管理 API、LLM 連携は必ず認証情報で境界を守る。

  • 監査可能性(Auditability)
    不具合や不正の切り分けのため、重要操作はログに残る設計にする(PIIを含めない)。


認証(Authentication)

目的

  • 「このリクエストが誰のものか」を確実に特定する(なりすまし防止)
  • user_id の真正性を担保する

前提

  • フロントエンドは外部の会員基盤(例: Memberstack)によりログイン状態を得る。
  • バックエンドは、フロントエンドから提示される認証情報を検証して user_id を確定する。

認証方式(選定中)

現時点では認証方式は未確定とし、以下の要件を満たす方式を採用する。
方式が確定したら、本節に「採用方式」と「検証手順」を記載する。

必須要件

  • 認証情報を検証し、user_id をバックエンド側で確定できること
  • なりすましを防止できること(改ざん検知)
  • リプレイ攻撃に対する耐性を持つこと(例: タイムスタンプ/nonce 等)
  • 認証情報は HTTPS 経由でのみ送信されること

候補(例)

  • 方式A: JWT
  • フロントから JWT を送信し、バックエンドは署名検証して user_id を取り出す。
  • 送信経路は Authorization: Bearer <token> とする。
  • 方式B: 署名付きリクエスト
  • フロントがリクエストに署名を付け、バックエンドが共有秘密で検証する。
  • 署名対象は method/path/body/timestamp 等を含める(リプレイ耐性のため)。

移行方針

現状が「user_id を単純に渡すだけ」の場合、認証方式の導入を最優先の作業として扱う。


  • 有料状態(paid)は user_flags.paid を参照する。
  • paid の更新経路は 40_課金と利用権限 に従う。
  • 認証により確定した user_id に対してのみ paid を参照する(任意の user_id 指定を許さない)。

Stripe Webhook の署名検証

目的

  • Webhook の送信元が Stripe であることを保証し、偽装を防ぐ。

必須要件

  • Stripe が付与する署名ヘッダ(例: Stripe-Signature)を検証する。
  • 検証に使用する秘密鍵(webhook secret)は 環境変数(Secrets) として安全に管理する。
  • 検証失敗時は 4xx を返し、DB更新等の副作用を起こさない。

追加要件

  • タイムスタンプ検証により、リプレイ攻撃の難易度を上げる。
  • Webhook の冪等性(重複排除)は 40_課金と利用権限 に従う。

管理用API(/api/admin/*)の保護

/api/admin/set_paid のような管理操作は、通常のユーザー操作と同等には扱えない。
誤用・悪用時の影響が大きいため、強い制限を必須とする。

必須要件

  • 管理者のみ実行可能
  • 管理者トークン、または環境変数で持つ共有秘密を用いて認証する。
  • 本番環境では最小限
  • 可能なら本番で露出させず、運用ツールや一時的な手段に閉じる。

追加要件

  • IP 制限(Cloudflare Access / Zero Trust など)
  • 監査ログ(誰がいつ何を変更したか)
  • レート制限(ブルートフォース対策)

Secrets の管理

対象

  • Stripe webhook secret
  • LLM API key
  • 管理者トークン(admin secret)
  • その他、外部サービスの API key / secret

方針

  • Secrets は リポジトリにコミットしない
  • Cloudflare Workers の Secrets / Vars に格納する
  • ログに出さない(例外メッセージに含めない)

PII(個人情報)の取り扱い

取り扱い対象

  • user_id(会員基盤の識別子)
  • ユーザー入力(シャドウワークの内容は機微性が高い)

方針

  • 最小限の保存: 必要な範囲に限定して保存する
  • ログには出さない: user_text / content をログに出さない
  • アクセス制御: 認証された本人のデータのみ取得可能とする
  • データ削除: 将来、ユーザー要求に応じた削除・退会対応を検討する(運用ポリシー)

入力検証(Validation)

  • すべての API は入力を検証し、想定外の型・範囲・サイズは拒否する。
  • 特に content(ユーザー入力)はサイズ上限を設ける。
  • id(run/thread/message 等)は形式を統一し、受け入れ可能な文字種を限定する。

CORS とブラウザ公開

  • ブラウザから API を呼ぶ場合、CORS を適切に設定する。
  • Origin を必要以上に許可しない(固定のフロントURLを許可する)。
  • 認証情報(Authorizationヘッダ等)を使う場合は、CORS で明示的に許可する。

参照

  • 20_API仕様: 認証前提、エラー形式
  • 40_課金と利用権限: Webhook と paid 更新の冪等性
  • 60_利用制限と運用ポリシー: 悪用対応、運用上の制限