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

Maintain html_safe? on sliced HTML safe strings #33808

Merged
merged 3 commits into from
Sep 6, 2018

Conversation

itsbagpack
Copy link
Contributor

@itsbagpack itsbagpack commented Sep 6, 2018

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

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
Member

Thanks! Can you add a CHANGELOG entry?

Co-authored-by: no-itsbackpack <no-itsbackpack@github.com>
@tenderlove
Copy link
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
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
Contributor

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

@SampsonCrowley
Copy link
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
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
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.

None yet

7 participants