Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

html_escape_once decodes items flagged html_safe #48256

Closed
antemasqued opened this issue May 19, 2023 · 3 comments · Fixed by #48265
Closed

html_escape_once decodes items flagged html_safe #48256

antemasqued opened this issue May 19, 2023 · 3 comments · Fixed by #48265

Comments

@antemasqued
Copy link

If we mark something html_safe, we typically expect it to be rendered as-is and left alone.

If we utilize html_escape_once then somehow the above purpose of html_safe is neglected and that item is decoded.

This doesn't appear to be an uncaught edge case, but rather something done explicitly as is shown below (ref)

# File activesupport/lib/active_support/core_ext/string/output_safety.rb, line 44
    def html_escape_once(s)
      result = s.to_s.gsub(HTML_ESCAPE_ONCE_REGEXP, HTML_ESCAPE)
      s.html_safe? ? result.html_safe : result
    end

This seems to be inconsistent behavior as html_escape itself explicitly skips the escaping. What's the purpose of this? We have an explicit line here for this, so surely there was some thought put into this 🤔.

https://github.com/rails/rails/blob/4e1fe73028f4b01c8e5179989511b21925f70b20/activesupport/lib/active_support/core_ext/erb/util.rb#LL67C1-L67C47

@flavorjones
Copy link
Member

Historical note: this behavior seems to date back to 608eddc (2012-01-12) when the method was extracted from TagHelper and the existing behavior was preserved.

The original implementation in TagHelper is from dbd0bd5 and 02358c8 (2006-10-18) and e711d8f (2007-09-24). Note that the concept of html_safe was not introduced until 9415935 (2009-10-08).

A reasonable conclusion might be that the decision to preserve the html_safe property was not an intentional one, but the existing behavior from 2009 has simply been preserved going forward. There have been quite a few inconsistencies like this raised or fixed in the past few years, see #47361 for a discussion and some links to prior issues and PRs.

I think it would be appropriate to update the behavior of this method to always return an html_safe string, but I'm interested in hearing what the Rails committers think. cc @jhawthorn and @matthewd who have chatted with me about html safety in the past.

@flavorjones
Copy link
Member

I've created #48265 to have this method always return an html_safe string.

byroot pushed a commit to flavorjones/rails that referenced this issue May 22, 2023
This method previously maintained the `html_safe?` property of a string on the return
value. Because this string has been escaped, however, not marking it as `html_safe` causes
entities to be double-escaped.

As an example, take this view snippet:

  ```html
  <p><%= html_escape_once("this & that &amp; the other") %></p>
  ```

Before this change, that would be double-escaped and render as:

  ```html
  <p>this &amp;amp; that &amp;amp; the other</p>
  ```

After this change, it renders correctly as:

  ```html
  <p>this &amp; that &amp; the other</p>
  ```

[Fix rails#48256]
@antemasqued
Copy link
Author

thanks @flavorjones and @byroot 🍾

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 a pull request may close this issue.

2 participants