mirror of
https://github.com/basecamp/once-campfire.git
synced 2026-10-23 06:16:52 +09:00
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.
This commit is contained in:
1 parent
2aa4141077
commit
424219e485
5 files changed
+44
-9
No files matched your search
@@ -5,6 +5,34 @@ class Accounts::CustomStylesControllerTest < ActionDispatch::IntegrationTest
|
||||
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
|
||||
|
||||
Reference in new issue
Block a user