Dynamic permissions policy sources now receive source mappings

rails/rails

Rails の PermissionsPolicy では、静的なディレクティブに対してはシンボルやキーワードを自動的にマッピングし、'self' のような正しい文字列を生成していました。動的(Proc)で返されたシンボルはこのマッピングが適用されず、self という裸の文字列が出力され、ポリシーが無効になるケースがありました。本変更は動的ソースにも同様のマッピングを適用し、Content Security Policy との一貫性を確保します。

背景

問題の概要: 動的な permissions policy ソースが :self のようなシンボルを返すと、従来はそのシンボルが文字列 self としてそのまま出力され、'self' に変換されませんでした。その結果、geolocation self のような無効なポリシー文字列が生成されました。

一貫性の欠如: 静的ソースでは apply_mappings がシンボルを正しく 'self' に変換していましたが、動的ソースでは呼び出し後にこの変換が行われていませんでした。これは Content Security Policy の取り扱いと齟齬があり、実装上のバグとして扱われました。

影響範囲: 無効なポリシーはブラウザ側でブロックされる可能性があり、機能的に期待したアクセス制御が行われなくなるリスクがありました。テストでも Invalid HTTP permissions policy source の例外は発生していましたが、正しいマッピングが行われないケースは検出できていませんでした。

技術的な変更

resolve_source の拡張: actionpack/lib/action_dispatch/http/permissions_policy.rbresolve_source メソッドに、Proc 実行後に返された結果へ apply_mappings を適用するロジックを追加しました。具体的には context.instance_exec(&source) の戻り値を変数 resolved に格納し、apply_mappings(Array.wrap(resolved)) を呼び出すよう変更しました。

変更前後の対比:

@@ -206,7 +206,8 @@ def resolve_source(source, context)
           if context.nil?
             raise RuntimeError, "Missing context for the dynamic permissions policy source: #{source.inspect}"
           else
-            context.instance_exec(&source)
+            resolved = context.instance_exec(&source)
+            apply_mappings(Array.wrap(resolved))
           end
         else
           raise RuntimeError, "Unexpected permissions policy source: #{source.inspect}"

複数ソースの対応: apply_mappings は配列でも受け取れるため、動的ソースが [:self, "https://example.com"] のように複数要素を返した場合でも、それぞれが正しくマッピングされ、最終的に geolocation 'self' https://example.com という有効な文字列が生成されます。テスト test_dynamic_directive_returning_multiple_sources によって検証されています。

設計判断

一貫性の確保: 動的ソースに対しても apply_mappings を適用することで、静的・動的問わず同一のマッピングロジックを共有する設計となりました。これによりコードの重複が排除され、将来的なマッピングロジックの変更が一箇所で済むようになります。

最小限の侵入性: 変更は resolve_source 内の数行追加に留められ、既存の API や既存の動的ソースの戻り値の型(シンボル、文字列、配列)に対して後方互換性を保ちます。apply_mappings は元から静的ソースでも使用されているため、追加の副作用は発生しません。

テストでの明示的検証: 新たに追加された test_dynamic_directivetest_dynamic_directive_returning_multiple_sources によって、動的ソースのマッピングが正しく機能することが自動的に検証され、回帰リスクが低減しました。

記事メタデータ

Generated by:
gpt-oss-120b for DiffDaily
LLM Trace:
2b8deea7

この記事はAIによって自動生成されています。内容の正確性については、必ずソースコードやPRを確認してください。

品質レビュー結果

Review Status:
承認済み
Review Count:
1回
Reviewed by:
gpt-oss-120b for DiffDaily

Review Criteria:

記事構成 ⚠ WARNING

Title, Context, Technical Detailの存在と明確さ

リード文・背景・技術的な変更はあるが、記事全体を締めくくる「まとめ」セクションが欠如している。結論がリード文の繰り返しでもなく、独立した段落が必要。

カスタムMarkdown構文 ✓ PASS

シンタックスハイライト・GitHubリンク記法の正確性

ファイル名付きシンタックスハイライトは正しい形式(```ruby:path)で使用され、PRリンクも # を含む正しいMarkdown記法で記載されている。

対象読者への適合性 ✓ PASS

エンジニア向けの適切な技術レベルと表現

内容はRailsの内部実装に関するもので、エンジニア向けの専門的な記述となっている。初心者向けの余計な説明はない。

パラグラフ・ライティング ⚠ WARNING

トピックセンテンス・1段落1トピック・段落長

各セクションは概ねトピックセンテンスで始まっているが、記事全体の結論が欠けている点と、背景セクションが複数のトピック(問題概要・一貫性・影響範囲)をひとつのパラグラフにまとめている点がガイドラインに合致していない。

Diff内容との照合 ⚠ WARNING

コードブロックとDiff内容の一致

permissions_policy.rb の diff は正確に掲載されているが、テストファイルの diff が記事に含まれていない。内容的に重大な欠落ではないが、完全な diff 提示が望ましい。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

使用されている用語(PermissionsPolicy、apply_mappings、Proc、Array.wrap 等)は正確で、PR の記述と一致している。

説明の技術的正確性 ✓ PASS

技術的主張の正確性と論理性

動的ソースへの apply_mappings 適用の理由や実装変更の説明は、Diff と PR の記述に基づき正確に記載されている。

事実の突合 ✓ PASS

PR情報による主張の裏付け(ハルシネーション検出)

記事内の主張はすべて PR のタイトル・説明・Diff に裏付けられており、根拠のない推測や外部知識は含まれていない。

数値・固有名詞の確認 ✓ PASS

PR番号・コミットID・バージョン等の正確性

PR 番号 #57939 などの数値・固有名詞は正確に記載されている。

タイトル・説明との一致 ✓ PASS

記事タイトル・説明とPR内容の一致

記事タイトルは PR の趣旨を正確に表現しており、意味的な食い違いはない。

外部知識の正確性 ✓ PASS

PRに記載のない外部知識(LTS、サポート状況など)の不使用

バージョンサポートやリリース日程など、PR に記載されていない外部知識は一切含まれていない。

時間表現の正確性 ✓ PASS

時間表現がPR情報と一致しているか

時間表現の歪曲はなく、PR の記述と一致している。