Skip to content

Add remote-form CSRF token coverage for the 3.2 to 4.0 hop - #130

Open
JuanVqz wants to merge 1 commit into
mainfrom
feature/remote-form-csrf-token
Open

Add remote-form CSRF token coverage for the 3.2 to 4.0 hop#130
JuanVqz wants to merge 1 commit into
mainfrom
feature/remote-form-csrf-token

Conversation

@JuanVqz

@JuanVqz JuanVqz commented Aug 26, 2026

Copy link
Copy Markdown
Member

Rails 4.0 flips embed_authenticity_token_in_remote_forms to false, so remote: true forms stop rendering the hidden authenticity_token. The token then only reaches the server as the X-CSRF-Token header UJS sets, so any submit path that bypasses UJS posts with no token. A bare protect_from_forgery nulls the session instead of raising, so the request silently loses its user.

Nothing warns and no test catches it: the Rails-side change is an absent config line, the failure is browser-only, and allow_forgery_protection is off in the test environment.

@JuanVqz
JuanVqz requested a review from etagwerker August 26, 2026 16:49
@JuanVqz
JuanVqz force-pushed the feature/remote-form-csrf-token branch from bda4ee3 to 670dc66 Compare August 27, 2026 00:38
@JuanVqz JuanVqz self-assigned this Aug 27, 2026
Rails 4.0 flips embed_authenticity_token_in_remote_forms from true to
false, so remote: true forms stop rendering the hidden authenticity_token
field. From then on the token reaches the server only as the X-CSRF-Token
header UJS sets from the csrf-token meta tag, which means the form is
protected only while UJS is the thing submitting it. Any other submit path
posts with no CSRF token at all, and a bare protect_from_forgery nulls the
session instead of raising, so the request silently loses its user rather
than erroring.

Rails made the change for fragment caching: the token is per-session, so
the hidden field makes the form's HTML unique per user and uncacheable.
Remote forms were assumed to always be submitted by UJS as an XHR, which
in a real application they are not.

Nothing warns and no test catches it. The Rails-side change is the absence
of a config line, the failure is browser-only, and allow_forgery_protection
is off in the test environment, so the missing field is invisible to the
whole suite.

- REMOTE_FORM_CSRF_TOKEN in rails-40-patterns.yml, with fixture
  expectations
- section 6 in upgrade-3.2-to-4.0.md (6 through 24 renumbered), carrying
  the mechanism, why Rails made the change, how to confirm the flip on both
  boots, the fix, the fetch case, and the regression test that catches it

The detail lives in the 4.0 guide rather than a new references/ file or a
testing-checklist item: the issue is specific to this hop, references/ is
for cross-version material, and the checklist already asks whether remote
forms and CSRF protection work. SKILL.md and the CHANGELOG are untouched.

Dry-run against a real 3.2 app: the pattern found 8 remote forms.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant