Skip to content

Maintain html_safe? on sliced HTML safe strings - #33808

Merged
tenderlove merged 3 commits into
rails:masterfrom
itsbagpack:fix-access-safety-buffer-slice
Sep 6, 2018
Merged

Maintain html_safe? on sliced HTML safe strings#33808
tenderlove merged 3 commits into
rails:masterfrom
itsbagpack:fix-access-safety-buffer-slice

Conversation

@itsbagpack

@itsbagpack itsbagpack commented Sep 6, 2018

Copy link
Copy Markdown
Contributor

Summary

This change allows for an HTML safe string to remain HTML safe even when accessed via a range.

Before

string = "<div>test</div>".html_safe
substring = string[-1..1]
substring.html_safe? # => false

After

string = "<div>test</div>".html_safe
substring = string[-1..1]
substring.html_safe? # => true

cc @tenderlove @no-itsbackpack

itsbagpack and others added 2 commits August 31, 2018 11:46
… original buffer was safe.

Co-Authored-By: no-itsbackpack <no-itsbackpack@github.com>
Co-authored-by: no-itsbackpack <no-itsbackpack@github.com>
@rails-bot

Copy link
Copy Markdown

Thanks for the pull request, and welcome! The Rails team is excited to review your changes, and you should hear from @pixeltrix (or someone else) soon.

If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes.

This repository is being automatically checked for code quality issues using Code Climate. You can see results for this analysis in the PR status below. Newly introduced issues should be fixed before a Pull Request is considered ready to review.

Please see the contribution instructions for more information.

@rafaelfranca

Copy link
Copy Markdown
Member

Thanks! Can you add a CHANGELOG entry?

Co-authored-by: no-itsbackpack <no-itsbackpack@github.com>
@tenderlove

Copy link
Copy Markdown
Member

The railties failures seem unrelated, so I'll merge this.

@tenderlove
tenderlove merged commit b31ae31 into rails:master Sep 6, 2018
@itsbagpack
itsbagpack deleted the fix-access-safety-buffer-slice branch September 6, 2018 22:02
@rafaelfranca

Copy link
Copy Markdown
Member

I thought that I already did 🤦‍♂️. Thanks

suketa added a commit to suketa/rails_sandbox that referenced this pull request May 19, 2019
Maintain html_safe? on sliced HTML safe strings
rails/rails#33808
@SampsonCrowley

Copy link
Copy Markdown
Contributor

I'm coming way late to the party but how is this not extremely dangerous?

@SampsonCrowley

Copy link
Copy Markdown
Contributor

"<wholetag>".slice[-1..-1] would then give you a closing tag that's marked as html_safe to inject. is this not a problem because it would have to be developer error to use that piece anyways?

@flavorjones

Copy link
Copy Markdown
Member

@SampsonCrowley I think the assumption here is that the string being operated on is marked "html safe" when it has been html-sanitized (for example, by ActionView::Helpers::SanitizeHelper#sanitize) or escaped (for example, by ERB::Util.html_escape).

In that case, any comments or dangerous tags (like <script>) will have been removed or escaped during sanitization, and so while a slice may not be well-formed, it's not malicious. If you are able to generate a string that, once it's been sanitized and marked safe, would have a malicious substring in it, please open an issue so we can discuss?

As a starting point, here's a script to generate two different "safe" HTML strings:

#! /usr/bin/env ruby

require "action_view"
require "active_support"

class Sanitizer
  include ActionView::Helpers::SanitizeHelper
end

class Escaper
  include ERB::Util

  def escape(string)
    html_escape(string)
  end
end

original = %{<div><script>alert("xss")</script></div>}
# => "<div><script>alert(\"xss\")</script></div>"

safe = Sanitizer.new.sanitize(original)
# => "<div>alert(\"xss\")</div>"
safe.html_safe? # => true

safe = Escaper.new.escape(original)
# => "&lt;div&gt;&lt;script&gt;alert(&quot;xss&quot;)&lt;/script&gt;&lt;/div&gt;"
safe.html_safe? # => true

@SampsonCrowley

Copy link
Copy Markdown
Contributor

@flavorjones sorry my original reply was missing the part marking the string as html_safe

Taking the original original comment as an example:

In the behavior before this PR: str = "<script>".html_safe would not be escaped, and it shouldn't be because it is being explicitly marked as an actual html "safe" string, i.e. any unsafe characters have already been properly formatted

But if you were to then call slice on it, str[-1..-1], the previous behavior was that the string was then decidedly not assumed safe for direct consumption because any html may no longer be properly formatted or escaped. In the previous call you would now have just a closing carrat ">", if you know as a developer that the string is still safe you could mark it as such, but otherwise it was previously assumed to no longer be safe for direct consumption

Now

str[-1..-1] will give you a closing carrat that is still marked html "safe", even though it's not the original structure and may be improperly formatted or contain partial html.

So I don't understand how it's is safe to assume by default that a string that has been sliced from an html_safe string is still html safe just because it was html safe in its original full string

Or maybe I'm just misunderstanding the use case

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.

7 participants