Created
October 14, 2020 03:03
-
-
Save mieko/5f40fcf42ca95150023c2c627d3272d8 to your computer and use it in GitHub Desktop.
Mixed HTML/Plaintext `flash` messages in Rails 4.1+ JSON cookie serializer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "rack/utils" | |
# Rails < 4.1 serialized sessions with Marshal, which could distinguish "html_safe" flash strings | |
# from unsafe strings because it encoded actual ActiveSupport::SafeBuffer objects. So when the | |
# flash message came back from the client, its "safe" status was preserved, and it was rendered | |
# correctly under both circumstances. | |
# | |
# This same "magic" ability is also why Rails moved away from it: multiple CVEs due to arbitrary | |
# object creation. But regardless, that was a *really* nice trick. | |
# | |
# The JSON encoder cannot discriminate between safe and unsafe strings: they're all just strings | |
# when they come back. So we now have to commit to rendering all flash messages as either | |
# plain-text or HTML at render time. | |
# | |
# This mixin HTML-escapes values assigned to `flash` keys on assignment, but does not escape | |
# objects which are `html_safe?`. This means we'll get escaped output by default (so we're still | |
# XSS-safe), but can override it when we need to use HTML in flash messages (via `#html_safe` on | |
# the string), much like the old Marshal serializer. | |
# | |
# So rendering flash notices in the layout as un-escaped is now safe, and does what we want again. | |
module SanitizedFlash | |
def []=(key, value) | |
super(key, value.html_safe? ? value : Rack::Utils.escape_html(value.to_s)) | |
end | |
end | |
ActionDispatch::Flash::FlashHash.prepend(::SanitizedFlash) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment