Files
once-campfire/test/controllers/accounts/custom_styles_controller_test.rb
T
Jeremy Daer 424219e485 Serve custom styles from a dedicated text/css route
Admin-authored custom styles were rendered inline into every page via
custom_styles_tag, marked html_safe inside a <style> element. A stored
payload containing </style><script>…</script> broke out of the style
context and executed as HTML — a stored XSS reaching everyone who
loads the app.

Deliver the styles as an external stylesheet instead, following the
account logo pattern: a new Accounts::CustomStyles#show renders the
raw CSS with a text/css content type (ETag on the account, 5-minute
public cache with stale-while-revalidate, fresh_custom_styles cache
buster on account updates), and the layout links it with
<link rel="stylesheet" data-turbo-track="reload">. In a CSS
document, markup is inert text — the HTML-context breakout is closed
by construction, and admins keep full custom-CSS capability.
2026-08-08 17:24:52 -07:00

58 lines
1.6 KiB
Ruby

require "test_helper"
class Accounts::CustomStylesControllerTest < ActionDispatch::IntegrationTest
setup do
sign_in :david
end
test "show serves custom styles as plain CSS" do
accounts(:signal).update! custom_styles: ":root { --color-text: red; }"
get account_custom_styles_url
assert_response :ok
assert_equal "text/css", @response.media_type
assert_equal ":root { --color-text: red; }", @response.body
end
test "show is accessible without authentication" do
accounts(:signal).update! custom_styles: ":root { --color-text: red; }"
reset!
get account_custom_styles_url
assert_response :ok
assert_equal "text/css", @response.media_type
end
test "show serves markup verbatim as inert CSS text, never HTML" do
payload = "</style><script>alert(1)</script>"
accounts(:signal).update! custom_styles: payload
get account_custom_styles_url
assert_response :ok
assert_equal "text/css", @response.media_type
assert_equal payload, @response.body
end
test "edit" do
get edit_account_custom_styles_url
assert_response :ok
end
test "update" do
assert users(:david).administrator?
put account_custom_styles_url, params: { account: { custom_styles: ":root { --color-text: red; }" } }
assert_redirected_to edit_account_custom_styles_url
assert_equal accounts(:signal).custom_styles, ":root { --color-text: red; }"
end
test "non-admins cannot update" do
sign_in :kevin
assert users(:kevin).member?
put account_custom_styles_url, params: { account: { custom_styles: ":root { --color-text: red; }" } }
assert_response :forbidden
end
end