Information Disclosure / Middleware Misconfiguration

MEDIUM
rails/rails
Commit: afd103d69abb
Affected: Rails 8.1.x before 8.1.3 (e.g., 8.1.0 through 8.1.2)
2026-04-05 12:08 UTC

Description

The commit changes the default middleware stack to only insert Rack::Sendfile when x_sendfile_header is configured. Previously Rack::Sendfile could be added to the stack with a nil header, which risks misconfiguration and potential information disclosure or exposure of internal file handling details. The fix ensures Rack::Sendfile is not in the stack unless a valid x_sendfile_header is set, reducing the chance of unintended file serving or exposure of internal paths.

Commit Details

Author: Jean Boussier

Date: 2026-03-02 11:14 UTC

Message:

Merge pull request #56915 from byroot/skip-sendfile Don't add Rack::Sendfile to the stack if `x_sendfile_header` is `nil`

Triage Assessment

Vulnerability Type: Information Disclosure / Misconfiguration

Confidence: MEDIUM

Reasoning:

The commit changes middleware stack behavior to only include Rack::Sendfile when x_sendfile_header is configured. This prevents potential exposure of internal file paths or unintended file serving when the header is not set, addressing a possible information disclosure risk and misconfiguration related to sendfile handling.

Verification Assessment

Vulnerability Type: Information Disclosure / Middleware Misconfiguration

Confidence: MEDIUM

Affected Versions: Rails 8.1.x before 8.1.3 (e.g., 8.1.0 through 8.1.2)

Code Diff

diff --git a/railties/lib/rails/application/default_middleware_stack.rb b/railties/lib/rails/application/default_middleware_stack.rb index a1e2d00bba300..adaccf35a6014 100644 --- a/railties/lib/rails/application/default_middleware_stack.rb +++ b/railties/lib/rails/application/default_middleware_stack.rb @@ -26,7 +26,9 @@ def build_stack ssl_default_redirect_status: config.action_dispatch.ssl_default_redirect_status end - middleware.use ::Rack::Sendfile, config.action_dispatch.x_sendfile_header + if config.action_dispatch.x_sendfile_header + middleware.use ::Rack::Sendfile, config.action_dispatch.x_sendfile_header + end if config.public_file_server.enabled headers = config.public_file_server.headers || {} diff --git a/railties/test/commands/middleware_test.rb b/railties/test/commands/middleware_test.rb index c7a3fc613e163..7243313130b56 100644 --- a/railties/test/commands/middleware_test.rb +++ b/railties/test/commands/middleware_test.rb @@ -27,7 +27,6 @@ def app assert_equal [ "ActionDispatch::HostAuthorization", - "Rack::Sendfile", "ActionDispatch::Static", "Propshaft::Server", "ActionDispatch::Executor", @@ -63,7 +62,6 @@ def app assert_equal [ "ActionDispatch::HostAuthorization", - "Rack::Sendfile", "ActionDispatch::Static", "Propshaft::Server", "ActionDispatch::Executor", @@ -98,7 +96,6 @@ def app assert_equal [ "ActionDispatch::HostAuthorization", - "Rack::Sendfile", "ActionDispatch::Static", "Propshaft::Server", "ActionDispatch::Executor", @@ -137,7 +134,7 @@ def app %w(ActionDispatch::Reloader ActionDispatch::ShowExceptions ActionDispatch::DebugExceptions), # Outright dependencies - %w(ActionDispatch::Static Rack::Sendfile), + %w(ActionDispatch::Static), %w(ActionDispatch::Flash ActionDispatch::Session::CookieStore), %w(ActionDispatch::Session::CookieStore ActionDispatch::Cookies), ] @@ -303,9 +300,9 @@ def app end test "insert middleware after" do - add_to_config "config.middleware.insert_after Rack::Sendfile, Rack::Config" + add_to_config "config.middleware.insert_after Rack::Runtime, Rack::Config" boot! - assert_equal "Rack::Config", middleware.third + assert_equal middleware.index("Rack::Runtime") + 1, middleware.index("Rack::Config") end test "unshift middleware" do @@ -317,20 +314,20 @@ def app test "Rails.cache does not respond to middleware" do add_to_config "config.cache_store = :file_store, '/tmp/cache'" boot! - assert_equal "Rack::Runtime", middleware[5] + assert_equal "Rack::Runtime", middleware[4] assert_instance_of ActiveSupport::Cache::FileStore, Rails.cache end test "Rails.cache does respond to middleware" do boot! - assert_equal "ActiveSupport::Cache::Strategy::LocalCache", middleware[5] - assert_equal "Rack::Runtime", middleware[6] + assert_equal "ActiveSupport::Cache::Strategy::LocalCache", middleware[4] + assert_equal "Rack::Runtime", middleware[5] end test "insert middleware before" do - add_to_config "config.middleware.insert_before Rack::Sendfile, Rack::Config" + add_to_config "config.middleware.insert_before Rack::Runtime, Rack::Config" boot! - assert_equal "Rack::Config", middleware.second + assert_operator middleware.index("Rack::Runtime"), :>, middleware.index("Rack::Config") end test "can't change middleware after it's built" do
← Back to Alerts View on GitHub →