Skip to content

Enforce CSRF protection in admin area (CVE-2024-7106) - #1441

Open
ringe wants to merge 2 commits into
SpinaCMS:mainfrom
soverein-it:fix/csrf-admin-cve-2024-7106
Open

Enforce CSRF protection in admin area (CVE-2024-7106)#1441
ringe wants to merge 2 commits into
SpinaCMS:mainfrom
soverein-it:fix/csrf-admin-cve-2024-7106

Conversation

@ringe

@ringe ringe commented Jun 16, 2026

Copy link
Copy Markdown

The admin controllers inherit from ActionController::Base but never declared protect_from_forgery, unlike the frontend ApplicationController. In host apps that don't enable default_protect_from_forgery (e.g. apps that don't load recent Rails defaults), the entire /admin namespace — including /admin/media_folders — accepted cross-site state-changing requests, the CSRF issue reported as GHSA-wqw3-p83g-r24v / CVE-2024-7106.

Declare protect_from_forgery with: :exception on AdminController so the admin area is self-protecting regardless of host configuration, mirroring Spina::ApplicationController. Add a regression test asserting forged (token-less) requests to an admin endpoint are rejected.

Fixes CVE-2024-7106 / GHSA-wqw3-p83g-r24v

Context

Spina CMS is affected by CVE-2024-7106 / GHSA-wqw3-p83g-r24v — a Cross-Site Request Forgery vulnerability in the admin area (reported against /admin/media_folders, medium severity, CWE-352).

Root cause: every admin controller inherits from Spina::Admin::AdminController < ActionController::Base, but that base controller never declared protect_from_forgery. The frontend Spina::ApplicationController does declare it explicitly — the admin side was relying implicitly on the host application's config.action_controller.default_protect_from_forgery (enabled by config.load_defaults).

Because Spina is a mountable engine dropped into arbitrary host apps, any host that doesn't load recent Rails defaults — or that sets default_protect_from_forgery = false — leaves the entire /admin namespace accepting cross-site, state-changing requests (create/update/destroy media folders, and every other admin action). The engine should not depend on host configuration for a security control it can guarantee itself.

Changes proposed in this pull request

  • Declare protect_from_forgery with: :exception on Spina::Admin::AdminController, so the whole admin area enforces CSRF protection independently of host-app configuration — mirroring what Spina::ApplicationController already does for the frontend.
  • Add a regression test (test/integration/spina/admin/media_folders_test.rb) that enables forgery protection and asserts a forged (token-less) POST /admin/media_folders is rejected and creates no record.

Guidance to review

  • Admin views already emit csrf_meta_tags (via layouts/spina/admin/application), and all admin forms use Rails form helpers / Turbo, which include the authenticity token automatically — so no admin flow needs to be re-plumbed. There are no manual fetch/XHR POSTs or ActiveStorage direct-upload paths in the admin JS that would lack a token.
  • The test env sets allow_forgery_protection = false, so the existing suite doesn't exercise CSRF; the new test toggles it on locally (logging in first, while protection is off, then flipping it on) to verify enforcement. Full admin integration suite stays green.
  • Suggested reviewer sanity check: confirm login, media upload, and page editing still work in an app with forgery protection enabled.

The admin controllers inherit from ActionController::Base but never
declared `protect_from_forgery`, unlike the frontend ApplicationController.
In host apps that don't enable `default_protect_from_forgery` (e.g. apps
that don't load recent Rails defaults), the entire /admin namespace —
including /admin/media_folders — accepted cross-site state-changing
requests, the CSRF issue reported as GHSA-wqw3-p83g-r24v / CVE-2024-7106.

Declare `protect_from_forgery with: :exception` on AdminController so the
admin area is self-protecting regardless of host configuration, mirroring
Spina::ApplicationController. Add a regression test asserting forged
(token-less) requests to an admin endpoint are rejected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@ringe
ringe requested a review from Bramjetten June 16, 2026 11:38
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