Skip to content

Skip CSRF protection for token-keyed invitation RSVP actions - #2838

Merged
mroderick merged 2 commits into
masterfrom
fix/skip-forgery-on-token-rsvp-actions
Sep 2, 2026
Merged

Skip CSRF protection for token-keyed invitation RSVP actions#2838
mroderick merged 2 commits into
masterfrom
fix/skip-forgery-on-token-rsvp-actions

Conversation

@mroderick

@mroderick mroderick commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Members who open invitation links from mail apps cannot RSVP: their browser withholds the session cookie, so CSRF verification fails with ActionController::InvalidAuthenticityToken (Rollbar 535). The invitation token in the URL already authenticates these actions, so this change removes the redundant CSRF check from them.

Key changes:

  • skip_forgery_protection for the six token-keyed RSVP actions: InvitationsController#attend/#reject, WorkshopInvitationController#update/#accept, and WaitingListsController#create/#destroy (scoped only:).
  • Each action looks up the invitation by a 128-bit SecureRandom token carried in the URL. The request carries no session authority, which is the only thing CSRF protects — an attacker who cannot guess the token cannot forge the request. PR fix: skip CSRF protection for feedback form submission #2641 applied the same reasoning to the feedback form.
  • Regression specs for all six actions: each posts without a CSRF token and asserts the mutation still happens.
Background and scope

Web browsers withhold cookies when they classify a navigation as cross-site. WebKit's Intelligent Tracking Prevention does this for every iOS browser, including Chrome, so members arriving from Mail, Gmail, or Slack reach the invitation page with an ephemeral session. The RSVP POST then arrives without a matching session and fails CSRF verification.

The failure first surfaced on the feedback form and was fixed for that form alone in PR #2641. An audit of all mutating routes found six more token-keyed actions with the same structure; everything else (self check-in, account settings, admin, OAuth) is session-gated and keeps CSRF protection.

Related, not addressed here: the workshop invitation "reject" link mutates via a GET request, which email prefetchers can trigger. That needs its own change.

@mroderick
mroderick force-pushed the fix/skip-forgery-on-token-rsvp-actions branch from 1bafa8a to 20e34fd Compare September 2, 2026 12:16
@mroderick
mroderick marked this pull request as ready for review September 2, 2026 12:27

@olleolleolle olleolleolle left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps some of the test preconditions could become a nested context.

Event and workshop invitation RSVP actions are authenticated solely by
the unguessable invitation token in the URL, so CSRF is redundant there.
It also fails outright when browsers withhold the session cookie (e.g.
WebKit ITP classifying the navigation from a mail client as cross-site),
which surfaces as ActionController::InvalidAuthenticityToken in Rollbar
#535 -- the same failure PR #2641 fixed for the feedback form.

Skip forgery protection for InvitationsController#attend/#reject,
WorkshopInvitationController#update/#accept, and both WaitingListsController
actions, and add regression specs that post without a CSRF token.
@mroderick
mroderick force-pushed the fix/skip-forgery-on-token-rsvp-actions branch from 20e34fd to e79e4e8 Compare September 2, 2026 14:02
@mroderick

Copy link
Copy Markdown
Collaborator Author

Applied: the CSRF-protection toggle now lives in a shared context (spec/support/shared_contexts/forgery_protection.rb) used by all seven specs, and each precondition moved into nested context blocks with let/before. The #update and #accept no-CSRF specs are now nested inside their existing action describes, reusing the file's top-level let(:invitation). The feedback spec from #2641 uses the shared context too.

@mroderick
mroderick enabled auto-merge September 2, 2026 21:31
@mroderick
mroderick merged commit 37d5cec into master Sep 2, 2026
9 checks passed
@mroderick
mroderick deleted the fix/skip-forgery-on-token-rsvp-actions branch September 2, 2026 21:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants