Spring Framework 7.0.9で確認すべきセキュリティ設定と移行ポイント

Java / Spring

Spring Framework 7.0.9は、多数の不具合修正や依存ライブラリの更新を含むメンテナンスリリースです。一方で、アップデート時に特に確認したい変更があります。ポイントは、リバースプロキシ経由のリクエストで使われる転送ヘッダーの扱いと、SpEL(Spring Expression Language)のコンパイル方針です。

まず確認したい2つの変更

今回の実務への影響が大きい変更は、次の2点です。

  • ForwardedHeaderFilterForwardedHeaderTransformerで、利用する転送ヘッダーを明示できるようになった
  • SimpleEvaluationContextではSpEL式のコンパイルがデフォルトで無効になった

どちらも、単純なAPI追加に見えて、設定次第では認証・認可、リダイレクト先、生成URL、式評価の安全性や性能に影響します。

1. Forwardedヘッダーを「暗黙の期待」に任せない

ロードバランサーやIngress、リバースプロキシの背後でSpringアプリケーションを動かす場合、アプリケーションから見える接続情報は実際のクライアントや外部公開URLと異なることがあります。そこで、プロキシは次のようなヘッダーを付与します。

  • 標準仕様のForwarded
  • 互換性のために広く使われてきたX-Forwarded-For
  • X-Forwarded-Proto
  • X-Forwarded-Host
  • X-Forwarded-Port
  • X-Forwarded-Prefix

Spring Framework 7.0.9では、MVCのForwardedHeaderFilterとWebFluxのForwardedHeaderTransformerに、標準のForwardedヘッダーを使うのか、X-Forwarded-*系を使うのかを指定するためのbooleanコンストラクターが追加されました。従来のデフォルトコンストラクターは既存動作を維持しますが、今後はプロキシの仕様に合わせて明示的に選択することが推奨されています。

例えば、プロキシが標準のForwardedヘッダーだけを信頼できる形で付与する構成なら、アプリケーション側でも標準ヘッダーを利用する設定にします。反対に、既存のロードバランサーがX-Forwarded-*を利用しているなら、その方式を明示します。

@Bean
ForwardedHeaderFilter forwardedHeaderFilter() {
    // 引数の意味は、採用するヘッダー方式に合わせて指定する
    return new ForwardedHeaderFilter(/* Forwarded または X-Forwarded を利用 */);
}

実際の引数の指定方法や、X-Forwarded-Prefixを利用するかどうかは、利用しているSpring FrameworkのAPIとプロキシ構成を確認してください。重要なのは、両方の形式が混在した状態で「たまたま期待どおりに動く」ことを避けることです。

なぜセキュリティ上重要なのか

転送ヘッダーは、外部から直接到達できるアプリケーションで無条件に信頼すると危険です。攻撃者がHostProto相当の情報を偽装できると、次のような問題につながる可能性があります。

  • HTTPS環境にもかかわらずHTTP向けURLを生成する
  • パスワードリセットなどのリンクに意図しないホスト名が入る
  • リダイレクト先を外部サイトに誘導する
  • セキュアCookieやリダイレクト判定を誤る
  • プロキシ間で異なるヘッダーが解釈され、リクエスト情報が不一致になる

そのため、プロキシがどのヘッダーを生成し、途中で書き換えや削除を行うのかを確認したうえで、Spring側の設定を合わせる必要があります。アプリケーションをインターネットへ直接公開している場合は、転送ヘッダーを信頼する経路自体を限定することも重要です。

7.1に向けた対応

Spring Framework 7.1では、デフォルトコンストラクターが非推奨となり、将来的な削除対象になる予定です。7.1への移行を見据え、次のようなコードを棚卸ししておくとよいでしょう。

  • ForwardedHeaderFilterをデフォルトコンストラクターで生成している箇所
  • WebFluxでForwardedHeaderTransformerを登録している箇所
  • Spring Bootのプロパティだけで転送ヘッダー処理を有効化している箇所
  • X-Forwarded-Prefixに依存するURL生成やコンテキストパス処理
  • テストでHostForwardedX-Forwarded-*を再現している箇所

2. SimpleEvaluationContextのSpELコンパイルがデフォルト無効に

もう一つの重要な変更は、SimpleEvaluationContextにおけるSpEL式のコンパイルです。7.0.9では、SpelParserConfigurationspring.expression.compiler.modeでコンパイルモードを指定していても、SimpleEvaluationContextでは原則として式コンパイルが無効になります。

SimpleEvaluationContextは、Bean参照や型参照などの機能を制限し、比較的安全に式を評価するためのコンテキストです。今回の変更は、その安全性を優先し、アプリケーション全体のコンパイル設定だけで安全性の制限を迂回できないようにする意図があります。

つまり、次のような構成では、以前と同じようにコンパイルが有効になるとは限りません。

SpelParserConfiguration configuration =
        new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE, getClass().getClassLoader());

