Skip to content

feat: opt-in CSRF protection for dashboard actions#40

Merged
vishaltps merged 3 commits into
vishaltps:mainfrom
TakuroOnoda:feature/csrf-compatibility
Jun 24, 2026
Merged

feat: opt-in CSRF protection for dashboard actions#40
vishaltps merged 3 commits into
vishaltps:mainfrom
TakuroOnoda:feature/csrf-compatibility

Conversation

@TakuroOnoda

Copy link
Copy Markdown
Contributor

Summary

Adds opt-in CSRF protection for the dashboard's destructive POST actions (retry / discard / pause / resume / execute / reject / remove / prune), gated behind a new csrf_protection_enabled config (default false).

Why opt-in (default off)

The gem renders raw HTML forms and doesn't assume a session store (it supports API-only apps).
Rails' CSRF tokens require a session, so enabling it by default would break session-less hosts.
Off by default = fully backward compatible.

Changes

  • New SolidQueueMonitor.csrf_protection_enabled (default false).
  • skip_before_action :verify_authenticity_token is now skipped only when protection is disabled. When enabled, unverified POSTs return 422; safe methods pass through.
  • Destructive forms embed a token via a new csrf_token_field helper; the layout adds csrf_meta_tags. Both render nothing when disabled.
  • Fixed the failed-jobs bulk submit to preserve the token (it previously stripped all hidden inputs).
  • README / CHANGELOG / initializer template updated.

Enable

SolidQueueMonitor.setup do |config|
  config.csrf_protection_enabled = true
end

Requires a session store, same-origin mount, and a non-api_only app.


Thanks for building and maintaining such a clean, lightweight gem.
I've tried to keep this change minimal and fully backward compatible.
Hope it's a useful addition, and I'd love to hear your thoughts. 🙂

Add `config.csrf_protection_enabled` (default false) so hosts with a
session store can enable Rails' CSRF protection for the dashboard's
destructive POST actions, on par with Sidekiq::Web.

When enabled, `verify_authenticity_token` is no longer skipped, all forms
embed an authenticity token via the `csrf_token_field` helper, and the
layout renders `csrf_meta_tags`. Disabled by default to keep working in
session-less / API-only hosts.
@TakuroOnoda TakuroOnoda marked this pull request as ready for review June 19, 2026 19:07
@TakuroOnoda TakuroOnoda requested a review from vishaltps as a code owner June 19, 2026 19:07
@TakuroOnoda

Copy link
Copy Markdown
Contributor Author

Hi @vishaltps 👋 Whenever you get a chance, I'd love a review on this PR.
Happy to tweak anything to fit the project's direction.
Thanks!

vishaltps
vishaltps previously approved these changes Jun 23, 2026

@vishaltps vishaltps left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Nice work on this, tested it locally against a session-backed app and the opt-in flow behaves exactly as described. 👍

One small, purely cosmetic note: the two helpers are both conditional on csrf_protection_enabled, but only one carries the _if_enabled suffix- csrf_meta_tags_if_enabled vs csrf_token_field. Would be nice to unify the naming so the pair reads consistently. Either direction works:

  • drop the suffix → csrf_meta_tags_if_enabled becomes csrf_meta_tags (but that would shadow Rails' built-in helper, so probably not this one), or
  • keep both explicit → e.g. csrf_token_fieldcsrf_token_field_if_enabled.

Given the shadowing concern, leaning toward making both explicit feels cleanest. Totally non-blocking - just a readability nit.

@TakuroOnoda

Copy link
Copy Markdown
Contributor Author

@vishaltps
renamed csrf_token_field to csrf_token_field_if_enabled so the pair reads consistently.
b6eae16

Thanks for the review!

@vishaltps vishaltps merged commit c6e8c8e into vishaltps:main Jun 24, 2026
3 checks passed
@vishaltps

Copy link
Copy Markdown
Owner

This shipped in v2.2.0 🎉

Thanks for the thoughtful contribution, @TakuroOnoda the opt-in design and the attention to the trickier edges (the cross-origin asset guard and preserving the token through the bulk submit) made this a clean one to merge. Users can enable it with config.csrf_protection_enabled = true. 🙏

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