Switch from report-only to actually using Sec-Fetch-Site for CSRF protection

As a fallback for Rails's token-based mechanism. To use Sec-Fetch-Site
exclusively, we'll wait until Rails offers that (when we upstream this).
This commit is contained in:
Rosa Gutierrez
2025-11-28 16:08:32 +01:00
committed by Rosa Gutierrez
parent 6941108cdb
commit f8a1e0500d
2 changed files with 51 additions and 112 deletions
@@ -12,14 +12,7 @@ module RequestForgeryProtection
end
def verified_request?
return true if request.get? || request.head? || !protect_against_forgery?
origin = valid_request_origin?
token = any_authenticity_token_valid?
sec_fetch_site = safe_fetch_site?
report_on_forgery_protection_results(origin:, token:, sec_fetch_site:)
origin && token
super || safe_fetch_site?
end
SAFE_FETCH_SITES = %w[ same-origin same-site ]
@@ -31,20 +24,4 @@ module RequestForgeryProtection
def sec_fetch_site_value
request.headers["Sec-Fetch-Site"].to_s.downcase
end
def report_on_forgery_protection_results(origin:, token:, sec_fetch_site:)
results = { origin:, token:, sec_fetch_site: }
unless results.values.all?
info = results.transform_values { it ? "pass" : "fail" }
info[:origin] += " (#{request.origin})"
info[:sec_fetch_site] += " (#{sec_fetch_site_value})"
Rails.logger.info "CSRF protection check: " + info.map { it.join(" ") }.join(", ")
if Fizzy.saas? && (origin && token) != sec_fetch_site
Sentry.capture_message "CSRF protection mismatch", level: :info, extra: { info: info }
end
end
end
end