コードレビューで気づいた「設定の甘さ」と、その対策の設計を、勉強のためにまとめたものです。
この記事でわかること
- Django の
SECRET_KEYの役割と、弱いデフォルト値が招くリスク - 「
baseに開発用デフォルト / 本番・開発設定で環境変数を必須化して上書き」という二層構造の考え方 - 重要設定を「未設定なら起動を止める」設計にする理由
概念: SECRET_KEY はアプリ全体の印鑑
Django の SECRET_KEY は アプリ全体の印鑑のようなものです。「この cookie は本物」「このセッションは改ざんされていない」「このパスワードリセットリンクは正規」といった署名処理のすべてに使われる、最重要の設定値です。
弱い値・公開された値での起動は、その印鑑を 悪意のある人にも複製できる 状態を意味します。署名できる = 偽造もできる、ということです。
共通設定 base にある「開発用デフォルト」
綴Photo の Django 設定は、共通の base.py を土台にして、環境ごとの設定(本番・開発)がそれを継承する構成になっています。その base.py に、環境変数が無いときのデフォルト値があります。
# base.py — 全環境が継承する共通の土台
SECRET_KEY = os.environ.get("DJANGO_SECRET_KEY", "django-insecure-dev-only-key")このデフォルト値 django-insecure-dev-only-key は、名前からして「本番では使うな」と言っています。django-insecure- は、Django がプロジェクト生成時に自動で付ける警告プレフィックスで、「この鍵はちゃんと管理されていない=本番では差し替えろ」というサインです。
コードを読めば誰でも同じ鍵を作れて、署名を偽造できます。
対策: 本番・開発設定で「必須化」して上書きする
ここが対策です。base を継承する本番・開発の設定で、SECRET_KEY を 環境変数の必須項目 として上書きします。
# production.py — 本番。base を継承して上書きする
from .base import *
SECRET_KEY = os.environ["DJANGO_SECRET_KEY"] # 必須。未設定なら起動時に KeyError で落ちるポイントは os.environ.get(...)(無ければデフォルト)ではなく os.environ[...](無ければエラー)にしていることです。
これが「base に開発用デフォルトを残しつつ、上の層で必ず必須化して上書きする」二層構造です。
なぜ base にデフォルトを残すのか(なぜそうなりやすいか)
「危ないなら base のデフォルトも消せばいいのでは」と思うかもしれません。だが、デフォルトを置きたくなるのには構造的な理由があります。
ローカルで毎回環境変数を設定するのは面倒だし、デフォルトがあれば git clone した直後でも一応動きます。チュートリアルやテンプレートも「とりあえず動く」を優先してデフォルト値を置きがちです。つまりこれは怠慢ではなく、開発体験を良くしようとする善意です。問題は、その善意が本番のセキュリティ設定をすり抜けてしまうことです。
だから「個人が気をつける」では防げません。「開発は楽・本番は厳格」は、個人の注意ではなくこの形で両立できます。
なぜ危険か(デフォルトのまま本番が動くと)
- 攻撃者が公開コードからデフォルト値を知れば、署名を偽造できます
- 弱い鍵で本番が動いても、警告が出ません
学びポイント
- 「デフォルトがあると便利」は開発者目線です。攻撃者目線では「コードを読めば同じ鍵を作れます」
- 重要設定は明示的に要求し、失敗を音にします(静かなバグではなく、起動失敗にします)
- この「重要設定は起動時に明示エラー」は1つの型にできます。綴Photo では、許可ホストや CORS / CSRF のオリジンを
_require_csvという共通ヘルパーで必須化し、未設定や*(全許可)をImproperlyConfiguredで弾いています。SECRET_KEY以外にも横展開すると、設定漏れが本番に出る前に潰せます
おわりに
「設定し忘れても動く」は便利だが、セキュリティ的には危険な性質です。重要設定の未設定は、静かなバグではなく起動失敗にしてしまう ほうが安全です。
SECRET_KEY だけでなく、DB の接続情報・ストレージのアクセスキー・各種許可オリジンなど、漏れたり緩かったりすると大ごとになる設定は、すべて「本番では必須・未設定なら起動失敗」で揃えておきたい。「開発は楽に、本番は厳しく」を、設定の二層構造で両立させるのが落とし所だと感じた。
この記事は2026年4月時点の自分の理解で書いています。Django の設定パターンは安定した領域ですが、公式ドキュメントの推奨方法も合わせて参照してください。