From 8c3d629d8878bcd9324751964e3d6122168f1ff7 Mon Sep 17 00:00:00 2001 From: Mike Dalessio Date: Tue, 17 Feb 2026 18:03:00 -0500 Subject: [PATCH 1/2] Add test coverage for structured logging request serialization Exercise the RailsStructuredLogging RequestSerializer to verify that internal params are filtered from serialized request parameters. --- .../rails_structured_logging_test.rb | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 saas/test/integration/rails_structured_logging_test.rb diff --git a/saas/test/integration/rails_structured_logging_test.rb b/saas/test/integration/rails_structured_logging_test.rb new file mode 100644 index 0000000000..e648ccef83 --- /dev/null +++ b/saas/test/integration/rails_structured_logging_test.rb @@ -0,0 +1,34 @@ +require "test_helper" + +class RailsStructuredLoggingTest < ActiveSupport::TestCase + test "request serializer filters internal params" do + request = ActionDispatch::Request.new( + "REQUEST_METHOD" => "GET", + "PATH_INFO" => "/test", + "QUERY_STRING" => "", + "SERVER_NAME" => "localhost", + "SERVER_PORT" => "3000", + "HTTP_HOST" => "www.example.com", + "HTTP_ACCEPT" => "*/*", + "rack.url_scheme" => "https" + ) + + now = Time.now + event = ActiveSupport::Notifications::Event.new( + "process_action.action_controller", now, now, SecureRandom.hex(10), + { + request: request, + controller: "TestController", + action: "index", + format: "html", + params: { "controller" => "TestController", "action" => "index", "id" => "1" } + } + ) + + json = RailsStructuredLogging::Serializers::Elastic::RequestSerializer.serialize(event, "") + data = JSON.parse(json) + + serialized_params = JSON.parse(data.dig("http", "request", "parameters")) + assert_equal({ "id" => "1" }, serialized_params) + end +end From af90440714b77574a9b205ddbb1eaa74f808d1ce Mon Sep 17 00:00:00 2001 From: Mike Dalessio Date: Tue, 17 Feb 2026 18:55:44 -0500 Subject: [PATCH 2/2] Upgrade Rails from 60d92e4e to fef11d43f 358 commits since 60d92e4e. Reviewed all for backwards compatibility: - INTERNAL_PARAMS removal (91fd4ec1): Breaking. rails_structured_logging gem referenced the removed constant. Updated gem to 0.3.0 which no longer depends on it. Defensive test added. - CSRF header-only protection for HTTP (88b5c78d): Breaking. Rails now natively handles insecure context requests in verified_via_header_only? using ActionDispatch::Http::URL.secure_protocol. Removed Fizzy's redundant allowed_insecure_context_request? method. Updated test to set secure_protocol alongside force_ssl. - Load hook guards (15f316a5..e7b02360): No impact. Warnings for components loaded before app initialization, not triggered here. - EventReporter filter change (4b8ae39f): No impact. Fizzy uses rails_structured_logging, not Rails::EventReporter directly. - Multibyte::Chars removal (76f770fd): No impact. No references in codebase. - Filter parameters changes (1475f5fb, fd766a3e): No impact. Standard filter_parameters usage only. - JSON hash key fix (b619c8ff): No impact. Bug fix for custom objects as hash keys. - Mail::Address.wrap deprecation (8a83cc08): No impact. Not used. - in_batches use_ranges limit fix (c0b82ff5): No impact. Not used. - Route helper method_missing move (3f4977e6): No impact. Integration tests unaffected. - Column #== and #hash changes (bdc7adce, 1a4305df, d79f65fa): Internal AR changes, no direct usage. - YAMLEncoder class-to-module (b29f3748): No impact. Not referenced. - X-XSS-Protection removal (ed115706): No impact. Header was already a no-op in modern browsers. - protect_from_forgery deprecation without strategy (61996576): No impact. Fizzy specifies `using: :header_only` explicitly. Remaining changes are safe bug fixes, docs, deprecations of unused adapters (sidekiq, delayed_job, resque, backburner, queue_classic), Ruby 3.2 EOL, and internal refactors. Also bumps nokogiri 1.19.1, rack 3.2.5, prism 1.9.0, irb 1.17.0, json 2.18.1, net-imap 0.6.3, rdoc 7.2.0, action_text-trix ~> 2.1.16. --- Gemfile.lock | 33 ++++++++--------- Gemfile.saas.lock | 35 ++++++++++--------- .../concerns/request_forgery_protection.rb | 6 +--- .../request_forgery_protection_test.rb | 3 ++ 4 files changed, 39 insertions(+), 38 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 559b2990b0..e46aa3c8a2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -13,7 +13,7 @@ GIT GIT remote: https://github.com/rails/rails.git - revision: 60d92e4e7dfe923528ccdccc18820ccfe841b7b8 + revision: fef11d43f3ee2f2c185059a97fc27c7f253f1111 branch: main specs: actioncable (8.2.0.alpha) @@ -47,7 +47,7 @@ GIT rails-html-sanitizer (~> 1.6) useragent (~> 0.16) actiontext (8.2.0.alpha) - action_text-trix (~> 2.1.15) + action_text-trix (~> 2.1.16) actionpack (= 8.2.0.alpha) activerecord (= 8.2.0.alpha) activestorage (= 8.2.0.alpha) @@ -213,15 +213,16 @@ GEM activesupport (>= 6.0.0) railties (>= 6.0.0) io-console (0.8.2) - irb (1.16.0) + irb (1.17.0) pp (>= 0.6.0) + prism (>= 1.3.0) rdoc (>= 4.0.0) reline (>= 0.4.2) jbuilder (2.14.1) actionview (>= 7.0.0) activesupport (>= 7.0.0) jmespath (1.6.2) - json (2.18.0) + json (2.18.1) jwt (3.1.2) base64 kamal (2.10.1) @@ -276,7 +277,7 @@ GEM msgpack (1.8.0) net-http-persistent (4.0.8) connection_pool (>= 2.2.4, < 4) - net-imap (0.6.2) + net-imap (0.6.3) date net-protocol net-pop (0.1.2) @@ -291,21 +292,21 @@ GEM net-protocol net-ssh (7.3.0) nio4r (2.7.5) - nokogiri (1.19.0-aarch64-linux-gnu) + nokogiri (1.19.1-aarch64-linux-gnu) racc (~> 1.4) - nokogiri (1.19.0-aarch64-linux-musl) + nokogiri (1.19.1-aarch64-linux-musl) racc (~> 1.4) - nokogiri (1.19.0-arm-linux-gnu) + nokogiri (1.19.1-arm-linux-gnu) racc (~> 1.4) - nokogiri (1.19.0-arm-linux-musl) + nokogiri (1.19.1-arm-linux-musl) racc (~> 1.4) - nokogiri (1.19.0-arm64-darwin) + nokogiri (1.19.1-arm64-darwin) racc (~> 1.4) - nokogiri (1.19.0-x86_64-darwin) + nokogiri (1.19.1-x86_64-darwin) racc (~> 1.4) - nokogiri (1.19.0-x86_64-linux-gnu) + nokogiri (1.19.1-x86_64-linux-gnu) racc (~> 1.4) - nokogiri (1.19.0-x86_64-linux-musl) + nokogiri (1.19.1-x86_64-linux-musl) racc (~> 1.4) openssl (4.0.0) ostruct (0.6.3) @@ -319,7 +320,7 @@ GEM pp (0.6.3) prettyprint prettyprint (0.2.0) - prism (1.8.0) + prism (1.9.0) propshaft (1.3.1) actionpack (>= 7.0.0) activesupport (>= 7.0.0) @@ -332,7 +333,7 @@ GEM nio4r (~> 2.0) raabro (1.4.0) racc (1.8.1) - rack (3.2.4) + rack (3.2.5) rack-mini-profiler (4.0.1) rack (>= 1.2.0) rack-session (2.1.1) @@ -351,7 +352,7 @@ GEM nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0) rainbow (3.1.1) rake (13.3.1) - rdoc (7.0.3) + rdoc (7.2.0) erb psych (>= 4.0.0) tsort diff --git a/Gemfile.saas.lock b/Gemfile.saas.lock index b09872738f..cae4d7e10d 100644 --- a/Gemfile.saas.lock +++ b/Gemfile.saas.lock @@ -39,9 +39,9 @@ GIT GIT remote: https://github.com/basecamp/rails-structured-logging - revision: 76960cb5c15fc2b6b5f7542e05d7dcc031cef9e6 + revision: f6633fd8fee5906d8affa2329c61de7a3450eb7e specs: - rails_structured_logging (0.2.1) + rails_structured_logging (0.3.0) json rails (>= 6.0.0) @@ -62,7 +62,7 @@ GIT GIT remote: https://github.com/rails/rails.git - revision: 60d92e4e7dfe923528ccdccc18820ccfe841b7b8 + revision: fef11d43f3ee2f2c185059a97fc27c7f253f1111 branch: main specs: actioncable (8.2.0.alpha) @@ -96,7 +96,7 @@ GIT rails-html-sanitizer (~> 1.6) useragent (~> 0.16) actiontext (8.2.0.alpha) - action_text-trix (~> 2.1.15) + action_text-trix (~> 2.1.16) actionpack (= 8.2.0.alpha) activerecord (= 8.2.0.alpha) activestorage (= 8.2.0.alpha) @@ -294,15 +294,16 @@ GEM activesupport (>= 6.0.0) railties (>= 6.0.0) io-console (0.8.2) - irb (1.16.0) + irb (1.17.0) pp (>= 0.6.0) + prism (>= 1.3.0) rdoc (>= 4.0.0) reline (>= 0.4.2) jbuilder (2.14.1) actionview (>= 7.0.0) activesupport (>= 7.0.0) jmespath (1.6.2) - json (2.18.0) + json (2.18.1) jwt (3.1.2) base64 kamal (2.10.1) @@ -357,7 +358,7 @@ GEM msgpack (1.8.0) net-http-persistent (4.0.8) connection_pool (>= 2.2.4, < 4) - net-imap (0.6.2) + net-imap (0.6.3) date net-protocol net-pop (0.1.2) @@ -372,19 +373,19 @@ GEM net-protocol net-ssh (7.3.0) nio4r (2.7.5) - nokogiri (1.19.0-aarch64-linux-gnu) + nokogiri (1.19.1-aarch64-linux-gnu) racc (~> 1.4) - nokogiri (1.19.0-aarch64-linux-musl) + nokogiri (1.19.1-aarch64-linux-musl) racc (~> 1.4) - nokogiri (1.19.0-arm-linux-gnu) + nokogiri (1.19.1-arm-linux-gnu) racc (~> 1.4) - nokogiri (1.19.0-arm-linux-musl) + nokogiri (1.19.1-arm-linux-musl) racc (~> 1.4) - nokogiri (1.19.0-arm64-darwin) + nokogiri (1.19.1-arm64-darwin) racc (~> 1.4) - nokogiri (1.19.0-x86_64-linux-gnu) + nokogiri (1.19.1-x86_64-linux-gnu) racc (~> 1.4) - nokogiri (1.19.0-x86_64-linux-musl) + nokogiri (1.19.1-x86_64-linux-musl) racc (~> 1.4) openssl (4.0.0) ostruct (0.6.3) @@ -398,7 +399,7 @@ GEM pp (0.6.3) prettyprint prettyprint (0.2.0) - prism (1.8.0) + prism (1.9.0) prometheus-client-mmap (1.4.0) base64 bigdecimal @@ -441,7 +442,7 @@ GEM nio4r (~> 2.0) raabro (1.4.0) racc (1.8.1) - rack (3.2.4) + rack (3.2.5) rack-mini-profiler (4.0.1) rack (>= 1.2.0) rack-session (2.1.1) @@ -463,7 +464,7 @@ GEM rake-compiler-dock (1.9.1) rb_sys (0.9.117) rake-compiler-dock (= 1.9.1) - rdoc (7.0.3) + rdoc (7.2.0) erb psych (>= 4.0.0) tsort diff --git a/app/controllers/concerns/request_forgery_protection.rb b/app/controllers/concerns/request_forgery_protection.rb index fdff7ba8ff..acfc4dbf15 100644 --- a/app/controllers/concerns/request_forgery_protection.rb +++ b/app/controllers/concerns/request_forgery_protection.rb @@ -7,14 +7,10 @@ module RequestForgeryProtection private def verified_via_header_only? - super || allowed_api_request? || allowed_insecure_context_request? + super || allowed_api_request? end def allowed_api_request? sec_fetch_site_value.nil? && request.format.json? end - - def allowed_insecure_context_request? - sec_fetch_site_value.nil? && !request.ssl? && !Rails.configuration.force_ssl - end end diff --git a/test/controllers/concerns/request_forgery_protection_test.rb b/test/controllers/concerns/request_forgery_protection_test.rb index db1a84e636..9f50e353ef 100644 --- a/test/controllers/concerns/request_forgery_protection_test.rb +++ b/test/controllers/concerns/request_forgery_protection_test.rb @@ -8,11 +8,13 @@ class RequestForgeryProtectionTest < ActionDispatch::IntegrationTest ActionController::Base.allow_forgery_protection = true @original_force_ssl = Rails.configuration.force_ssl + @original_secure_protocol = ActionDispatch::Http::URL.secure_protocol end teardown do ActionController::Base.allow_forgery_protection = @original_allow_forgery_protection Rails.configuration.force_ssl = @original_force_ssl + ActionDispatch::Http::URL.secure_protocol = @original_secure_protocol end test "JSON request succeeds with missing Sec-Fetch-Site header" do @@ -38,6 +40,7 @@ class RequestForgeryProtectionTest < ActionDispatch::IntegrationTest test "HTTP request fails with missing Sec-Fetch-Site header when force_ssl is enabled" do Rails.configuration.force_ssl = true + ActionDispatch::Http::URL.secure_protocol = true assert_no_difference -> { Board.count } do post boards_path,