ExpressionParser parser = new SpelExpressionParser(configuration);
SimpleEvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding()
        .build();

SimpleEvaluationContextを利用しているコードで、コンパイルによる性能向上を意図的に必要とする場合は、ビルダーで明示的にオプトインします。

SimpleEvaluationContext context = SimpleEvaluationContext
        .forReadOnlyDataBinding()
        .withCompilationSupported()
        .build();

ただし、withCompilationSupported()は単なる性能設定として扱うべきではありません。コンパイルを有効にすると、解釈実行時に適用されていた安全ガードが失われる可能性があります。ユーザー入力や外部設定を式として評価している場合は、原則としてコンパイルを有効にしないでください。

コンパイルを検討してよいケース

次の条件を満たす場合に限り、コンパイルを検討できます。

  • 式がアプリケーションのコードやデプロイ時設定として管理されている
  • 式の作成者と運用者が信頼できる
  • 利用可能なプロパティ、メソッド、型を設計上制限している
  • 式評価の対象オブジェクトに機密情報や危険な操作が含まれていない
  • 解釈モードとコンパイルモードの両方でテストしている
  • 性能測定によってコンパイルの必要性を確認している

特に、管理画面から登録された式、テナントが入力するルール、HTTPリクエストに含まれる式を評価する用途では、コンパイルの有効化よりも、式自体を受け付けない設計や、専用のルールエンジン・ホワイトリスト方式を優先すべきです。

その他の実務上の注目点

7.0.9には、セキュリティ設定以外にも運用や障害解析に関係する修正が含まれています。

WebSocket、RSocket、Reactor Netty

WebSocketのハンドシェイクエラーのログ改善、Jetty WebSocketセッションのエラー処理、RSocketのSETUPフレーム処理におけるバッファリーク修正、Reactor Nettyサーバーのリクエストパス処理改善が行われています。リアルタイム通信を利用するサービスでは、アップデート前後で接続失敗率、切断数、バッファ使用量を比較するとよいでしょう。

SpELの計算量とキャッシュ

BigDecimalBigIntegerのべき乗結果サイズの制限、コンパイルモードにおける可変リストのキャッシュ、プロパティアクセサーやコンストラクターエグゼキューターの不正キャッシュ利用など、SpEL関連の修正も複数あります。式を大量に評価するシステムでは、式の入力元だけでなく、異常に大きな数値や複雑な式によるCPU・メモリ消費も確認してください。

ネイティブイメージとメタデータ

アノテーションメタデータがクラスファイルを保持し続けないようにする改善、ラムダヒントだけが存在する場合のネイティブ設定ファイル生成、ネイティブ設定ファイルのUTF-8出力などが含まれています。GraalVM Native ImageやSpring AOTを利用している場合は、ビルド成果物の差分だけでなく、リフレクション設定、文字コード、起動時の警告も確認します。

依存ライブラリの更新

Micrometer 1.16.7、Micrometer Tracing 1.6.7、Reactor 2025.0.7への更新も含まれます。Spring Framework単体では問題がなくても、Spring Boot、Micrometer、Reactor、Webサーバー実装の組み合わせによって挙動が変わる可能性があります。利用中のSpring Bootが対応するバージョン範囲も確認し、依存関係を個別に上書きする場合は特に注意してください。

アップデート時のチェックリスト

Spring Framework 7.0.9への更新では、最低限次の項目を確認するとよいでしょう。

  1. リバースプロキシがForwardedX-Forwarded-*のどちらを付与するか確認する
  2. ForwardedHeaderFilterまたはForwardedHeaderTransformerの方式を明示する
  3. X-Forwarded-Prefixの利用有無と、URL生成への影響を確認する
  4. 外部から転送ヘッダーを偽装できないネットワーク構成になっているか確認する
  5. SimpleEvaluationContextで式コンパイルを前提にしている処理を検索する
  6. withCompilationSupported()を使う箇所では、式の入力元と信頼境界をレビューする
  7. ログイン、認証エラー、リダイレクト、パスワードリセットURLをプロキシ経由でテストする
  8. WebSocket、SSE、RSocketを利用する場合は接続・切断・再接続を検証する
  9. Native Image利用時はAOTメタデータとUTF-8出力を確認する
  10. Spring Bootおよび関連ライブラリとの互換性を確認する

まとめ

Spring Framework 7.0.9は、単に不具合を修正するだけのリリースではありません。転送ヘッダーの解釈やSpELコンパイルのように、「既存設定が動いているから問題ない」と考えやすい部分に、より明示的で安全な設定を求める変更が入っています。

特に重要なのは、プロキシが付与するヘッダーを信頼する境界と、SpEL式を誰が作成できるのかを明確にすることです。7.1では転送ヘッダー処理のデフォルトコンストラクターが非推奨となる予定のため、今回のアップデートを機に設定をコードとインフラの両面から見直しておくと、将来の移行コストとセキュリティリスクを抑えられます。

出典: GitHub Spring Framework Releases

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