Django5.2.11および6.0.2セキュリティアップデートとorder_by()の安全な書き方

Django

この記事の内容

2026年2月3日に Django のセキュリティリリースが公開されました。

  • Django 6.0.2
  • Django 5.2.11
  • Django 4.2.28

https://www.djangoproject.com/weblog/2026/feb/03/security-releases/

今回の修正には、QuerySet.order_by() に関連する SQLインジェクション脆弱性(CVE-2026-1312) が含まれています。

この記事では、このSQLインジェクション脆弱性(CVE-2026-1312)について、

  • アップデートすれば安全なのか?
  • 自分のコードは大丈夫なのか?
  • order_by() の正しい書き方は?

を整理します。

今回の脆弱性のポイント

今回の脆弱性は、

order_by() に渡される「列名(識別子)」周りの検証不備

が原因でした。

ここで重要なのは、

  • filter(username=q)q は「値」
  • order_by(sort_item)sort_item は「列名」

という違いです。

なぜ order_by() が危険になりやすいのか?

SQLでは、

SELECT * FROM users ORDER BY username;

username列名(識別子) です。

一方、

SELECT * FROM users WHERE username = 'taro';

'taro' です。

値はバインド変数として安全に渡せますが、
列名はバインドできません。

つまり、

queryset.order_by(sort_item)

と書いた場合、

  • フレームワークの検証に依存する
  • 将来バグが出た場合に巻き込まれる
  • 設計としては安全ではない

という性質があります。

よくある危険なコード

sort_item = self.request.GET.get("sortItem")
return queryset.order_by(sort_item)

一見問題なさそうですが、

  • 外部入力を
  • SQL構造部分(列名)に直接渡している

という点でアンチパターンです。

今回のCVEは「特定条件下で突破できた」ケースですが、

将来の脆弱性に再び巻き込まれる構造

になっています。

正しい書き方(allowlist方式)

安全な方法は、

許可したフィールドのみ辞書でマッピングする

です。

SORT_MAP = {
    "id": "id",
    "-id": "-id",
    "username": "username",
    "-username": "-username",
    "email": "email",
    "-email": "-email",
}

sort_item = self.request.GET.get("sortItem")
order = SORT_MAP.get(sort_item, "-id")
return queryset.order_by(order)

これなら:

  • ユーザーは許可されたフィールドしか指定できない
  • 想定外の列指定ができない
  • 例外500を防げる
  • 将来の脆弱性の影響を受けにくい

filter の q は大丈夫?

例えば次のコード:

if q := query.get("q"):
    queryset = queryset.filter(
        Q(username__icontains=q)
        | Q(email__icontains=q)
    )

これは 基本的に安全です。

理由:

  • q は「値」
  • Djangoがバインド変数として処理する
  • SQL文字列に直接結合されない

filter() は値側なので安全、
order_by() は識別子側なので注意、という違いがあります。

では 5.2.11 or 6.0.2 にすれば安心?

結論:

✅ 今回の脆弱性は解消される

❌ 設計が安全になったわけではない

つまり、

対策今回のCVE将来耐性
5.2.11 or 6.0.2へ更新のみ
更新+allowlist

アップデートは必須ですが、
設計改善もやっておくと安心です。

セキュリティ設計の原則

覚えておくと便利な原則:

値は自由入力OK
識別子(列名・テーブル名・alias)は allowlist

これが ORM を使うときの基本です。

まとめ

  • Django 5.2.11 or 6.0.2 へのアップデートは必須
  • filter() の値は基本的に安全
  • order_by() に外部入力を直接渡すのは避ける
  • allowlist方式がベストプラクティス

今回のCVEは「Djangoのバグ」でしたが、

安全なコードはフレームワークに依存しすぎない

という良い見直し機会になりました。
この記事が、どなたかのお役に立てば幸いです。

コメント

タイトルとURLをコピーしました